1use crate::ast::{Decl, DeclBody};
6use crate::checker::check_module;
7use crate::engine::{Engine, RootSrc};
8use crate::parse::parse_source;
9
10use crate::semantics::{sort_diags, Diag, Env, Scope};
11use std::rc::Rc;
12
13pub struct Pipeline {
14 pub env: Rc<Env>,
15 pub eng: Rc<Engine>,
16 pub diags: Vec<Diag>,
17}
18
19pub fn run_pipeline(decls: &[Decl]) -> Pipeline {
20 let env = Env::new();
21 env.load(decls);
22 let eng = Engine::new(env.clone());
23 let outs = env.outputs.borrow().clone();
24 for (name, ty_ast, expr) in outs {
25 let sc = Scope::new(&name, None);
26 match env.resolve(&ty_ast, None) {
27 Ok(rt) => eng.bind_root(&name, RootSrc::Expr(&expr), &rt, &sc),
28 Err(e) => env.report(Diag::error(e, name.clone(), None)),
29 }
30 }
31 eng.drive(&env);
32 let diags = sort_diags(env.diagnostics_vec()); env.diag_set(diags.clone());
34 Pipeline { env, eng, diags }
35}
36
37#[derive(Clone, Copy, PartialEq, Debug)]
39pub enum Phase {
40 Parse,
41 Check,
42 Evaluate,
43}
44pub struct Report {
45 pub phase: Phase,
46 pub ok: bool,
47 pub parse_errors: Vec<(usize, usize)>,
48 pub checks: Vec<Diag>,
50 pub diagnostics: Vec<Diag>,
52 pub outputs: Vec<(String, String)>,
54 pub inputs: Vec<String>,
56}
57
58pub fn evaluate_source(source: &str) -> Report {
60 let parsed = parse_source(source);
61 let inputs: Vec<String> = parsed
62 .decls
63 .iter()
64 .filter_map(|d| {
65 if let DeclBody::Input { name, .. } = &d.body {
66 Some(name.clone())
67 } else {
68 None
69 }
70 })
71 .collect();
72 if !parsed.errors.is_empty() {
73 return Report {
74 phase: Phase::Parse,
75 ok: false,
76 parse_errors: parsed.errors,
77 checks: vec![],
78 diagnostics: vec![],
79 outputs: vec![],
80 inputs,
81 };
82 }
83 let checks = check_module(&parsed.decls, None, None);
84 if checks.iter().any(|d| d.severity == "error") {
85 return Report {
86 phase: Phase::Check,
87 ok: false,
88 parse_errors: vec![],
89 checks,
90 diagnostics: vec![],
91 outputs: vec![],
92 inputs,
93 };
94 }
95 let Pipeline { env, eng, diags } = run_pipeline(&parsed.decls);
96 let ok = !diags.iter().any(|d| d.severity == "error");
97 let outputs = if ok {
98 env.outputs
99 .borrow()
100 .iter()
101 .filter_map(|(n, _, _)| {
102 env.root(n)
103 .map(|v| (n.clone(), eng.serialize(&v, n, false)))
104 })
105 .collect()
106 } else {
107 vec![]
108 };
109 Report {
110 phase: Phase::Evaluate,
111 ok,
112 parse_errors: vec![],
113 checks,
114 diagnostics: diags,
115 outputs,
116 inputs,
117 }
118}