@devaloop/devalang 0.0.1-alpha.7 → 0.0.1-alpha.8

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 (61) hide show
  1. package/Cargo.toml +1 -1
  2. package/README.md +29 -10
  3. package/docs/CHANGELOG.md +22 -2
  4. package/docs/ROADMAP.md +2 -2
  5. package/docs/SYNTAX.md +41 -7
  6. package/docs/TODO.md +3 -3
  7. package/examples/condition.deva +24 -0
  8. package/examples/index.deva +4 -5
  9. package/examples/variables.deva +1 -1
  10. package/out-tsc/bin/devalang.exe +0 -0
  11. package/package.json +1 -1
  12. package/project-version.json +3 -3
  13. package/rust/cli/build.rs +6 -1
  14. package/rust/core/audio/evaluator.rs +31 -0
  15. package/rust/core/audio/interpreter/call.rs +42 -0
  16. package/rust/core/audio/interpreter/condition.rs +65 -0
  17. package/rust/core/audio/interpreter/driver.rs +204 -0
  18. package/rust/core/audio/interpreter/let_.rs +19 -0
  19. package/rust/core/audio/interpreter/load.rs +18 -0
  20. package/rust/core/audio/interpreter/loop_.rs +59 -0
  21. package/rust/core/audio/interpreter/mod.rs +11 -0
  22. package/rust/core/audio/interpreter/sleep.rs +36 -0
  23. package/rust/core/audio/interpreter/spawn.rs +65 -0
  24. package/rust/core/audio/interpreter/tempo.rs +16 -0
  25. package/rust/core/audio/interpreter/trigger.rs +69 -0
  26. package/rust/core/audio/loader/mod.rs +1 -0
  27. package/rust/core/audio/{loader.rs → loader/trigger.rs} +3 -1
  28. package/rust/core/audio/mod.rs +2 -1
  29. package/rust/core/audio/{render.rs → renderer.rs} +6 -2
  30. package/rust/core/builder/mod.rs +1 -1
  31. package/rust/core/debugger/lexer.rs +1 -1
  32. package/rust/core/debugger/mod.rs +1 -0
  33. package/rust/core/debugger/store.rs +25 -0
  34. package/rust/core/error/mod.rs +1 -1
  35. package/rust/core/lexer/handler/driver.rs +215 -0
  36. package/rust/core/lexer/handler/identifier.rs +2 -0
  37. package/rust/core/lexer/handler/mod.rs +3 -227
  38. package/rust/core/lexer/handler/operator.rs +44 -0
  39. package/rust/core/lexer/mod.rs +1 -1
  40. package/rust/core/lexer/token.rs +36 -9
  41. package/rust/core/parser/driver.rs +312 -0
  42. package/rust/core/parser/handler/at.rs +3 -7
  43. package/rust/core/parser/handler/bank.rs +5 -2
  44. package/rust/core/parser/handler/condition.rs +74 -0
  45. package/rust/core/parser/handler/dot.rs +1 -1
  46. package/rust/core/parser/handler/identifier.rs +38 -36
  47. package/rust/core/parser/handler/loop_.rs +1 -1
  48. package/rust/core/parser/handler/mod.rs +2 -1
  49. package/rust/core/parser/handler/tempo.rs +1 -1
  50. package/rust/core/parser/mod.rs +3 -237
  51. package/rust/core/parser/statement.rs +29 -36
  52. package/rust/core/preprocessor/loader.rs +7 -6
  53. package/rust/core/preprocessor/processor.rs +1 -1
  54. package/rust/core/preprocessor/resolver/call.rs +53 -0
  55. package/rust/core/preprocessor/resolver/condition.rs +66 -0
  56. package/rust/core/preprocessor/resolver/driver.rs +182 -0
  57. package/rust/core/preprocessor/resolver/group.rs +89 -84
  58. package/rust/core/preprocessor/resolver/mod.rs +5 -153
  59. package/rust/core/preprocessor/resolver/spawn.rs +53 -0
  60. package/rust/core/audio/interpreter.rs +0 -317
  61. package/rust/core/lexer/handler/equal.rs +0 -32
