@devaloop/devalang 0.0.1-alpha.14 → 0.0.1-alpha.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) hide show
  1. package/.devalang +10 -8
  2. package/.github/workflows/ci.yml +92 -0
  3. package/Cargo.toml +60 -58
  4. package/README.md +32 -15
  5. package/docs/CHANGELOG.md +93 -1
  6. package/docs/CONTRIBUTING.md +101 -1
  7. package/docs/ROADMAP.md +2 -2
  8. package/docs/TODO.md +1 -1
  9. package/examples/automation.deva +42 -0
  10. package/examples/bank.deva +4 -4
  11. package/examples/events.deva +12 -0
  12. package/examples/function.deva +4 -4
  13. package/examples/index.deva +39 -25
  14. package/examples/loop.deva +5 -11
  15. package/examples/pattern.deva +8 -0
  16. package/examples/plugin.deva +16 -0
  17. package/examples/variables.deva +1 -1
  18. package/out-tsc/bin/index.js +51 -7
  19. package/out-tsc/index.js +3 -1
  20. package/out-tsc/scripts/postbuild.js +9 -10
  21. package/out-tsc/scripts/postinstall.js +49 -0
  22. package/package.json +12 -4
  23. package/project-version.json +3 -3
  24. package/rust/cli/bank.rs +462 -456
  25. package/rust/cli/build.rs +252 -199
  26. package/rust/cli/check.rs +221 -180
  27. package/rust/cli/driver.rs +297 -292
  28. package/rust/cli/generator.rs +1 -0
  29. package/rust/cli/init.rs +87 -79
  30. package/rust/cli/install.rs +35 -32
  31. package/rust/cli/login.rs +127 -134
  32. package/rust/cli/mod.rs +13 -11
  33. package/rust/cli/play.rs +1123 -218
  34. package/rust/cli/telemetry.rs +19 -0
  35. package/rust/cli/template.rs +69 -57
  36. package/rust/cli/update.rs +6 -4
  37. package/rust/common/api.rs +5 -8
  38. package/rust/common/cdn.rs +3 -6
  39. package/rust/common/mod.rs +3 -3
  40. package/rust/common/sso.rs +3 -6
  41. package/rust/config/driver.rs +118 -94
  42. package/rust/config/loader.rs +165 -156
  43. package/rust/config/mod.rs +4 -2
  44. package/rust/config/settings.rs +91 -0
  45. package/rust/config/stats.rs +257 -0
  46. package/rust/core/audio/engine.rs +696 -518
  47. package/rust/core/audio/evaluator.rs +263 -31
  48. package/rust/core/audio/interpreter/arrow_call.rs +198 -161
  49. package/rust/core/audio/interpreter/automate.rs +18 -0
  50. package/rust/core/audio/interpreter/call.rs +98 -95
  51. package/rust/core/audio/interpreter/condition.rs +70 -71
  52. package/rust/core/audio/interpreter/driver.rs +487 -198
  53. package/rust/core/audio/interpreter/function.rs +26 -21
  54. package/rust/core/audio/interpreter/let_.rs +38 -19
  55. package/rust/core/audio/interpreter/load.rs +18 -18
  56. package/rust/core/audio/interpreter/loop_.rs +113 -73
  57. package/rust/core/audio/interpreter/mod.rs +14 -13
  58. package/rust/core/audio/interpreter/sleep.rs +27 -30
  59. package/rust/core/audio/interpreter/spawn.rs +105 -102
  60. package/rust/core/audio/interpreter/tempo.rs +19 -16
  61. package/rust/core/audio/interpreter/trigger.rs +239 -210
  62. package/rust/core/audio/loader/mod.rs +1 -1
  63. package/rust/core/audio/loader/trigger.rs +100 -97
  64. package/rust/core/audio/mod.rs +7 -6
  65. package/rust/core/audio/player.rs +64 -64
  66. package/rust/core/audio/renderer.rs +56 -53
  67. package/rust/core/audio/special/easing.rs +189 -0
  68. package/rust/core/audio/special/env.rs +43 -0
  69. package/rust/core/audio/special/math.rs +102 -0
  70. package/rust/core/audio/special/mod.rs +9 -0
  71. package/rust/core/audio/special/modulator.rs +143 -0
  72. package/rust/core/builder/mod.rs +80 -85
  73. package/rust/core/debugger/lexer.rs +27 -27
  74. package/rust/core/debugger/mod.rs +24 -23
  75. package/rust/core/debugger/module.rs +55 -47
  76. package/rust/core/debugger/preprocessor.rs +27 -27
  77. package/rust/core/debugger/store.rs +40 -39
  78. package/rust/core/error/mod.rs +80 -66
  79. package/rust/core/lexer/handler/arrow.rs +82 -31
  80. package/rust/core/lexer/handler/at.rs +21 -21
  81. package/rust/core/lexer/handler/brace.rs +41 -41
  82. package/rust/core/lexer/handler/colon.rs +21 -21
  83. package/rust/core/lexer/handler/comment.rs +30 -30
  84. package/rust/core/lexer/handler/dot.rs +21 -21
  85. package/rust/core/lexer/handler/driver.rs +337 -263
  86. package/rust/core/lexer/handler/identifier.rs +46 -42
  87. package/rust/core/lexer/handler/indent.rs +66 -66
  88. package/rust/core/lexer/handler/mod.rs +16 -16
  89. package/rust/core/lexer/handler/newline.rs +23 -23
  90. package/rust/core/lexer/handler/number.rs +31 -31
  91. package/rust/core/lexer/handler/operator.rs +46 -44
  92. package/rust/core/lexer/handler/parenthesis.rs +41 -41
  93. package/rust/core/lexer/handler/slash.rs +21 -21
  94. package/rust/core/lexer/handler/string.rs +63 -63
  95. package/rust/core/lexer/mod.rs +54 -51
  96. package/rust/core/lexer/token.rs +97 -91
  97. package/rust/core/mod.rs +11 -11
  98. package/rust/core/parser/driver.rs +513 -408
  99. package/rust/core/parser/handler/arrow_call.rs +233 -211
  100. package/rust/core/parser/handler/at.rs +245 -162
  101. package/rust/core/parser/handler/bank.rs +94 -69
  102. package/rust/core/parser/handler/condition.rs +80 -74
  103. package/rust/core/parser/handler/dot.rs +143 -135
  104. package/rust/core/parser/handler/identifier/automate.rs +257 -0
  105. package/rust/core/parser/handler/identifier/call.rs +91 -88
  106. package/rust/core/parser/handler/identifier/emit.rs +66 -0
  107. package/rust/core/parser/handler/identifier/function.rs +100 -92
  108. package/rust/core/parser/handler/identifier/group.rs +85 -75
  109. package/rust/core/parser/handler/identifier/let_.rs +158 -127
  110. package/rust/core/parser/handler/identifier/mod.rs +54 -52
  111. package/rust/core/parser/handler/identifier/on.rs +98 -0
  112. package/rust/core/parser/handler/identifier/print.rs +52 -0
  113. package/rust/core/parser/handler/identifier/sleep.rs +36 -33
  114. package/rust/core/parser/handler/identifier/spawn.rs +91 -88
  115. package/rust/core/parser/handler/identifier/synth.rs +65 -65
  116. package/rust/core/parser/handler/loop_.rs +170 -72
  117. package/rust/core/parser/handler/mod.rs +8 -8
  118. package/rust/core/parser/handler/tempo.rs +53 -47
  119. package/rust/core/parser/mod.rs +4 -4
  120. package/rust/core/parser/statement.rs +142 -108
  121. package/rust/core/plugin/loader.rs +123 -48
  122. package/rust/core/plugin/mod.rs +2 -1
  123. package/rust/core/plugin/runner.rs +296 -0
  124. package/rust/core/preprocessor/loader.rs +515 -326
  125. package/rust/core/preprocessor/mod.rs +4 -4
  126. package/rust/core/preprocessor/module.rs +60 -58
  127. package/rust/core/preprocessor/processor.rs +99 -101
  128. package/rust/core/preprocessor/resolver/bank.rs +51 -49
  129. package/rust/core/preprocessor/resolver/call.rs +100 -100
  130. package/rust/core/preprocessor/resolver/condition.rs +97 -97
  131. package/rust/core/preprocessor/resolver/driver.rs +310 -278
  132. package/rust/core/preprocessor/resolver/function.rs +69 -78
  133. package/rust/core/preprocessor/resolver/group.rs +96 -91
  134. package/rust/core/preprocessor/resolver/let_.rs +32 -28
  135. package/rust/core/preprocessor/resolver/loop_.rs +320 -91
  136. package/rust/core/preprocessor/resolver/mod.rs +15 -15
  137. package/rust/core/preprocessor/resolver/spawn.rs +76 -92
  138. package/rust/core/preprocessor/resolver/synth.rs +56 -50
  139. package/rust/core/preprocessor/resolver/tempo.rs +50 -49
  140. package/rust/core/preprocessor/resolver/trigger.rs +113 -116
  141. package/rust/core/preprocessor/resolver/value.rs +81 -87
  142. package/rust/core/shared/bank.rs +1 -1
  143. package/rust/core/shared/duration.rs +9 -9
  144. package/rust/core/shared/mod.rs +3 -3
  145. package/rust/core/shared/value.rs +35 -32
  146. package/rust/core/store/function.rs +34 -34
  147. package/rust/core/store/global.rs +55 -38
  148. package/rust/core/store/mod.rs +5 -5
  149. package/rust/core/store/variable.rs +37 -34
  150. package/rust/core/utils/mod.rs +2 -2
  151. package/rust/core/utils/path.rs +37 -31
  152. package/rust/core/utils/validation.rs +35 -37
  153. package/rust/installer/addon.rs +84 -80
  154. package/rust/installer/bank.rs +62 -65
  155. package/rust/installer/mod.rs +5 -5
  156. package/rust/installer/plugin.rs +54 -55
  157. package/rust/installer/utils.rs +56 -56
  158. package/rust/lib.rs +156 -164
  159. package/rust/main.rs +250 -145
  160. package/rust/utils/error.rs +200 -0
  161. package/rust/utils/file.rs +38 -35
  162. package/rust/utils/first_usage.rs +76 -0
  163. package/rust/utils/logger.rs +195 -139
  164. package/rust/utils/mod.rs +9 -50
  165. package/rust/utils/signature.rs +19 -17
  166. package/rust/utils/spinner.rs +22 -19
  167. package/rust/utils/telemetry.rs +292 -0
  168. package/rust/utils/watcher.rs +34 -33
  169. package/templates/minimal/README.md +97 -121
  170. package/templates/welcome/README.md +97 -121
  171. package/typescript/bin/index.ts +19 -5
  172. package/typescript/index.ts +3 -1
  173. package/typescript/scripts/postbuild.ts +10 -6
  174. package/typescript/scripts/postinstall.ts +56 -0
  175. package/typescript/scripts/version/bump.ts +0 -1
  176. package/typescript/scripts/version/index.ts +0 -1
  177. package/out-tsc/bin/devalang.exe +0 -0
