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

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 (59) hide show
  1. package/Cargo.toml +1 -1
  2. package/README.md +4 -8
  3. package/docs/CHANGELOG.md +27 -0
  4. package/examples/condition.deva +8 -12
  5. package/examples/group.deva +3 -3
  6. package/examples/index.deva +10 -8
  7. package/examples/loop.deva +10 -8
  8. package/examples/synth.deva +14 -0
  9. package/examples/variables.deva +1 -1
  10. package/out-tsc/bin/devalang.exe +0 -0
  11. package/out-tsc/scripts/version/fetch.js +1 -5
  12. package/package.json +1 -1
  13. package/project-version.json +3 -3
  14. package/rust/core/audio/engine.rs +89 -12
  15. package/rust/core/audio/interpreter/arrow_call.rs +129 -0
  16. package/rust/core/audio/interpreter/call.rs +29 -7
  17. package/rust/core/audio/interpreter/condition.rs +5 -1
  18. package/rust/core/audio/interpreter/driver.rs +41 -29
  19. package/rust/core/audio/interpreter/loop_.rs +11 -3
  20. package/rust/core/audio/interpreter/mod.rs +1 -0
  21. package/rust/core/audio/interpreter/spawn.rs +43 -42
  22. package/rust/core/audio/interpreter/trigger.rs +1 -1
  23. package/rust/core/audio/renderer.rs +15 -18
  24. package/rust/core/lexer/handler/arrow.rs +31 -0
  25. package/rust/core/lexer/handler/driver.rs +12 -1
  26. package/rust/core/lexer/handler/identifier.rs +1 -0
  27. package/rust/core/lexer/handler/mod.rs +1 -0
  28. package/rust/core/lexer/mod.rs +24 -3
  29. package/rust/core/lexer/token.rs +4 -0
  30. package/rust/core/parser/driver.rs +23 -4
  31. package/rust/core/parser/handler/arrow_call.rs +126 -0
  32. package/rust/core/parser/handler/identifier/call.rs +41 -0
  33. package/rust/core/parser/handler/identifier/group.rs +75 -0
  34. package/rust/core/parser/handler/identifier/let_.rs +133 -0
  35. package/rust/core/parser/handler/identifier/mod.rs +51 -0
  36. package/rust/core/parser/handler/identifier/sleep.rs +33 -0
  37. package/rust/core/parser/handler/identifier/spawn.rs +41 -0
  38. package/rust/core/parser/handler/identifier/synth.rs +65 -0
  39. package/rust/core/parser/handler/loop_.rs +24 -18
  40. package/rust/core/parser/handler/mod.rs +2 -1
  41. package/rust/core/parser/statement.rs +8 -0
  42. package/rust/core/preprocessor/loader.rs +57 -43
  43. package/rust/core/preprocessor/module.rs +3 -6
  44. package/rust/core/preprocessor/processor.rs +13 -4
  45. package/rust/core/preprocessor/resolver/call.rs +99 -29
  46. package/rust/core/preprocessor/resolver/condition.rs +38 -12
  47. package/rust/core/preprocessor/resolver/driver.rs +74 -29
  48. package/rust/core/preprocessor/resolver/group.rs +24 -81
  49. package/rust/core/preprocessor/resolver/let_.rs +31 -0
  50. package/rust/core/preprocessor/resolver/loop_.rs +62 -116
  51. package/rust/core/preprocessor/resolver/mod.rs +5 -1
  52. package/rust/core/preprocessor/resolver/spawn.rs +41 -36
  53. package/rust/core/preprocessor/resolver/synth.rs +50 -0
  54. package/rust/core/preprocessor/resolver/trigger.rs +51 -50
  55. package/rust/core/preprocessor/resolver/value.rs +78 -0
  56. package/rust/core/utils/path.rs +17 -32
  57. package/rust/core/utils/validation.rs +30 -28
  58. package/typescript/scripts/version/fetch.ts +1 -6
  59. package/rust/core/parser/handler/identifier.rs +0 -262
