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