@@ -0,0 +1,204 @@
1
+ use crate::core::{
2
+ audio::{
3
+ engine::AudioEngine,
4
+ interpreter::{
5
+ call::interprete_call_statement,
6
+ condition::interprete_condition_statement,
7
+ let_::interprete_let_statement,
8
+ load::interprete_load_statement,
9
+ loop_::interprete_loop_statement,
10
+ sleep::interprete_sleep_statement,
11
+ spawn::interprete_spawn_statement,
12
+ tempo::interprete_tempo_statement,
13
+ trigger::interprete_trigger_statement,
14
+ },
15
+ },
16
+ parser::statement::{ Statement, StatementKind },
17
+ store::variable::VariableTable,
18
+ };
19
+
20
+ pub fn run_audio_program(
21
+ statements: &Vec<Statement>,
22
+ audio_engine: AudioEngine,
23
+ entry: String,
24
+ output: String
25
+ ) -> (AudioEngine, f32, f32) {
26
+ let mut base_bpm = 120.0;
27
+ let mut base_duration = 60.0 / base_bpm;
28
+
29
+ let variable_table = audio_engine.variables.clone();
30
+
31
+ let (updated_audio_engine, base_bpm, max_end_time) = execute_audio_block(
32
+ audio_engine.clone(),
33
+ variable_table.clone(),
34
+ statements.clone(),
35
+ base_bpm.clone(),
36
+ base_duration.clone(),
37
+ 0.0,
38
+ 0.0
39
+ );
40
+
41
+ (updated_audio_engine, base_bpm, max_end_time)
42
+ }
43
+
44
+ pub fn execute_audio_block(
45
+ mut audio_engine: AudioEngine,
46
+ mut variable_table: VariableTable,
47
+ mut statements: Vec<Statement>,
48
+ mut base_bpm: f32,
49
+ mut base_duration: f32,
50
+ mut max_end_time: f32,
51
+ mut cursor_time: f32
52
+ ) -> (AudioEngine, f32, f32) {
53
+ for stmt in statements {
54
+ match &stmt.kind {
55
+ StatementKind::Load { .. } => {
56
+ if
57
+ let Some(new_variable_table) = interprete_load_statement(
58
+ &stmt,
59
+ &mut variable_table
60
+ )
61
+ {
62
+ variable_table = new_variable_table;
63
+ } else {
64
+ eprintln!("❌ Failed to interpret load statement: {:?}", stmt);
65
+ }
66
+ }
67
+
68
+ StatementKind::Let { .. } => {
69
+ if
70
+ let Some(new_variable_table) = interprete_let_statement(
71
+ &stmt,
72
+ &mut variable_table
73
+ )
74
+ {
75
+ variable_table = new_variable_table;
76
+ } else {
77
+ eprintln!("❌ Failed to interpret let statement: {:?}", stmt);
78
+ }
79
+ }
80
+
81
+ StatementKind::Tempo => {
82
+ if let Some((new_bpm, new_duration)) = interprete_tempo_statement(&stmt) {
83
+ base_bpm = new_bpm;
84
+ base_duration = new_duration;
85
+ } else {
86
+ eprintln!("❌ Failed to interpret tempo statement: {:?}", stmt);
87
+ }
88
+ }
89
+
90
+ StatementKind::Trigger { .. } => {
91
+ if
92
+ let Some((new_cursor_time, new_max_end_time, updated_engine)) =
93
+ interprete_trigger_statement(
94
+ &stmt,
95
+ &mut audio_engine,
96
+ &variable_table,
97
+ base_duration,
98
+ cursor_time,
99
+ max_end_time
100
+ )
101
+ {
102
+ cursor_time = new_cursor_time;
103
+ max_end_time = new_max_end_time;
104
+ audio_engine = updated_engine;
105
+ } else {
106
+ eprintln!("❌ Failed to interpret trigger statement: {:?}", stmt);
107
+ }
108
+ }
109
+
110
+ StatementKind::Spawn => {
111
+ if
112
+ let Some((new_cursor_time, new_max_end_time, updated_engine)) =
113
+ interprete_spawn_statement(
114
+ &stmt,
115
+ &mut audio_engine,
116
+ &variable_table,
117
+ base_bpm,
118
+ base_duration,
119
+ cursor_time,
120
+ max_end_time
121
+ )
122
+ {
123
+ cursor_time = new_cursor_time;
124
+ max_end_time = new_max_end_time;
125
+ audio_engine = updated_engine;
126
+ } else {
127
+ eprintln!("❌ Failed to interpret spawn statement: {:?}", stmt);
128
+ }
129
+ }
130
+
131
+ StatementKind::Sleep => {
132
+ let (new_cursor, new_max) = interprete_sleep_statement(
133
+ &stmt,
134
+ cursor_time,
135
+ max_end_time
136
+ );
137
+ cursor_time = new_cursor;
138
+ max_end_time = new_max;
139
+ }
140
+
141
+ StatementKind::Loop => {
142
+ let (loop_engine, new_max, new_cursor) = interprete_loop_statement(
143
+ &stmt,
144
+ audio_engine.clone(),
145
+ variable_table.clone(),
146
+ base_bpm,
147
+ base_duration,
148
+ max_end_time,
149
+ cursor_time
150
+ );
151
+ audio_engine = loop_engine;
152
+ cursor_time = new_cursor;
153
+ max_end_time = new_max;
154
+ }
155
+
156
+ StatementKind::Call => {
157
+ let (call_engine, new_max, new_cursor) = interprete_call_statement(
158
+ &stmt,
159
+ audio_engine.clone(),
160
+ variable_table.clone(),
161
+ base_bpm,
162
+ base_duration,
163
+ max_end_time,
164
+ cursor_time
165
+ );
166
+ audio_engine = call_engine;
167
+ cursor_time = new_cursor;
168
+ max_end_time = new_max;
169
+ }
170
+
171
+ StatementKind::If | StatementKind::ElseIf | StatementKind::Else => {
172
+ let (condition_engine, new_max, new_cursor) = interprete_condition_statement(
173
+ &stmt,
174
+ audio_engine.clone(),
175
+ variable_table.clone(),
176
+ base_bpm,
177
+ base_duration,
178
+ max_end_time,
179
+ cursor_time
180
+ );
181
+
182
+ audio_engine = condition_engine;
183
+ cursor_time = new_cursor;
184
+ max_end_time = new_max;
185
+ }
186
+
187
+ | StatementKind::Bank
188
+ | StatementKind::Import { .. }
189
+ | StatementKind::Export { .. }
190
+ | StatementKind::Group
191
+ | StatementKind::Unknown => {
192
+ // NOTE: Ignoring unsupported statement kinds for now.
193
+ }
194
+
195
+ _ => {
196
+ eprintln!("Unsupported audio statement kind: {:?}", stmt);
197
+ }
198
+ }
199
+ }
200
+
201
+ audio_engine.set_variables(variable_table);
202
+
203
+ (audio_engine, base_bpm, max_end_time)
204
+ }
@@ -0,0 +1,19 @@
1
+ use crate::core::{
2
+ audio::engine::AudioEngine,
3
+ parser::statement::{ Statement, StatementKind },
4
+ shared::value::Value,
5
+ store::variable::VariableTable,
6
+ };
7
+
8
+ pub fn interprete_let_statement(
9
+ stmt: &Statement,
10
+ variable_table: &mut VariableTable
11
+ ) -> Option<VariableTable> {
12
+ if let StatementKind::Let { name } = &stmt.kind {
13
+ variable_table.set(name.to_string(), stmt.value.clone());
14
+
15
+ return Some(variable_table.clone())
16
+ }
17
+
18
+ None
19
+ }
@@ -0,0 +1,18 @@
1
+ use crate::core::{
2
+ parser::statement::{ Statement, StatementKind },
3
+ shared::value::Value,
4
+ store::variable::VariableTable,
5
+ };
6
+
7
+ pub fn interprete_load_statement(
8
+ stmt: &Statement,
9
+ variable_table: &mut VariableTable
10
+ ) -> Option<VariableTable> {
11
+ if let StatementKind::Load { source, alias } = &stmt.kind {
12
+ variable_table.set(alias.to_string(), Value::String(source.clone()));
13
+
14
+ return Some(variable_table.clone());
15
+ }
16
+
17
+ None
18
+ }
@@ -0,0 +1,59 @@
1
+ use crate::core::{
2
+ audio::{ engine::AudioEngine, interpreter::driver::execute_audio_block },
3
+ parser::statement::{ Statement, StatementKind },
4
+ shared::{ duration::Duration, value::Value },
5
+ store::variable::VariableTable,
6
+ };
7
+
8
+ pub fn interprete_loop_statement(
9
+ stmt: &Statement,
10
+ audio_engine: AudioEngine,
11
+ variable_table: VariableTable,
12
+ base_bpm: f32,
13
+ base_duration: f32,
14
+ max_end_time: f32,
15
+ cursor_time: f32
16
+ ) -> (AudioEngine, f32, f32) {
17
+ if let Value::Map(loop_value) = &stmt.value {
18
+ let loop_count = match loop_value.get("iterator") {
19
+ Some(Value::Number(n)) => *n as usize,
20
+ _ => {
21
+ eprintln!("❌ Loop iterator must be a number");
22
+ return (audio_engine, max_end_time, cursor_time);
23
+ }
24
+ };
25
+
26
+ let loop_body = match loop_value.get("body") {
27
+ Some(Value::Block(body)) => body.clone(),
28
+ _ => {
29
+ eprintln!("❌ Loop body must be a block");
30
+ return (audio_engine, max_end_time, cursor_time);
31
+ }
32
+ };
33
+
34
+ let mut engine = audio_engine;
35
+ let mut cur_time = cursor_time;
36
+ let mut max_time = max_end_time;
37
+
38
+ for _ in 0..loop_count {
39
+ let (eng, _, end_time) = execute_audio_block(
40
+ engine.clone(),
41
+ variable_table.clone(),
42
+ loop_body.clone(),
43
+ base_bpm,
44
+ base_duration,
45
+ max_time,
46
+ cur_time
47
+ );
48
+
49
+ engine = eng;
50
+ cur_time = end_time;
51
+ max_time = max_time.max(end_time);
52
+ }
53
+
54
+ (engine, max_time, cur_time)
55
+ } else {
56
+ eprintln!("❌ Loop statement value is not a map");
57
+ (audio_engine, max_end_time, cursor_time)
58
+ }
59
+ }
@@ -0,0 +1,11 @@
1
+ pub mod driver;
2
+
3
+ pub mod load;
4
+ pub mod let_;
5
+ pub mod tempo;
6
+ pub mod trigger;
7
+ pub mod spawn;
8
+ pub mod sleep;
9
+ pub mod loop_;
10
+ pub mod call;
11
+ pub mod condition;
@@ -0,0 +1,36 @@
1
+ use crate::core::{
2
+ audio::{ engine::AudioEngine, loader::trigger::load_trigger },
3
+ parser::statement::{ Statement, StatementKind },
4
+ shared::{ duration::Duration, value::Value },
5
+ store::variable::VariableTable,
6
+ };
7
+
8
+ pub fn interprete_sleep_statement(
9
+ stmt: &Statement,
10
+ cursor_time: f32,
11
+ max_end_time: f32,
12
+ ) -> (f32, f32) {
13
+ let duration_secs = match &stmt.value {
14
+ Value::Number(ms) => *ms / 1000.0,
15
+ Value::String(s) if s.ends_with("ms") => {
16
+ s.trim_end_matches("ms").parse::<f32>().map(|ms| ms / 1000.0).unwrap_or_else(|_| {
17
+ eprintln!("❌ Invalid sleep value (ms): {}", s);
18
+ 0.0
19
+ })
20
+ }
21
+ Value::String(s) if s.ends_with("s") => {
22
+ s.trim_end_matches("s").parse::<f32>().unwrap_or_else(|_| {
23
+ eprintln!("❌ Invalid sleep value (s): {}", s);
24
+ 0.0
25
+ })
26
+ }
27
+ other => {
28
+ eprintln!("❌ Invalid sleep value: {:?}", other);
29
+ 0.0
30
+ }
31
+ };
32
+
33
+ let new_cursor = cursor_time + duration_secs;
34
+ let new_max = max_end_time.max(new_cursor);
35
+ (new_cursor, new_max)
36
+ }
@@ -0,0 +1,65 @@
1
+ use crate::core::{
2
+ audio::{ engine::AudioEngine, interpreter::driver::execute_audio_block },
3
+ parser::statement::Statement,
4
+ shared::value::Value,
5
+ store::variable::VariableTable,
6
+ };
7
+
8
+ pub fn interprete_spawn_statement(
9
+ stmt: &Statement,
10
+ audio_engine: &mut AudioEngine,
11
+ variable_table: &VariableTable,
12
+ base_bpm: f32,
13
+ base_duration: f32,
14
+ cursor_time: f32,
15
+ max_end_time: f32
16
+ ) -> Option<(f32, f32, AudioEngine)> {
17
+ if let Value::String(identifier) = &stmt.value {
18
+ match variable_table.get(identifier) {
19
+ Some(Value::Map(map)) => {
20
+ if let Some(Value::Block(block)) = map.get("body") {
21
+ let mut local_max = cursor_time;
22
+ let mut updated_engine = audio_engine.clone();
23
+
24
+ for inner_stmt in block {
25
+ let (inner_engine, _, inner_end_time) = execute_audio_block(
26
+ updated_engine.clone(),
27
+ variable_table.clone(),
28
+ vec![inner_stmt.clone()],
29
+ base_bpm,
30
+ base_duration,
31
+ max_end_time,
32
+ cursor_time
33
+ );
34
+
35
+ updated_engine = inner_engine;
36
+
37
+ if inner_end_time > local_max {
38
+ local_max = inner_end_time;
39
+ }
40
+ }
41
+
42
+ let new_max_end_time = local_max.max(max_end_time);
43
+
44
+ return Some((local_max, new_max_end_time, updated_engine));
45
+ } else {
46
+ eprintln!("❌ Cannot spawn '{}': no valid body block", identifier);
47
+ }
48
+ }
49
+ Some(other) => {
50
+ eprintln!(
51
+ "❌ Cannot spawn '{}': expected map with block, got {:?}",
52
+ identifier,
53
+ other
54
+ );
55
+ }
56
+ None => {
57
+ eprintln!("❌ Cannot spawn '{}': not found in variable table", identifier);
58
+ }
59
+ }
60
+ } else {
61
+ eprintln!("❌ Invalid spawn statement: expected a string identifier, got {:?}", stmt.value);
62
+ }
63
+
64
+ None
65
+ }
@@ -0,0 +1,16 @@
1
+ use crate::core::{ parser::statement::{ Statement, StatementKind }, shared::value::Value };
2
+
3
+ pub fn interprete_tempo_statement(stmt: &Statement) -> Option<(f32, f32)> {
4
+ if let StatementKind::Tempo = &stmt.kind {
5
+ if let Value::Number(bpm) = &stmt.value {
6
+ let bpm = *bpm as f32;
7
+ let duration = 60.0 / bpm;
8
+
9
+ return Some((bpm, duration));
10
+ } else {
11
+ eprintln!("❌ Invalid tempo value: {:?}", stmt.value);
12
+ }
13
+ }
14
+
15
+ None
16
+ }
@@ -0,0 +1,69 @@
1
+ use crate::core::{
2
+ audio::{ engine::AudioEngine, loader::trigger::load_trigger },
3
+ parser::statement::{ Statement, StatementKind },
4
+ shared::{ duration::Duration, value::Value },
5
+ store::variable::VariableTable,
6
+ };
7
+
8
+ pub fn interprete_trigger_statement(
9
+ stmt: &Statement,
10
+ audio_engine: &mut AudioEngine,
11
+ variable_table: &VariableTable,
12
+ base_duration: f32,
13
+ cursor_time: f32,
14
+ max_end_time: f32
15
+ ) -> Option<(f32, f32, AudioEngine)> {
16
+ if let StatementKind::Trigger { entity, duration } = &stmt.kind {
17
+ if let Some(trigger_val) = variable_table.get(entity) {
18
+ let duration_secs = match duration {
19
+ Duration::Number(n) => *n,
20
+
21
+ Duration::Identifier(id) => {
22
+ if id == "auto" {
23
+ 1.0
24
+ } else {
25
+ match variable_table.get(id) {
26
+ Some(Value::Number(n)) => *n,
27
+ Some(Value::Identifier(other)) if other == "auto" => 1.0,
28
+ Some(other) => {
29
+ eprintln!(
30
+ "❌ Invalid duration reference '{}': expected number, got {:?}",
31
+ id,
32
+ other
33
+ );
34
+ return None;
35
+ }
36
+ None => {
37
+ eprintln!("❌ Duration identifier '{}' not found", id);
38
+ return None;
39
+ }
40
+ }
41
+ }
42
+ }
43
+
44
+ Duration::Auto => 1.0,
45
+ };
46
+
47
+ let duration_final = duration_secs * base_duration;
48
+
49
+ let (src, _) = load_trigger(
50
+ trigger_val,
51
+ duration,
52
+ base_duration,
53
+ variable_table.clone()
54
+ );
55
+
56
+ let mut updated_engine = audio_engine.clone();
57
+ updated_engine.insert(&src, cursor_time, duration_final, None);
58
+
59
+ let new_cursor_time = cursor_time + duration_final;
60
+ let new_max_end_time = new_cursor_time.max(max_end_time);
61
+
62
+ return Some((new_cursor_time, new_max_end_time, updated_engine));
63
+ } else {
64
+ eprintln!("❌ Unknown trigger entity: {}", entity);
65
+ }
66
+ }
67
+
68
+ None
69
+ }
@@ -0,0 +1 @@
1
+ pub mod trigger;
@@ -26,7 +26,9 @@ pub fn load_trigger(
26
26
  duration_as_secs = *num;
27
27
  } else if let Some(Value::String(num_str)) = variable_table.get(duration_identifier) {
28
28
  duration_as_secs = num_str.parse::<f32>().unwrap_or(base_duration);
29
- } else if let Some(Value::Identifier(num_str)) = variable_table.get(duration_identifier) {
29
+ } else if
30
+ let Some(Value::Identifier(num_str)) = variable_table.get(duration_identifier)
31
+ {
30
32
  duration_as_secs = num_str.parse::<f32>().unwrap_or(base_duration);
31
33
  } else {
32
34
  eprintln!("❌ Invalid duration identifier: {}", duration_identifier);
@@ -2,4 +2,5 @@ pub mod engine;
2
2
  pub mod interpreter;
3
3
  pub mod loader;
4
4
  pub mod player;
5
- pub mod render;
5
+ pub mod renderer;
6
+ pub mod evaluator;
@@ -1,7 +1,11 @@
1
1
  use std::collections::HashMap;
2
2
 
3
3
  use crate::{
4
- core::{ audio::{engine::AudioEngine, interpreter::interprete_statements}, parser::statement::Statement, store::global::GlobalStore },
4
+ core::{
5
+ audio::{ engine::AudioEngine, interpreter::driver::run_audio_program },
6
+ parser::statement::Statement,
7
+ store::global::GlobalStore,
8
+ },
5
9
  utils::logger::{ LogLevel, Logger },
6
10
  };
7
11
 
@@ -22,7 +26,7 @@ pub fn render_audio_with_modules(
22
26
  }
23
27
 
24
28
  // Interpret the statements to fill the audio buffer
25
- let (mut audio_engine, module_base_bpm, module_max_end_time) = interprete_statements(
29
+ let (mut audio_engine, module_base_bpm, module_max_end_time) = run_audio_program(
26
30
  &statements,
27
31
  audio_engine,
28
32
  module_name.clone(),
@@ -1,4 +1,4 @@
1
- use crate::core::audio::render::render_audio_with_modules;
1
+ use crate::core::audio::renderer::render_audio_with_modules;
2
2
  use crate::core::parser::statement::Statement;
3
3
  use crate::core::store::global::GlobalStore;
4
4
  use std::{ collections::HashMap, fs::create_dir_all };
@@ -1,5 +1,5 @@
1
1
  use std::{ collections::HashMap, fs::create_dir_all };
2
- use crate::core::{ debugger::Debugger, lexer::token::Token, parser::statement::Statement };
2
+ use crate::core::{ debugger::Debugger, lexer::token::Token };
3
3
 
4
4
  pub fn write_lexer_log_file(
5
5
  output_dir: &str,
@@ -1,5 +1,6 @@
1
1
  pub mod preprocessor;
2
2
  pub mod lexer;
3
+ pub mod store;
3
4
 
4
5
  use std::io::Write;
5
6
 
@@ -0,0 +1,25 @@
1
+ use std::{ collections::HashMap, fs::create_dir_all };
2
+ use crate::core::{ debugger::Debugger, preprocessor::module::Module };
3
+
4
+ pub fn write_store_log_file(output_dir: &str, file_name: &str, modules: HashMap<String, Module>) {
5
+ let debugger = Debugger::new();
6
+ let mut content = String::new();
7
+
8
+ let log_directory = format!("{}/logs", output_dir);
9
+ create_dir_all(&log_directory).expect("Failed to create log directory");
10
+
11
+ for (path, module) in modules {
12
+ content.push_str(&format!("--- Module: {} ---\n", path));
13
+
14
+ for (index, var_value) in module.variable_table.variables.iter().enumerate() {
15
+ let var_name = var_value.0.clone();
16
+ let var_data = var_value.1;
17
+
18
+ content.push_str(&format!("{}: {:?} = {:?}\n", index + 1, var_name, var_data));
19
+ }
20
+
21
+ content.push_str("\n");
22
+ }
23
+
24
+ debugger.write_log_file(&log_directory, file_name, &content);
25
+ }
@@ -1,4 +1,4 @@
1
- use crate::core::parser::{ statement::{ Statement, StatementKind }, Parser };
1
+ use crate::core::parser::{ statement::{ Statement, StatementKind }, driver::Parser };
2
2
 
3
3
  pub struct ErrorHandler {
4
4
  errors: Vec<Error>,