Start converting over directives to new format
This commit is contained in:
parent
e12ff6f30b
commit
fd517351de
@ -1,11 +1,11 @@
|
||||
use super::Repl;
|
||||
use super::{Repl, InterpreterDirectiveOutput};
|
||||
|
||||
use colored::*;
|
||||
|
||||
pub type BoxedCommandFunction = Box<(fn(&mut Repl, &[&str]) -> Option<String>)>;
|
||||
|
||||
/// A CommandTree is either a `Terminal` or a `NonTerminal`. When command parsing reaches the first
|
||||
/// Terminal, it will use the `ReplAction` found there to find an appropriate function to execute,
|
||||
/// Terminal, it will use the `DirectiveAction` found there to find an appropriate function to execute,
|
||||
/// and then execute it with any remaining arguments
|
||||
//TODO remove function: BoxedCommandFunction
|
||||
#[derive(Clone)]
|
||||
@ -15,41 +15,49 @@ pub enum CommandTree {
|
||||
children: Vec<CommandTree>,
|
||||
help_msg: Option<String>,
|
||||
function: BoxedCommandFunction,
|
||||
action: ReplAction,
|
||||
action: DirectiveAction,
|
||||
},
|
||||
NonTerminal {
|
||||
name: String,
|
||||
children: Vec<CommandTree>,
|
||||
help_msg: Option<String>,
|
||||
action: ReplAction,
|
||||
action: DirectiveAction,
|
||||
},
|
||||
//TODO get rid of Top
|
||||
Top(Vec<CommandTree>),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum ReplAction {
|
||||
pub enum DirectiveAction {
|
||||
Null,
|
||||
Help,
|
||||
QuitProgram
|
||||
}
|
||||
|
||||
impl ReplAction {
|
||||
fn get_function(&self) -> impl Fn(&mut Repl, &[&str]) -> Option<String> {
|
||||
|_: &mut Repl, _: &[&str]| { None }
|
||||
impl DirectiveAction {
|
||||
fn perform(&self, repl: &mut Repl, arguments: &[&str]) -> InterpreterDirectiveOutput {
|
||||
use DirectiveAction::*;
|
||||
match self {
|
||||
Null => None,
|
||||
Help => Some(repl.print_help_message(arguments)),
|
||||
QuitProgram => {
|
||||
repl.save_before_exit();
|
||||
::std::process::exit(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CommandTree {
|
||||
pub fn nonterm_no_further_tab_completions(s: &str, help: Option<&str>) -> CommandTree {
|
||||
CommandTree::NonTerminal {name: s.to_string(), help_msg: help.map(|x| x.to_string()), children: vec![], action: ReplAction::Null }
|
||||
CommandTree::NonTerminal {name: s.to_string(), help_msg: help.map(|x| x.to_string()), children: vec![], action: DirectiveAction::Null }
|
||||
}
|
||||
|
||||
pub fn terminal(s: &str, help: Option<&str>, children: Vec<CommandTree>, function: BoxedCommandFunction) -> CommandTree {
|
||||
CommandTree::Terminal {name: s.to_string(), help_msg: help.map(|x| x.to_string()), function, children, action: ReplAction::Null }
|
||||
CommandTree::Terminal {name: s.to_string(), help_msg: help.map(|x| x.to_string()), function, children, action: DirectiveAction::Null }
|
||||
}
|
||||
|
||||
pub fn terminal_act(s: &str, help: Option<&str>, children: Vec<CommandTree>, action: ReplAction) -> CommandTree {
|
||||
pub fn terminal_act(s: &str, help: Option<&str>, children: Vec<CommandTree>, action: DirectiveAction) -> CommandTree {
|
||||
CommandTree::Terminal {name: s.to_string(), help_msg: help.map(|x| x.to_string()), function: Box::new(|_,_| { None }), children, action}
|
||||
}
|
||||
|
||||
@ -58,7 +66,7 @@ impl CommandTree {
|
||||
name: s.to_string(),
|
||||
help_msg: help.map(|x| x.to_string()),
|
||||
children,
|
||||
action: ReplAction::Null
|
||||
action: DirectiveAction::Null
|
||||
}
|
||||
}
|
||||
|
||||
@ -85,11 +93,11 @@ impl CommandTree {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn execute(&self, repl: &mut Repl, arguments: &Vec<&str>) -> Option<String> {
|
||||
pub fn perform(&self, repl: &mut Repl, arguments: &Vec<&str>) -> InterpreterDirectiveOutput {
|
||||
let mut dir_pointer: &CommandTree = self;
|
||||
let mut idx = 0;
|
||||
|
||||
let res: Result<(ReplAction, usize), String> = loop {
|
||||
let res: Result<(DirectiveAction, usize), String> = loop {
|
||||
match dir_pointer {
|
||||
CommandTree::Top(subcommands) | CommandTree::NonTerminal { children: subcommands, .. } => {
|
||||
let next_command = match arguments.get(idx) {
|
||||
@ -111,10 +119,7 @@ impl CommandTree {
|
||||
};
|
||||
|
||||
match res {
|
||||
Ok((action, idx)) => {
|
||||
let f = action.get_function();
|
||||
f(repl, &arguments[idx..])
|
||||
},
|
||||
Ok((action, idx)) => action.perform(repl, &arguments[idx..]),
|
||||
Err(err) => Some(err.red().to_string())
|
||||
}
|
||||
}
|
||||
|
@ -2,26 +2,19 @@ use std::fmt::Write as FmtWrite;
|
||||
use itertools::Itertools;
|
||||
|
||||
use crate::repl::Repl;
|
||||
use crate::repl::command_tree::CommandTree;
|
||||
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("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::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![
|
||||
|
@ -17,6 +17,8 @@ use directives::directives_from_pass_names;
|
||||
const HISTORY_SAVE_FILE: &'static str = ".schala_history";
|
||||
const OPTIONS_SAVE_FILE: &'static str = ".schala_repl";
|
||||
|
||||
type InterpreterDirectiveOutput = Option<String>;
|
||||
|
||||
pub struct Repl {
|
||||
interpreter_directive_sigil: char,
|
||||
line_reader: ::linefeed::interface::Interface<::linefeed::terminal::DefaultTerminal>,
|
||||
@ -101,33 +103,7 @@ impl Repl {
|
||||
self.options.save_to_file(OPTIONS_SAVE_FILE);
|
||||
}
|
||||
|
||||
fn get_function_from_directives<'a>(directives: &'a CommandTree, commands: &Vec<&str>) -> Result<(&'a BoxedCommandFunction, usize), String> {
|
||||
let mut dir_pointer: &CommandTree = &directives;
|
||||
let mut idx = 0;
|
||||
|
||||
loop {
|
||||
match dir_pointer {
|
||||
CommandTree::Top(subcommands) | CommandTree::NonTerminal { children: subcommands, .. } => {
|
||||
let next_command = match commands.get(idx) {
|
||||
Some(cmd) => cmd,
|
||||
None => break Err(format!("Command requires arguments"))
|
||||
};
|
||||
idx += 1;
|
||||
match subcommands.iter().find(|sc| sc.get_cmd() == *next_command) {
|
||||
Some(command_tree) => {
|
||||
dir_pointer = command_tree;
|
||||
},
|
||||
None => break Err(format!("Command {} not found", next_command))
|
||||
};
|
||||
},
|
||||
CommandTree::Terminal { function, .. } => {
|
||||
break Ok((function, idx));
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_interpreter_directive(&mut self, input: &str) -> Option<String> {
|
||||
fn handle_interpreter_directive(&mut self, input: &str) -> InterpreterDirectiveOutput {
|
||||
let mut iter = input.chars();
|
||||
iter.next();
|
||||
let arguments: Vec<&str> = iter
|
||||
@ -140,15 +116,7 @@ impl Repl {
|
||||
}
|
||||
|
||||
let directives = self.get_directives();
|
||||
directives.execute(self, &arguments)
|
||||
|
||||
/*
|
||||
let result: Result<(&BoxedCommandFunction, _), String> = Repl::get_function_from_directives(&directives, &commands);
|
||||
match result {
|
||||
Ok((f, idx)) => f(self, &commands[idx..]),
|
||||
Err(err) => Some(err.red().to_string())
|
||||
}
|
||||
*/
|
||||
directives.perform(self, &arguments)
|
||||
}
|
||||
|
||||
fn print_help_message(&mut self, commands_passed_to_help: &[&str] ) -> String {
|
||||
|
Loading…
Reference in New Issue
Block a user