the evaluator architecture is also only a temporary solution and very flawed but i have no other ideas
117 lines
3.1 KiB
Rust
117 lines
3.1 KiB
Rust
use std::{collections::HashMap, process::exit};
|
|
|
|
use clap::error::Result;
|
|
use codespan_reporting::{
|
|
files::SimpleFiles,
|
|
term::{
|
|
self,
|
|
termcolor::{ColorChoice, StandardStream},
|
|
},
|
|
};
|
|
|
|
use crate::{
|
|
builtins::initialise_globals,
|
|
error::{ErrorKind, Errors},
|
|
syntax::{
|
|
check::{self, check},
|
|
parse_syntax, PipelineElement,
|
|
},
|
|
typed::into_typed_repr,
|
|
};
|
|
|
|
// this is also bad
|
|
// need a better architecture for this
|
|
|
|
pub struct Evaluator<'a> {
|
|
curr_phase: EvalPhase,
|
|
files: SimpleFiles<&'a str, String>,
|
|
errors: HashMap<usize, Vec<Errors>>,
|
|
}
|
|
|
|
impl<'a> Evaluator<'a> {
|
|
pub fn init() -> Self {
|
|
Self {
|
|
curr_phase: EvalPhase::Lex,
|
|
files: SimpleFiles::new(),
|
|
errors: HashMap::new(),
|
|
}
|
|
}
|
|
|
|
pub fn run(&mut self, input: String, name: Option<&'a str>) {
|
|
let fid = self.files.add(name.unwrap_or("input"), input.clone());
|
|
|
|
let syntax = parse_syntax(&input);
|
|
|
|
match syntax {
|
|
Ok(syntax) => self.curr_phase = EvalPhase::Check(fid, syntax),
|
|
Err(errs) => {
|
|
self.errors.insert(
|
|
fid,
|
|
vec![Errors {
|
|
kind: ErrorKind::InvalidToken,
|
|
locs: errs,
|
|
}],
|
|
);
|
|
self.curr_phase = EvalPhase::Failed
|
|
}
|
|
};
|
|
}
|
|
|
|
pub fn next(mut self) {
|
|
match self.curr_phase {
|
|
EvalPhase::Lex => {
|
|
todo!()
|
|
}
|
|
EvalPhase::Check(file_id, syntax) => {
|
|
let r = check(&syntax);
|
|
|
|
if let Err(errs) = r {
|
|
self.errors.insert(file_id, errs);
|
|
self.curr_phase = EvalPhase::Failed;
|
|
} else {
|
|
self.curr_phase = EvalPhase::BareTyped(file_id, syntax.clone())
|
|
}
|
|
}
|
|
EvalPhase::BareTyped(file_id, syntax) => {
|
|
let ns = initialise_globals();
|
|
let r = into_typed_repr(&ns, syntax);
|
|
|
|
if let Err(errs) = r {
|
|
self.errors.insert(file_id, vec![errs]);
|
|
self.curr_phase = EvalPhase::Failed;
|
|
} else {
|
|
todo!()
|
|
}
|
|
}
|
|
EvalPhase::Failed => self.error_out().unwrap(),
|
|
}
|
|
self.next()
|
|
}
|
|
|
|
pub fn error_out(self) -> Result<!, codespan_reporting::files::Error> {
|
|
let Evaluator {
|
|
curr_phase,
|
|
files,
|
|
errors,
|
|
} = self;
|
|
|
|
let writer = StandardStream::stderr(ColorChoice::Always);
|
|
let config = term::Config::default();
|
|
|
|
for (file_id, errors) in errors.iter() {
|
|
let writer = &mut writer.lock();
|
|
for error in errors {
|
|
term::emit(writer, &config, &files, &error.into_diag(*file_id, &files))?;
|
|
}
|
|
}
|
|
|
|
exit(1)
|
|
}
|
|
}
|
|
|
|
enum EvalPhase {
|
|
Lex,
|
|
Check(usize, Vec<PipelineElement>),
|
|
BareTyped(usize, Vec<PipelineElement>),
|
|
Failed,
|
|
}
|