package/rust/cli/build.rs CHANGED
@@ -1,199 +1,252 @@
1
- use crate::{
2
- config::driver::Config,
3
- core::{
4
- builder::Builder,
5
- debugger::{
6
- lexer::write_lexer_log_file,
7
- module::{ write_module_function_log_file, write_module_variable_log_file },
8
- preprocessor::write_preprocessor_log_file,
9
- store::{ write_function_log_file, write_variables_log_file },
10
- },
11
- preprocessor::loader::ModuleLoader,
12
- store::global::GlobalStore,
13
- utils::path::{ find_entry_file, normalize_path },
14
- },
15
- utils::{ logger::{ LogLevel, Logger }, spinner::with_spinner, watcher::watch_directory },
16
- };
17
- use std::{ thread, time::Duration };
18
-
19
- #[cfg(feature = "cli")]
20
- pub fn handle_build_command(
21
- config: Option<Config>,
22
- entry: Option<String>,
23
- output: Option<String>,
24
- watch: bool,
25
- debug: bool,
26
- compress: bool
27
- ) {
28
- let fetched_entry = if entry.is_none() {
29
- config
30
- .as_ref()
31
- .and_then(|c| c.defaults.entry.clone())
32
- .unwrap_or_else(|| "".to_string())
33
- } else {
34
- entry.clone().unwrap_or_else(|| "".to_string())
35
- };
36
-
37
- let fetched_output = if output.is_none() {
38
- config
39
- .as_ref()
40
- .and_then(|c| c.defaults.output.clone())
41
- .unwrap_or_else(|| "".to_string())
42
- } else {
43
- output.clone().unwrap_or_else(|| "".to_string())
44
- };
45
-
46
- let fetched_watch = if watch {
47
- watch
48
- } else {
49
- config
50
- .as_ref()
51
- .and_then(|c| c.defaults.watch)
52
- .unwrap_or(false)
53
- };
54
-
55
- let logger = Logger::new();
56
-
57
- if fetched_entry.is_empty() {
58
- logger.log_message(
59
- LogLevel::Error,
60
- "Entry path is not specified. Please provide a valid entry path."
61
- );
62
- std::process::exit(1);
63
- }
64
- if fetched_output.is_empty() {
65
- logger.log_message(
66
- LogLevel::Error,
67
- "Output directory is not specified. Please provide a valid output directory."
68
- );
69
- std::process::exit(1);
70
- }
71
-
72
- let entry_file = find_entry_file(&fetched_entry).unwrap_or_else(|| {
73
- logger.log_message(
74
- LogLevel::Error,
75
- &format!("❌ index.deva not found in directory: {}", fetched_entry)
76
- );
77
- std::process::exit(1);
78
- });
79
-
80
- // SECTION Begin build
81
- if fetched_watch {
82
- begin_build(entry_file.clone(), fetched_output.clone(), debug, compress);
83
-
84
- logger.log_message(
85
- LogLevel::Watcher,
86
- &format!("Watching for changes in '{}'...", fetched_entry)
87
- );
88
-
89
- watch_directory(entry_file.clone(), move || {
90
- logger.log_message(LogLevel::Watcher, "Detected changes, re-building...");
91
-
92
- begin_build(entry_file.clone(), fetched_output.clone(), debug, compress);
93
- }).unwrap();
94
- } else {
95
- begin_build(entry_file.clone(), fetched_output.clone(), debug, compress);
96
- }
97
- }
98
-
99
- fn begin_build(entry: String, output: String, debug: bool, compress: bool) {
100
- let spinner = with_spinner("Building...", || {
101
- thread::sleep(Duration::from_millis(800));
102
- });
103
-
104
- let duration = std::time::Instant::now();
105
-
106
- let normalized_entry_file = normalize_path(&entry);
107
- let normalized_output_dir = normalize_path(&output);
108
-
109
- let mut global_store = GlobalStore::new();
110
- let module_loader = ModuleLoader::new(&normalized_entry_file, &normalized_output_dir);
111
-
112
- // SECTION Load
113
- // NOTE: We use modules in the build command, so we need to load them
114
- let (modules_tokens, modules_statements) = module_loader.load_all_modules(&mut global_store);
115
-
116
- // SECTION Write logs
117
- if debug {
118
- for (module_path, module) in global_store.modules.clone() {
119
- write_module_variable_log_file(
120
- &normalized_output_dir,
121
- &module_path,
122
- &module.variable_table
123
- );
124
- write_module_function_log_file(
125
- &normalized_output_dir,
126
- &module_path,
127
- &module.function_table
128
- );
129
- }
130
-
131
- write_lexer_log_file(&normalized_output_dir, "lexer_tokens.log", modules_tokens.clone());
132
- write_preprocessor_log_file(
133
- &normalized_output_dir,
134
- "resolved_statements.log",
135
- modules_statements.clone()
136
- );
137
- write_variables_log_file(
138
- &normalized_output_dir,
139
- "global_variables.log",
140
- global_store.variables.clone()
141
- );
142
- write_function_log_file(
143
- &normalized_output_dir,
144
- "global_functions.log",
145
- global_store.functions.clone()
146
- );
147
- }
148
-
149
- // SECTION Building AST and Audio
150
- let builder = Builder::new();
151
- builder.build_ast(&modules_statements, &normalized_output_dir, compress);
152
- builder.build_audio(&modules_statements, &normalized_output_dir, &mut global_store);
153
-
154
- // SECTION Logging
155
- let logger = Logger::new();
156
-
157
- if debug {
158
- let modules_loaded = global_store.modules
159
- .iter()
160
- .map(|(k, _)| k)
161
- .collect::<Vec<_>>();
162
- let global_variables_loaded = global_store.variables.variables.keys().collect::<Vec<_>>();
163
- let global_functions_loaded = global_store.functions.functions.keys().collect::<Vec<_>>();
164
-
165
- logger.log_message_with_trace(
166
- LogLevel::Debug,
167
- &format!("Modules loaded: {}", global_store.modules.len()),
168
- modules_loaded
169
- .iter()
170
- .map(|s| s.as_str())
171
- .collect()
172
- );
173
- logger.log_message_with_trace(
174
- LogLevel::Debug,
175
- &format!("Global variables: {}", global_store.variables.variables.len()),
176
- global_variables_loaded
177
- .iter()
178
- .map(|s| s.as_str())
179
- .collect()
180
- );
181
- logger.log_message_with_trace(
182
- LogLevel::Debug,
183
- &format!("Global functions: {}", global_store.functions.functions.len()),
184
- global_functions_loaded
185
- .iter()
186
- .map(|s| s.as_str())
187
- .collect()
188
- );
189
- }
190
-
191
- let success_message = format!(
192
- "Build completed successfully in {:.2?}. Output files written to: '{}'",
193
- duration.elapsed(),
194
- normalized_output_dir
195
- );
196
-
197
- spinner.finish_and_clear();
198
- logger.log_message(LogLevel::Success, &success_message);
199
- }
1
+ use crate::{
2
+ config::driver::ProjectConfig,
3
+ core::{
4
+ builder::Builder,
5
+ debugger::{
6
+ lexer::write_lexer_log_file,
7
+ module::{write_module_function_log_file, write_module_variable_log_file},
8
+ preprocessor::write_preprocessor_log_file,
9
+ store::{write_function_log_file, write_variables_log_file},
10
+ },
11
+ preprocessor::loader::ModuleLoader,
12
+ store::global::GlobalStore,
13
+ utils::path::{find_entry_file, normalize_path},
14
+ },
15
+ utils::{
16
+ logger::{LogLevel, Logger},
17
+ spinner::with_spinner,
18
+ watcher::watch_directory,
19
+ },
20
+ };
21
+ use std::{thread, time::Duration};
22
+
23
+ #[cfg(feature = "cli")]
24
+ pub fn handle_build_command(
25
+ config: Option<ProjectConfig>,
26
+ entry: Option<String>,
27
+ output: Option<String>,
28
+ watch: bool,
29
+ debug: bool,
30
+ compress: bool,
31
+ ) -> Result<(), String> {
32
+ let fetched_entry = if entry.is_none() {
33
+ config
34
+ .as_ref()
35
+ .and_then(|c| c.defaults.entry.clone())
36
+ .unwrap_or_else(|| "".to_string())
37
+ } else {
38
+ entry.clone().unwrap_or_else(|| "".to_string())
39
+ };
40
+
41
+ let fetched_output = if output.is_none() {
42
+ config
43
+ .as_ref()
44
+ .and_then(|c| c.defaults.output.clone())
45
+ .unwrap_or_else(|| "".to_string())
46
+ } else {
47
+ output.clone().unwrap_or_else(|| "".to_string())
48
+ };
49
+
50
+ let fetched_watch = if watch {
51
+ watch
52
+ } else {
53
+ config
54
+ .as_ref()
55
+ .and_then(|c| c.defaults.watch)
56
+ .unwrap_or(false)
57
+ };
58
+
59
+ let logger = Logger::new();
60
+
61
+ if fetched_entry.is_empty() {
62
+ logger.log_message(
63
+ LogLevel::Error,
64
+ "Entry path is not specified. Please provide a valid entry path.",
65
+ );
66
+ return Err("missing entry path".to_string());
67
+ }
68
+ if fetched_output.is_empty() {
69
+ logger.log_message(
70
+ LogLevel::Error,
71
+ "Output directory is not specified. Please provide a valid output directory.",
72
+ );
73
+ return Err("missing output directory".to_string());
74
+ }
75
+
76
+ let entry_file = match find_entry_file(&fetched_entry) {
77
+ Some(p) => p,
78
+ None => {
79
+ logger.log_message(
80
+ LogLevel::Error,
81
+ &format!("❌ index.deva not found in directory: {}", fetched_entry),
82
+ );
83
+ return Err("index.deva not found".to_string());
84
+ }
85
+ };
86
+
87
+ // SECTION Begin build
88
+ if fetched_watch {
89
+ let _ = begin_build(entry_file.clone(), fetched_output.clone(), debug, compress);
90
+
91
+ logger.log_message(
92
+ LogLevel::Watcher,
93
+ &format!("Watching for changes in '{}'...", fetched_entry),
94
+ );
95
+
96
+ watch_directory(entry_file.clone(), move || {
97
+ logger.log_message(LogLevel::Watcher, "Detected changes, re-building...");
98
+
99
+ let _ = begin_build(entry_file.clone(), fetched_output.clone(), debug, compress);
100
+ })
101
+ .unwrap();
102
+ } else {
103
+ let stats_input = begin_build(entry_file.clone(), fetched_output.clone(), debug, compress)?;
104
+ let stats = crate::config::stats::compute_from(
105
+ &stats_input.statements_by_module,
106
+ &stats_input.global_store,
107
+ &config,
108
+ Some(&fetched_output),
109
+ );
110
+ crate::config::stats::set_memory_stats(stats.clone());
111
+ if let Err(e) = crate::config::stats::save_to_file(&stats) {
112
+ eprintln!("[stats] failed to save: {}", e);
113
+ }
114
+ }
115
+ Ok(())
116
+ }
117
+
118
+ struct BuildStatsInput {
119
+ pub statements_by_module:
120
+ std::collections::HashMap<String, Vec<crate::core::parser::statement::Statement>>,
121
+ pub global_store: crate::core::store::global::GlobalStore,
122
+ }
123
+
124
+ fn begin_build(
125
+ entry: String,
126
+ output: String,
127
+ debug: bool,
128
+ compress: bool,
129
+ ) -> Result<BuildStatsInput, String> {
130
+ let spinner = with_spinner("Building...", || {
131
+ thread::sleep(Duration::from_millis(800));
132
+ });
133
+
134
+ let duration = std::time::Instant::now();
135
+
136
+ let normalized_entry_file = normalize_path(&entry);
137
+ let normalized_output_dir = normalize_path(&output);
138
+
139
+ let mut global_store = GlobalStore::new();
140
+ let module_loader = ModuleLoader::new(&normalized_entry_file, &normalized_output_dir);
141
+
142
+ // SECTION Load
143
+ // NOTE: We use modules in the build command, so we need to load them
144
+ let (modules_tokens, modules_statements) = module_loader.load_all_modules(&mut global_store);
145
+
146
+ // SECTION Write logs
147
+ if debug {
148
+ for (module_path, module) in global_store.modules.clone() {
149
+ write_module_variable_log_file(
150
+ &normalized_output_dir,
151
+ &module_path,
152
+ &module.variable_table,
153
+ );
154
+ write_module_function_log_file(
155
+ &normalized_output_dir,
156
+ &module_path,
157
+ &module.function_table,
158
+ );
159
+ }
160
+
161
+ write_lexer_log_file(
162
+ &normalized_output_dir,
163
+ "lexer_tokens.log",
164
+ modules_tokens.clone(),
165
+ );
166
+ write_preprocessor_log_file(
167
+ &normalized_output_dir,
168
+ "resolved_statements.log",
169
+ modules_statements.clone(),
170
+ );
171
+ write_variables_log_file(
172
+ &normalized_output_dir,
173
+ "global_variables.log",
174
+ global_store.variables.clone(),
175
+ );
176
+ write_function_log_file(
177
+ &normalized_output_dir,
178
+ "global_functions.log",
179
+ global_store.functions.clone(),
180
+ );
181
+ }
182
+
183
+ // SECTION Detect build-time errors prior to building
184
+ let all_errors = crate::utils::error::collect_all_errors_with_modules(&modules_statements);
185
+ let (warnings, criticals) = crate::utils::error::partition_errors(all_errors);
186
+ crate::utils::error::log_errors_with_stack("Build", &warnings, &criticals);
187
+ if !criticals.is_empty() {
188
+ spinner.finish_and_clear();
189
+ return Err(format!(
190
+ "build failed with {} critical error(s): {}",
191
+ criticals.len(),
192
+ criticals[0].message
193
+ ));
194
+ }
195
+
196
+ // SECTION Building AST and Audio
197
+ let builder = Builder::new();
198
+ builder.build_ast(&modules_statements, &normalized_output_dir, compress);
199
+ builder.build_audio(
200
+ &modules_statements,
201
+ &normalized_output_dir,
202
+ &mut global_store,
203
+ );
204
+
205
+ // SECTION Logging
206
+ let logger = Logger::new();
207
+
208
+ if debug {
209
+ let modules_loaded = global_store
210
+ .modules
211
+ .iter()
212
+ .map(|(k, _)| k)
213
+ .collect::<Vec<_>>();
214
+ let global_variables_loaded = global_store.variables.variables.keys().collect::<Vec<_>>();
215
+ let global_functions_loaded = global_store.functions.functions.keys().collect::<Vec<_>>();
216
+
217
+ logger.log_message_with_trace(
218
+ LogLevel::Debug,
219
+ &format!("Modules loaded: {}", global_store.modules.len()),
220
+ modules_loaded.iter().map(|s| s.as_str()).collect(),
221
+ );
222
+ logger.log_message_with_trace(
223
+ LogLevel::Debug,
224
+ &format!(
225
+ "Global variables: {}",
226
+ global_store.variables.variables.len()
227
+ ),
228
+ global_variables_loaded.iter().map(|s| s.as_str()).collect(),
229
+ );
230
+ logger.log_message_with_trace(
231
+ LogLevel::Debug,
232
+ &format!(
233
+ "Global functions: {}",
234
+ global_store.functions.functions.len()
235
+ ),
236
+ global_functions_loaded.iter().map(|s| s.as_str()).collect(),
237
+ );
238
+ }
239
+
240
+ let success_message = format!(
241
+ "Build completed successfully in {:.2?}. Output files written to: '{}'",
242
+ duration.elapsed(),
243
+ normalized_output_dir
244
+ );
245
+
246
+ spinner.finish_and_clear();
247
+ logger.log_message(LogLevel::Success, &success_message);
248
+ Ok(BuildStatsInput {
249
+ statements_by_module: modules_statements,
250
+ global_store,
251
+ })
252
+ }