renderbox_sdk/compile/
pipeline.rs1use std::path::Path;
2
3use renderbox_dsl::{Arena, NodeId, OpNode};
4use renderbox_dsl::backend::codegen::codegen;
5use renderbox_dsl::diag::error::{Diagnostics, render_diagnostic, render_diagnostics_json};
6use renderbox_dsl::sema::module::{FileModuleResolver, load_modules};
7use renderbox_dsl::sema::op_registry::OpRegistry;
8use renderbox_dsl::sema::resolve::resolve;
9use renderbox_dsl::sema::typeck::typecheck;
10use renderbox_dsl::syntax::lexer::Lexer;
11use renderbox_dsl::syntax::parser::Parser;
12
13pub enum CompileError {
18 Dsl(Diagnostics),
19 Plan(String),
20}
21
22impl std::fmt::Debug for CompileError {
23 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
24 match self {
25 CompileError::Dsl(diags) => write!(f, "CompileError::Dsl({diags:?})"),
26 CompileError::Plan(err) => write!(f, "CompileError::Plan({err})"),
27 }
28 }
29}
30
31impl CompileError {
32 pub fn render(&self, source: &str, filename: &str) -> String {
33 match self {
34 CompileError::Dsl(diags) => {
35 let mut out = String::new();
36 for diag in diags.iter() {
37 if !out.is_empty() {
38 out.push('\n');
39 }
40 out.push_str(&render_diagnostic(source, filename, diag));
41 }
42 out
43 }
44 CompileError::Plan(err) => format!("plan error: {err}"),
45 }
46 }
47
48 pub fn render_json(&self, source: &str, filename: &str) -> String {
49 match self {
50 CompileError::Dsl(diags) => render_diagnostics_json(source, filename, diags),
51 CompileError::Plan(err) => {
52 format!(r#"{{"type":"plan","message":"{}"}}"#, err)
53 }
54 }
55 }
56}
57
58pub(crate) struct FrontendResult {
63 pub arena: Arena<OpNode>,
64 pub outputs: Vec<NodeId>,
65}
66
67pub(crate) fn run_frontend(source: &str, base_dir: &Path) -> Result<FrontendResult, CompileError> {
68 let registry = OpRegistry::builtin();
69
70 let tokens = Lexer::tokenize(source);
71 let parser = Parser::new(source, tokens, ®istry);
72 let (program, diags) = parser.parse_program();
73 check(diags)?;
74
75 let (resolve_result, diags) = resolve(&program, ®istry);
76 check(diags)?;
77
78 let resolver = FileModuleResolver::new(base_dir.to_path_buf());
79 let (module_env, diags) = load_modules(&program, ®istry, &resolver);
80 check(diags)?;
81
82 let (typeck_result, diags) = typecheck(&program, &resolve_result, ®istry, &module_env);
83 check(diags)?;
84
85 let (codegen_result, diags) = codegen(&program, &resolve_result, &typeck_result, ®istry, &module_env);
86 check(diags)?;
87
88 Ok(FrontendResult {
89 arena: codegen_result.arena,
90 outputs: codegen_result.outputs,
91 })
92}
93
94pub(crate) fn check(diags: Diagnostics) -> Result<(), CompileError> {
95 if diags.has_errors() {
96 return Err(CompileError::Dsl(diags));
97 }
98 Ok(())
99}