1pub mod validate;
2
3use flutmax_codegen::{
4 build_graph, build_graph_with_objdb, generate, generate_with_options, generate_with_ui,
5 BuildError, CodeFiles, CodegenError, GenerateOptions, UiData,
6};
7use flutmax_objdb::ObjectDb;
8use flutmax_parser::parse;
9use flutmax_sema::registry::AbstractionRegistry;
10use flutmax_sema::type_check::{type_check, type_check_with_registry, TypeError};
11
12#[derive(Debug)]
14pub enum CompileError {
15 Parse(flutmax_parser::ParseError),
16 Type(Vec<TypeError>),
17 BuildGraph(BuildError),
18 Codegen(CodegenError),
19}
20
21impl std::fmt::Display for CompileError {
22 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
23 match self {
24 CompileError::Parse(e) => write!(f, "parse error: {}", e),
25 CompileError::Type(errors) => {
26 let msg = errors
27 .iter()
28 .map(|e| format!("{}", e))
29 .collect::<Vec<_>>()
30 .join("\n");
31 write!(f, "{}", msg)
32 }
33 CompileError::BuildGraph(e) => write!(f, "graph build error: {}", e),
34 CompileError::Codegen(e) => write!(f, "codegen error: {}", e),
35 }
36 }
37}
38
39impl std::error::Error for CompileError {}
40
41impl From<flutmax_parser::ParseError> for CompileError {
42 fn from(e: flutmax_parser::ParseError) -> Self {
43 CompileError::Parse(e)
44 }
45}
46
47impl From<BuildError> for CompileError {
48 fn from(e: BuildError) -> Self {
49 CompileError::BuildGraph(e)
50 }
51}
52
53impl From<CodegenError> for CompileError {
54 fn from(e: CodegenError) -> Self {
55 CompileError::Codegen(e)
56 }
57}
58
59pub fn compile(source: &str) -> Result<String, Box<dyn std::error::Error>> {
61 let ast = parse(source)?;
62 let type_errors = type_check(&ast);
63 if !type_errors.is_empty() {
64 let msg = type_errors
65 .iter()
66 .map(|e| format!("{}", e))
67 .collect::<Vec<_>>()
68 .join("\n");
69 return Err(msg.into());
70 }
71 let graph = build_graph(&ast)?;
72 let json = generate(&graph)?;
73 Ok(json)
74}
75
76pub fn compile_with_registry(
81 source: &str,
82 registry: Option<&AbstractionRegistry>,
83) -> Result<String, Box<dyn std::error::Error>> {
84 compile_with_registry_and_code_files(source, registry, None)
85}
86
87pub fn compile_with_registry_and_code_files(
89 source: &str,
90 registry: Option<&AbstractionRegistry>,
91 code_files: Option<&CodeFiles>,
92) -> Result<String, Box<dyn std::error::Error>> {
93 compile_full(source, registry, code_files, None)
94}
95
96pub fn compile_full(
98 source: &str,
99 registry: Option<&AbstractionRegistry>,
100 code_files: Option<&CodeFiles>,
101 objdb: Option<&ObjectDb>,
102) -> Result<String, Box<dyn std::error::Error>> {
103 let ast = parse(source)?;
104 let type_errors = type_check_with_registry(&ast, registry);
105 if !type_errors.is_empty() {
106 let msg = type_errors
107 .iter()
108 .map(|e| format!("{}", e))
109 .collect::<Vec<_>>()
110 .join("\n");
111 return Err(msg.into());
112 }
113 let graph = build_graph_with_objdb(&ast, registry, code_files, objdb)?;
114 let json = generate(&graph)?;
115 Ok(json)
116}
117
118pub fn compile_rnbo(source: &str) -> Result<String, Box<dyn std::error::Error>> {
120 let ast = parse(source)?;
121 let type_errors = type_check(&ast);
122 if !type_errors.is_empty() {
123 let msg = type_errors
124 .iter()
125 .map(|e| format!("{}", e))
126 .collect::<Vec<_>>()
127 .join("\n");
128 return Err(msg.into());
129 }
130 let graph = build_graph(&ast)?;
131 let opts = GenerateOptions {
132 classnamespace: "rnbo".to_string(),
133 };
134 let json = generate_with_options(&graph, &opts)?;
135 Ok(json)
136}
137
138pub fn compile_full_with_ui(
140 source: &str,
141 registry: Option<&AbstractionRegistry>,
142 code_files: Option<&CodeFiles>,
143 objdb: Option<&ObjectDb>,
144 ui_data: Option<&UiData>,
145) -> Result<String, Box<dyn std::error::Error>> {
146 let ast = parse(source)?;
147 let type_errors = type_check_with_registry(&ast, registry);
148 if !type_errors.is_empty() {
149 let msg = type_errors
150 .iter()
151 .map(|e| format!("{}", e))
152 .collect::<Vec<_>>()
153 .join("\n");
154 return Err(msg.into());
155 }
156 let graph = build_graph_with_objdb(&ast, registry, code_files, objdb)?;
157 let json = generate_with_ui(&graph, &GenerateOptions::default(), ui_data)?;
158 Ok(json)
159}
160
161pub fn compile_gen(source: &str) -> Result<String, Box<dyn std::error::Error>> {
167 let ast = parse(source)?;
168 let type_errors: Vec<_> = type_check(&ast)
169 .into_iter()
170 .filter(|e| e.code != "E001" && e.code != "E005")
171 .collect();
172 if !type_errors.is_empty() {
173 let msg = type_errors
174 .iter()
175 .map(|e| format!("{}", e))
176 .collect::<Vec<_>>()
177 .join("\n");
178 return Err(msg.into());
179 }
180 let graph = build_graph(&ast)?;
181 let opts = GenerateOptions {
182 classnamespace: "dsp.gen".to_string(),
183 };
184 let json = generate_with_options(&graph, &opts)?;
185 Ok(json)
186}