Compare commits

..

No commits in common. "ec6f4b510e562fcf1419bdf392111322d2d633dc" and "77bf42be6cf1329ee3089bc1af2bad6f8cda671f" have entirely different histories.

14 changed files with 655 additions and 798 deletions

View File

@ -2,8 +2,6 @@
name = "schala"
version = "0.1.0"
authors = ["greg <greg.shuflin@protonmail.com>"]
edition = "2018"
resolver = "2"
[dependencies]

View File

@ -3,7 +3,6 @@ name = "schala-lang-codegen"
version = "0.1.0"
authors = ["greg <greg.shuflin@protonmail.com>"]
edition = "2018"
resolver = "2"
[lib]
proc-macro = true

View File

@ -3,7 +3,6 @@ name = "schala-lang"
version = "0.1.0"
authors = ["greg <greg.shuflin@protonmail.com>"]
edition = "2018"
resolver = "2"
[dependencies]
itertools = "0.10"

View File

@ -3,7 +3,6 @@ name = "schala-repl"
version = "0.1.0"
authors = ["greg <greg.shuflin@protonmail.com>"]
edition = "2018"
resolver = "2"
[dependencies]
llvm-sys = "70.0.2"

View File

@ -1,5 +1,5 @@
use std::collections::HashSet;
use std::time;
use std::collections::HashSet;
pub trait ProgrammingLanguageInterface {
fn get_language_name(&self) -> String;
@ -14,10 +14,7 @@ pub trait ProgrammingLanguageInterface {
}
fn request_meta(&mut self, _request: LangMetaRequest) -> LangMetaResponse {
LangMetaResponse::Custom {
kind: format!("not-implemented"),
value: format!(""),
}
LangMetaResponse::Custom { kind: format!("not-implemented"), value: format!("") }
}
}
@ -35,42 +32,49 @@ pub struct ComputationResponse {
#[derive(Default, Debug)]
pub struct GlobalOutputStats {
pub total_duration: time::Duration,
pub stage_durations: Vec<(String, time::Duration)>,
pub stage_durations: Vec<(String, time::Duration)>
}
#[derive(Debug, Clone, Hash, Eq, PartialEq, Deserialize, Serialize)]
pub enum DebugAsk {
Timing,
ByStage {
stage_name: String,
token: Option<String>,
},
ByStage { stage_name: String, token: Option<String> },
}
impl DebugAsk {
pub fn is_for_stage(&self, name: &str) -> bool {
match self {
DebugAsk::ByStage { stage_name, .. } if stage_name == name => true,
_ => false,
_ => false
}
}
}
pub struct DebugResponse {
pub ask: DebugAsk,
pub value: String,
pub value: String
}
pub enum LangMetaRequest {
StageNames,
Docs { source: String },
Custom { kind: String, value: String },
Docs {
source: String,
},
Custom {
kind: String,
value: String
},
ImmediateDebug(DebugAsk),
}
pub enum LangMetaResponse {
StageNames(Vec<String>),
Docs { doc_string: String },
Custom { kind: String, value: String },
Docs {
doc_string: String,
},
Custom {
kind: String,
value: String
},
ImmediateDebug(DebugResponse),
}

View File

@ -1,37 +1,35 @@
#![feature(box_patterns, box_syntax, proc_macro_hygiene, decl_macro)]
#![feature(plugin)]
extern crate colored;
extern crate getopts;
extern crate itertools;
extern crate linefeed;
extern crate itertools;
extern crate colored;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate includedir;
extern crate phf;
extern crate serde_json;
use std::collections::HashSet;
use std::path::Path;
use std::fs::File;
use std::io::Read;
use std::path::Path;
use std::process::exit;
mod language;
mod repl;
mod language;
pub use language::{
ComputationRequest, ComputationResponse, DebugAsk, DebugResponse, GlobalOutputStats,
LangMetaRequest, LangMetaResponse, ProgrammingLanguageInterface,
};
pub use language::{ProgrammingLanguageInterface,
ComputationRequest, ComputationResponse,
LangMetaRequest, LangMetaResponse,
DebugResponse, DebugAsk, GlobalOutputStats};
include!(concat!(env!("OUT_DIR"), "/static.rs"));
const VERSION_STRING: &'static str = "0.1.0";
pub fn start_repl(langs: Vec<Box<dyn ProgrammingLanguageInterface>>) {
let options = command_line_options()
.parse(std::env::args())
.unwrap_or_else(|e| {
let options = command_line_options().parse(std::env::args()).unwrap_or_else(|e| {
println!("{:?}", e);
exit(1);
});
@ -54,22 +52,15 @@ pub fn start_repl(langs: Vec<Box<dyn ProgrammingLanguageInterface>>) {
fn run_noninteractive(filename: &str, languages: Vec<Box<dyn ProgrammingLanguageInterface>>) {
let path = Path::new(filename);
let ext = path
.extension()
.and_then(|e| e.to_str())
.unwrap_or_else(|| {
let ext = path.extension().and_then(|e| e.to_str()).unwrap_or_else(|| {
println!("Source file lacks extension");
exit(1);
});
let mut language = Box::new(
languages
.into_iter()
.find(|lang| lang.get_source_file_suffix() == ext)
let mut language = Box::new(languages.into_iter().find(|lang| lang.get_source_file_suffix() == ext)
.unwrap_or_else(|| {
println!("Extension .{} not recognized", ext);
exit(1);
}),
);
}));
let mut source_file = File::open(path).unwrap();
let mut buffer = String::new();
@ -83,13 +74,18 @@ fn run_noninteractive(filename: &str, languages: Vec<Box<dyn ProgrammingLanguage
let response = language.run_computation(request);
match response.main_output {
Ok(s) => println!("{}", s),
Err(s) => println!("{}", s),
Err(s) => println!("{}", s)
};
}
fn command_line_options() -> getopts::Options {
let mut options = getopts::Options::new();
options.optflag("h", "help", "Show help text");
options.optflag("w", "webapp", "Start up web interpreter");
options.optflag("h",
"help",
"Show help text");
options.optflag("w",
"webapp",
"Start up web interpreter");
options
}

View File

@ -1,4 +1,4 @@
use super::{InterpreterDirectiveOutput, Repl};
use super::{Repl, InterpreterDirectiveOutput};
use crate::repl::directive_actions::DirectiveAction;
use colored::*;
@ -24,26 +24,11 @@ pub enum CommandTree {
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: DirectiveAction::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>,
action: DirectiveAction,
) -> CommandTree {
CommandTree::Terminal {
name: s.to_string(),
help_msg: help.map(|x| x.to_string()),
children,
action,
}
pub fn terminal(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()), children, action}
}
pub fn nonterm(s: &str, help: Option<&str>, children: Vec<CommandTree>) -> CommandTree {
@ -51,7 +36,7 @@ impl CommandTree {
name: s.to_string(),
help_msg: help.map(|x| x.to_string()),
children,
action: DirectiveAction::Null,
action: DirectiveAction::Null
}
}
@ -64,21 +49,17 @@ impl CommandTree {
}
pub fn get_help(&self) -> &str {
match self {
CommandTree::Terminal { help_msg, .. } => help_msg
.as_ref()
.map(|s| s.as_str())
.unwrap_or("<no help text provided>"),
CommandTree::NonTerminal { help_msg, .. } => help_msg
.as_ref()
.map(|s| s.as_str())
.unwrap_or("<no help text provided>"),
CommandTree::Top(_) => "",
CommandTree::Terminal { help_msg, ..} => help_msg.as_ref().map(|s| s.as_str()).unwrap_or("<no help text provided>"),
CommandTree::NonTerminal { help_msg, .. } => help_msg.as_ref().map(|s| s.as_str()).unwrap_or("<no help text provided>"),
CommandTree::Top(_) => ""
}
}
pub fn get_children(&self) -> &Vec<CommandTree> {
use CommandTree::*;
match self {
Terminal { children, .. } | NonTerminal { children, .. } | Top(children) => children,
Terminal { children, .. } |
NonTerminal { children, .. } |
Top(children) => children
}
}
pub fn get_subcommands(&self) -> Vec<&str> {
@ -91,32 +72,28 @@ impl CommandTree {
let res: Result<(DirectiveAction, usize), String> = loop {
match dir_pointer {
CommandTree::Top(subcommands)
| CommandTree::NonTerminal {
children: subcommands,
..
} => {
CommandTree::Top(subcommands) | CommandTree::NonTerminal { children: subcommands, .. } => {
let next_command = match arguments.get(idx) {
Some(cmd) => cmd,
None => break Err(format!("Command requires arguments")),
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)),
},
None => break Err(format!("Command {} not found", next_command))
};
}
},
CommandTree::Terminal { action, .. } => {
break Ok((action.clone(), idx));
}
},
}
};
match res {
Ok((action, idx)) => action.perform(repl, &arguments[idx..]),
Err(err) => Some(err.red().to_string()),
Err(err) => Some(err.red().to_string())
}
}
}

View File

@ -1,6 +1,6 @@
use super::{InterpreterDirectiveOutput, Repl};
use crate::language::{DebugAsk, DebugResponse, LangMetaRequest, LangMetaResponse};
use super::{Repl, InterpreterDirectiveOutput};
use crate::repl::help::help;
use crate::language::{LangMetaRequest, LangMetaResponse, DebugAsk, DebugResponse};
use std::fmt::Write as FmtWrite;
#[derive(Debug, Clone)]
@ -28,7 +28,7 @@ impl DirectiveAction {
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) {
@ -44,31 +44,25 @@ impl DirectiveAction {
}
}
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 = 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")),
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(),
@ -77,29 +71,24 @@ impl DirectiveAction {
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,
_ => true
});
let ask = DebugAsk::ByStage {
stage_name: this_stage_name,
token,
};
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,
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),
@ -130,16 +119,14 @@ fn stage_time_off(repl: &mut Repl, _: &[&str]) -> InterpreterDirectiveOutput {
}
fn doc(repl: &mut Repl, arguments: &[&str]) -> InterpreterDirectiveOutput {
arguments
.get(0)
.map(|cmd| {
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")),
_ => Some(format!("Invalid doc response"))
}
})
.unwrap_or(Some(format!(":docs needs an argument")))
}).unwrap_or(Some(format!(":docs needs an argument")))
}

