@devaloop/devalang 0.0.1-alpha.15 → 0.0.1-alpha.16-hotfix.0

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 (173) hide show
  1. package/.devalang +2 -0
  2. package/.github/workflows/ci.yml +92 -0
  3. package/Cargo.toml +60 -58
  4. package/README.md +1 -1
  5. package/docs/CHANGELOG.md +34 -1
  6. package/docs/CONTRIBUTING.md +101 -1
  7. package/docs/ROADMAP.md +1 -1
  8. package/docs/TODO.md +1 -1
  9. package/examples/automation.deva +1 -3
  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 +3 -5
  14. package/examples/loop.deva +5 -11
  15. package/examples/pattern.deva +8 -0
  16. package/examples/plugin.deva +12 -11
  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 -455
  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 -5
  38. package/rust/common/mod.rs +3 -3
  39. package/rust/config/driver.rs +118 -94
  40. package/rust/config/loader.rs +165 -156
  41. package/rust/config/mod.rs +4 -2
  42. package/rust/config/settings.rs +91 -0
  43. package/rust/config/stats.rs +257 -0
  44. package/rust/core/audio/engine.rs +696 -659
  45. package/rust/core/audio/evaluator.rs +263 -132
  46. package/rust/core/audio/interpreter/arrow_call.rs +198 -187
  47. package/rust/core/audio/interpreter/call.rs +98 -95
  48. package/rust/core/audio/interpreter/condition.rs +70 -71
  49. package/rust/core/audio/interpreter/driver.rs +487 -231
  50. package/rust/core/audio/interpreter/function.rs +26 -21
  51. package/rust/core/audio/interpreter/let_.rs +38 -26
  52. package/rust/core/audio/interpreter/load.rs +18 -18
  53. package/rust/core/audio/interpreter/loop_.rs +113 -106
  54. package/rust/core/audio/interpreter/mod.rs +14 -14
  55. package/rust/core/audio/interpreter/sleep.rs +27 -28
  56. package/rust/core/audio/interpreter/spawn.rs +105 -102
  57. package/rust/core/audio/interpreter/tempo.rs +19 -16
  58. package/rust/core/audio/interpreter/trigger.rs +239 -210
  59. package/rust/core/audio/loader/mod.rs +1 -1
  60. package/rust/core/audio/loader/trigger.rs +100 -94
  61. package/rust/core/audio/mod.rs +7 -7
  62. package/rust/core/audio/player.rs +64 -64
  63. package/rust/core/audio/renderer.rs +56 -53
  64. package/rust/core/audio/special/easing.rs +189 -120
  65. package/rust/core/audio/special/env.rs +43 -41
  66. package/rust/core/audio/special/math.rs +102 -92
  67. package/rust/core/audio/special/mod.rs +9 -9
  68. package/rust/core/audio/special/modulator.rs +143 -120
  69. package/rust/core/builder/mod.rs +80 -85
  70. package/rust/core/debugger/lexer.rs +27 -27
  71. package/rust/core/debugger/mod.rs +24 -23
  72. package/rust/core/debugger/module.rs +55 -47
  73. package/rust/core/debugger/preprocessor.rs +27 -27
  74. package/rust/core/debugger/store.rs +40 -39
  75. package/rust/core/error/mod.rs +80 -69
  76. package/rust/core/lexer/handler/arrow.rs +82 -82
  77. package/rust/core/lexer/handler/at.rs +21 -21
  78. package/rust/core/lexer/handler/brace.rs +41 -41
  79. package/rust/core/lexer/handler/colon.rs +21 -21
  80. package/rust/core/lexer/handler/comment.rs +30 -30
  81. package/rust/core/lexer/handler/dot.rs +21 -21
  82. package/rust/core/lexer/handler/driver.rs +337 -292
  83. package/rust/core/lexer/handler/identifier.rs +46 -43
  84. package/rust/core/lexer/handler/indent.rs +66 -66
  85. package/rust/core/lexer/handler/mod.rs +16 -16
  86. package/rust/core/lexer/handler/newline.rs +23 -23
  87. package/rust/core/lexer/handler/number.rs +31 -31
  88. package/rust/core/lexer/handler/operator.rs +46 -46
  89. package/rust/core/lexer/handler/parenthesis.rs +41 -41
  90. package/rust/core/lexer/handler/slash.rs +21 -21
  91. package/rust/core/lexer/handler/string.rs +63 -63
  92. package/rust/core/lexer/mod.rs +54 -51
  93. package/rust/core/lexer/token.rs +97 -94
  94. package/rust/core/mod.rs +11 -11
  95. package/rust/core/parser/driver.rs +513 -490
  96. package/rust/core/parser/handler/arrow_call.rs +233 -227
  97. package/rust/core/parser/handler/at.rs +245 -162
  98. package/rust/core/parser/handler/bank.rs +94 -69
  99. package/rust/core/parser/handler/condition.rs +80 -74
  100. package/rust/core/parser/handler/dot.rs +143 -135
  101. package/rust/core/parser/handler/identifier/automate.rs +257 -194
  102. package/rust/core/parser/handler/identifier/call.rs +91 -88
  103. package/rust/core/parser/handler/identifier/emit.rs +66 -0
  104. package/rust/core/parser/handler/identifier/function.rs +100 -91
  105. package/rust/core/parser/handler/identifier/group.rs +85 -75
  106. package/rust/core/parser/handler/identifier/let_.rs +158 -143
  107. package/rust/core/parser/handler/identifier/mod.rs +54 -56
  108. package/rust/core/parser/handler/identifier/on.rs +98 -0
  109. package/rust/core/parser/handler/identifier/print.rs +52 -29
  110. package/rust/core/parser/handler/identifier/sleep.rs +36 -33
  111. package/rust/core/parser/handler/identifier/spawn.rs +91 -88
  112. package/rust/core/parser/handler/identifier/synth.rs +65 -63
  113. package/rust/core/parser/handler/loop_.rs +170 -89
  114. package/rust/core/parser/handler/mod.rs +8 -8
  115. package/rust/core/parser/handler/tempo.rs +53 -47
  116. package/rust/core/parser/mod.rs +4 -4
  117. package/rust/core/parser/statement.rs +142 -113
  118. package/rust/core/plugin/loader.rs +123 -48
  119. package/rust/core/plugin/mod.rs +2 -1
  120. package/rust/core/plugin/runner.rs +296 -0
  121. package/rust/core/preprocessor/loader.rs +515 -326
  122. package/rust/core/preprocessor/mod.rs +4 -4
  123. package/rust/core/preprocessor/module.rs +60 -58
  124. package/rust/core/preprocessor/processor.rs +99 -101
  125. package/rust/core/preprocessor/resolver/bank.rs +51 -48
  126. package/rust/core/preprocessor/resolver/call.rs +100 -101
  127. package/rust/core/preprocessor/resolver/condition.rs +97 -97
  128. package/rust/core/preprocessor/resolver/driver.rs +310 -280
  129. package/rust/core/preprocessor/resolver/function.rs +69 -68
  130. package/rust/core/preprocessor/resolver/group.rs +96 -91
  131. package/rust/core/preprocessor/resolver/let_.rs +32 -28
  132. package/rust/core/preprocessor/resolver/loop_.rs +320 -121
  133. package/rust/core/preprocessor/resolver/mod.rs +15 -15
  134. package/rust/core/preprocessor/resolver/spawn.rs +76 -73
  135. package/rust/core/preprocessor/resolver/synth.rs +56 -50
  136. package/rust/core/preprocessor/resolver/tempo.rs +50 -49
  137. package/rust/core/preprocessor/resolver/trigger.rs +113 -115
  138. package/rust/core/preprocessor/resolver/value.rs +81 -81
  139. package/rust/core/shared/duration.rs +9 -9
  140. package/rust/core/shared/mod.rs +3 -3
  141. package/rust/core/shared/value.rs +35 -32
  142. package/rust/core/store/function.rs +34 -34
  143. package/rust/core/store/global.rs +55 -38
  144. package/rust/core/store/mod.rs +5 -5
  145. package/rust/core/store/variable.rs +37 -34
  146. package/rust/core/utils/mod.rs +2 -2
  147. package/rust/core/utils/path.rs +37 -31
  148. package/rust/core/utils/validation.rs +35 -36
  149. package/rust/installer/addon.rs +84 -80
  150. package/rust/installer/bank.rs +62 -65
  151. package/rust/installer/mod.rs +5 -5
  152. package/rust/installer/plugin.rs +54 -55
  153. package/rust/installer/utils.rs +56 -56
  154. package/rust/lib.rs +156 -164
  155. package/rust/main.rs +250 -144
  156. package/rust/utils/error.rs +200 -51
  157. package/rust/utils/file.rs +38 -35
  158. package/rust/utils/first_usage.rs +76 -0
  159. package/rust/utils/logger.rs +195 -143
  160. package/rust/utils/mod.rs +9 -7
  161. package/rust/utils/signature.rs +19 -17
  162. package/rust/utils/spinner.rs +22 -19
  163. package/rust/utils/telemetry.rs +292 -0
  164. package/rust/utils/watcher.rs +34 -33
  165. package/templates/minimal/README.md +97 -121
  166. package/templates/welcome/README.md +97 -121
  167. package/typescript/bin/index.ts +19 -5
  168. package/typescript/index.ts +3 -1
  169. package/typescript/scripts/postbuild.ts +10 -6
  170. package/typescript/scripts/postinstall.ts +56 -0
  171. package/typescript/scripts/version/bump.ts +0 -1
  172. package/typescript/scripts/version/index.ts +0 -1
  173. 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
+ }