schala/schala-repl/src/repl/directives.rs

120 lines
5.0 KiB
Rust

use std::fmt::Write as FmtWrite;
use itertools::Itertools;
use crate::repl::Repl;
use crate::repl::command_tree::{CommandTree, DirectiveAction};
use crate::language::{LangMetaRequest, LangMetaResponse, DebugAsk, DebugResponse};
pub fn directives_from_pass_names(pass_names: &Vec<String>) -> CommandTree {
let passes_directives: Vec<CommandTree> = pass_names.iter()
.map(|pass_name| { CommandTree::nonterm_no_further_tab_completions(pass_name, None) })
.collect();
CommandTree::Top(vec![
CommandTree::terminal_act("exit", Some("exit the REPL"), vec![], DirectiveAction::QuitProgram),
CommandTree::terminal_act("quit", Some("exit the REPL"), vec![], DirectiveAction::QuitProgram),
CommandTree::terminal_act("help", Some("Print this help message"), vec![], DirectiveAction::Help),
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("stage-times", Some("Computation time per-stage"), vec![
CommandTree::terminal("on", None, vec![], Box::new(|repl: &mut Repl, _: &[&str]| {
repl.options.show_stage_times = true;
None
})),
CommandTree::terminal("off", None, vec![], Box::new(|repl: &mut Repl, _: &[&str]| {
repl.options.show_stage_times = false;
None
})),
])
]
),
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<String> {
repl.options.show_total_time = false;
None
}