use super::{InterpreterDirectiveOutput, Repl}; use crate::language::{ DebugAsk, DebugResponse, LangMetaRequest, LangMetaResponse, ProgrammingLanguageInterface, }; use crate::repl::help::help; use std::fmt::Write as FmtWrite; #[derive(Debug, Clone)] pub enum DirectiveAction { Null, Help, QuitProgram, ListPasses, ShowImmediate, Show, Hide, TotalTimeOff, TotalTimeOn, StageTimeOff, StageTimeOn, Doc, } impl DirectiveAction { pub fn perform( &self, repl: &mut Repl, arguments: &[&str], ) -> InterpreterDirectiveOutput { use DirectiveAction::*; match self { Null => None, Help => help(repl, arguments), QuitProgram => { repl.save_before_exit(); ::std::process::exit(0) } ListPasses => { let pass_names = match repl .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) } ShowImmediate => { let stage_name = match arguments.get(0) { 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(), token: None, }); let meta_response = repl.language_state.request_meta(meta); let response = match meta_response { LangMetaResponse::ImmediateDebug(DebugResponse { ask, value }) => match ask { DebugAsk::ByStage { stage_name: ref this_stage_name, .. } if *this_stage_name == stage_name => value, _ => return Some(format!("Wrong debug stage")), }, _ => return Some(format!("Invalid language meta response")), }; Some(response) } Show => { let this_stage_name = match arguments.get(0) { Some(s) => s.to_string(), None => return Some(format!("Must specify a stage to show")), }; let token = arguments.get(1).map(|s| s.to_string()); repl.options.debug_asks.retain(|ask| match ask { DebugAsk::ByStage { stage_name, .. } if *stage_name == this_stage_name => false, _ => true, }); let ask = DebugAsk::ByStage { stage_name: this_stage_name, token, }; repl.options.debug_asks.insert(ask); None } Hide => { let stage_name_to_remove = match arguments.get(0) { Some(s) => s.to_string(), None => return Some(format!("Must specify a stage to hide")), }; repl.options.debug_asks.retain(|ask| match ask { DebugAsk::ByStage { stage_name, .. } if *stage_name == stage_name_to_remove => { false } _ => true, }); None } TotalTimeOff => { repl.options.show_total_time = false; None } TotalTimeOn => { repl.options.show_total_time = true; None } StageTimeOff => { repl.options.show_stage_times = false; None } StageTimeOn => { repl.options.show_stage_times = true; None } Doc => doc(repl, arguments), } } } fn doc( repl: &mut Repl, arguments: &[&str], ) -> InterpreterDirectiveOutput { arguments .get(0) .map(|cmd| { let source = cmd.to_string(); let meta = LangMetaRequest::Docs { source }; match repl.language_state.request_meta(meta) { LangMetaResponse::Docs { doc_string } => Some(doc_string), _ => Some(format!("Invalid doc response")), } }) .unwrap_or(Some(format!(":docs needs an argument"))) }