diff --git a/schala-repl/src/repl/command_tree.rs b/schala-repl/src/repl/command_tree.rs index 2f7f130..c8cd05a 100644 --- a/schala-repl/src/repl/command_tree.rs +++ b/schala-repl/src/repl/command_tree.rs @@ -2,6 +2,8 @@ use super::Repl; pub type BoxedCommandFunction = Box<(fn(&mut Repl, &[&str]) -> Option)>; +/// A CommandTree is either a `Terminal` or a `NonTerminal`. When command parsing reaches the first +/// Terminal, it will execute the `BoxedCommandFunction` found there with any remaining arguments #[derive(Clone)] pub enum CommandTree { Terminal { @@ -23,7 +25,7 @@ impl CommandTree { CommandTree::NonTerminal {name: s.to_string(), help_msg: help.map(|x| x.to_string()), children: vec![] } } - pub fn term_with_function(s: &str, help: Option<&str>, children: Vec, function: BoxedCommandFunction) -> CommandTree { + pub fn terminal(s: &str, help: Option<&str>, children: Vec, function: BoxedCommandFunction) -> CommandTree { CommandTree::Terminal {name: s.to_string(), help_msg: help.map(|x| x.to_string()), function, children } } diff --git a/schala-repl/src/repl/mod.rs b/schala-repl/src/repl/mod.rs index 99b6755..c12d2e0 100644 --- a/schala-repl/src/repl/mod.rs +++ b/schala-repl/src/repl/mod.rs @@ -217,21 +217,21 @@ impl Repl { .collect(); CommandTree::Top(vec![ - CommandTree::term_with_function("exit", Some("exit the REPL"), vec![], Box::new(|repl: &mut Repl, _cmds: &[&str]| { + CommandTree::terminal("exit", Some("exit the REPL"), vec![], Box::new(|repl: &mut Repl, _cmds: &[&str]| { repl.save_before_exit(); ::std::process::exit(0) })), - CommandTree::term_with_function("quit", Some("exit the REPL"), vec![], Box::new(|repl: &mut Repl, _cmds: &[&str]| { + CommandTree::terminal("quit", Some("exit the REPL"), vec![], Box::new(|repl: &mut Repl, _cmds: &[&str]| { repl.save_before_exit(); ::std::process::exit(0) })), - CommandTree::term_with_function("help", Some("Print this help message"), vec![], Box::new(|repl: &mut Repl, cmds: &[&str]| { + CommandTree::terminal("help", Some("Print this help message"), vec![], Box::new(|repl: &mut Repl, cmds: &[&str]| { Some(repl.print_help_message(cmds)) })), - CommandTree::term_with_function("debug", + CommandTree::nonterm("debug", Some("Configure debug information"), vec![ - CommandTree::term_with_function("list-passes", Some("List all registered compiler passes"), vec![], Box::new(|repl: &mut Repl, _cmds: &[&str]| { + CommandTree::terminal("list-passes", Some("List all registered compiler passes"), vec![], Box::new(|repl: &mut Repl, _cmds: &[&str]| { let language_state = repl.get_cur_language_state(); let pass_names = match language_state.request_meta(LangMetaRequest::StageNames) { LangMetaResponse::StageNames(names) => names, @@ -247,66 +247,56 @@ impl Repl { } Some(buf) })), - CommandTree::nonterm("show-immediate", None, passes_directives.clone()), - CommandTree::nonterm("show", None, passes_directives.clone()), - CommandTree::nonterm("hide", None, passes_directives.clone()), + CommandTree::terminal("show-immediate", None, passes_directives.clone(), + Box::new(|repl: &mut Repl, cmds: &[&str]| { + let cur_state = repl.get_cur_language_state(); + let stage_name = match cmds.get(1) { + Some(s) => s.to_string(), + None => return Some(format!("Must specify a thing to debug")), + }; + let meta = LangMetaRequest::ImmediateDebug( + DebugRequest { ask: DebugAsk::ByStage { stage_name: stage_name.clone() } } + ); + let response = match cur_state.request_meta(meta) { + LangMetaResponse::ImmediateDebug(DebugResponse { ask, value }) => { + if (ask != DebugAsk::ByStage { stage_name: stage_name }) { + return Some(format!("Didn't get debug stage requested")); + } + value + }, + _ => return Some(format!("Invalid language meta response")), + }; + Some(response) + })), + CommandTree::terminal("show", None, passes_directives.clone(), Box::new(|repl: &mut Repl, cmds: &[&str]| { + let stage_name = match cmds.get(0) { + Some(s) => s.to_string(), + None => return Some(format!("Must specify a stage to show")), + }; + let ask = DebugAsk::ByStage { stage_name }; + repl.options.debug_asks.insert(ask); + None + })), + CommandTree::terminal("hide", None, passes_directives.clone(), Box::new(|repl: &mut Repl, cmds: &[&str]| { + let stage_name = match cmds.get(0) { + Some(s) => s.to_string(), + None => return Some(format!("Must specify a stage to hide")), + }; + let ask = DebugAsk::ByStage { stage_name }; + repl.options.debug_asks.remove(&ask); + None + })), CommandTree::nonterm("total-time", None, vec![ - CommandTree::term_with_function("on", None, vec![], Box::new(|repl: &mut Repl, _: &[&str]| { + CommandTree::terminal("on", None, vec![], Box::new(|repl: &mut Repl, _: &[&str]| { repl.options.show_total_time = true; None })), - CommandTree::term_with_function("off", None, vec![], Box::new(|repl: &mut Repl, _: &[&str]| { + CommandTree::terminal("off", None, vec![], Box::new(|repl: &mut Repl, _: &[&str]| { repl.options.show_total_time = false; None })), ]) - ], - Box::new(|repl: &mut Repl, cmds: &[&str]| { - let cur_state = repl.get_cur_language_state(); - match cmds.get(0) { - Some(&"show-immediate") => { - let stage_name = match cmds.get(1) { - Some(s) => s.to_string(), - None => return Some(format!("Must specify a thing to debug")), - }; - let meta = LangMetaRequest::ImmediateDebug( - DebugRequest { ask: DebugAsk::ByStage { stage_name: stage_name.clone() } } - ); - let response = match cur_state.request_meta(meta) { - LangMetaResponse::ImmediateDebug(DebugResponse { ask, value }) => { - if (ask != DebugAsk::ByStage { stage_name: stage_name }) { - return Some(format!("Didn't get debug stage requested")); - } - value - }, - _ => return Some(format!("Invalid language meta response")), - }; - Some(response) - }, - cmd @ Some(&"show") | cmd @ Some(&"hide") => { - let stage_name = match cmds.get(1) { - Some(s) => s.to_string(), - None => return Some(format!("Must specify a stage to show or hide")), - }; - let ask = DebugAsk::ByStage { stage_name }; - if cmd == Some(&"show") { - repl.options.debug_asks.insert(ask); - } else { - repl.options.debug_asks.remove(&ask); - } - None - }, - Some(&"timing") => { - match cmds.get(1) { - Some(&"on") => repl.options.debug_asks.insert(DebugAsk::Timing), - Some(&"off") => repl.options.debug_asks.remove(&DebugAsk::Timing), - _ => return Some(format!("Must specify 'on' or 'off'")), - }; - None - }, - e => Some(format!("Unsupported command: {:?}", e)), - } - }) + ] ), CommandTree::nonterm("lang", Some("switch between languages, or go directly to a langauge by name"), @@ -316,7 +306,7 @@ impl Repl { CommandTree::nonterm("go", None, vec![]), ] ), - CommandTree::term_with_function("doc", Some("Get language-specific help for an item"), vec![], Box::new(|repl: &mut Repl, cmds: &[&str]| { + CommandTree::terminal("doc", Some("Get language-specific help for an item"), vec![], Box::new(|repl: &mut Repl, cmds: &[&str]| { cmds.get(0).map(|cmd| { let source = cmd.to_string(); let meta = LangMetaRequest::Docs { source };