From 36bef81ceb9483b5a539e1d6525e71b4e05b7d7c Mon Sep 17 00:00:00 2001 From: Windel Bouwman Date: Sat, 14 Jul 2018 16:03:50 +0200 Subject: [PATCH] Change eval compile to statement --- README.md | 7 +++++++ parser/src/lexer.rs | 16 +++++++++++++--- parser/src/parser.rs | 12 ++++++++++-- parser/src/python.lalrpop | 2 +- src/main.rs | 2 +- vm/src/compile.rs | 17 +++++++++++++---- vm/src/vm.rs | 4 ++-- 7 files changed, 47 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index cc1f6cbd2..93155cccd 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,13 @@ To test RustPython, do the following: $ cargo run demo.py 42 +Or use the interactive shell: + + $ cargo run + Welcome to rustpython + >>>>> 2+2 + 4 + Or use pip to install extra modules: $ cargo run -m pip install requests diff --git a/parser/src/lexer.rs b/parser/src/lexer.rs index 71206b51c..33a28ee68 100644 --- a/parser/src/lexer.rs +++ b/parser/src/lexer.rs @@ -157,7 +157,7 @@ impl<'input> Lexer<'input> { fn is_char(&self) -> bool { match self.chr0 { - Some('a'...'z') => return true, + Some('a'...'z') | Some('A'...'Z') => return true, _ => return false, } } @@ -226,8 +226,7 @@ impl<'input> Lexer<'input> { match self.chr0 { Some('0'...'9') => return Some(self.lex_number()), - // TODO: 'A'...'Z' - Some('a'...'z') => return Some(self.lex_identifier()), + Some('a'...'z') | Some('A'...'Z') => return Some(self.lex_identifier()), Some('#') => { self.lex_comment(); continue; @@ -370,6 +369,17 @@ impl<'input> Lexer<'input> { _ => return Some(Ok((tok_start, Tok::At, self.location + 1))), } } + Some('!') => { + let tok_start = self.location; + self.next_char(); + match self.chr0 { + Some('=') => { + self.next_char(); + return Some(Ok((tok_start, Tok::NotEqual, self.location + 1))); + }, + _ => panic!("Invalid token '!'"), + } + } Some('~') => { self.next_char(); return Some(Ok((0, Tok::Tilde, 0))); diff --git a/parser/src/parser.rs b/parser/src/parser.rs index 3eb4285de..86e021dde 100644 --- a/parser/src/parser.rs +++ b/parser/src/parser.rs @@ -46,6 +46,14 @@ pub fn parse_program(source: &String) -> Result { } } +pub fn parse_statement(source: &String) -> Result { + let lxr = lexer::Lexer::new(&source); + match python::StatementParser::new().parse(lxr) { + Err(why) => Err(String::from(format!("{:?}", why))), + Ok(p) => Ok(p), + } +} + pub fn parse_expression(source: &String) -> Result { let lxr = lexer::Lexer::new(&source); match python::ExpressionParser::new().parse(lxr) { @@ -56,7 +64,7 @@ pub fn parse_expression(source: &String) -> Result { #[cfg(test)] mod tests { - use super::parse_source; + use super::parse_program; use super::ast; #[test] @@ -87,7 +95,7 @@ mod tests { #[test] fn test_parse_print_2() { let source = String::from("print('Hello world', 2)\n"); - let parse_ast = parse_source(&source).unwrap(); + let parse_ast = parse_program(&source).unwrap(); assert_eq!( parse_ast, ast::Program { diff --git a/parser/src/python.lalrpop b/parser/src/python.lalrpop index 5ddc4a490..a8bee6f6b 100644 --- a/parser/src/python.lalrpop +++ b/parser/src/python.lalrpop @@ -20,7 +20,7 @@ Suite: Vec = { "\n" indent dedent => s, }; -Statement: ast::Statement = { +pub Statement: ast::Statement = { SimpleStatement, CompoundStatement, }; diff --git a/src/main.rs b/src/main.rs index 058f0437e..6f0663ddd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -66,7 +66,7 @@ fn run_shell() { 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(); + // input = input.trim().to_string(); debug!("You entered {:?}", input); let result = eval(&mut vm, &input); match result { diff --git a/vm/src/compile.rs b/vm/src/compile.rs index 342533e42..d19e2e06d 100644 --- a/vm/src/compile.rs +++ b/vm/src/compile.rs @@ -26,9 +26,17 @@ pub fn compile(source: &String, mode: Mode) -> Result { } } Mode::Eval => { - match parser::parse_expression(source) { - Ok(ast) => { - compiler.compile_expression(ast); + 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()) } @@ -90,7 +98,8 @@ impl Compiler { self.compile_expression(expression); // Pop result of stack, since we not use it: - self.emit(Instruction::Pop); + // TODO: do we need to clean the stack here? + // self.emit(Instruction::Pop); } ast::Statement::If { test, body } => { self.compile_expression(test); diff --git a/vm/src/vm.rs b/vm/src/vm.rs index 59df6087b..ca569a5f4 100644 --- a/vm/src/vm.rs +++ b/vm/src/vm.rs @@ -295,7 +295,7 @@ impl VirtualMachine { fn _eq(&mut self, a: PyObjectRef, b: PyObjectRef) -> PyResult { let b2 = &*b.borrow(); let a2 = &*a.borrow(); - let result_bool = a == b; + let result_bool = a2 == b2; let result = self.ctx.new_bool(result_bool); Ok(result) } @@ -303,7 +303,7 @@ impl VirtualMachine { fn _ne(&mut self, a: PyObjectRef, b: PyObjectRef) -> PyResult { let b2 = &*b.borrow(); let a2 = &*a.borrow(); - let result_bool = a != b; + let result_bool = a2 != b2; let result = self.ctx.new_bool(result_bool); Ok(result) }