iowo/src/evaluator.rs
Schrottkatze 17878b3e87 rewrite error system and add evaluator architecture
the evaluator architecture is also only a temporary solution and very flawed
but i have no other ideas
2023-11-19 16:52:38 +01:00

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,
}