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::*;
|
use colored::*;
|
||||||
|
|
||||||
pub type BoxedCommandFunction = Box<(fn(&mut Repl, &[&str]) -> Option<String>)>;
|
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
|
/// 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
|
/// and then execute it with any remaining arguments
|
||||||
//TODO remove function: BoxedCommandFunction
|
//TODO remove function: BoxedCommandFunction
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@ -15,41 +15,49 @@ pub enum CommandTree {
|
|||||||
children: Vec<CommandTree>,
|
children: Vec<CommandTree>,
|
||||||
help_msg: Option<String>,
|
help_msg: Option<String>,
|
||||||
function: BoxedCommandFunction,
|
function: BoxedCommandFunction,
|
||||||
action: ReplAction,
|
action: DirectiveAction,
|
||||||
},
|
},
|
||||||
NonTerminal {
|
NonTerminal {
|
||||||
name: String,
|
name: String,
|
||||||
children: Vec<CommandTree>,
|
children: Vec<CommandTree>,
|
||||||
help_msg: Option<String>,
|
help_msg: Option<String>,
|
||||||
action: ReplAction,
|
action: DirectiveAction,
|
||||||
},
|
},
|
||||||
//TODO get rid of Top
|
//TODO get rid of Top
|
||||||
Top(Vec<CommandTree>),
|
Top(Vec<CommandTree>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum ReplAction {
|
pub enum DirectiveAction {
|
||||||
Null,
|
Null,
|
||||||
Help,
|
Help,
|
||||||
QuitProgram
|
QuitProgram
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ReplAction {
|
impl DirectiveAction {
|
||||||
fn get_function(&self) -> impl Fn(&mut Repl, &[&str]) -> Option<String> {
|
fn perform(&self, repl: &mut Repl, arguments: &[&str]) -> InterpreterDirectiveOutput {
|
||||||
|_: &mut Repl, _: &[&str]| { None }
|
use DirectiveAction::*;
|
||||||
|
match self {
|
||||||
|
Null => None,
|
||||||
|
Help => Some(repl.print_help_message(arguments)),
|
||||||
|
QuitProgram => {
|
||||||
|
repl.save_before_exit();
|
||||||
|
::std::process::exit(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CommandTree {
|
impl CommandTree {
|
||||||
pub fn nonterm_no_further_tab_completions(s: &str, help: Option<&str>) -> 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 {
|
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}
|
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(),
|
name: s.to_string(),
|
||||||
help_msg: help.map(|x| x.to_string()),
|
help_msg: help.map(|x| x.to_string()),
|
||||||
children,
|
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 dir_pointer: &CommandTree = self;
|
||||||
let mut idx = 0;
|
let mut idx = 0;
|
||||||
|
|
||||||
let res: Result<(ReplAction, usize), String> = loop {
|
let res: Result<(DirectiveAction, usize), String> = loop {
|
||||||
match dir_pointer {
|
match dir_pointer {
|
||||||
CommandTree::Top(subcommands) | CommandTree::NonTerminal { children: subcommands, .. } => {
|
CommandTree::Top(subcommands) | CommandTree::NonTerminal { children: subcommands, .. } => {
|
||||||
let next_command = match arguments.get(idx) {
|
let next_command = match arguments.get(idx) {
|
||||||
@ -111,10 +119,7 @@ impl CommandTree {
|
|||||||
};
|
};
|
||||||
|
|
||||||
match res {
|
match res {
|
||||||
Ok((action, idx)) => {
|
Ok((action, idx)) => action.perform(repl, &arguments[idx..]),
|
||||||
let f = action.get_function();
|
|
||||||
f(repl, &arguments[idx..])
|
|
||||||
},
|
|
||||||
Err(err) => Some(err.red().to_string())
|
Err(err) => Some(err.red().to_string())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,26 +2,19 @@ use std::fmt::Write as FmtWrite;
|
|||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
|
||||||
use crate::repl::Repl;
|
use crate::repl::Repl;
|
||||||
use crate::repl::command_tree::CommandTree;
|
use crate::repl::command_tree::{CommandTree, DirectiveAction};
|
||||||
use crate::language::{LangMetaRequest, LangMetaResponse, DebugAsk, DebugResponse};
|
use crate::language::{LangMetaRequest, LangMetaResponse, DebugAsk, DebugResponse};
|
||||||
|
|
||||||
|
|
||||||
pub fn directives_from_pass_names(pass_names: &Vec<String>) -> CommandTree {
|
pub fn directives_from_pass_names(pass_names: &Vec<String>) -> CommandTree {
|
||||||
let passes_directives: Vec<CommandTree> = pass_names.iter()
|
let passes_directives: Vec<CommandTree> = pass_names.iter()
|
||||||
.map(|pass_name| { CommandTree::nonterm_no_further_tab_completions(pass_name, None) })
|
.map(|pass_name| { CommandTree::nonterm_no_further_tab_completions(pass_name, None) })
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
CommandTree::Top(vec![
|
CommandTree::Top(vec![
|
||||||
CommandTree::terminal("exit", Some("exit the REPL"), vec![], Box::new(|repl: &mut Repl, _cmds: &[&str]| {
|
CommandTree::terminal_act("exit", Some("exit the REPL"), vec![], DirectiveAction::QuitProgram),
|
||||||
repl.save_before_exit();
|
CommandTree::terminal_act("quit", Some("exit the REPL"), vec![], DirectiveAction::QuitProgram),
|
||||||
::std::process::exit(0)
|
CommandTree::terminal_act("help", Some("Print this help message"), vec![], DirectiveAction::Help),
|
||||||
})),
|
|
||||||
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",
|
CommandTree::nonterm("debug",
|
||||||
Some("Configure debug information"),
|
Some("Configure debug information"),
|
||||||
vec![
|
vec![
|
||||||
|
@ -17,6 +17,8 @@ use directives::directives_from_pass_names;
|
|||||||
const HISTORY_SAVE_FILE: &'static str = ".schala_history";
|
const HISTORY_SAVE_FILE: &'static str = ".schala_history";
|
||||||
const OPTIONS_SAVE_FILE: &'static str = ".schala_repl";
|
const OPTIONS_SAVE_FILE: &'static str = ".schala_repl";
|
||||||
|
|
||||||
|
type InterpreterDirectiveOutput = Option<String>;
|
||||||
|
|
||||||
pub struct Repl {
|
pub struct Repl {
|
||||||
interpreter_directive_sigil: char,
|
interpreter_directive_sigil: char,
|
||||||
line_reader: ::linefeed::interface::Interface<::linefeed::terminal::DefaultTerminal>,
|
line_reader: ::linefeed::interface::Interface<::linefeed::terminal::DefaultTerminal>,
|
||||||
@ -101,33 +103,7 @@ impl Repl {
|
|||||||
self.options.save_to_file(OPTIONS_SAVE_FILE);
|
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> {
|
fn handle_interpreter_directive(&mut self, input: &str) -> InterpreterDirectiveOutput {
|
||||||
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> {
|
|
||||||
let mut iter = input.chars();
|
let mut iter = input.chars();
|
||||||
iter.next();
|
iter.next();
|
||||||
let arguments: Vec<&str> = iter
|
let arguments: Vec<&str> = iter
|
||||||
@ -140,15 +116,7 @@ impl Repl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let directives = self.get_directives();
|
let directives = self.get_directives();
|
||||||
directives.execute(self, &arguments)
|
directives.perform(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())
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_help_message(&mut self, commands_passed_to_help: &[&str] ) -> String {
|
fn print_help_message(&mut self, commands_passed_to_help: &[&str] ) -> String {
|
||||||
|
Loading…
Reference in New Issue
Block a user