Make REPL interpreter return a value

This commit is contained in:
greg 2018-03-25 00:09:51 -07:00
parent 0b2e2cf68b
commit 7f21b70e3f
1 changed files with 35 additions and 50 deletions

View File

@ -20,6 +20,7 @@ use std::fs::File;
use std::io::{Read, Write}; use std::io::{Read, Write};
use std::process::exit; use std::process::exit;
use std::default::Default; use std::default::Default;
use std::fmt::Write as FmtWrite;
use rustyline::error::ReadlineError; use rustyline::error::ReadlineError;
use rustyline::Editor; use rustyline::Editor;
@ -181,12 +182,13 @@ impl Repl {
println!("Terminal read error: {}", e); println!("Terminal read error: {}", e);
}, },
Ok(ref input) => { Ok(ref input) => {
self.console.add_history_entry(input); let output = match input.chars().nth(0) {
if self.handle_interpreter_directive(input) { Some(ch) if ch == self.interpreter_directive_sigil => self.handle_interpreter_directive(input),
continue; _ => Some(self.input_handler(input)),
};
if let Some(o) = output {
println!("=> {}", o);
} }
let output = self.input_handler(input);
println!("=> {}", output);
} }
} }
} }
@ -201,22 +203,16 @@ impl Repl {
interpreter_output.to_repl() interpreter_output.to_repl()
} }
fn handle_interpreter_directive(&mut self, input: &str) -> bool { fn handle_interpreter_directive(&mut self, input: &str) -> Option<String> {
match input.chars().nth(0) {
Some(ch) if ch == self.interpreter_directive_sigil => (),
_ => return false
}
let mut iter = input.chars(); let mut iter = input.chars();
iter.next(); iter.next();
let trimmed_sigil: &str = iter.as_str(); let commands: Vec<&str> = iter
.as_str()
let commands: Vec<&str> = trimmed_sigil
.split_whitespace() .split_whitespace()
.collect(); .collect();
let cmd: &str = match commands.get(0).clone() { let cmd: &str = match commands.get(0).clone() {
None => return true, None => return None,
Some(s) => s Some(s) => s
}; };
@ -226,49 +222,46 @@ impl Repl {
exit(0) exit(0)
}, },
"help" => { "help" => {
println!("Commands:"); Some(r#"Commands:
println!("exit | quit"); exit | quit
println!("lang(uage) [go|show|next|previous]"); lang(uage) [go|show|next|previous]
println!("set [show|hide] [tokens|parse|symbols|eval|llvm]"); set [show|hide] [tokens|parse|symbols|eval|llvm]
println!("options"); options"#.to_string())
} }
"lang" | "language" => { "lang" | "language" => {
match commands.get(1) { match commands.get(1) {
Some(&"show") => { Some(&"show") => {
let mut buf = String::new();
for (i, lang) in self.languages.iter().enumerate() { for (i, lang) in self.languages.iter().enumerate() {
if i == self.current_language_index { write!(buf, "{}{}\n", if i == self.current_language_index { "* "} else { "" }, lang.get_language_name()).unwrap();
println!("* {}", lang.get_language_name());
} else {
println!("{}", lang.get_language_name());
}
} }
Some(buf)
}, },
Some(&"go") => { Some(&"go") => {
match commands.get(2) { match commands.get(2) {
None => println!("Must specify a language name"), None => Some(format!("Must specify a language name")),
Some(&desired_name) => { Some(&desired_name) => {
for (i, _) in self.languages.iter().enumerate() { for (i, _) in self.languages.iter().enumerate() {
let lang_name = self.languages[i].get_language_name(); let lang_name = self.languages[i].get_language_name();
if lang_name.to_lowercase() == desired_name.to_lowercase() { if lang_name.to_lowercase() == desired_name.to_lowercase() {
self.current_language_index = i; self.current_language_index = i;
println!("Switching to {}", self.languages[self.current_language_index].get_language_name()); return Some(format!("Switching to {}", self.languages[self.current_language_index].get_language_name()));
return true;
} }
} }
println!("Language {} not found", desired_name); Some(format!("Language {} not found", desired_name))
} }
} }
}, },
Some(&"next") => { Some(&"next") => {
self.current_language_index = (self.current_language_index + 1) % self.languages.len(); self.current_language_index = (self.current_language_index + 1) % self.languages.len();
println!("Switching to {}", self.languages[self.current_language_index].get_language_name()); Some(format!("Switching to {}", self.languages[self.current_language_index].get_language_name()))
} }
Some(&"prev") | Some(&"previous") => { Some(&"prev") | Some(&"previous") => {
self.current_language_index = if self.current_language_index == 0 { self.languages.len() - 1 } else { self.current_language_index - 1 }; self.current_language_index = if self.current_language_index == 0 { self.languages.len() - 1 } else { self.current_language_index - 1 };
println!("Switching to {}", self.languages[self.current_language_index].get_language_name()); Some(format!("Switching to {}", self.languages[self.current_language_index].get_language_name()))
}, },
Some(e) => println!("Bad `lang` argument: {}", e), Some(e) => Some(format!("Bad `lang` argument: {}", e)),
None => println!("`lang` - valid arguments `show`, `next`, `prev`|`previous`"), None => Some(format!("`lang` - valid arguments `show`, `next`, `prev`|`previous`")),
} }
}, },
"set" => { "set" => {
@ -276,12 +269,10 @@ impl Repl {
Some(&"show") => true, Some(&"show") => true,
Some(&"hide") => false, Some(&"hide") => false,
Some(e) => { Some(e) => {
println!("Bad `set` argument: {}", e); return Some(format!("Bad `set` argument: {}", e));
return true;
} }
None => { None => {
println!("`set` - valid arguments `show {{option}}`, `hide {{option}}`"); return Some(format!("`set` - valid arguments `show {{option}}`, `hide {{option}}`"));
return true;
} }
}; };
match commands.get(2) { match commands.get(2) {
@ -290,15 +281,10 @@ impl Repl {
Some(&"ast") => self.options.debug.ast = show, Some(&"ast") => self.options.debug.ast = show,
Some(&"symbols") => self.options.debug.symbol_table = show, Some(&"symbols") => self.options.debug.symbol_table = show,
Some(&"llvm") => self.options.debug.llvm_ir = show, Some(&"llvm") => self.options.debug.llvm_ir = show,
Some(e) => { Some(e) => return Some(format!("Bad `show`/`hide` argument: {}", e)),
println!("Bad `show`/`hide` argument: {}", e); None => return Some(format!("`show`/`hide` requires an argument")),
return true; };
} None
None => {
println!("`show`/`hide` requires an argument");
return true;
}
}
}, },
"options" => { "options" => {
let ref d = self.options.debug; let ref d = self.options.debug;
@ -306,12 +292,11 @@ impl Repl {
let parse_tree = if d.parse_tree { "true".green() } else { "false".red() }; let parse_tree = if d.parse_tree { "true".green() } else { "false".red() };
let ast = if d.ast { "true".green() } else { "false".red() }; let ast = if d.ast { "true".green() } else { "false".red() };
let symbol_table = if d.symbol_table { "true".green() } else { "false".red() }; let symbol_table = if d.symbol_table { "true".green() } else { "false".red() };
println!(r#"Debug: Some(format!(r#"Debug:
tokens: {}, parse: {}, ast: {}, symbols: {}"#, tokens, parse_tree, ast, symbol_table); tokens: {}, parse: {}, ast: {}, symbols: {}"#, tokens, parse_tree, ast, symbol_table))
}, },
e => println!("Unknown command: {}", e) e => Some(format!("Unknown command: {}", e))
} }
return true;
} }
} }