use std::fmt::Write as FmtWrite; use itertools::Itertools; use crate::repl::Repl; use crate::repl::command_tree::CommandTree; use crate::language::{ProgrammingLanguageInterface, LangMetaRequest, LangMetaResponse, DebugAsk, DebugResponse}; pub fn get_directives(language_state: &mut Box) -> CommandTree { let pass_names = match language_state.request_meta(LangMetaRequest::StageNames) { LangMetaResponse::StageNames(names) => names, _ => vec![], }; let passes_directives: Vec = pass_names.iter() .map(|pass_name| { CommandTree::nonterm_no_further_tab_completions(pass_name, None) }) .collect(); CommandTree::Top(vec![ CommandTree::terminal("exit", Some("exit the REPL"), vec![], Box::new(|repl: &mut Repl, _cmds: &[&str]| { repl.save_before_exit(); ::std::process::exit(0) })), CommandTree::terminal("quit", Some("exit the REPL"), vec![], Box::new(|repl: &mut Repl, _cmds: &[&str]| { repl.save_before_exit(); ::std::process::exit(0) })), CommandTree::terminal("help", Some("Print this help message"), vec![], Box::new(|repl: &mut Repl, cmds: &[&str]| { Some(repl.print_help_message(cmds)) })), CommandTree::nonterm("debug", Some("Configure debug information"), vec![ 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, _ => vec![], }; let mut buf = String::new(); for pass in pass_names.iter().map(|name| Some(name)).intersperse(None) { match pass { Some(pass) => write!(buf, "{}", pass).unwrap(), None => write!(buf, " -> ").unwrap(), } } Some(buf) })), 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(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::terminal("on", None, vec![], Box::new(|repl: &mut Repl, _: &[&str]| { repl.options.show_total_time = true; None })), CommandTree::terminal("off", None, vec![], Box::new(turn_off)), ]) ] ), CommandTree::nonterm("lang", Some("switch between languages, or go directly to a langauge by name"), vec![ CommandTree::nonterm_no_further_tab_completions("next", None), CommandTree::nonterm_no_further_tab_completions("prev", None), CommandTree::nonterm("go", None, vec![]), ] ), 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 }; let cur_state = repl.get_cur_language_state(); match cur_state.request_meta(meta) { LangMetaResponse::Docs { doc_string } => Some(doc_string), _ => Some(format!("Invalid doc response")) } }).unwrap_or(Some(format!(":docs needs an argument"))) })) ]) } fn turn_off(repl: &mut Repl, _cmds: &[&str]) -> Option { repl.options.show_total_time = false; None }