use super::{Repl, InterpreterDirectiveOutput}; use crate::repl::help::help; use crate::language::{LangMetaRequest, LangMetaResponse, DebugAsk, DebugResponse}; use itertools::Itertools; 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 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) }, ShowImmediate => { let cur_state = repl.get_cur_language_state(); 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 = cur_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 => total_time_off(repl, arguments), TotalTimeOn => total_time_on(repl, arguments), StageTimeOff => stage_time_off(repl, arguments), StageTimeOn => stage_time_on(repl, arguments), Doc => doc(repl, arguments), } } } fn total_time_on(repl: &mut Repl, _: &[&str]) -> InterpreterDirectiveOutput { repl.options.show_total_time = true; None } fn total_time_off(repl: &mut Repl, _: &[&str]) -> InterpreterDirectiveOutput { repl.options.show_total_time = false; None } fn stage_time_on(repl: &mut Repl, _: &[&str]) -> InterpreterDirectiveOutput { repl.options.show_stage_times = true; None } fn stage_time_off(repl: &mut Repl, _: &[&str]) -> InterpreterDirectiveOutput { repl.options.show_stage_times = false; None } fn doc(repl: &mut Repl, arguments: &[&str]) -> InterpreterDirectiveOutput { arguments.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"))) }