@devaloop/devalang 0.0.1-alpha.1 → 0.0.1-alpha.10

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 (155) hide show
  1. package/.devalang +4 -0
  2. package/Cargo.toml +49 -45
  3. package/README.md +127 -46
  4. package/docs/CHANGELOG.md +172 -0
  5. package/docs/COMMANDS.md +60 -6
  6. package/docs/CONFIG.md +30 -0
  7. package/docs/ROADMAP.md +10 -7
  8. package/docs/SYNTAX.md +100 -18
  9. package/docs/TODO.md +31 -28
  10. package/examples/condition.deva +20 -0
  11. package/examples/group.deva +12 -0
  12. package/examples/index.deva +13 -4
  13. package/examples/loop.deva +16 -0
  14. package/examples/samples/hat-808.wav +0 -0
  15. package/examples/synth.deva +14 -0
  16. package/examples/variables.deva +9 -0
  17. package/out-tsc/bin/devalang.exe +0 -0
  18. package/out-tsc/scripts/version/fetch.js +1 -5
  19. package/package.json +5 -4
  20. package/project-version.json +3 -3
  21. package/rust/cli/build.rs +114 -28
  22. package/rust/cli/check.rs +96 -103
  23. package/rust/cli/init.rs +79 -0
  24. package/rust/cli/mod.rs +203 -1
  25. package/rust/cli/play.rs +193 -0
  26. package/rust/cli/template.rs +57 -0
  27. package/rust/config/loader.rs +13 -0
  28. package/rust/config/mod.rs +16 -0
  29. package/rust/core/audio/engine.rs +214 -0
  30. package/rust/core/audio/evaluator.rs +31 -0
  31. package/rust/core/audio/interpreter/arrow_call.rs +129 -0
  32. package/rust/core/audio/interpreter/call.rs +70 -0
  33. package/rust/core/audio/interpreter/condition.rs +69 -0
  34. package/rust/core/audio/interpreter/driver.rs +236 -0
  35. package/rust/core/audio/interpreter/let_.rs +19 -0
  36. package/rust/core/audio/interpreter/load.rs +18 -0
  37. package/rust/core/audio/interpreter/loop_.rs +67 -0
  38. package/rust/core/audio/interpreter/mod.rs +12 -0
  39. package/rust/core/audio/interpreter/sleep.rs +36 -0
  40. package/rust/core/audio/interpreter/spawn.rs +84 -0
  41. package/rust/core/audio/interpreter/tempo.rs +16 -0
  42. package/rust/core/audio/interpreter/trigger.rs +69 -0
  43. package/rust/core/audio/loader/mod.rs +1 -0
  44. package/rust/core/audio/loader/trigger.rs +52 -0
  45. package/rust/core/audio/mod.rs +6 -0
  46. package/rust/core/audio/player.rs +54 -0
  47. package/rust/core/audio/renderer.rs +54 -0
  48. package/rust/core/builder/mod.rs +70 -27
  49. package/rust/core/debugger/lexer.rs +27 -0
  50. package/rust/core/debugger/mod.rs +13 -49
  51. package/rust/core/debugger/preprocessor.rs +27 -0
  52. package/rust/core/debugger/store.rs +25 -0
  53. package/rust/core/error/mod.rs +60 -0
  54. package/rust/core/lexer/handler/arrow.rs +31 -0
  55. package/rust/core/lexer/handler/at.rs +21 -0
  56. package/rust/core/lexer/handler/brace.rs +41 -0
  57. package/rust/core/lexer/handler/colon.rs +21 -0
  58. package/rust/core/lexer/handler/comment.rs +30 -0
  59. package/rust/core/lexer/handler/dot.rs +21 -0
  60. package/rust/core/lexer/handler/driver.rs +230 -0
  61. package/rust/core/lexer/handler/identifier.rs +41 -0
  62. package/rust/core/lexer/handler/indent.rs +52 -0
  63. package/rust/core/lexer/handler/mod.rs +14 -0
  64. package/rust/core/lexer/handler/newline.rs +23 -0
  65. package/rust/core/lexer/handler/number.rs +31 -0
  66. package/rust/core/lexer/handler/operator.rs +44 -0
  67. package/rust/core/lexer/handler/string.rs +63 -0
  68. package/rust/core/lexer/mod.rs +37 -319
  69. package/rust/core/lexer/token.rs +86 -0
  70. package/rust/core/mod.rs +6 -2
  71. package/rust/core/parser/driver.rs +331 -0
  72. package/rust/core/parser/handler/arrow_call.rs +126 -0
  73. package/rust/core/parser/handler/at.rs +162 -0
  74. package/rust/core/parser/handler/bank.rs +41 -0
  75. package/rust/core/parser/handler/condition.rs +74 -0
  76. package/rust/core/parser/handler/dot.rs +112 -0
  77. package/rust/core/parser/handler/identifier/call.rs +41 -0
  78. package/rust/core/parser/handler/identifier/group.rs +75 -0
  79. package/rust/core/parser/handler/identifier/let_.rs +133 -0
  80. package/rust/core/parser/handler/identifier/mod.rs +51 -0
  81. package/rust/core/parser/handler/identifier/sleep.rs +33 -0
  82. package/rust/core/parser/handler/identifier/spawn.rs +41 -0
  83. package/rust/core/parser/handler/identifier/synth.rs +65 -0
  84. package/rust/core/parser/handler/loop_.rs +72 -0
  85. package/rust/core/parser/handler/mod.rs +8 -0
  86. package/rust/core/parser/handler/tempo.rs +47 -0
  87. package/rust/core/parser/mod.rs +3 -200
  88. package/rust/core/parser/statement.rs +96 -0
  89. package/rust/core/preprocessor/loader.rs +229 -0
  90. package/rust/core/preprocessor/mod.rs +2 -24
  91. package/rust/core/preprocessor/module.rs +42 -56
  92. package/rust/core/preprocessor/processor.rs +76 -0
  93. package/rust/core/preprocessor/resolver/bank.rs +41 -51
  94. package/rust/core/preprocessor/resolver/call.rs +123 -0
  95. package/rust/core/preprocessor/resolver/condition.rs +92 -0
  96. package/rust/core/preprocessor/resolver/driver.rs +227 -0
  97. package/rust/core/preprocessor/resolver/group.rs +61 -0
  98. package/rust/core/preprocessor/resolver/let_.rs +31 -0
  99. package/rust/core/preprocessor/resolver/loop_.rs +76 -67
  100. package/rust/core/preprocessor/resolver/mod.rs +12 -111
  101. package/rust/core/preprocessor/resolver/spawn.rs +58 -0
  102. package/rust/core/preprocessor/resolver/synth.rs +50 -0
  103. package/rust/core/preprocessor/resolver/tempo.rs +40 -61
  104. package/rust/core/preprocessor/resolver/trigger.rs +90 -154
  105. package/rust/core/preprocessor/resolver/value.rs +78 -0
  106. package/rust/core/shared/duration.rs +8 -0
  107. package/rust/core/shared/mod.rs +2 -0
  108. package/rust/core/shared/value.rs +28 -0
  109. package/rust/core/store/export.rs +28 -0
  110. package/rust/core/store/global.rs +39 -0
  111. package/rust/core/store/import.rs +28 -0
  112. package/rust/core/store/mod.rs +4 -0
  113. package/rust/core/store/variable.rs +28 -0
  114. package/rust/core/utils/mod.rs +2 -0
  115. package/rust/core/utils/path.rs +31 -0
  116. package/rust/core/utils/validation.rs +37 -0
  117. package/rust/lib.rs +161 -1
  118. package/rust/main.rs +46 -30
  119. package/rust/utils/file.rs +35 -0
  120. package/rust/utils/logger.rs +108 -34
  121. package/rust/utils/mod.rs +3 -2
  122. package/rust/utils/{loader.rs → spinner.rs} +2 -0
  123. package/rust/utils/watcher.rs +33 -0
  124. package/templates/minimal/.devalang +5 -0
  125. package/templates/minimal/README.md +202 -0
  126. package/templates/minimal/src/index.deva +2 -0
  127. package/templates/welcome/.devalang +5 -0
  128. package/templates/welcome/README.md +202 -0
  129. package/templates/welcome/samples/kick-808.wav +0 -0
  130. package/templates/welcome/src/index.deva +13 -0
  131. package/templates/welcome/src/variables.deva +5 -0
  132. package/typescript/scripts/version/fetch.ts +1 -6
  133. package/examples/exported.deva +0 -7
  134. package/rust/audio/mod.rs +0 -1
  135. package/rust/cli/new.rs +0 -1
  136. package/rust/core/parser/at.rs +0 -142
  137. package/rust/core/parser/bank.rs +0 -42
  138. package/rust/core/parser/dot.rs +0 -107
  139. package/rust/core/parser/identifer.rs +0 -91
  140. package/rust/core/parser/loop_.rs +0 -62
  141. package/rust/core/parser/tempo.rs +0 -42
  142. package/rust/core/parser/variable.rs +0 -129
  143. package/rust/core/preprocessor/dependencies.rs +0 -54
  144. package/rust/core/preprocessor/resolver/at.rs +0 -24
  145. package/rust/core/types/cli.rs +0 -160
  146. package/rust/core/types/mod.rs +0 -7
  147. package/rust/core/types/module.rs +0 -41
  148. package/rust/core/types/parser.rs +0 -73
  149. package/rust/core/types/statement.rs +0 -105
  150. package/rust/core/types/store.rs +0 -116
  151. package/rust/core/types/token.rs +0 -83
  152. package/rust/core/types/variable.rs +0 -32
  153. package/rust/runner/executer.rs +0 -44
  154. package/rust/runner/mod.rs +0 -1
  155. package/rust/utils/path.rs +0 -46
