1mod driver;
9
10pub use brink_driver::AnalysisOptions;
11pub use brink_ir::FileId;
12
13use brink_format::StoryData;
14use brink_ir::Diagnostic;
15use std::io;
16use std::path::Path;
17
18#[derive(Debug)]
20pub struct CompileOutput {
21 pub data: StoryData,
22 pub warnings: Vec<Diagnostic>,
23}
24
25pub struct LirOutput {
27 pub program: brink_ir::lir::Program,
28 pub warnings: Vec<Diagnostic>,
29}
30
31pub fn compile_path(path: &Path) -> Result<CompileOutput, CompileError> {
36 compile(path.to_string_lossy().as_ref(), |p| {
37 std::fs::read_to_string(p).map_err(|e| io::Error::new(e.kind(), format!("{p}: {e}")))
38 })
39}
40
41pub fn compile<F>(entry: &str, read_file: F) -> Result<CompileOutput, CompileError>
47where
48 F: FnMut(&str) -> Result<String, io::Error>,
49{
50 driver::compile(entry, read_file)
51}
52
53pub fn compile_with_options<F>(
58 entry: &str,
59 read_file: F,
60 options: AnalysisOptions,
61) -> Result<CompileOutput, CompileError>
62where
63 F: FnMut(&str) -> Result<String, io::Error>,
64{
65 driver::compile_with_options(entry, read_file, options)
66}
67
68pub fn compile_to_json<F>(entry: &str, read_file: F) -> Result<brink_json::InkJson, CompileError>
72where
73 F: FnMut(&str) -> Result<String, io::Error>,
74{
75 let lir_output = driver::compile_to_lir(entry, read_file)?;
76 Ok(brink_codegen_json::emit(&lir_output.program))
77}
78
79pub fn compile_string_to_json(source: &str) -> Result<brink_json::InkJson, CompileError> {
81 compile_to_json("<string>", |_| Ok(source.to_string()))
82}
83
84#[derive(Debug, thiserror::Error)]
86pub enum CompileError {
87 #[error("I/O error: {0}")]
89 Io(#[from] io::Error),
90 #[error("{} diagnostic(s) prevented compilation", .0.len())]
92 Diagnostics(Vec<Diagnostic>),
93 #[error("circular INCLUDE dependency: {0}")]
95 CircularInclude(String),
96}
97
98impl From<brink_driver::DiscoverError> for CompileError {
99 fn from(err: brink_driver::DiscoverError) -> Self {
100 match err {
101 brink_driver::DiscoverError::Io(e) => Self::Io(e),
102 brink_driver::DiscoverError::CircularInclude(msg) => Self::CircularInclude(msg),
103 }
104 }
105}