Parameterize Repl over language type
This commit is contained in:
parent
0f7e568341
commit
3cbe80e933
@ -174,11 +174,11 @@ fn stage_names() -> Vec<&'static str> {
|
|||||||
|
|
||||||
|
|
||||||
impl ProgrammingLanguageInterface for Schala {
|
impl ProgrammingLanguageInterface for Schala {
|
||||||
fn language_name(&self) -> String {
|
fn language_name() -> String {
|
||||||
"Schala".to_owned()
|
"Schala".to_owned()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn source_file_suffix(&self) -> String {
|
fn source_file_suffix() -> String {
|
||||||
"schala".to_owned()
|
"schala".to_owned()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,8 +2,8 @@ use std::collections::HashSet;
|
|||||||
use std::time;
|
use std::time;
|
||||||
|
|
||||||
pub trait ProgrammingLanguageInterface {
|
pub trait ProgrammingLanguageInterface {
|
||||||
fn language_name(&self) -> String;
|
fn language_name() -> String;
|
||||||
fn source_file_suffix(&self) -> String;
|
fn source_file_suffix() -> String;
|
||||||
|
|
||||||
fn run_computation(&mut self, _request: ComputationRequest) -> ComputationResponse;
|
fn run_computation(&mut self, _request: ComputationRequest) -> ComputationResponse;
|
||||||
|
|
||||||
|
@ -7,12 +7,6 @@ extern crate includedir;
|
|||||||
extern crate phf;
|
extern crate phf;
|
||||||
extern crate serde_json;
|
extern crate serde_json;
|
||||||
|
|
||||||
use std::collections::HashSet;
|
|
||||||
use std::fs::File;
|
|
||||||
use std::io::Read;
|
|
||||||
use std::path::PathBuf;
|
|
||||||
use std::process::exit;
|
|
||||||
|
|
||||||
mod language;
|
mod language;
|
||||||
mod repl;
|
mod repl;
|
||||||
|
|
||||||
@ -21,49 +15,7 @@ pub use language::{
|
|||||||
LangMetaRequest, LangMetaResponse, ProgrammingLanguageInterface,
|
LangMetaRequest, LangMetaResponse, ProgrammingLanguageInterface,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub use repl::Repl;
|
||||||
|
|
||||||
include!(concat!(env!("OUT_DIR"), "/static.rs"));
|
include!(concat!(env!("OUT_DIR"), "/static.rs"));
|
||||||
const VERSION_STRING: &'static str = "0.1.0";
|
const VERSION_STRING: &'static str = "0.1.0";
|
||||||
|
|
||||||
pub fn start_repl(langs: Vec<Box<dyn ProgrammingLanguageInterface>>) {
|
|
||||||
let mut repl = repl::Repl::new(langs);
|
|
||||||
repl.run_repl();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn run_noninteractive(filenames: Vec<PathBuf>, languages: Vec<Box<dyn ProgrammingLanguageInterface>>) {
|
|
||||||
// for now, ony do something with the first filename
|
|
||||||
|
|
||||||
let filename = &filenames[0];
|
|
||||||
let ext = filename
|
|
||||||
.extension()
|
|
||||||
.and_then(|e| e.to_str())
|
|
||||||
.unwrap_or_else(|| {
|
|
||||||
println!("Source file `{}` has no extension.", filename.display());
|
|
||||||
exit(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
let mut language = Box::new(
|
|
||||||
languages
|
|
||||||
.into_iter()
|
|
||||||
.find(|lang| lang.source_file_suffix() == ext)
|
|
||||||
.unwrap_or_else(|| {
|
|
||||||
println!("Extension .{} not recognized", ext);
|
|
||||||
exit(1);
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut source_file = File::open(filename).unwrap();
|
|
||||||
let mut buffer = String::new();
|
|
||||||
source_file.read_to_string(&mut buffer).unwrap();
|
|
||||||
|
|
||||||
let request = ComputationRequest {
|
|
||||||
source: &buffer,
|
|
||||||
debug_requests: HashSet::new(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let response = language.run_computation(request);
|
|
||||||
match response.main_output {
|
|
||||||
Ok(s) => println!("{}", s),
|
|
||||||
Err(s) => println!("{}", s),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use super::{InterpreterDirectiveOutput, Repl};
|
use super::{InterpreterDirectiveOutput, Repl};
|
||||||
|
use crate::language::ProgrammingLanguageInterface;
|
||||||
use crate::repl::directive_actions::DirectiveAction;
|
use crate::repl::directive_actions::DirectiveAction;
|
||||||
use colored::*;
|
use colored::*;
|
||||||
|
|
||||||
@ -85,7 +86,11 @@ impl CommandTree {
|
|||||||
self.get_children().iter().map(|x| x.get_cmd()).collect()
|
self.get_children().iter().map(|x| x.get_cmd()).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn perform(&self, repl: &mut Repl, arguments: &Vec<&str>) -> InterpreterDirectiveOutput {
|
pub fn perform<L: ProgrammingLanguageInterface>(
|
||||||
|
&self,
|
||||||
|
repl: &mut Repl<L>,
|
||||||
|
arguments: &Vec<&str>,
|
||||||
|
) -> InterpreterDirectiveOutput {
|
||||||
let mut dir_pointer: &CommandTree = self;
|
let mut dir_pointer: &CommandTree = self;
|
||||||
let mut idx = 0;
|
let mut idx = 0;
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
use super::{InterpreterDirectiveOutput, Repl};
|
use super::{InterpreterDirectiveOutput, Repl};
|
||||||
use crate::language::{DebugAsk, DebugResponse, LangMetaRequest, LangMetaResponse};
|
use crate::language::{
|
||||||
|
DebugAsk, DebugResponse, LangMetaRequest, LangMetaResponse, ProgrammingLanguageInterface,
|
||||||
|
};
|
||||||
use crate::repl::help::help;
|
use crate::repl::help::help;
|
||||||
use std::fmt::Write as FmtWrite;
|
use std::fmt::Write as FmtWrite;
|
||||||
|
|
||||||
@ -20,7 +22,11 @@ pub enum DirectiveAction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl DirectiveAction {
|
impl DirectiveAction {
|
||||||
pub fn perform(&self, repl: &mut Repl, arguments: &[&str]) -> InterpreterDirectiveOutput {
|
pub fn perform<L: ProgrammingLanguageInterface>(
|
||||||
|
&self,
|
||||||
|
repl: &mut Repl<L>,
|
||||||
|
arguments: &[&str],
|
||||||
|
) -> InterpreterDirectiveOutput {
|
||||||
use DirectiveAction::*;
|
use DirectiveAction::*;
|
||||||
match self {
|
match self {
|
||||||
Null => None,
|
Null => None,
|
||||||
@ -30,8 +36,10 @@ impl DirectiveAction {
|
|||||||
::std::process::exit(0)
|
::std::process::exit(0)
|
||||||
}
|
}
|
||||||
ListPasses => {
|
ListPasses => {
|
||||||
let language_state = repl.get_cur_language_state();
|
let pass_names = match repl
|
||||||
let pass_names = match language_state.request_meta(LangMetaRequest::StageNames) {
|
.language_state
|
||||||
|
.request_meta(LangMetaRequest::StageNames)
|
||||||
|
{
|
||||||
LangMetaResponse::StageNames(names) => names,
|
LangMetaResponse::StageNames(names) => names,
|
||||||
_ => vec![],
|
_ => vec![],
|
||||||
};
|
};
|
||||||
@ -46,7 +54,6 @@ impl DirectiveAction {
|
|||||||
Some(buf)
|
Some(buf)
|
||||||
}
|
}
|
||||||
ShowImmediate => {
|
ShowImmediate => {
|
||||||
let cur_state = repl.get_cur_language_state();
|
|
||||||
let stage_name = match arguments.get(0) {
|
let stage_name = match arguments.get(0) {
|
||||||
Some(s) => s.to_string(),
|
Some(s) => s.to_string(),
|
||||||
None => return Some(format!("Must specify a thing to debug")),
|
None => return Some(format!("Must specify a thing to debug")),
|
||||||
@ -55,7 +62,7 @@ impl DirectiveAction {
|
|||||||
stage_name: stage_name.clone(),
|
stage_name: stage_name.clone(),
|
||||||
token: None,
|
token: None,
|
||||||
});
|
});
|
||||||
let meta_response = cur_state.request_meta(meta);
|
let meta_response = repl.language_state.request_meta(meta);
|
||||||
|
|
||||||
let response = match meta_response {
|
let response = match meta_response {
|
||||||
LangMetaResponse::ImmediateDebug(DebugResponse { ask, value }) => match ask {
|
LangMetaResponse::ImmediateDebug(DebugResponse { ask, value }) => match ask {
|
||||||
@ -100,43 +107,37 @@ impl DirectiveAction {
|
|||||||
});
|
});
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
TotalTimeOff => total_time_off(repl, arguments),
|
TotalTimeOff => {
|
||||||
TotalTimeOn => total_time_on(repl, arguments),
|
repl.options.show_total_time = false;
|
||||||
StageTimeOff => stage_time_off(repl, arguments),
|
None
|
||||||
StageTimeOn => stage_time_on(repl, arguments),
|
}
|
||||||
|
TotalTimeOn => {
|
||||||
|
repl.options.show_total_time = true;
|
||||||
|
None
|
||||||
|
}
|
||||||
|
StageTimeOff => {
|
||||||
|
repl.options.show_stage_times = false;
|
||||||
|
None
|
||||||
|
}
|
||||||
|
StageTimeOn => {
|
||||||
|
repl.options.show_stage_times = true;
|
||||||
|
None
|
||||||
|
}
|
||||||
Doc => doc(repl, arguments),
|
Doc => doc(repl, arguments),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn total_time_on(repl: &mut Repl, _: &[&str]) -> InterpreterDirectiveOutput {
|
fn doc<L: ProgrammingLanguageInterface>(
|
||||||
repl.options.show_total_time = true;
|
repl: &mut Repl<L>,
|
||||||
None
|
arguments: &[&str],
|
||||||
}
|
) -> InterpreterDirectiveOutput {
|
||||||
|
|
||||||
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
|
arguments
|
||||||
.get(0)
|
.get(0)
|
||||||
.map(|cmd| {
|
.map(|cmd| {
|
||||||
let source = cmd.to_string();
|
let source = cmd.to_string();
|
||||||
let meta = LangMetaRequest::Docs { source };
|
let meta = LangMetaRequest::Docs { source };
|
||||||
let cur_state = repl.get_cur_language_state();
|
match repl.language_state.request_meta(meta) {
|
||||||
match cur_state.request_meta(meta) {
|
|
||||||
LangMetaResponse::Docs { doc_string } => Some(doc_string),
|
LangMetaResponse::Docs { doc_string } => Some(doc_string),
|
||||||
_ => Some(format!("Invalid doc response")),
|
_ => Some(format!("Invalid doc response")),
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,7 @@ fn get_list(passes_directives: &Vec<CommandTree>, include_help: bool) -> Vec<Com
|
|||||||
|
|
||||||
vec![
|
vec![
|
||||||
CommandTree::terminal("exit", Some("exit the REPL"), vec![], QuitProgram),
|
CommandTree::terminal("exit", Some("exit the REPL"), vec![], QuitProgram),
|
||||||
|
//TODO there should be an alias for this
|
||||||
CommandTree::terminal("quit", Some("exit the REPL"), vec![], QuitProgram),
|
CommandTree::terminal("quit", Some("exit the REPL"), vec![], QuitProgram),
|
||||||
CommandTree::terminal(
|
CommandTree::terminal(
|
||||||
"help",
|
"help",
|
||||||
@ -85,15 +86,6 @@ fn get_list(passes_directives: &Vec<CommandTree>, include_help: bool) -> Vec<Com
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
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(
|
CommandTree::terminal(
|
||||||
"doc",
|
"doc",
|
||||||
Some("Get language-specific help for an item"),
|
Some("Get language-specific help for an item"),
|
||||||
|
@ -2,9 +2,13 @@ use std::fmt::Write as FmtWrite;
|
|||||||
|
|
||||||
use super::command_tree::CommandTree;
|
use super::command_tree::CommandTree;
|
||||||
use super::{InterpreterDirectiveOutput, Repl};
|
use super::{InterpreterDirectiveOutput, Repl};
|
||||||
|
use crate::language::ProgrammingLanguageInterface;
|
||||||
use colored::*;
|
use colored::*;
|
||||||
|
|
||||||
pub fn help(repl: &mut Repl, arguments: &[&str]) -> InterpreterDirectiveOutput {
|
pub fn help<L: ProgrammingLanguageInterface>(
|
||||||
|
repl: &mut Repl<L>,
|
||||||
|
arguments: &[&str],
|
||||||
|
) -> InterpreterDirectiveOutput {
|
||||||
match arguments {
|
match arguments {
|
||||||
[] => return global_help(repl),
|
[] => return global_help(repl),
|
||||||
commands => {
|
commands => {
|
||||||
@ -46,7 +50,7 @@ fn get_directive_from_commands<'a>(
|
|||||||
matched_directive
|
matched_directive
|
||||||
}
|
}
|
||||||
|
|
||||||
fn global_help(repl: &mut Repl) -> InterpreterDirectiveOutput {
|
fn global_help<L: ProgrammingLanguageInterface>(repl: &mut Repl<L>) -> InterpreterDirectiveOutput {
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
|
|
||||||
writeln!(
|
writeln!(
|
||||||
@ -69,12 +73,11 @@ fn global_help(repl: &mut Repl) -> InterpreterDirectiveOutput {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
let ref lang = repl.get_cur_language_state();
|
|
||||||
writeln!(buf, "").unwrap();
|
writeln!(buf, "").unwrap();
|
||||||
writeln!(
|
writeln!(
|
||||||
buf,
|
buf,
|
||||||
"Language-specific help for {}",
|
"Language-specific help for {}",
|
||||||
lang.language_name()
|
<L as ProgrammingLanguageInterface>::language_name()
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
writeln!(buf, "-----------------------").unwrap();
|
writeln!(buf, "-----------------------").unwrap();
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
|
use colored::*;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use colored::*;
|
|
||||||
|
|
||||||
use crate::language::{
|
use crate::language::{
|
||||||
ComputationRequest, LangMetaRequest, LangMetaResponse, ProgrammingLanguageInterface,
|
ComputationRequest, LangMetaRequest, LangMetaResponse, ProgrammingLanguageInterface,
|
||||||
@ -22,13 +22,13 @@ const OPTIONS_SAVE_FILE: &'static str = ".schala_repl";
|
|||||||
|
|
||||||
type InterpreterDirectiveOutput = Option<String>;
|
type InterpreterDirectiveOutput = Option<String>;
|
||||||
|
|
||||||
pub struct Repl {
|
pub struct Repl<L: ProgrammingLanguageInterface> {
|
||||||
/// If this is the first character typed by a user into the repl, the following
|
/// If this is the first character typed by a user into the repl, the following
|
||||||
/// will be interpreted as a directive to the REPL rather than a command in the
|
/// will be interpreted as a directive to the REPL rather than a command in the
|
||||||
/// running programming language.
|
/// running programming language.
|
||||||
sigil: char,
|
sigil: char,
|
||||||
line_reader: ::linefeed::interface::Interface<::linefeed::terminal::DefaultTerminal>,
|
line_reader: ::linefeed::interface::Interface<::linefeed::terminal::DefaultTerminal>,
|
||||||
language_states: Vec<Box<dyn ProgrammingLanguageInterface>>,
|
language_state: L,
|
||||||
options: ReplOptions,
|
options: ReplOptions,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,8 +38,8 @@ enum PromptStyle {
|
|||||||
Multiline,
|
Multiline,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Repl {
|
impl<L: ProgrammingLanguageInterface> Repl<L> {
|
||||||
pub fn new(initial_states: Vec<Box<dyn ProgrammingLanguageInterface>>) -> Repl {
|
pub fn new(initial_state: L) -> Self {
|
||||||
use linefeed::Interface;
|
use linefeed::Interface;
|
||||||
let line_reader = Interface::new("schala-repl").unwrap();
|
let line_reader = Interface::new("schala-repl").unwrap();
|
||||||
let sigil = ':';
|
let sigil = ':';
|
||||||
@ -47,7 +47,7 @@ impl Repl {
|
|||||||
Repl {
|
Repl {
|
||||||
sigil,
|
sigil,
|
||||||
line_reader,
|
line_reader,
|
||||||
language_states: initial_states,
|
language_state: initial_state,
|
||||||
options: ReplOptions::new(),
|
options: ReplOptions::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -55,7 +55,8 @@ impl Repl {
|
|||||||
pub fn run_repl(&mut self) {
|
pub fn run_repl(&mut self) {
|
||||||
println!("Schala meta-interpeter version {}", crate::VERSION_STRING);
|
println!("Schala meta-interpeter version {}", crate::VERSION_STRING);
|
||||||
println!(
|
println!(
|
||||||
"Type {} for help with the REPL", format!("{}help", self.sigil).bright_green().bold()
|
"Type {} for help with the REPL",
|
||||||
|
format!("{}help", self.sigil).bright_green().bold()
|
||||||
);
|
);
|
||||||
self.load_options();
|
self.load_options();
|
||||||
self.handle_repl_loop();
|
self.handle_repl_loop();
|
||||||
@ -68,10 +69,10 @@ impl Repl {
|
|||||||
.load_history(HISTORY_SAVE_FILE)
|
.load_history(HISTORY_SAVE_FILE)
|
||||||
.unwrap_or(());
|
.unwrap_or(());
|
||||||
match ReplOptions::load_from_file(OPTIONS_SAVE_FILE) {
|
match ReplOptions::load_from_file(OPTIONS_SAVE_FILE) {
|
||||||
Ok(options) => {
|
Ok(options) => {
|
||||||
self.options = options;
|
self.options = options;
|
||||||
}
|
}
|
||||||
Err(e) => eprintln!("{}",e)
|
Err(e) => eprintln!("{}", e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,8 +133,7 @@ impl Repl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn update_line_reader(&mut self) {
|
fn update_line_reader(&mut self) {
|
||||||
let tab_complete_handler =
|
let tab_complete_handler = TabCompleteHandler::new(self.sigil, self.get_directives());
|
||||||
TabCompleteHandler::new(self.sigil, self.get_directives());
|
|
||||||
self.line_reader
|
self.line_reader
|
||||||
.set_completer(Arc::new(tab_complete_handler)); //TODO fix this here
|
.set_completer(Arc::new(tab_complete_handler)); //TODO fix this here
|
||||||
self.set_prompt(PromptStyle::Normal);
|
self.set_prompt(PromptStyle::Normal);
|
||||||
@ -166,11 +166,6 @@ impl Repl {
|
|||||||
directives.perform(self, &arguments)
|
directives.perform(self, &arguments)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_cur_language_state(&mut self) -> &mut Box<dyn ProgrammingLanguageInterface> {
|
|
||||||
//TODO this is obviously not complete
|
|
||||||
&mut self.language_states[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
fn handle_input(&mut self, input: &str) -> Vec<ReplResponse> {
|
fn handle_input(&mut self, input: &str) -> Vec<ReplResponse> {
|
||||||
let mut debug_requests = HashSet::new();
|
let mut debug_requests = HashSet::new();
|
||||||
for ask in self.options.debug_asks.iter() {
|
for ask in self.options.debug_asks.iter() {
|
||||||
@ -181,14 +176,15 @@ impl Repl {
|
|||||||
source: input,
|
source: input,
|
||||||
debug_requests,
|
debug_requests,
|
||||||
};
|
};
|
||||||
let ref mut language_state = self.get_cur_language_state();
|
let response = self.language_state.run_computation(request);
|
||||||
let response = language_state.run_computation(request);
|
|
||||||
response::handle_computation_response(response, &self.options)
|
response::handle_computation_response(response, &self.options)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_directives(&mut self) -> CommandTree {
|
fn get_directives(&mut self) -> CommandTree {
|
||||||
let language_state = self.get_cur_language_state();
|
let pass_names = match self
|
||||||
let pass_names = match language_state.request_meta(LangMetaRequest::StageNames) {
|
.language_state
|
||||||
|
.request_meta(LangMetaRequest::StageNames)
|
||||||
|
{
|
||||||
LangMetaResponse::StageNames(names) => names,
|
LangMetaResponse::StageNames(names) => names,
|
||||||
_ => vec![],
|
_ => vec![],
|
||||||
};
|
};
|
||||||
|
52
src/main.rs
52
src/main.rs
@ -1,8 +1,9 @@
|
|||||||
use schala_repl::{run_noninteractive, start_repl, ProgrammingLanguageInterface};
|
use schala_repl::{Repl, ProgrammingLanguageInterface, ComputationRequest};
|
||||||
|
|
||||||
use std::path::PathBuf;
|
use std::{fs::File, io::Read, path::PathBuf, process::exit, collections::HashSet};
|
||||||
use std::process::exit;
|
use schala_lang::Schala;
|
||||||
|
|
||||||
|
//TODO specify multiple langs, and have a way to switch between them
|
||||||
fn main() {
|
fn main() {
|
||||||
let args: Vec<String> = std::env::args().collect();
|
let args: Vec<String> = std::env::args().collect();
|
||||||
let matches = command_line_options()
|
let matches = command_line_options()
|
||||||
@ -17,17 +18,50 @@ fn main() {
|
|||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
let langs: Vec<Box<dyn ProgrammingLanguageInterface>> =
|
|
||||||
vec![Box::new(schala_lang::Schala::new())];
|
|
||||||
|
|
||||||
if matches.free.is_empty() {
|
if matches.free.is_empty() {
|
||||||
start_repl(langs);
|
let state = Schala::new();
|
||||||
|
let mut repl = Repl::new(state);
|
||||||
|
repl.run_repl();
|
||||||
} else {
|
} else {
|
||||||
let paths = matches.free.iter().map(PathBuf::from).collect();
|
let paths: Vec<PathBuf> = matches.free.iter().map(PathBuf::from).collect();
|
||||||
run_noninteractive(paths, langs);
|
//TODO handle more than one file
|
||||||
|
let filename = &paths[0];
|
||||||
|
let extension = filename.extension().and_then(|e| e.to_str())
|
||||||
|
.unwrap_or_else(|| {
|
||||||
|
eprintln!("Source file `{}` has no extension.", filename.display());
|
||||||
|
exit(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
//TODO this proably should be a macro for every supported language
|
||||||
|
if extension == Schala::source_file_suffix() {
|
||||||
|
run_noninteractive(paths, Schala::new());
|
||||||
|
} else {
|
||||||
|
eprintln!("Extension .{} not recognized", extension);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn run_noninteractive<L: ProgrammingLanguageInterface>(filenames: Vec<PathBuf>, mut language: L) {
|
||||||
|
// for now, ony do something with the first filename
|
||||||
|
|
||||||
|
let filename = &filenames[0];
|
||||||
|
let mut source_file = File::open(filename).unwrap();
|
||||||
|
let mut buffer = String::new();
|
||||||
|
source_file.read_to_string(&mut buffer).unwrap();
|
||||||
|
|
||||||
|
let request = ComputationRequest {
|
||||||
|
source: &buffer,
|
||||||
|
debug_requests: HashSet::new(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let response = language.run_computation(request);
|
||||||
|
match response.main_output {
|
||||||
|
Ok(s) => println!("{}", s),
|
||||||
|
Err(s) => eprintln!("{}", s),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
fn command_line_options() -> getopts::Options {
|
fn command_line_options() -> getopts::Options {
|
||||||
let mut options = getopts::Options::new();
|
let mut options = getopts::Options::new();
|
||||||
options.optflag("h", "help", "Show help text");
|
options.optflag("h", "help", "Show help text");
|
||||||
|
Loading…
Reference in New Issue
Block a user