Thread SchalaConfig for repl/non-repl in runner

This commit is contained in:
Greg Shuflin 2021-10-31 03:30:45 -07:00
parent d084deac80
commit 76f7524fdb
6 changed files with 30 additions and 20 deletions

View File

@ -31,4 +31,4 @@ mod identifier;
mod schala; mod schala;
pub use schala::Schala; pub use schala::{Schala, SchalaConfig};

View File

@ -57,7 +57,7 @@ impl<'a> Schala<'a> {
let prelude = include_str!("../source-files/prelude.schala"); let prelude = include_str!("../source-files/prelude.schala");
let mut env = Schala::new_blank_env(); let mut env = Schala::new_blank_env();
let response = env.run_pipeline(prelude); let response = env.run_pipeline(prelude, SchalaConfig::default());
if let Err(err) = response { if let Err(err) = response {
panic!("Error in prelude, panicking: {}", err.display()); panic!("Error in prelude, panicking: {}", err.display());
} }
@ -67,7 +67,7 @@ impl<'a> Schala<'a> {
/// This is where the actual action of interpreting/compilation happens. /// This is where the actual action of interpreting/compilation happens.
/// Note: this should eventually use a query-based system for parallelization, cf. /// Note: this should eventually use a query-based system for parallelization, cf.
/// https://rustc-dev-guide.rust-lang.org/overview.html /// https://rustc-dev-guide.rust-lang.org/overview.html
fn run_pipeline(&mut self, source: &str) -> Result<String, SchalaError> { fn run_pipeline(&mut self, source: &str, config: SchalaConfig) -> Result<String, SchalaError> {
// 1st stage - tokenization // 1st stage - tokenization
// TODO tokenize should return its own error type // TODO tokenize should return its own error type
let tokens = tokenizing::tokenize(source); let tokens = tokenizing::tokenize(source);
@ -93,7 +93,7 @@ impl<'a> Schala<'a> {
let reduced_ir = reduced_ir::reduce(&ast, &self.symbol_table, &self.type_context); let reduced_ir = reduced_ir::reduce(&ast, &self.symbol_table, &self.type_context);
let evaluation_outputs = self.eval_state.evaluate(reduced_ir, &self.type_context, true); let evaluation_outputs = self.eval_state.evaluate(reduced_ir, &self.type_context, config.repl);
let text_output: Result<Vec<String>, String> = evaluation_outputs.into_iter().collect(); let text_output: Result<Vec<String>, String> = evaluation_outputs.into_iter().collect();
let text_output: Result<Vec<String>, SchalaError> = let text_output: Result<Vec<String>, SchalaError> =
@ -145,9 +145,14 @@ fn stage_names() -> Vec<&'static str> {
vec!["tokenizing", "parsing", "symbol-table", "typechecking", "ast-reduction", "ast-walking-evaluation"] vec!["tokenizing", "parsing", "symbol-table", "typechecking", "ast-reduction", "ast-walking-evaluation"]
} }
#[derive(Default, Clone)]
pub struct SchalaConfig {
pub repl: bool,
}
impl<'a> ProgrammingLanguageInterface for Schala<'a> { impl<'a> ProgrammingLanguageInterface for Schala<'a> {
//TODO flesh out Config //TODO flesh out Config
type Config = (); type Config = SchalaConfig;
fn language_name() -> String { fn language_name() -> String {
"Schala".to_owned() "Schala".to_owned()
} }
@ -161,7 +166,8 @@ impl<'a> ProgrammingLanguageInterface for Schala<'a> {
self.source_reference.load_new_source(source); self.source_reference.load_new_source(source);
let sw = Stopwatch::start_new(); let sw = Stopwatch::start_new();
let main_output = self.run_pipeline(source).map_err(|schala_err| schala_err.display()); let main_output =
self.run_pipeline(source, request.config).map_err(|schala_err| schala_err.display());
let global_output_stats = GlobalOutputStats { total_duration: sw.elapsed(), stage_durations: vec![] }; let global_output_stats = GlobalOutputStats { total_duration: sw.elapsed(), stage_durations: vec![] };

View File

@ -50,7 +50,6 @@ impl<'a, 'b> Evaluator<'a, 'b> {
fn statement(&mut self, stmt: Statement) -> EvalResult<Option<MemoryValue>> { fn statement(&mut self, stmt: Statement) -> EvalResult<Option<MemoryValue>> {
match stmt { match stmt {
Statement::Binding { ref id, expr, constant: _ } => { Statement::Binding { ref id, expr, constant: _ } => {
println!("eval() binding id: {}", id);
let evaluated = self.expression(expr)?; let evaluated = self.expression(expr)?;
self.state.environments.insert(id.into(), evaluated.into()); self.state.environments.insert(id.into(), evaluated.into());
Ok(None) Ok(None)

View File

@ -2,7 +2,7 @@ use std::collections::HashSet;
use std::time; use std::time;
pub trait ProgrammingLanguageInterface { pub trait ProgrammingLanguageInterface {
type Config: Default; type Config: Default + Clone;
fn language_name() -> String; fn language_name() -> String;
fn source_file_suffix() -> String; fn source_file_suffix() -> String;

View File

@ -66,14 +66,14 @@ impl<L: ProgrammingLanguageInterface> Repl<L> {
} }
} }
pub fn run_repl(&mut self) { pub fn run_repl(&mut self, config: L::Config) {
println!("Schala meta-interpeter version {}", VERSION_STRING); println!("Schala meta-interpeter version {}", VERSION_STRING);
println!( println!(
"Type {} for help with the REPL", "Type {} for help with the REPL",
format!("{}help", self.sigil).bright_green().bold() format!("{}help", self.sigil).bright_green().bold()
); );
self.load_options(); self.load_options();
self.handle_repl_loop(); self.handle_repl_loop(config);
self.save_before_exit(); self.save_before_exit();
println!("Exiting..."); println!("Exiting...");
} }
@ -90,7 +90,7 @@ impl<L: ProgrammingLanguageInterface> Repl<L> {
} }
} }
fn handle_repl_loop(&mut self) { fn handle_repl_loop(&mut self, config: L::Config) {
use linefeed::ReadResult::*; use linefeed::ReadResult::*;
'main: loop { 'main: loop {
@ -128,7 +128,7 @@ impl<L: ProgrammingLanguageInterface> Repl<L> {
buf.push('\n'); buf.push('\n');
} }
} }
self.handle_input(&buf) self.handle_input(&buf, &config)
} else { } else {
if let Some(output) = self.handle_interpreter_directive(input.get(1..).unwrap()) { if let Some(output) = self.handle_interpreter_directive(input.get(1..).unwrap()) {
println!("{}", output); println!("{}", output);
@ -136,7 +136,7 @@ impl<L: ProgrammingLanguageInterface> Repl<L> {
continue; continue;
} }
} }
_ => self.handle_input(input), _ => self.handle_input(input, &config),
}; };
for repl_response in repl_responses.iter() { for repl_response in repl_responses.iter() {
@ -179,7 +179,7 @@ impl<L: ProgrammingLanguageInterface> Repl<L> {
directives.perform(self, &arguments) directives.perform(self, &arguments)
} }
fn handle_input(&mut self, input: &str) -> Vec<ReplResponse> { fn handle_input(&mut self, input: &str, config: &L::Config) -> 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() {
debug_requests.insert(ask.clone()); debug_requests.insert(ask.clone());
@ -187,7 +187,7 @@ impl<L: ProgrammingLanguageInterface> Repl<L> {
let request = ComputationRequest { let request = ComputationRequest {
source: input, source: input,
config: Default::default(), config: config.clone(),
debug_requests, debug_requests,
}; };
let response = self.language_state.run_computation(request); let response = self.language_state.run_computation(request);

View File

@ -1,7 +1,7 @@
use schala_repl::{Repl, ProgrammingLanguageInterface, ComputationRequest}; use schala_repl::{Repl, ProgrammingLanguageInterface, ComputationRequest};
use std::{fs::File, io::Read, path::PathBuf, process::exit, collections::HashSet}; use std::{fs::File, io::Read, path::PathBuf, process::exit, collections::HashSet};
use schala_lang::Schala; use schala_lang::{Schala, SchalaConfig};
//TODO specify multiple langs, and have a way to switch between them //TODO specify multiple langs, and have a way to switch between them
fn main() { fn main() {
@ -21,7 +21,8 @@ fn main() {
if matches.free.is_empty() { if matches.free.is_empty() {
let state = Schala::new(); let state = Schala::new();
let mut repl = Repl::new(state); let mut repl = Repl::new(state);
repl.run_repl(); let config = SchalaConfig { repl: true };
repl.run_repl(config);
} else { } else {
let paths: Vec<PathBuf> = matches.free.iter().map(PathBuf::from).collect(); let paths: Vec<PathBuf> = matches.free.iter().map(PathBuf::from).collect();
//TODO handle more than one file //TODO handle more than one file
@ -34,7 +35,11 @@ fn main() {
//TODO this proably should be a macro for every supported language //TODO this proably should be a macro for every supported language
if extension == Schala::source_file_suffix() { if extension == Schala::source_file_suffix() {
run_noninteractive(paths, Schala::new()); let config = SchalaConfig {
repl: false,
};
run_noninteractive(paths, Schala::new(), config);
} else { } else {
eprintln!("Extension .{} not recognized", extension); eprintln!("Extension .{} not recognized", extension);
exit(1); exit(1);
@ -42,7 +47,7 @@ fn main() {
} }
} }
pub fn run_noninteractive<L: ProgrammingLanguageInterface>(filenames: Vec<PathBuf>, mut language: L) { pub fn run_noninteractive<L: ProgrammingLanguageInterface>(filenames: Vec<PathBuf>, mut language: L, config: L::Config) {
// for now, ony do something with the first filename // for now, ony do something with the first filename
let filename = &filenames[0]; let filename = &filenames[0];
@ -52,7 +57,7 @@ pub fn run_noninteractive<L: ProgrammingLanguageInterface>(filenames: Vec<PathBu
let request = ComputationRequest { let request = ComputationRequest {
source: &buffer, source: &buffer,
config: Default::default(), config,
debug_requests: HashSet::new(), debug_requests: HashSet::new(),
}; };