@@ -1,4 +1,4 @@
1
- use std::collections::HashMap;
1
+ use std::{ collections::HashMap, path::Path };
2
2
  use crate::{
3
3
  core::{
4
4
  error::ErrorHandler,
@@ -14,17 +14,26 @@ use crate::core::preprocessor::resolver::driver::{
14
14
  resolve_all_modules,
15
15
  resolve_and_flatten_all_modules,
16
16
  };
17
+ use crate::core::utils::path::resolve_relative_path;
17
18
 
18
19
  pub struct ModuleLoader {
19
20
  pub entry: String,
20
21
  pub output: String,
22
+ pub base_dir: String,
21
23
  }
22
24
 
23
25
  impl ModuleLoader {
24
26
  pub fn new(entry: &str, output: &str) -> Self {
27
+ let base_dir = Path::new(entry)
28
+ .parent()
29
+ .unwrap_or(Path::new(""))
30
+ .to_string_lossy()
31
+ .replace('\\', "/");
32
+
25
33
  Self {
26
34
  entry: entry.to_string(),
27
35
  output: output.to_string(),
36
+ base_dir: base_dir,
28
37
  }
29
38
  }
30
39
 
@@ -39,13 +48,12 @@ impl ModuleLoader {
39
48
  let mut module = Module::new(&entry_path);
40
49
  module.content = content.to_string();
41
50
 
42
- println!("Loading module from raw source: {}", normalized_entry_path);
43
-
44
51
  global_store.insert_module(normalized_entry_path.to_string(), module);
45
52
 
46
53
  Self {
47
54
  entry: normalized_entry_path.to_string(),
48
55
  output: output_path.to_string(),
56
+ base_dir: "".to_string(),
49
57
  }
50
58
  }
51
59
 
@@ -108,72 +116,78 @@ impl ModuleLoader {
108
116
  #[cfg(feature = "cli")]
109
117
  fn load_module_recursively(
110
118
  &self,
111
- path: &str,
119
+ raw_path: &str,
112
120
  global_store: &mut GlobalStore
113
121
  ) -> HashMap<String, Vec<Token>> {
114
- if global_store.modules.contains_key(path) {
122
+ let path = normalize_path(raw_path);
123
+
124
+ // Check if already loaded
125
+ if global_store.modules.contains_key(&path) {
115
126
  return HashMap::new();
116
127
  }
117
128
 
118
129
  let lexer = Lexer::new();
119
- let tokens = lexer.lex_tokens(path);
130
+ let tokens = lexer.lex_tokens(&path);
120
131
 
121
132
  let mut parser = Parser::new();
122
- parser.set_current_module(path.to_string());
133
+ parser.set_current_module(path.clone());
123
134
 
124
135
  let statements = parser.parse_tokens(tokens.clone(), global_store);
125
136
 
126
- // SECTION Error handling
137
+ // Error handling
127
138
  let mut error_handler = ErrorHandler::new();
128
139
  error_handler.detect_from_statements(&mut parser, &statements);
129
140
 
130
- error_handler.has_errors().then(|| {
141
+ if error_handler.has_errors() {
131
142
  let logger = Logger::new();
132
- let errors = error_handler.get_errors();
133
-
134
- for error in errors {
135
- let stacktrace = format!("{}:{}:{}", path, error.line, error.column);
136
- logger.log_error_with_stacktrace(&error.message, &stacktrace);
143
+ for error in error_handler.get_errors() {
144
+ let trace = format!("{}:{}:{}", path, error.line, error.column);
145
+ logger.log_error_with_stacktrace(&error.message, &trace);
137
146
  }
138
- });
147
+ }
139
148
 
140
- // SECTION Module creation
141
- let mut module = Module::new(path);
149
+ // Insert module into store
150
+ let mut module = Module::new(&path);
142
151
  module.tokens = tokens.clone();
143
152
  module.statements = statements.clone();
153
+ global_store.insert_module(path.clone(), module);
144
154
 
145
- global_store.insert_module(path.to_string(), module);
146
-
147
- // Then load the imports recursively
148
- self.load_module_imports(&path.to_string(), global_store);
155
+ // Load dependencies
156
+ self.load_module_imports(&path, global_store);
149
157
 
150
- // Return all tokens by module
151
- let mut tokens_by_module = HashMap::new();
152
-
153
- global_store.modules.iter().for_each(|(path, module)| {
154
- tokens_by_module.insert(path.clone(), module.tokens.clone());
155
- });
156
-
157
- tokens_by_module
158
+ // Return tokens per module
159
+ global_store.modules
160
+ .iter()
161
+ .map(|(p, m)| (p.clone(), m.tokens.clone()))
162
+ .collect()
158
163
  }
159
164
 
160
165
  #[cfg(feature = "cli")]
161
166
  fn load_module_imports(&self, path: &String, global_store: &mut GlobalStore) {
162
- let imports = global_store.modules
163
- .get(path)
164
- .unwrap()
165
- .statements.iter()
166
- .filter_map(|stmt| {
167
- if let StatementKind::Import { source, .. } = &stmt.kind {
168
- Some(source.clone())
169
- } else {
170
- None
167
+ let import_paths: Vec<String> = {
168
+ let current_module = match global_store.modules.get(path) {
169
+ Some(module) => module,
170
+ None => {
171
+ eprintln!("[warn] Cannot resolve imports: module '{}' not found in store", path);
172
+ return;
171
173
  }
172
- })
173
- .collect::<Vec<_>>();
174
-
175
- for import_path in imports {
176
- self.load_module_recursively(&import_path, global_store);
174
+ };
175
+
176
+ current_module.statements
177
+ .iter()
178
+ .filter_map(|stmt| {
179
+ if let StatementKind::Import { source, .. } = &stmt.kind {
180
+ Some(source.clone())
181
+ } else {
182
+ None
183
+ }
184
+ })
185
+ .collect()
186
+ };
187
+
188
+ for import_path in import_paths {
189
+ let resolved = resolve_relative_path(path, &import_path);
190
+ self.load_module_recursively(&resolved, global_store);
177
191
  }
178
192
  }
179
193
  }
@@ -1,12 +1,7 @@
1
1
  use crate::core::{
2
2
  lexer::token::Token,
3
3
  parser::statement::Statement,
4
- store::{
5
- export::ExportTable,
6
- global::GlobalStore,
7
- import::ImportTable,
8
- variable::VariableTable,
9
- },
4
+ store::{ export::ExportTable, import::ImportTable, variable::VariableTable },
10
5
  };
11
6
 
12
7
  #[derive(Debug, Clone)]
@@ -19,6 +14,7 @@ pub struct Module {
19
14
  pub export_table: ExportTable,
20
15
  pub import_table: ImportTable,
21
16
  pub content: String,
17
+ pub current_dir: String,
22
18
  }
23
19
 
24
20
  impl Module {
@@ -32,6 +28,7 @@ impl Module {
32
28
  import_table: ImportTable::new(),
33
29
  resolved: false,
34
30
  content: String::new(),
31
+ current_dir: String::new(),
35
32
  }
36
33
  }
37
34
 
@@ -1,10 +1,11 @@
1
- use std::collections::HashMap;
1
+ use std::{ collections::HashMap, path::Path };
2
2
 
3
3
  use crate::core::{
4
- parser::{ statement::StatementKind, driver::Parser },
4
+ parser::{ driver::Parser, statement::StatementKind },
5
5
  preprocessor::{ loader::ModuleLoader, resolver::group },
6
6
  shared::value::Value,
7
7
  store::global::GlobalStore,
8
+ utils::path::{normalize_path, resolve_relative_path},
8
9
  };
9
10
 
10
11
  pub fn process_modules(module_loader: &ModuleLoader, global_store: &mut GlobalStore) {
@@ -16,9 +17,13 @@ pub fn process_modules(module_loader: &ModuleLoader, global_store: &mut GlobalSt
16
17
  }
17
18
 
18
19
  StatementKind::Load { source, alias } => {
20
+ let module_dir = Path::new(&module.path).parent().unwrap_or(Path::new(""));
21
+
22
+ let resolved_path = normalize_path(&module_dir.join(source));
23
+
19
24
  module.variable_table.variables.insert(
20
25
  alias.clone(),
21
- Value::Sample(source.clone())
26
+ Value::Sample(resolved_path)
22
27
  );
23
28
  }
24
29
 
@@ -31,8 +36,12 @@ pub fn process_modules(module_loader: &ModuleLoader, global_store: &mut GlobalSt
31
36
  }
32
37
 
33
38
  StatementKind::Import { names, source } => {
39
+ let resolved = resolve_relative_path(&module.path, source);
34
40
  for name in names {
35
- module.import_table.add_import(name.clone(), Value::String(source.clone()));
41
+ module.import_table.add_import(
42
+ name.clone(),
43
+ Value::String(resolved.clone())
44
+ );
36
45
  }
37
46
  }
38
47
 
@@ -1,52 +1,122 @@
1
1
  use crate::{
2
2
  core::{
3
- parser::statement::{Statement, StatementKind},
4
- preprocessor::module::Module,
3
+ parser::statement::{ Statement, StatementKind },
4
+ preprocessor::{ module::Module, resolver::driver::resolve_statement },
5
5
  shared::value::Value,
6
6
  store::global::GlobalStore,
7
7
  },
8
- utils::logger::Logger,
8
+ utils::logger::{ Logger, LogLevel },
9
9
  };
10
10
 
11
11
  pub fn resolve_call(
12
12
  stmt: &Statement,
13
13
  module: &Module,
14
- _path: &str,
15
- _global_store: &GlobalStore,
14
+ path: &str,
15
+ global_store: &mut GlobalStore
16
16
  ) -> Statement {
17
17
  let logger = Logger::new();
18
18
 
19
- let Value::String(name) = &stmt.value else {
20
- return type_error(&logger, module, stmt, "Call expects a group name as string.".to_string());
21
- };
19
+ match &stmt.value {
20
+ Value::Identifier(ident) => {
21
+ match module.variable_table.get(ident) {
22
+ Some(Value::String(group_name)) =>
23
+ resolve_group_by_name(group_name, stmt, module, path, global_store, &logger),
24
+ Some(Value::Map(group_map)) =>
25
+ resolved_call(stmt, group_map, module, path, global_store),
26
+ Some(other) =>
27
+ error_stmt(
28
+ &logger,
29
+ module,
30
+ stmt,
31
+ &format!(
32
+ "Identifier '{ident}' must resolve to a group name or map, found {:?}",
33
+ other
34
+ )
35
+ ),
36
+ None =>
37
+ error_stmt(
38
+ &logger,
39
+ module,
40
+ stmt,
41
+ &format!("Identifier '{ident}' not found in variable table")
42
+ ),
43
+ }
44
+ }
22
45
 
23
- match module.variable_table.variables.get(name) {
24
- Some(Value::Map(group_stmt)) => Statement {
25
- kind: StatementKind::Call,
26
- value: Value::Map(group_stmt.clone()),
27
- ..stmt.clone()
28
- },
29
- Some(other) => type_error(
30
- &logger,
31
- module,
32
- stmt,
33
- format!("Expected a group for '{}', but found {:?}", name, other),
34
- ),
35
- None => type_error(
36
- &logger,
37
- module,
38
- stmt,
39
- format!("Group '{}' not found in module '{}'", name, module.path),
40
- ),
46
+ Value::String(name) =>
47
+ resolve_group_by_name(name, stmt, module, path, global_store, &logger),
48
+
49
+ Value::Map(group_map) => resolved_call(stmt, group_map, module, path, global_store),
50
+
51
+ other =>
52
+ error_stmt(
53
+ &logger,
54
+ module,
55
+ stmt,
56
+ &format!("Call expects a group name as string or identifier, found {:?}", other)
57
+ ),
41
58
  }
42
59
  }
43
60
 
44
- fn type_error(logger: &Logger, module: &Module, stmt: &Statement, message: String) -> Statement {
61
+ fn resolve_group_by_name(
62
+ name: &str,
63
+ stmt: &Statement,
64
+ module: &Module,
65
+ path: &str,
66
+ global_store: &mut GlobalStore,
67
+ logger: &Logger
68
+ ) -> Statement {
69
+ match module.variable_table.get(name) {
70
+ Some(Value::Map(group_map)) => resolved_call(stmt, group_map, module, path, global_store),
71
+ Some(other) =>
72
+ error_stmt(
73
+ logger,
74
+ module,
75
+ stmt,
76
+ &format!("Expected a group for '{}', but found {:?}", name, other)
77
+ ),
78
+ None =>
79
+ error_stmt(
80
+ logger,
81
+ module,
82
+ stmt,
83
+ &format!("Group '{}' not found in module '{}'", name, module.path)
84
+ ),
85
+ }
86
+ }
87
+
88
+ fn resolved_call(
89
+ stmt: &Statement,
90
+ group_map: &std::collections::HashMap<String, Value>,
91
+ module: &Module,
92
+ path: &str,
93
+ global_store: &mut GlobalStore
94
+ ) -> Statement {
95
+ let mut cloned_map = group_map.clone();
96
+
97
+ if let Some(Value::Block(stmts)) = group_map.get("body") {
98
+ let resolved = stmts
99
+ .iter()
100
+ .map(|s| resolve_statement(s, module, path, global_store))
101
+ .collect();
102
+ cloned_map.insert("body".to_string(), Value::Block(resolved));
103
+ }
104
+
105
+ Statement {
106
+ kind: StatementKind::Call,
107
+ value: Value::Map(cloned_map),
108
+ ..stmt.clone()
109
+ }
110
+ }
111
+
112
+ fn error_stmt(logger: &Logger, module: &Module, stmt: &Statement, message: &str) -> Statement {
45
113
  let stacktrace = format!("{}:{}:{}", module.path, stmt.line, stmt.column);
46
- logger.log_error_with_stacktrace(&message, &stacktrace);
114
+ logger.log_message(LogLevel::Error, &format!("{message}\n → at {stacktrace}"));
47
115
 
48
116
  Statement {
49
- kind: StatementKind::Error { message },
117
+ kind: StatementKind::Error {
118
+ message: message.to_string(),
119
+ },
50
120
  value: Value::Null,
51
121
  ..stmt.clone()
52
122
  }
@@ -1,6 +1,6 @@
1
1
  use crate::{
2
2
  core::{
3
- parser::statement::{ Statement, StatementKind },
3
+ parser::statement::{Statement, StatementKind},
4
4
  preprocessor::{module::Module, resolver::driver::resolve_statement},
5
5
  shared::value::Value,
6
6
  store::global::GlobalStore,
@@ -12,7 +12,7 @@ pub fn resolve_condition(
12
12
  stmt: &Statement,
13
13
  module: &Module,
14
14
  path: &str,
15
- global_store: &GlobalStore
15
+ global_store: &mut GlobalStore,
16
16
  ) -> Statement {
17
17
  let logger = Logger::new();
18
18
 
@@ -22,27 +22,29 @@ pub fn resolve_condition(
22
22
 
23
23
  let mut resolved_map = condition_map.clone();
24
24
 
25
- // Body resolution
25
+ // Main body resolution
26
26
  if let Some(Value::Block(body)) = condition_map.get("body") {
27
- let resolved_body = body
28
- .iter()
29
- .map(|s| resolve_statement(s, module, path, global_store))
30
- .collect::<Vec<_>>();
31
-
27
+ let resolved_body = resolve_block_statements(body, module, path, global_store);
32
28
  resolved_map.insert("body".to_string(), Value::Block(resolved_body));
33
29
  }
34
30
 
35
- // Next resolution
36
- if let Some(Value::Map(next)) = condition_map.get("next") {
31
+ // Recursive resolution of next condition
32
+ if let Some(Value::Map(next_map)) = condition_map.get("next") {
37
33
  let next_stmt = Statement {
38
34
  kind: StatementKind::If,
39
- value: Value::Map(next.clone()),
35
+ value: Value::Map(next_map.clone()),
40
36
  ..stmt.clone()
41
37
  };
42
38
 
43
39
  let resolved_next = resolve_condition(&next_stmt, module, path, global_store);
44
40
 
45
- if let Value::Map(resolved_next_map) = resolved_next.value {
41
+ if let Value::Map(mut resolved_next_map) = resolved_next.value {
42
+ // Body next resolution
43
+ if let Some(Value::Block(body)) = resolved_next_map.get("body") {
44
+ let resolved_body = resolve_block_statements(body, module, path, global_store);
45
+ resolved_next_map.insert("body".to_string(), Value::Block(resolved_body));
46
+ }
47
+
46
48
  resolved_map.insert("next".to_string(), Value::Map(resolved_next_map));
47
49
  }
48
50
  }
@@ -54,6 +56,30 @@ pub fn resolve_condition(
54
56
  }
55
57
  }
56
58
 
59
+ fn resolve_block_statements(
60
+ body: &[Statement],
61
+ module: &Module,
62
+ path: &str,
63
+ global_store: &mut GlobalStore,
64
+ ) -> Vec<Statement> {
65
+ body.iter()
66
+ .flat_map(|stmt| {
67
+ let resolved = resolve_statement(stmt, module, path, global_store);
68
+
69
+ if let StatementKind::Call = resolved.kind {
70
+ if let Value::Block(inner) = &resolved.value {
71
+ return inner
72
+ .iter()
73
+ .map(|s| resolve_statement(s, module, path, global_store))
74
+ .collect();
75
+ }
76
+ }
77
+
78
+ vec![resolved]
79
+ })
80
+ .collect()
81
+ }
82
+
57
83
  fn type_error(logger: &Logger, module: &Module, stmt: &Statement, message: String) -> Statement {
58
84
  let stacktrace = format!("{}:{}:{}", module.path, stmt.line, stmt.column);
59
85
  logger.log_error_with_stacktrace(&message, &stacktrace);
@@ -1,17 +1,24 @@
1
1
  use std::collections::HashMap;
2
2
  use crate::{
3
3
  core::{
4
- parser::statement::{ self, Statement, StatementKind },
4
+ parser::statement::{ Statement, StatementKind },
5
5
  preprocessor::{
6
6
  loader::ModuleLoader,
7
7
  module::Module,
8
8
  resolver::{
9
- bank::resolve_bank, call::resolve_call, condition::resolve_condition, group::resolve_group, loop_::resolve_loop, spawn::resolve_spawn, tempo::resolve_tempo, trigger::resolve_trigger
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,
10
18
  },
11
19
  },
12
- shared::{ duration::Duration, value::Value },
20
+ shared::value::Value,
13
21
  store::global::GlobalStore,
14
- utils::validation::{ is_valid_entity, is_valid_identifier },
15
22
  },
16
23
  utils::logger::Logger,
17
24
  };
@@ -26,35 +33,75 @@ pub fn resolve_statement(
26
33
  stmt: &Statement,
27
34
  module: &Module,
28
35
  path: &str,
29
- global_store: &GlobalStore
36
+ global_store: &mut GlobalStore
30
37
  ) -> Statement {
31
38
  match &stmt.kind {
32
- StatementKind::Trigger { entity, duration } => {
33
- resolve_trigger(
34
- &mut stmt.clone(),
35
- entity,
36
- &mut duration.clone(),
37
- module,
38
- path,
39
- global_store
40
- )
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
+ }
41
57
  }
58
+ }
59
+ }
42
60
 
43
- StatementKind::If => { resolve_condition(stmt, module, path, global_store) }
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
+ }
44
67
 
45
- StatementKind::Group => { resolve_group(stmt, module, path, global_store) }
68
+ if let Some(export_val) = find_export_value(name, global_store) {
69
+ return resolve_value(&export_val, module, global_store);
70
+ }
46
71
 
47
- StatementKind::Call => { resolve_call(stmt, module, path, global_store) }
72
+ eprintln!("⚠️ Unresolved identifier '{}'", name);
73
+ Value::Null
74
+ }
48
75
 
49
- StatementKind::Spawn => { resolve_spawn(stmt, module, path, global_store) }
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
+ }
50
83
 
51
- // TODO: Handle other statement kinds if necessary
52
- // ...
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
+ }
53
91
 
54
- _ => stmt.clone(),
92
+ other => other.clone(),
55
93
  }
56
94
  }
57
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
+
58
105
  pub fn resolve_imports(module_loader: &ModuleLoader, global_store: &mut GlobalStore) {
59
106
  for (module_path, module) in global_store.clone().modules.iter_mut() {
60
107
  for (name, source_path) in &module.import_table.imports {
@@ -124,9 +171,7 @@ pub fn resolve_and_flatten_all_modules(
124
171
 
125
172
  // 2. Statements resolution
126
173
  let mut resolved_map: HashMap<String, Vec<Statement>> = HashMap::new();
127
- let store_snapshot = global_store.clone();
128
-
129
- for (path, module) in &store_snapshot.modules {
174
+ for (path, module) in global_store.modules.clone() {
130
175
  let mut resolved = Vec::new();
131
176
 
132
177
  for stmt in &module.statements {
@@ -140,23 +185,23 @@ pub fn resolve_and_flatten_all_modules(
140
185
  &mut duration.clone(),
141
186
  &module,
142
187
  &path,
143
- &store_snapshot
188
+ global_store
144
189
  );
145
190
  resolved.push(resolved_stmt);
146
191
  }
147
192
 
148
193
  StatementKind::Loop => {
149
- let resolved_stmt = resolve_loop(&stmt, &module, &path, &store_snapshot);
194
+ let resolved_stmt = resolve_loop(&stmt, &module, &path, global_store);
150
195
  resolved.push(resolved_stmt);
151
196
  }
152
197
 
153
198
  StatementKind::Bank => {
154
- let resolved_stmt = resolve_bank(&stmt, &module, &path, &store_snapshot);
199
+ let resolved_stmt = resolve_bank(&stmt, &module, &path, global_store);
155
200
  resolved.push(resolved_stmt);
156
201
  }
157
202
 
158
203
  StatementKind::Tempo => {
159
- let resolved_stmt = resolve_tempo(&stmt, &module, &path, &store_snapshot);
204
+ let resolved_stmt = resolve_tempo(&stmt, &module, &path, global_store);
160
205
  resolved.push(resolved_stmt);
161
206
  }
162
207
 
@@ -165,7 +210,7 @@ pub fn resolve_and_flatten_all_modules(
165
210
  }
166
211
 
167
212
  StatementKind::Group => {
168
- let resolved_stmt = resolve_group(&stmt, &module, &path, &store_snapshot);
213
+ let resolved_stmt = resolve_group(&stmt, &module, &path, global_store);
169
214
  resolved.push(resolved_stmt);
170
215
  }
171
216