Skip to content

Commit c6ef62c

Browse files
committed
Improved interpreter using compile single and with multiline input.
1 parent 1333e62 commit c6ef62c

2 files changed

Lines changed: 45 additions & 8 deletions

File tree

parser/src/parser.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
extern crate lalrpop_util;
2+
13
use std::error::Error;
24
use std::fs::File;
35
use std::io::Read;
@@ -41,6 +43,8 @@ pub fn parse(filename: &Path) -> Result<ast::Program, String> {
4143
pub fn parse_program(source: &String) -> Result<ast::Program, String> {
4244
let lxr = lexer::Lexer::new(&source);
4345
match python::ProgramParser::new().parse(lxr) {
46+
Err(lalrpop_util::ParseError::UnrecognizedToken{token: None, expected: _}) =>
47+
Err(String::from("Unexpected end of input.")),
4448
Err(why) => Err(String::from(format!("{:?}", why))),
4549
Ok(p) => Ok(p),
4650
}

src/main.rs

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,12 @@ use clap::{App, Arg};
1111
use rustpython_parser::parser;
1212
use rustpython_vm::VirtualMachine;
1313
use rustpython_vm::compile;
14-
use rustpython_vm::eval::eval;
1514
use std::io;
1615
use std::io::prelude::*;
1716
use std::path::Path;
1817

18+
use rustpython_vm::pyobject::PyObjectRef;
19+
1920
fn main() {
2021
env_logger::init();
2122
let matches = App::new("RustPython")
@@ -85,6 +86,30 @@ fn run_script(script_file: &String) {
8586
}
8687
}
8788

89+
fn shell_exec(vm: &mut VirtualMachine, source: &String, scope: PyObjectRef) -> bool {
90+
match compile::compile(vm, source, compile::Mode::Single) {
91+
Ok(code) => {
92+
match vm.run_code_obj(code, scope.clone()) {
93+
Ok(_value) => {
94+
// Printed already.
95+
}
96+
Err(msg) => {
97+
println!("Error: {:?}", msg);
98+
},
99+
}
100+
}
101+
Err(msg) => {
102+
// Enum rather than special string here.
103+
if msg == "Unexpected end of input." {
104+
return false;
105+
} else {
106+
println!("Error: {:?}", msg)
107+
}
108+
}
109+
};
110+
true
111+
}
112+
88113
fn run_shell() {
89114
println!(
90115
"Welcome to the magnificent Rust Python {} interpreter",
@@ -94,20 +119,28 @@ fn run_shell() {
94119
let builtins = vm.get_builtin_scope();
95120
let vars = vm.context().new_scope(Some(builtins)); // Keep track of local variables
96121
// Read a single line:
122+
let mut input = String::new();
97123
loop {
98-
let mut input = String::new();
99-
print!(">>>>> "); // Use 5 items. pypy has 4, cpython has 3.
124+
let mut line = String::new();
125+
if input == String::new() {
126+
print!(">>>>> "); // Use 5 items. pypy has 4, cpython has 3.
127+
} else {
128+
print!("..... ");
129+
}
100130
io::stdout().flush().ok().expect("Could not flush stdout");
101-
match io::stdin().read_line(&mut input) {
131+
match io::stdin().read_line(&mut line) {
102132
Ok(0) => {
103133
break;
104134
}
105135
Ok(_) => {
136+
input += &line;
106137
debug!("You entered {:?}", input);
107-
match eval(&mut vm, &input, vars.clone()) {
108-
Ok(value) => println!("{}", vm.to_str(value)),
109-
Err(value) => println!("Error: {:?}", value),
110-
};
138+
if shell_exec(&mut vm, &input, vars.clone()) {
139+
// Line was complete.
140+
input = String::new();
141+
} else {
142+
// More input needed.
143+
}
111144
}
112145
Err(msg) => {
113146
panic!("Error: {:?}", msg)

0 commit comments

Comments
 (0)