Thread SchalaConfig for repl/non-repl in runner
This commit is contained in:
parent
d084deac80
commit
76f7524fdb
@ -31,4 +31,4 @@ mod identifier;
|
||||
|
||||
mod schala;
|
||||
|
||||
pub use schala::Schala;
|
||||
pub use schala::{Schala, SchalaConfig};
|
||||
|
@ -57,7 +57,7 @@ impl<'a> Schala<'a> {
|
||||
let prelude = include_str!("../source-files/prelude.schala");
|
||||
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 {
|
||||
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.
|
||||
/// Note: this should eventually use a query-based system for parallelization, cf.
|
||||
/// 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
|
||||
// TODO tokenize should return its own error type
|
||||
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 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>, SchalaError> =
|
||||
@ -145,9 +145,14 @@ fn stage_names() -> Vec<&'static str> {
|
||||
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> {
|
||||
//TODO flesh out Config
|
||||
type Config = ();
|
||||
type Config = SchalaConfig;
|
||||
fn language_name() -> String {
|
||||
"Schala".to_owned()
|
||||
}
|
||||
@ -161,7 +166,8 @@ impl<'a> ProgrammingLanguageInterface for Schala<'a> {
|
||||
self.source_reference.load_new_source(source);
|
||||
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![] };
|
||||
|
||||
|
@ -50,7 +50,6 @@ impl<'a, 'b> Evaluator<'a, 'b> {
|
||||
fn statement(&mut self, stmt: Statement) -> EvalResult<Option<MemoryValue>> {
|
||||
match stmt {
|
||||
Statement::Binding { ref id, expr, constant: _ } => {
|
||||
println!("eval() binding id: {}", id);
|
||||
let evaluated = self.expression(expr)?;
|
||||
self.state.environments.insert(id.into(), evaluated.into());
|
||||
Ok(None)
|
||||
|
@ -2,7 +2,7 @@ use std::collections::HashSet;
|
||||
use std::time;
|
||||
|
||||
pub trait ProgrammingLanguageInterface {
|
||||
type Config: Default;
|
||||
type Config: Default + Clone;
|
||||
fn language_name() -> String;
|
||||
fn source_file_suffix() -> String;
|
||||
|
||||
|
@ -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!(
|
||||
"Type {} for help with the REPL",
|
||||
format!("{}help", self.sigil).bright_green().bold()
|
||||
);
|
||||
self.load_options();
|
||||
self.handle_repl_loop();
|
||||
self.handle_repl_loop(config);
|
||||
self.save_before_exit();
|
||||
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::*;
|
||||
|
||||
'main: loop {
|
||||
@ -128,7 +128,7 @@ impl<L: ProgrammingLanguageInterface> Repl<L> {
|
||||
buf.push('\n');
|
||||
}
|
||||
}
|
||||
self.handle_input(&buf)
|
||||
self.handle_input(&buf, &config)
|
||||
} else {
|
||||
if let Some(output) = self.handle_interpreter_directive(input.get(1..).unwrap()) {
|
||||
println!("{}", output);
|
||||
@ -136,7 +136,7 @@ impl<L: ProgrammingLanguageInterface> Repl<L> {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
_ => self.handle_input(input),
|
||||
_ => self.handle_input(input, &config),
|
||||
};
|
||||
|
||||
for repl_response in repl_responses.iter() {
|
||||
@ -179,7 +179,7 @@ impl<L: ProgrammingLanguageInterface> Repl<L> {
|
||||
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();
|
||||
for ask in self.options.debug_asks.iter() {
|
||||
debug_requests.insert(ask.clone());
|
||||
@ -187,7 +187,7 @@ impl<L: ProgrammingLanguageInterface> Repl<L> {
|
||||
|
||||
let request = ComputationRequest {
|
||||
source: input,
|
||||
config: Default::default(),
|
||||
config: config.clone(),
|
||||
debug_requests,
|
||||
};
|
||||
let response = self.language_state.run_computation(request);
|
||||
|
15
src/main.rs
15
src/main.rs
@ -1,7 +1,7 @@
|
||||
use schala_repl::{Repl, ProgrammingLanguageInterface, ComputationRequest};
|
||||
|
||||
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
|
||||
fn main() {
|
||||
@ -21,7 +21,8 @@ fn main() {
|
||||
if matches.free.is_empty() {
|
||||
let state = Schala::new();
|
||||
let mut repl = Repl::new(state);
|
||||
repl.run_repl();
|
||||
let config = SchalaConfig { repl: true };
|
||||
repl.run_repl(config);
|
||||
} else {
|
||||
let paths: Vec<PathBuf> = matches.free.iter().map(PathBuf::from).collect();
|
||||
//TODO handle more than one file
|
||||
@ -34,7 +35,11 @@ fn main() {
|
||||
|
||||
//TODO this proably should be a macro for every supported language
|
||||
if extension == Schala::source_file_suffix() {
|
||||
run_noninteractive(paths, Schala::new());
|
||||
let config = SchalaConfig {
|
||||
repl: false,
|
||||
};
|
||||
|
||||
run_noninteractive(paths, Schala::new(), config);
|
||||
} else {
|
||||
eprintln!("Extension .{} not recognized", extension);
|
||||
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
|
||||
|
||||
let filename = &filenames[0];
|
||||
@ -52,7 +57,7 @@ pub fn run_noninteractive<L: ProgrammingLanguageInterface>(filenames: Vec<PathBu
|
||||
|
||||
let request = ComputationRequest {
|
||||
source: &buffer,
|
||||
config: Default::default(),
|
||||
config,
|
||||
debug_requests: HashSet::new(),
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user