View File

@ -2,19 +2,14 @@ use crate::repl::command_tree::CommandTree;
use crate::repl::directive_actions::DirectiveAction;
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| {
if pass_name == "parsing" {
CommandTree::nonterm(
pass_name,
None,
vec![
CommandTree::nonterm(pass_name, None, vec![
CommandTree::nonterm_no_further_tab_completions("compact", None),
CommandTree::nonterm_no_further_tab_completions("expanded", None),
CommandTree::nonterm_no_further_tab_completions("trace", None),
],
)
])
} else {
CommandTree::nonterm_no_further_tab_completions(pass_name, None)
}
@ -29,76 +24,32 @@ fn get_list(passes_directives: &Vec<CommandTree>, include_help: bool) -> Vec<Com
vec![
CommandTree::terminal("exit", Some("exit the REPL"), vec![], QuitProgram),
CommandTree::terminal("quit", Some("exit the REPL"), vec![], QuitProgram),
CommandTree::terminal(
"help",
Some("Print this help message"),
if include_help {
get_list(passes_directives, false)
} else {
vec![]
},
Help,
),
CommandTree::nonterm(
"debug",
CommandTree::terminal("help", Some("Print this help message"), if include_help { get_list(passes_directives, false) } else { vec![] }, Help),
CommandTree::nonterm("debug",
Some("Configure debug information"),
vec![
CommandTree::terminal(
"list-passes",
Some("List all registered compiler passes"),
vec![],
ListPasses,
),
CommandTree::terminal(
"show-immediate",
None,
passes_directives.clone(),
ShowImmediate,
),
CommandTree::terminal(
"show",
Some("Show debug output for a specific pass"),
passes_directives.clone(),
Show,
),
CommandTree::terminal(
"hide",
Some("Hide debug output for a specific pass"),
passes_directives.clone(),
Hide,
),
CommandTree::nonterm(
"total-time",
None,
vec![
CommandTree::terminal("list-passes", Some("List all registered compiler passes"), vec![], ListPasses),
CommandTree::terminal("show-immediate", None, passes_directives.clone(), ShowImmediate),
CommandTree::terminal("show", Some("Show debug output for a specific pass"), passes_directives.clone(), Show),
CommandTree::terminal("hide", Some("Hide debug output for a specific pass"), passes_directives.clone(), Hide),
CommandTree::nonterm("total-time", None, vec![
CommandTree::terminal("on", None, vec![], TotalTimeOn),
CommandTree::terminal("off", None, vec![], TotalTimeOff),
],
),
CommandTree::nonterm(
"stage-times",
Some("Computation time per-stage"),
vec![
]),
CommandTree::nonterm("stage-times", Some("Computation time per-stage"), vec![
CommandTree::terminal("on", None, vec![], StageTimeOn),
CommandTree::terminal("off", None, vec![], StageTimeOff),
],
])
]
),
],
),
CommandTree::nonterm(
"lang",
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![],
Doc,
]
),
CommandTree::terminal("doc", Some("Get language-specific help for an item"), vec![], Doc),
]
}