@@ -0,0 +1,227 @@
1
+ use std::collections::HashMap;
2
+ use crate::{
3
+ core::{
4
+ parser::statement::{ Statement, StatementKind },
5
+ preprocessor::{
6
+ loader::ModuleLoader,
7
+ module::Module,
8
+ resolver::{
9
+ bank::resolve_bank,
10
+ call::resolve_call,
11
+ condition::resolve_condition,
12
+ group::resolve_group,
13
+ let_::resolve_let,
14
+ loop_::resolve_loop,
15
+ spawn::resolve_spawn,
16
+ tempo::resolve_tempo,
17
+ trigger::resolve_trigger,
18
+ },
19
+ },
20
+ shared::value::Value,
21
+ store::global::GlobalStore,
22
+ },
23
+ utils::logger::Logger,
24
+ };
25
+
26
+ pub fn resolve_all_modules(module_loader: &ModuleLoader, global_store: &mut GlobalStore) {
27
+ for module in global_store.clone().modules.values_mut() {
28
+ resolve_imports(module_loader, global_store);
29
+ }
30
+ }
31
+
32
+ pub fn resolve_statement(
33
+ stmt: &Statement,
34
+ module: &Module,
35
+ path: &str,
36
+ global_store: &mut GlobalStore
37
+ ) -> Statement {
38
+ match &stmt.kind {
39
+ StatementKind::Trigger { entity, duration } =>
40
+ resolve_trigger(stmt, entity, &mut duration.clone(), module, path, global_store),
41
+ StatementKind::If => resolve_condition(stmt, module, path, global_store),
42
+ StatementKind::Group => resolve_group(stmt, module, path, global_store),
43
+ StatementKind::Call => resolve_call(stmt, module, path, global_store),
44
+ StatementKind::Spawn => resolve_spawn(stmt, module, path, global_store),
45
+ StatementKind::Bank => resolve_bank(stmt, module, path, global_store),
46
+ StatementKind::Tempo => resolve_tempo(stmt, module, path, global_store),
47
+ StatementKind::Loop => resolve_loop(stmt, module, path, global_store),
48
+ StatementKind::Let { name, .. } => resolve_let(stmt, name, module, path, global_store),
49
+
50
+ _ => {
51
+ let resolved_value = resolve_value(&stmt.value, module, global_store);
52
+
53
+ Statement {
54
+ value: resolved_value,
55
+ ..stmt.clone()
56
+ }
57
+ }
58
+ }
59
+ }
60
+
61
+ fn resolve_value(value: &Value, module: &Module, global_store: &mut GlobalStore) -> Value {
62
+ match value {
63
+ Value::Identifier(name) => {
64
+ if let Some(original_val) = module.variable_table.get(name) {
65
+ return resolve_value(original_val, module, global_store);
66
+ }
67
+
68
+ if let Some(export_val) = find_export_value(name, global_store) {
69
+ return resolve_value(&export_val, module, global_store);
70
+ }
71
+
72
+ eprintln!("⚠️ Unresolved identifier '{}'", name);
73
+ Value::Null
74
+ }
75
+
76
+ Value::Map(map) => {
77
+ let mut resolved = HashMap::new();
78
+ for (k, v) in map {
79
+ resolved.insert(k.clone(), resolve_value(v, module, global_store));
80
+ }
81
+ Value::Map(resolved)
82
+ }
83
+
84
+ Value::Block(stmts) => {
85
+ let resolved_stmts = stmts
86
+ .iter()
87
+ .map(|stmt| resolve_statement(stmt, module, &module.path, global_store))
88
+ .collect();
89
+ Value::Block(resolved_stmts)
90
+ }
91
+
92
+ other => other.clone(),
93
+ }
94
+ }
95
+
96
+ fn find_export_value(name: &str, global_store: &GlobalStore) -> Option<Value> {
97
+ for (_path, module) in &global_store.modules {
98
+ if let Some(val) = module.export_table.get_export(name) {
99
+ return Some(val.clone());
100
+ }
101
+ }
102
+ None
103
+ }
104
+
105
+ pub fn resolve_imports(module_loader: &ModuleLoader, global_store: &mut GlobalStore) {
106
+ for (module_path, module) in global_store.clone().modules.iter_mut() {
107
+ for (name, source_path) in &module.import_table.imports {
108
+ match source_path {
109
+ Value::String(source_path) => {
110
+ if let Some(source_module) = global_store.modules.get(source_path) {
111
+ if let Some(value) = source_module.export_table.get_export(name) {
112
+ module.variable_table.set(name.clone(), value.clone());
113
+ } else {
114
+ println!(
115
+ "[warn] '{module_path}': '{name}' not found in exports of '{source_path}'"
116
+ );
117
+ }
118
+ } else {
119
+ println!(
120
+ "[warn] '{module_path}': cannot find source module '{source_path}'"
121
+ );
122
+ }
123
+ }
124
+ _ => {
125
+ println!(
126
+ "[warn] '{module_path}': expected string for import source, found {:?}",
127
+ source_path
128
+ );
129
+ }
130
+ }
131
+ }
132
+ }
133
+ }
134
+
135
+ pub fn resolve_and_flatten_all_modules(
136
+ global_store: &mut GlobalStore
137
+ ) -> HashMap<String, Vec<Statement>> {
138
+ let logger = Logger::new();
139
+ let snapshot = global_store.clone();
140
+
141
+ // 1. Imports resolution
142
+ for (module_path, module) in global_store.modules.iter_mut() {
143
+ for (name, source_path) in &module.import_table.imports {
144
+ if let Value::String(source_path_str) = source_path {
145
+ match snapshot.modules.get(source_path_str) {
146
+ Some(source_module) => {
147
+ if let Some(value) = source_module.export_table.get_export(name) {
148
+ module.variable_table.set(name.clone(), value.clone());
149
+ } else {
150
+ logger.log_error_with_stacktrace(
151
+ &format!("'{name}' not found in exports of '{source_path_str}'"),
152
+ module_path
153
+ );
154
+ }
155
+ }
156
+ None => {
157
+ logger.log_error_with_stacktrace(
158
+ &format!("Cannot find source module '{source_path_str}'"),
159
+ module_path
160
+ );
161
+ }
162
+ }
163
+ } else {
164
+ logger.log_error_with_stacktrace(
165
+ &format!("Expected string for import source, found {:?}", source_path),
166
+ module_path
167
+ );
168
+ }
169
+ }
170
+ }
171
+
172
+ // 2. Statements resolution
173
+ let mut resolved_map: HashMap<String, Vec<Statement>> = HashMap::new();
174
+ for (path, module) in global_store.modules.clone() {
175
+ let mut resolved = Vec::new();
176
+
177
+ for stmt in &module.statements {
178
+ let mut stmt = stmt.clone();
179
+
180
+ match &stmt.kind {
181
+ StatementKind::Trigger { entity, duration } => {
182
+ let resolved_stmt = resolve_trigger(
183
+ &stmt,
184
+ entity.as_str(),
185
+ &mut duration.clone(),
186
+ &module,
187
+ &path,
188
+ global_store
189
+ );
190
+ resolved.push(resolved_stmt);
191
+ }
192
+
193
+ StatementKind::Loop => {
194
+ let resolved_stmt = resolve_loop(&stmt, &module, &path, global_store);
195
+ resolved.push(resolved_stmt);
196
+ }
197
+
198
+ StatementKind::Bank => {
199
+ let resolved_stmt = resolve_bank(&stmt, &module, &path, global_store);
200
+ resolved.push(resolved_stmt);
201
+ }
202
+
203
+ StatementKind::Tempo => {
204
+ let resolved_stmt = resolve_tempo(&stmt, &module, &path, global_store);
205
+ resolved.push(resolved_stmt);
206
+ }
207
+
208
+ StatementKind::Import { .. } | StatementKind::Export { .. } => {
209
+ resolved.push(stmt.clone());
210
+ }
211
+
212
+ StatementKind::Group => {
213
+ let resolved_stmt = resolve_group(&stmt, &module, &path, global_store);
214
+ resolved.push(resolved_stmt);
215
+ }
216
+
217
+ _ => {
218
+ resolved.push(stmt);
219
+ }
220
+ }
221
+ }
222
+
223
+ resolved_map.insert(path.clone(), resolved);
224
+ }
225
+
226
+ resolved_map
227
+ }
@@ -0,0 +1,61 @@
1
+ use std::collections::HashMap;
2
+
3
+ use crate::{
4
+ core::{
5
+ parser::statement::{ Statement, StatementKind },
6
+ preprocessor::{ module::Module, resolver::driver::resolve_statement },
7
+ shared::value::Value,
8
+ store::{ global::GlobalStore, variable::VariableTable },
9
+ },
10
+ utils::logger::{ LogLevel, Logger },
11
+ };
12
+
13
+ pub fn resolve_group(
14
+ stmt: &Statement,
15
+ module: &Module,
16
+ path: &str,
17
+ global_store: &mut GlobalStore
18
+ ) -> Statement {
19
+ let logger = Logger::new();
20
+
21
+ let Value::Map(group_map) = &stmt.value else {
22
+ return type_error(&logger, module, stmt, "Expected a map in group statement".to_string());
23
+ };
24
+
25
+ let mut resolved_map = group_map.clone();
26
+
27
+ if let Some(Value::Block(body)) = group_map.get("body") {
28
+ let resolved_body = resolve_block_statements(body, module, path, global_store);
29
+ resolved_map.insert("body".to_string(), Value::Block(resolved_body));
30
+ } else {
31
+ logger.log_message(LogLevel::Warning, "group without a body");
32
+ }
33
+
34
+ Statement {
35
+ kind: StatementKind::Group,
36
+ value: Value::Map(resolved_map),
37
+ ..stmt.clone()
38
+ }
39
+ }
40
+
41
+ fn resolve_block_statements(
42
+ body: &[Statement],
43
+ module: &Module,
44
+ path: &str,
45
+ global_store: &mut GlobalStore
46
+ ) -> Vec<Statement> {
47
+ body.iter()
48
+ .map(|stmt| resolve_statement(stmt, module, path, global_store))
49
+ .collect()
50
+ }
51
+
52
+ fn type_error(logger: &Logger, module: &Module, stmt: &Statement, message: String) -> Statement {
53
+ let stacktrace = format!("{}:{}:{}", module.path, stmt.line, stmt.column);
54
+ logger.log_error_with_stacktrace(&message, &stacktrace);
55
+
56
+ Statement {
57
+ kind: StatementKind::Error { message },
58
+ value: Value::Null,
59
+ ..stmt.clone()
60
+ }
61
+ }
@@ -0,0 +1,31 @@
1
+ use crate::
2
+ core::{
3
+ parser::statement:: Statement ,
4
+ preprocessor::{
5
+ module::Module,
6
+ resolver:: value::resolve_value ,
7
+ },
8
+ store:: global::GlobalStore ,
9
+ }
10
+ ;
11
+
12
+ pub fn resolve_let(
13
+ stmt: &Statement,
14
+ name: &str,
15
+ module: &Module,
16
+ path: &str,
17
+ global_store: &mut GlobalStore
18
+ ) -> Statement {
19
+ let resolved_value = resolve_value(&stmt.value, module, global_store);
20
+
21
+ if let Some(current_mod) = global_store.modules.get_mut(path) {
22
+ current_mod.variable_table.set(name.to_string(), resolved_value.clone());
23
+ } else {
24
+ eprintln!("[resolve_statement] ❌ Module path not found: {path}");
25
+ }
26
+
27
+ Statement {
28
+ value: resolved_value,
29
+ ..stmt.clone()
30
+ }
31
+ }
@@ -1,82 +1,91 @@
1
- use crate::core::{
2
- parser::parse_without_resolving_with_module,
3
- preprocessor::resolver::resolve_statement,
4
- types::{
5
- module::Module,
6
- statement::{
7
- Statement,
8
- StatementIterator,
9
- StatementKind,
10
- StatementResolved,
11
- StatementResolvedValue,
1
+ use std::collections::HashMap;
2
+
3
+ use crate::{
4
+ core::{
5
+ parser::statement::{ Statement, StatementKind },
6
+ preprocessor::{
7
+ module::Module,
8
+ resolver::{ driver::resolve_statement, value::resolve_value },
12
9
  },
13
- variable::VariableValue,
10
+ shared::value::Value,
11
+ store::global::GlobalStore,
14
12
  },
13
+ utils::logger::Logger,
15
14
  };
16
15
 
17
- pub fn resolve_loop_statement(
18
- loop_statement: &Statement,
19
- iterator: StatementIterator,
20
- module: &Module
21
- ) -> StatementResolved {
22
- let mut resolved_iterator = StatementIterator::Unknown;
16
+ pub fn resolve_loop(
17
+ stmt: &Statement,
18
+ module: &Module,
19
+ path: &str,
20
+ global_store: &mut GlobalStore
21
+ ) -> Statement {
22
+ let logger = Logger::new();
23
23
 
24
- match iterator.clone() {
25
- StatementIterator::Identifier(id) => {
26
- if let Some(value) = module.variable_table.variables.get(&id) {
27
- match value {
28
- VariableValue::Array(arr) => {
29
- resolved_iterator = StatementIterator::Array(
30
- parse_without_resolving_with_module(arr.clone(), module)
31
- );
32
- }
33
- VariableValue::Number(num) => {
34
- resolved_iterator = StatementIterator::Number(*num);
35
- }
36
- _ => {
37
- eprintln!("⚠️ Unsupported variable type for loop iterator: {:?}", value);
38
- resolved_iterator = StatementIterator::Unknown;
39
- }
40
- }
41
- } else {
42
- eprintln!("⚠️ Loop iterator variable '{}' not found", id);
43
- resolved_iterator = StatementIterator::Unknown;
44
- }
45
- }
46
- StatementIterator::Number(num) => {
47
- resolved_iterator = StatementIterator::Number(num);
48
- }
49
- _ => {
50
- resolved_iterator = iterator.clone();
51
- }
52
- }
24
+ let resolved_value = resolve_value(&stmt.value, module, global_store);
53
25
 
54
- let mut resolved_body: StatementResolvedValue = StatementResolvedValue::Unknown;
55
-
56
- match &loop_statement.value {
57
- VariableValue::Array(arr) => {
58
- let raw_statements = parse_without_resolving_with_module(arr.clone(), &module.clone());
26
+ let Value::Map(value_map) = &resolved_value else {
27
+ return error_stmt(&logger, module, stmt, "Expected a map for loop value");
28
+ };
59
29
 
60
- let mut resolved_statements = Vec::new();
30
+ let mut resolved_map: HashMap<String, Value> = HashMap::new();
31
+ for (key, val) in value_map {
32
+ resolved_map.insert(key.clone(), resolve_value(val, module, global_store));
33
+ }
61
34
 
62
- for raw_stmt in raw_statements {
63
- let resolved_stmt = resolve_statement(&raw_stmt, &mut module.clone());
64
- resolved_statements.push(resolved_stmt);
65
- }
35
+ let iterator_value = match resolved_map.get("iterator") {
36
+ Some(Value::Number(n)) => Value::Number(*n),
37
+ Some(other) => {
38
+ error_value(
39
+ &logger,
40
+ module,
41
+ stmt,
42
+ &format!("Loop iterator must be a number, found: {:?}", other)
43
+ );
44
+ Value::Number(1.0)
45
+ }
46
+ None => {
47
+ error_value(&logger, module, stmt, "Missing 'iterator' in loop");
48
+ Value::Number(1.0)
49
+ }
50
+ };
66
51
 
67
- resolved_body = StatementResolvedValue::Array(resolved_statements);
52
+ let body_value = match resolved_map.remove("body") {
53
+ Some(Value::Block(stmts)) => {
54
+ let resolved = stmts
55
+ .iter()
56
+ .map(|s| resolve_statement(s, module, path, global_store))
57
+ .collect();
58
+ Value::Block(resolved)
68
59
  }
69
60
  _ => {
70
- resolved_body = StatementResolvedValue::Unknown;
71
- eprintln!("⚠️ Unsupported value type for loop body: {:?}", loop_statement.value);
61
+ error_value(&logger, module, stmt, "Invalid or missing loop body");
62
+ Value::Block(vec![])
72
63
  }
64
+ };
65
+
66
+ let mut final_map = HashMap::new();
67
+ final_map.insert("iterator".to_string(), iterator_value);
68
+ final_map.insert("body".to_string(), body_value);
69
+
70
+ Statement {
71
+ kind: StatementKind::Loop,
72
+ value: Value::Map(final_map),
73
+ ..stmt.clone()
73
74
  }
75
+ }
74
76
 
75
- return StatementResolved {
76
- kind: StatementKind::Loop { iterator: resolved_iterator },
77
- value: resolved_body,
78
- indent: loop_statement.indent,
79
- line: loop_statement.line,
80
- column: loop_statement.column,
81
- };
77
+ fn error_value(logger: &Logger, module: &Module, stmt: &Statement, msg: &str) {
78
+ let stacktrace = format!("{}:{}:{}", module.path, stmt.line, stmt.column);
79
+ logger.log_error_with_stacktrace(msg, &stacktrace);
80
+ }
81
+
82
+ fn error_stmt(logger: &Logger, module: &Module, stmt: &Statement, msg: &str) -> Statement {
83
+ error_value(logger, module, stmt, msg);
84
+ Statement {
85
+ kind: StatementKind::Error {
86
+ message: msg.to_string(),
87
+ },
88
+ value: Value::Null,
89
+ ..stmt.clone()
90
+ }
82
91
  }
@@ -1,113 +1,14 @@
1
- pub mod bank;
2
- pub mod loop_;
3
- pub mod tempo;
4
- pub mod trigger;
5
- pub mod at;
6
-
7
- use crate::core::{
8
- preprocessor::resolver::{
9
- bank::resolve_bank_statement,
10
- loop_::resolve_loop_statement,
11
- tempo::resolve_tempo_statement,
12
- trigger::resolve_trigger_statement,
13
- at::{ resolve_load_statement },
14
- },
15
- types::{
16
- module::Module,
17
- parser::Parser,
18
- statement::{ Statement, StatementKind, StatementResolved, StatementResolvedValue },
19
- store::{ ExportTable, GlobalStore, ImportTable },
20
- variable::VariableValue,
21
- },
22
- };
23
-
24
- pub fn resolve_exports(statements: &[Statement], parser: &Parser) -> ExportTable {
25
- let mut export_table = parser.export_table.clone();
26
-
27
- for stmt in statements {
28
- if let StatementKind::Export = &stmt.kind {
29
- if let VariableValue::Array(tokens) = &stmt.value {
30
- for token in tokens {
31
- let var_name = &token.lexeme;
32
- if let Some(value) = parser.variable_table.variables.get(var_name) {
33
- export_table.add_export(var_name.clone(), value.clone());
34
- } else {
35
- eprintln!("⚠️ Variable '{}' not found in scope, export skipped", var_name);
36
- }
37
- }
38
- } else {
39
- eprintln!("⚠️ Unexpected value type in export: {:?}", stmt.value);
40
- }
41
- }
42
- }
43
-
44
- export_table
45
- }
46
-
47
- pub fn resolve_imports(module: &mut Module, global_store: &GlobalStore) -> ImportTable {
48
- let mut import_table = ImportTable::default();
49
-
50
- for stmt in &module.statements {
51
- if let StatementKind::Import { names, source } = &stmt.kind {
52
- if let Some(from_module) = global_store.modules.get(source) {
53
- for name in names {
54
- if let Some(value) = from_module.export_table.exports.get(name) {
55
- module.variable_table.variables.insert(name.clone(), value.clone());
56
- import_table.add_import(name.clone(), value.clone());
57
- } else {
58
- eprintln!("⚠️ '{}' not found in exports of '{}'", name, source);
59
- }
60
- }
61
- } else {
62
- eprintln!("⚠️ Module '{}' not found", source);
63
- }
64
- }
65
- }
66
-
67
- import_table
68
- }
1
+ pub mod driver;
69
2
 
70
- pub fn resolve_statement(stmt: &Statement, module: &mut Module) -> StatementResolved {
71
- match &stmt.kind {
72
- StatementKind::Loop { iterator } => {
73
- resolve_loop_statement(stmt, iterator.clone(), module)
74
- }
3
+ pub mod value;
75
4
 
76
- StatementKind::Trigger { entity, duration } => {
77
- resolve_trigger_statement(stmt, entity.clone(), duration.clone(), module)
78
- }
79
-
80
- StatementKind::Bank { .. } => { resolve_bank_statement(stmt, module) }
81
-
82
- StatementKind::Tempo { .. } => { resolve_tempo_statement(stmt, module) }
83
-
84
- StatementKind::Load { source, alias } => {
85
- resolve_load_statement(stmt, source, alias, module)
86
- }
87
-
88
- // TODO Handle other statement kinds
89
-
90
- StatementKind::Error => {
91
- StatementResolved {
92
- kind: StatementKind::Error,
93
- value: match stmt.value {
94
- VariableValue::Text(ref msg) => StatementResolvedValue::String(msg.clone()),
95
- _ => StatementResolvedValue::Unknown,
96
- },
97
- indent: stmt.indent,
98
- line: stmt.line,
99
- column: stmt.column,
100
- }
101
- }
102
-
103
- _ => {
104
- StatementResolved {
105
- kind: StatementKind::Unknown,
106
- value: StatementResolvedValue::Unknown,
107
- indent: stmt.indent,
108
- line: stmt.line,
109
- column: stmt.column,
110
- }
111
- }
112
- }
113
- }
5
+ pub mod trigger;
6
+ pub mod loop_;
7
+ pub mod bank;
8
+ pub mod tempo;
9
+ pub mod group;
10
+ pub mod condition;
11
+ pub mod spawn;
12
+ pub mod call;
13
+ pub mod synth;
14
+ pub mod let_;
@@ -0,0 +1,58 @@
1
+ use crate::{
2
+ core::{
3
+ parser::statement::{ Statement, StatementKind },
4
+ preprocessor::{
5
+ module::Module,
6
+ resolver::driver::resolve_statement,
7
+ resolver::value::resolve_value,
8
+ },
9
+ shared::value::Value,
10
+ store::global::GlobalStore,
11
+ },
12
+ utils::logger::{ Logger, LogLevel },
13
+ };
14
+
15
+ pub fn resolve_spawn(
16
+ stmt: &Statement,
17
+ module: &Module,
18
+ path: &str,
19
+ global_store: &mut GlobalStore
20
+ ) -> Statement {
21
+ let logger = Logger::new();
22
+
23
+ let resolved_value = resolve_value(&stmt.value, module, global_store);
24
+
25
+ match resolved_value {
26
+ Value::Map(mut map) => {
27
+ if let Some(Value::Block(stmts)) = map.get("body") {
28
+ let resolved_block = stmts
29
+ .iter()
30
+ .map(|s| resolve_statement(s, module, path, global_store))
31
+ .collect();
32
+ map.insert("body".to_string(), Value::Block(resolved_block));
33
+ }
34
+
35
+ Statement {
36
+ kind: StatementKind::Spawn,
37
+ value: Value::Map(map),
38
+ ..stmt.clone()
39
+ }
40
+ }
41
+
42
+ _ => {
43
+ let stacktrace = format!("{}:{}:{}", module.path, stmt.line, stmt.column);
44
+ logger.log_message(
45
+ LogLevel::Error,
46
+ &format!("Expected a map in spawn statement\n → at {stacktrace}")
47
+ );
48
+
49
+ Statement {
50
+ kind: StatementKind::Error {
51
+ message: "Invalid spawn value".to_string(),
52
+ },
53
+ value: Value::Null,
54
+ ..stmt.clone()
55
+ }
56
+ }
57
+ }
58
+ }