use crate::ast::{Decl, DeclBody};
use crate::checker::check_module;
use crate::engine::{Engine, RootSrc};
use crate::parse::parse_source;
use crate::semantics::{sort_diags, Diag, Env, Scope};
use std::rc::Rc;
pub struct Pipeline {
pub env: Rc<Env>,
pub eng: Rc<Engine>,
pub diags: Vec<Diag>,
}
pub fn run_pipeline(decls: &[Decl]) -> Pipeline {
let env = Env::new();
env.load(decls);
let eng = Engine::new(env.clone());
let outs = env.outputs.borrow().clone();
for (name, ty_ast, expr) in outs {
let sc = Scope::new(&name, None);
match env.resolve(&ty_ast, None) {
Ok(rt) => eng.bind_root(&name, RootSrc::Expr(&expr), &rt, &sc),
Err(e) => env.report(Diag::error(e, name.clone(), None)),
}
}
eng.drive(&env);
let diags = sort_diags(env.diagnostics_vec()); env.diag_set(diags.clone());
Pipeline { env, eng, diags }
}
#[derive(Clone, Copy, PartialEq, Debug)]
pub enum Phase {
Parse,
Check,
Evaluate,
}
pub struct Report {
pub phase: Phase,
pub ok: bool,
pub parse_errors: Vec<(usize, usize)>,
pub checks: Vec<Diag>,
pub diagnostics: Vec<Diag>,
pub outputs: Vec<(String, String)>,
pub inputs: Vec<String>,
}
pub fn evaluate_source(source: &str) -> Report {
let parsed = parse_source(source);
let inputs: Vec<String> = parsed
.decls
.iter()
.filter_map(|d| {
if let DeclBody::Input { name, .. } = &d.body {
Some(name.clone())
} else {
None
}
})
.collect();
if !parsed.errors.is_empty() {
return Report {
phase: Phase::Parse,
ok: false,
parse_errors: parsed.errors,
checks: vec![],
diagnostics: vec![],
outputs: vec![],
inputs,
};
}
let checks = check_module(&parsed.decls, None, None);
if checks.iter().any(|d| d.severity == "error") {
return Report {
phase: Phase::Check,
ok: false,
parse_errors: vec![],
checks,
diagnostics: vec![],
outputs: vec![],
inputs,
};
}
let Pipeline { env, eng, diags } = run_pipeline(&parsed.decls);
let ok = !diags.iter().any(|d| d.severity == "error");
let outputs = if ok {
env.outputs
.borrow()
.iter()
.filter_map(|(n, _, _)| {
env.root(n)
.map(|v| (n.clone(), eng.serialize(&v, n, false)))
})
.collect()
} else {
vec![]
};
Report {
phase: Phase::Evaluate,
ok,
parse_errors: vec![],
checks,
diagnostics: diags,
outputs,
inputs,
}
}