View File

@ -1,8 +1,8 @@
use std::fmt::Write as FmtWrite;
use super::command_tree::CommandTree;
use super::{InterpreterDirectiveOutput, Repl};
use colored::*;
use super::command_tree::CommandTree;
use super::{Repl, InterpreterDirectiveOutput};
pub fn help(repl: &mut Repl, arguments: &[&str]) -> InterpreterDirectiveOutput {
match arguments {
@ -17,8 +17,7 @@ pub fn help(repl: &mut Repl, arguments: &[&str]) -> InterpreterDirectiveOutput {
let children = dir.get_children();
writeln!(buf, "`{}` - {}", cmd, dir.get_help()).unwrap();
for sub in children.iter() {
writeln!(buf, "\t`{} {}` - {}", cmd, sub.get_cmd(), sub.get_help())
.unwrap();
writeln!(buf, "\t`{} {}` - {}", cmd, sub.get_cmd(), sub.get_help()).unwrap();
}
buf
}
@ -27,16 +26,11 @@ pub fn help(repl: &mut Repl, arguments: &[&str]) -> InterpreterDirectiveOutput {
}
}
fn get_directive_from_commands<'a>(
commands: &[&str],
dirs: &'a CommandTree,
) -> Option<&'a CommandTree> {
fn get_directive_from_commands<'a>(commands: &[&str], dirs: &'a CommandTree) -> Option<&'a CommandTree> {
let mut directive_list = dirs.get_children();
let mut matched_directive = None;
for cmd in commands {
let found = directive_list
.iter()
.find(|directive| directive.get_cmd() == *cmd);
let found = directive_list.iter().find(|directive| directive.get_cmd() == *cmd);
if let Some(dir) = found {
directive_list = dir.get_children();
}
@ -50,34 +44,16 @@ fn global_help(repl: &mut Repl) -> InterpreterDirectiveOutput {
let mut buf = String::new();
let sigil = repl.interpreter_directive_sigil;
writeln!(
buf,
"{} version {}",
"Schala REPL".bright_red().bold(),
crate::VERSION_STRING
)
.unwrap();
writeln!(buf, "{} version {}", "Schala REPL".bright_red().bold(), crate::VERSION_STRING).unwrap();
writeln!(buf, "-----------------------").unwrap();
for directive in repl.get_directives().get_children() {
writeln!(
buf,
"{}{} - {}",
sigil,
directive.get_cmd(),
directive.get_help()
)
.unwrap();
writeln!(buf, "{}{} - {}", sigil, directive.get_cmd(), directive.get_help()).unwrap();
}
let ref lang = repl.get_cur_language_state();
writeln!(buf, "").unwrap();
writeln!(
buf,
"Language-specific help for {}",
lang.get_language_name()
)
.unwrap();
writeln!(buf, "Language-specific help for {}", lang.get_language_name()).unwrap();
writeln!(buf, "-----------------------").unwrap();
Some(buf)
}

View File

@ -1,9 +1,8 @@
use std::collections::HashSet;
use std::sync::Arc;
use std::collections::HashSet;
use crate::language::{
ComputationRequest, LangMetaRequest, LangMetaResponse, ProgrammingLanguageInterface,
};
use crate::language::{ProgrammingLanguageInterface,
ComputationRequest, LangMetaResponse, LangMetaRequest};
mod command_tree;
use self::command_tree::CommandTree;
@ -31,7 +30,7 @@ pub struct Repl {
#[derive(Clone)]
enum PromptStyle {
Normal,
Multiline,
Multiline
}
impl Repl {
@ -50,10 +49,7 @@ impl Repl {
pub fn run_repl(&mut self) {
println!("Schala MetaInterpreter version {}", crate::VERSION_STRING);
println!(
"Type {}help for help with the REPL",
self.interpreter_directive_sigil
);
println!("Type {}help for help with the REPL", self.interpreter_directive_sigil);
self.load_options();
self.handle_repl_loop();
self.save_before_exit();
@ -61,14 +57,12 @@ impl Repl {
}
fn load_options(&mut self) {
self.line_reader
.load_history(HISTORY_SAVE_FILE)
.unwrap_or(());
self.line_reader.load_history(HISTORY_SAVE_FILE).unwrap_or(());
match ReplOptions::load_from_file(OPTIONS_SAVE_FILE) {
Ok(options) => {
self.options = options;
}
Err(()) => (),
},
Err(()) => ()
};
}
@ -83,11 +77,11 @@ impl Repl {
Err(e) => {
println!("readline IO Error: {}", e);
break 'main;
}
},
Ok(Eof) | Ok(Signal(_)) => break 'main,
Ok(Input(ref input)) => input,
}
};
}
}
self.update_line_reader();
let line = self.line_reader.read_line();
@ -117,10 +111,10 @@ impl Repl {
Some(directive_output) => println!("<> {}", directive_output),
None => (),
}
continue;
continue
}
}
_ => self.handle_input(input),
},
_ => self.handle_input(input)
};
for repl_response in repl_responses.iter() {
@ -130,10 +124,8 @@ impl Repl {
}
fn update_line_reader(&mut self) {
let tab_complete_handler =
TabCompleteHandler::new(self.interpreter_directive_sigil, self.get_directives());
self.line_reader
.set_completer(Arc::new(tab_complete_handler)); //TODO fix this here
let tab_complete_handler = TabCompleteHandler::new(self.interpreter_directive_sigil, self.get_directives());
self.line_reader.set_completer(Arc::new(tab_complete_handler)); //TODO fix this here
self.set_prompt(PromptStyle::Normal);
}
@ -147,16 +139,17 @@ impl Repl {
}
fn save_before_exit(&self) {
self.line_reader
.save_history(HISTORY_SAVE_FILE)
.unwrap_or(());
self.line_reader.save_history(HISTORY_SAVE_FILE).unwrap_or(());
self.options.save_to_file(OPTIONS_SAVE_FILE);
}
fn handle_interpreter_directive(&mut self, input: &str) -> InterpreterDirectiveOutput {
let mut iter = input.chars();
iter.next();
let arguments: Vec<&str> = iter.as_str().split_whitespace().collect();
let arguments: Vec<&str> = iter
.as_str()
.split_whitespace()
.collect();
if arguments.len() < 1 {
return None;
@ -177,10 +170,7 @@ impl Repl {
debug_requests.insert(ask.clone());
}
let request = ComputationRequest {
source: input,
debug_requests,
};
let request = ComputationRequest { source: input, debug_requests };
let ref mut language_state = self.get_cur_language_state();
let response = language_state.run_computation(request);
response::handle_computation_response(response, &self.options)
@ -197,12 +187,13 @@ impl Repl {
}
}
struct TabCompleteHandler {
sigil: char,
top_level_commands: CommandTree,
}
use linefeed::complete::{Completer, Completion};
use linefeed::complete::{Completion, Completer};
use linefeed::terminal::Terminal;
impl TabCompleteHandler {
@ -215,13 +206,7 @@ impl TabCompleteHandler {
}
impl<T: Terminal> Completer<T> for TabCompleteHandler {
fn complete(
&self,
word: &str,
prompter: &::linefeed::prompter::Prompter<T>,
start: usize,
_end: usize,
) -> Option<Vec<Completion>> {
fn complete(&self, word: &str, prompter: &::linefeed::prompter::Prompter<T>, start: usize, _end: usize) -> Option<Vec<Completion>> {
let line = prompter.buffer();
if !line.starts_with(self.sigil) {
@ -237,33 +222,25 @@ impl<T: Terminal> Completer<T> for TabCompleteHandler {
None => {
let top = match command_tree {
Some(CommandTree::Top(_)) => true,
_ => false,
_ => false
};
let word = if top { word.get(1..).unwrap() } else { word };
for cmd in command_tree
.map(|x| x.get_subcommands())
.unwrap_or(vec![])
.into_iter()
{
for cmd in command_tree.map(|x| x.get_subcommands()).unwrap_or(vec![]).into_iter() {
if cmd.starts_with(word) {
completions.push(Completion {
completion: format!("{}{}", if top { ":" } else { "" }, cmd),
display: Some(cmd.to_string()),
suffix: ::linefeed::complete::Suffix::Some(' '),
suffix: ::linefeed::complete::Suffix::Some(' ')
})
}
}
break;
}
},
Some(s) => {
let new_ptr: Option<&CommandTree> = command_tree.and_then(|cm| match cm {
CommandTree::Top(children) => children.iter().find(|c| c.get_cmd() == s),
CommandTree::NonTerminal { children, .. } => {
children.iter().find(|c| c.get_cmd() == s)
}
CommandTree::Terminal { children, .. } => {
children.iter().find(|c| c.get_cmd() == s)
}
CommandTree::NonTerminal { children, .. } => children.iter().find(|c| c.get_cmd() == s),
CommandTree::Terminal { children, .. } => children.iter().find(|c| c.get_cmd() == s),
});
command_tree = new_ptr;
}

View File

@ -1,8 +1,8 @@
use crate::language::DebugAsk;
use std::io::{Read, Write};
use std::collections::HashSet;
use std::fs::File;
use std::io::{Read, Write};
#[derive(Serialize, Deserialize)]
pub struct ReplOptions {
@ -21,7 +21,8 @@ impl ReplOptions {
}
pub fn save_to_file(&self, filename: &str) {
let res = File::create(filename).and_then(|mut file| {
let res = File::create(filename)
.and_then(|mut file| {
let buf = crate::serde_json::to_string(self).unwrap();
file.write_all(buf.as_bytes())
});

View File

@ -3,12 +3,12 @@ use std::fmt;
use std::fmt::Write;
use super::ReplOptions;
use crate::language::{ComputationResponse, DebugAsk};
use crate::language::{ DebugAsk, ComputationResponse};
pub struct ReplResponse {
label: Option<String>,
text: String,
color: Option<Color>,
color: Option<Color>
}
impl fmt::Display for ReplResponse {
@ -18,21 +18,15 @@ impl fmt::Display for ReplResponse {
write!(buf, "({})", label).unwrap();
}
write!(buf, "=> {}", self.text).unwrap();
write!(
f,
"{}",
match self.color {
write!(f, "{}", match self.color {
Some(c) => buf.color(c),
None => buf.normal(),
}
)
None => buf.normal()
})
}
}
pub fn handle_computation_response(
response: ComputationResponse,
options: &ReplOptions,
) -> Vec<ReplResponse> {
pub fn handle_computation_response(response: ComputationResponse, options: &ReplOptions) -> Vec<ReplResponse> {
let mut responses = vec![];
if options.show_total_time {
@ -64,17 +58,10 @@ pub fn handle_computation_response(
}
responses.push(match response.main_output {
Ok(s) => ReplResponse {
label: None,
text: s,
color: None,
},
Err(e) => ReplResponse {
label: Some("Error".to_string()),
text: e,
color: Some(Color::Red),
},
Ok(s) => ReplResponse { label: None, text: s, color: None },
Err(e) => ReplResponse { label: Some("Error".to_string()), text: e, color: Some(Color::Red) },
});
responses
}

View File

@ -1,3 +1,9 @@
extern crate schala_repl;
//extern crate maaru_lang;
//extern crate rukka_lang;
//extern crate robo_lang;
extern crate schala_lang;
use schala_repl::{ProgrammingLanguageInterface, start_repl};
extern { }