@devaloop/devalang 0.0.1-alpha.12 → 0.0.1-alpha.13
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.
- package/Cargo.toml +54 -53
- package/README.md +1 -14
- package/docs/CHANGELOG.md +26 -0
- package/docs/TODO.md +1 -1
- package/examples/index.deva +10 -13
- package/out-tsc/bin/devalang.exe +0 -0
- package/package.json +1 -1
- package/project-version.json +3 -3
- package/rust/cli/build.rs +25 -2
- package/rust/cli/check.rs +26 -3
- package/rust/cli/play.rs +1 -1
- package/rust/core/audio/engine.rs +126 -73
- package/rust/core/audio/interpreter/call.rs +72 -47
- package/rust/core/audio/interpreter/condition.rs +14 -12
- package/rust/core/audio/interpreter/driver.rs +84 -127
- package/rust/core/audio/interpreter/function.rs +21 -0
- package/rust/core/audio/interpreter/load.rs +1 -1
- package/rust/core/audio/interpreter/loop_.rs +24 -18
- package/rust/core/audio/interpreter/mod.rs +2 -1
- package/rust/core/audio/interpreter/sleep.rs +0 -6
- package/rust/core/audio/interpreter/spawn.rs +78 -60
- package/rust/core/audio/interpreter/trigger.rs +157 -70
- package/rust/core/audio/loader/trigger.rs +37 -4
- package/rust/core/audio/player.rs +20 -10
- package/rust/core/audio/renderer.rs +24 -25
- package/rust/core/debugger/mod.rs +2 -0
- package/rust/core/debugger/module.rs +47 -0
- package/rust/core/debugger/store.rs +25 -11
- package/rust/core/error/mod.rs +6 -0
- package/rust/core/lexer/handler/driver.rs +23 -1
- package/rust/core/lexer/handler/identifier.rs +1 -0
- package/rust/core/lexer/handler/mod.rs +1 -0
- package/rust/core/lexer/handler/parenthesis.rs +41 -0
- package/rust/core/lexer/token.rs +3 -0
- package/rust/core/parser/driver.rs +3 -1
- package/rust/core/parser/handler/dot.rs +64 -127
- package/rust/core/parser/handler/identifier/call.rs +69 -22
- package/rust/core/parser/handler/identifier/function.rs +92 -0
- package/rust/core/parser/handler/identifier/let_.rs +13 -19
- package/rust/core/parser/handler/identifier/mod.rs +1 -0
- package/rust/core/parser/handler/identifier/spawn.rs +74 -27
- package/rust/core/parser/statement.rs +16 -4
- package/rust/core/preprocessor/loader.rs +45 -29
- package/rust/core/preprocessor/module.rs +3 -1
- package/rust/core/preprocessor/processor.rs +26 -1
- package/rust/core/preprocessor/resolver/call.rs +61 -84
- package/rust/core/preprocessor/resolver/condition.rs +11 -6
- package/rust/core/preprocessor/resolver/driver.rs +52 -6
- package/rust/core/preprocessor/resolver/function.rs +78 -0
- package/rust/core/preprocessor/resolver/group.rs +43 -13
- package/rust/core/preprocessor/resolver/let_.rs +7 -10
- package/rust/core/preprocessor/resolver/mod.rs +2 -1
- package/rust/core/preprocessor/resolver/spawn.rs +64 -30
- package/rust/core/preprocessor/resolver/trigger.rs +7 -3
- package/rust/core/preprocessor/resolver/value.rs +10 -1
- package/rust/core/shared/value.rs +4 -1
- package/rust/core/store/function.rs +34 -0
- package/rust/core/store/global.rs +9 -10
- package/rust/core/store/mod.rs +2 -1
- package/rust/core/store/variable.rs +6 -0
- package/rust/lib.rs +10 -7
- package/rust/utils/mod.rs +45 -1
|
@@ -49,6 +49,11 @@ pub enum StatementKind {
|
|
|
49
49
|
method: String,
|
|
50
50
|
args: Vec<Value>,
|
|
51
51
|
},
|
|
52
|
+
Function {
|
|
53
|
+
name: String,
|
|
54
|
+
parameters: Vec<String>,
|
|
55
|
+
body: Vec<Statement>,
|
|
56
|
+
},
|
|
52
57
|
|
|
53
58
|
// ───── Instruments ─────
|
|
54
59
|
Synth,
|
|
@@ -57,12 +62,19 @@ pub enum StatementKind {
|
|
|
57
62
|
Trigger {
|
|
58
63
|
entity: String,
|
|
59
64
|
duration: Duration,
|
|
65
|
+
effects: Option<Value>,
|
|
60
66
|
},
|
|
61
67
|
Sleep,
|
|
62
|
-
Call
|
|
63
|
-
|
|
68
|
+
Call {
|
|
69
|
+
name: String,
|
|
70
|
+
args: Vec<Value>,
|
|
71
|
+
},
|
|
72
|
+
Spawn {
|
|
73
|
+
name: String,
|
|
74
|
+
args: Vec<Value>,
|
|
75
|
+
},
|
|
64
76
|
Loop,
|
|
65
|
-
|
|
77
|
+
|
|
66
78
|
// ───── Structure & Logic ─────
|
|
67
79
|
Group,
|
|
68
80
|
|
|
@@ -93,4 +105,4 @@ pub enum StatementKind {
|
|
|
93
105
|
Error {
|
|
94
106
|
message: String,
|
|
95
107
|
},
|
|
96
|
-
}
|
|
108
|
+
}
|
|
@@ -127,6 +127,11 @@ impl ModuleLoader {
|
|
|
127
127
|
updated_module.tokens = tokens;
|
|
128
128
|
updated_module.statements = statements;
|
|
129
129
|
|
|
130
|
+
// Step four : Injecting bank triggers if any
|
|
131
|
+
if let Err(e) = self.inject_bank_triggers(&mut updated_module, "808") {
|
|
132
|
+
return Err(format!("Failed to inject bank triggers: {}", e));
|
|
133
|
+
}
|
|
134
|
+
|
|
130
135
|
// Step four : error handling
|
|
131
136
|
let mut error_handler = ErrorHandler::new();
|
|
132
137
|
error_handler.detect_from_statements(&mut parser, &updated_module.statements);
|
|
@@ -143,16 +148,16 @@ impl ModuleLoader {
|
|
|
143
148
|
global_store: &mut GlobalStore
|
|
144
149
|
) -> (HashMap<String, Vec<Token>>, HashMap<String, Vec<Statement>>) {
|
|
145
150
|
// SECTION Load the entry module and its dependencies
|
|
146
|
-
|
|
147
151
|
let tokens_by_module = self.load_module_recursively(&self.entry, global_store);
|
|
148
152
|
|
|
149
153
|
// SECTION Process and resolve modules
|
|
150
154
|
process_modules(self, global_store);
|
|
151
155
|
resolve_all_modules(self, global_store);
|
|
152
156
|
|
|
153
|
-
|
|
157
|
+
// SECTION Flatten all modules to get statements (+ injects)
|
|
158
|
+
let statements_by_module = resolve_and_flatten_all_modules(global_store);
|
|
154
159
|
|
|
155
|
-
(tokens_by_module,
|
|
160
|
+
(tokens_by_module, statements_by_module)
|
|
156
161
|
}
|
|
157
162
|
|
|
158
163
|
#[cfg(feature = "cli")]
|
|
@@ -182,12 +187,15 @@ impl ModuleLoader {
|
|
|
182
187
|
module.statements = statements.clone();
|
|
183
188
|
|
|
184
189
|
// Inject triggers for each bank used in module
|
|
185
|
-
for bank_name in
|
|
186
|
-
|
|
187
|
-
return HashMap::new(); // Return empty map on error
|
|
188
|
-
}
|
|
190
|
+
for bank_name in self.extract_bank_names(&statements) {
|
|
191
|
+
self.inject_bank_triggers(&mut module, &bank_name);
|
|
189
192
|
}
|
|
190
193
|
|
|
194
|
+
// Inject module variables and functions into global store
|
|
195
|
+
global_store.variables.variables.extend(module.variable_table.variables.clone());
|
|
196
|
+
global_store.functions.functions.extend(module.function_table.functions.clone());
|
|
197
|
+
|
|
198
|
+
// Inject the module into the global store
|
|
191
199
|
global_store.insert_module(path.clone(), module);
|
|
192
200
|
|
|
193
201
|
// Load dependencies
|
|
@@ -241,25 +249,29 @@ impl ModuleLoader {
|
|
|
241
249
|
}
|
|
242
250
|
}
|
|
243
251
|
|
|
244
|
-
pub fn inject_bank_triggers(
|
|
252
|
+
pub fn inject_bank_triggers(
|
|
253
|
+
&self,
|
|
254
|
+
module: &mut Module,
|
|
255
|
+
bank_name: &str
|
|
256
|
+
) -> Result<Module, String> {
|
|
245
257
|
let bank_path = Path::new("./.deva/bank").join(bank_name);
|
|
246
|
-
let
|
|
258
|
+
let bank_toml_path = bank_path.join("bank.toml");
|
|
247
259
|
|
|
248
|
-
if !
|
|
249
|
-
return Ok(());
|
|
260
|
+
if !bank_toml_path.exists() {
|
|
261
|
+
return Ok(module.clone());
|
|
250
262
|
}
|
|
251
263
|
|
|
252
264
|
let content = std::fs
|
|
253
|
-
::read_to_string(&
|
|
254
|
-
.map_err(|e| format!("Failed to read '{}': {}",
|
|
265
|
+
::read_to_string(&bank_toml_path)
|
|
266
|
+
.map_err(|e| format!("Failed to read '{}': {}", bank_toml_path.display(), e))?;
|
|
255
267
|
|
|
256
|
-
let
|
|
268
|
+
let parsed_bankfile: BankFile = toml
|
|
257
269
|
::from_str(&content)
|
|
258
|
-
.map_err(|e| format!("Failed to parse '{}': {}",
|
|
270
|
+
.map_err(|e| format!("Failed to parse '{}': {}", bank_toml_path.display(), e))?;
|
|
259
271
|
|
|
260
272
|
let mut bank_map = HashMap::new();
|
|
261
273
|
|
|
262
|
-
for bank_trigger in
|
|
274
|
+
for bank_trigger in parsed_bankfile.triggers.unwrap_or_default() {
|
|
263
275
|
let trigger_name = bank_trigger.name.clone().replace("./", "");
|
|
264
276
|
let bank_trigger_path = format!("devalang://bank/{}/{}", bank_name, trigger_name);
|
|
265
277
|
|
|
@@ -268,7 +280,8 @@ impl ModuleLoader {
|
|
|
268
280
|
if module.variable_table.variables.contains_key(bank_name) {
|
|
269
281
|
eprintln!(
|
|
270
282
|
"⚠️ Trigger '{}' already defined in module '{}', skipping injection.",
|
|
271
|
-
bank_name,
|
|
283
|
+
bank_name,
|
|
284
|
+
module.path
|
|
272
285
|
);
|
|
273
286
|
continue;
|
|
274
287
|
}
|
|
@@ -282,24 +295,27 @@ impl ModuleLoader {
|
|
|
282
295
|
// Inject the map under the bank name
|
|
283
296
|
module.variable_table.set(bank_name.to_string(), Value::Map(bank_map));
|
|
284
297
|
|
|
285
|
-
Ok(())
|
|
298
|
+
Ok(module.clone())
|
|
286
299
|
}
|
|
287
300
|
|
|
288
|
-
fn extract_bank_names(statements: &[Statement]) -> HashSet<String> {
|
|
301
|
+
fn extract_bank_names(&self, statements: &[Statement]) -> HashSet<String> {
|
|
289
302
|
let mut banks = HashSet::new();
|
|
290
303
|
|
|
291
304
|
for stmt in statements {
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
305
|
+
match &stmt.kind {
|
|
306
|
+
// Extract only bank declarations
|
|
307
|
+
StatementKind::Bank => {
|
|
308
|
+
if let Value::String(name) = &stmt.value {
|
|
309
|
+
banks.insert(name.clone());
|
|
310
|
+
}
|
|
311
|
+
if let Value::Number(num) = &stmt.value {
|
|
312
|
+
banks.insert(num.to_string());
|
|
313
|
+
}
|
|
314
|
+
if let Value::Identifier(name) = &stmt.value {
|
|
315
|
+
banks.insert(name.clone());
|
|
316
|
+
}
|
|
302
317
|
}
|
|
318
|
+
_ => {}
|
|
303
319
|
}
|
|
304
320
|
}
|
|
305
321
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
use crate::core::{
|
|
2
2
|
lexer::token::Token,
|
|
3
3
|
parser::statement::Statement,
|
|
4
|
-
store::{ export::ExportTable, import::ImportTable, variable::VariableTable },
|
|
4
|
+
store::{ export::ExportTable, function::FunctionTable, import::ImportTable, variable::VariableTable },
|
|
5
5
|
};
|
|
6
6
|
|
|
7
7
|
#[derive(Debug, Clone)]
|
|
@@ -11,6 +11,7 @@ pub struct Module {
|
|
|
11
11
|
pub tokens: Vec<Token>,
|
|
12
12
|
pub statements: Vec<Statement>,
|
|
13
13
|
pub variable_table: VariableTable,
|
|
14
|
+
pub function_table: FunctionTable,
|
|
14
15
|
pub export_table: ExportTable,
|
|
15
16
|
pub import_table: ImportTable,
|
|
16
17
|
pub content: String,
|
|
@@ -24,6 +25,7 @@ impl Module {
|
|
|
24
25
|
tokens: Vec::new(),
|
|
25
26
|
statements: Vec::new(),
|
|
26
27
|
variable_table: VariableTable::new(),
|
|
28
|
+
function_table: FunctionTable::new(),
|
|
27
29
|
export_table: ExportTable::new(),
|
|
28
30
|
import_table: ImportTable::new(),
|
|
29
31
|
resolved: false,
|
|
@@ -5,7 +5,7 @@ use crate::core::{
|
|
|
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
|
+
utils::path::{ normalize_path, resolve_relative_path },
|
|
9
9
|
};
|
|
10
10
|
|
|
11
11
|
pub fn process_modules(module_loader: &ModuleLoader, global_store: &mut GlobalStore) {
|
|
@@ -13,6 +13,31 @@ pub fn process_modules(module_loader: &ModuleLoader, global_store: &mut GlobalSt
|
|
|
13
13
|
for stmt in &module.statements {
|
|
14
14
|
match &stmt.kind {
|
|
15
15
|
StatementKind::Let { name } => {
|
|
16
|
+
if let Value::Null = stmt.value {
|
|
17
|
+
eprintln!("❌ Variable '{}' is declared but not initialized.", name);
|
|
18
|
+
|
|
19
|
+
module.variable_table.variables.insert(
|
|
20
|
+
name.clone(),
|
|
21
|
+
Value::StatementKind(Box::new(stmt.kind.clone()))
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if module.variable_table.get(name).is_some() {
|
|
28
|
+
eprintln!("❌ Variable '{}' is already defined in this scope.", name);
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if let Some(module_variable) = module.variable_table.variables.get(name) {
|
|
33
|
+
eprintln!(
|
|
34
|
+
"❌ Variable '{}' is already defined globally with value: {:?}",
|
|
35
|
+
name,
|
|
36
|
+
module_variable
|
|
37
|
+
);
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
|
|
16
41
|
module.variable_table.variables.insert(name.clone(), stmt.value.clone());
|
|
17
42
|
}
|
|
18
43
|
|
|
@@ -10,103 +10,80 @@ use crate::{
|
|
|
10
10
|
|
|
11
11
|
pub fn resolve_call(
|
|
12
12
|
stmt: &Statement,
|
|
13
|
+
name: String,
|
|
14
|
+
args: Vec<Value>,
|
|
13
15
|
module: &Module,
|
|
14
16
|
path: &str,
|
|
15
17
|
global_store: &mut GlobalStore
|
|
16
18
|
) -> Statement {
|
|
17
19
|
let logger = Logger::new();
|
|
18
20
|
|
|
19
|
-
match &stmt.
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
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
|
-
}
|
|
21
|
+
match &stmt.kind {
|
|
22
|
+
StatementKind::Call { .. } => {
|
|
23
|
+
// Check if it's a function
|
|
24
|
+
if let Some(func) = global_store.functions.functions.get(&name) {
|
|
25
|
+
let mut call_map = std::collections::HashMap::new();
|
|
26
|
+
call_map.insert("name".to_string(), Value::Identifier(name.clone()));
|
|
27
|
+
call_map.insert(
|
|
28
|
+
"parameters".to_string(),
|
|
29
|
+
Value::Array(
|
|
30
|
+
func.parameters
|
|
31
|
+
.iter()
|
|
32
|
+
.map(|p| Value::Identifier(p.clone()))
|
|
33
|
+
.collect()
|
|
34
|
+
)
|
|
35
|
+
);
|
|
36
|
+
call_map.insert("args".to_string(), Value::Array(args.clone()));
|
|
37
|
+
call_map.insert("body".to_string(), Value::Block(func.body.clone()));
|
|
45
38
|
|
|
46
|
-
|
|
47
|
-
|
|
39
|
+
return Statement {
|
|
40
|
+
kind: StatementKind::Call { name, args },
|
|
41
|
+
value: Value::Map(call_map),
|
|
42
|
+
..stmt.clone()
|
|
43
|
+
};
|
|
44
|
+
}
|
|
48
45
|
|
|
49
|
-
|
|
46
|
+
// Otherwise, check if it's a variable (e.g. group)
|
|
47
|
+
if let Some(variable) = global_store.variables.variables.get(&name) {
|
|
48
|
+
if let Value::Statement(stmt_box) = variable {
|
|
49
|
+
if let StatementKind::Group = stmt_box.kind {
|
|
50
|
+
if let Value::Map(map) = &stmt_box.value {
|
|
51
|
+
if let Some(Value::Block(body)) = map.get("body") {
|
|
52
|
+
let mut resolved_map = std::collections::HashMap::new();
|
|
53
|
+
resolved_map.insert(
|
|
54
|
+
"identifier".to_string(),
|
|
55
|
+
Value::String(name.clone())
|
|
56
|
+
);
|
|
57
|
+
resolved_map.insert("args".to_string(), Value::Array(args.clone()));
|
|
58
|
+
resolved_map.insert("body".to_string(), Value::Block(body.clone()));
|
|
50
59
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
}
|
|
60
|
+
return Statement {
|
|
61
|
+
kind: StatementKind::Call { name, args },
|
|
62
|
+
value: Value::Map(resolved_map),
|
|
63
|
+
..stmt.clone()
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
60
70
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
)
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
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
|
-
),
|
|
71
|
+
// Otherwise, log an error
|
|
72
|
+
logger.log_message(LogLevel::Error, &format!("Function or group '{}' not found", name));
|
|
73
|
+
Statement {
|
|
74
|
+
kind: StatementKind::Error {
|
|
75
|
+
message: format!("Function or group '{}' not found", name),
|
|
76
|
+
},
|
|
77
|
+
value: Value::Null,
|
|
78
|
+
..stmt.clone()
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
_ => error_stmt(&logger, module, stmt, "Expected StatementKind::Call in resolve_call()"),
|
|
85
82
|
}
|
|
86
83
|
}
|
|
87
84
|
|
|
88
|
-
fn
|
|
89
|
-
|
|
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
|
-
}
|
|
85
|
+
fn get_group_body(stmt_box: &Statement) -> Vec<Statement> {
|
|
86
|
+
if let Value::Block(body) = &stmt_box.value { body.clone() } else { vec![] }
|
|
110
87
|
}
|
|
111
88
|
|
|
112
89
|
fn error_stmt(logger: &Logger, module: &Module, stmt: &Statement, message: &str) -> Statement {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
use crate::{
|
|
2
2
|
core::{
|
|
3
|
-
parser::statement::{Statement, StatementKind},
|
|
4
|
-
preprocessor::{module::Module, resolver::driver::resolve_statement},
|
|
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
|
},
|
|
@@ -12,12 +12,17 @@ pub fn resolve_condition(
|
|
|
12
12
|
stmt: &Statement,
|
|
13
13
|
module: &Module,
|
|
14
14
|
path: &str,
|
|
15
|
-
global_store: &mut GlobalStore
|
|
15
|
+
global_store: &mut GlobalStore
|
|
16
16
|
) -> Statement {
|
|
17
17
|
let logger = Logger::new();
|
|
18
18
|
|
|
19
19
|
let Value::Map(condition_map) = &stmt.value else {
|
|
20
|
-
return type_error(
|
|
20
|
+
return type_error(
|
|
21
|
+
&logger,
|
|
22
|
+
module,
|
|
23
|
+
stmt,
|
|
24
|
+
"Expected a map in condition statement".to_string()
|
|
25
|
+
);
|
|
21
26
|
};
|
|
22
27
|
|
|
23
28
|
let mut resolved_map = condition_map.clone();
|
|
@@ -60,13 +65,13 @@ fn resolve_block_statements(
|
|
|
60
65
|
body: &[Statement],
|
|
61
66
|
module: &Module,
|
|
62
67
|
path: &str,
|
|
63
|
-
global_store: &mut GlobalStore
|
|
68
|
+
global_store: &mut GlobalStore
|
|
64
69
|
) -> Vec<Statement> {
|
|
65
70
|
body.iter()
|
|
66
71
|
.flat_map(|stmt| {
|
|
67
72
|
let resolved = resolve_statement(stmt, module, path, global_store);
|
|
68
73
|
|
|
69
|
-
if let StatementKind::Call = resolved.kind {
|
|
74
|
+
if let StatementKind::Call { .. } = resolved.kind {
|
|
70
75
|
if let Value::Block(inner) = &resolved.value {
|
|
71
76
|
return inner
|
|
72
77
|
.iter()
|
|
@@ -9,6 +9,7 @@ use crate::{
|
|
|
9
9
|
bank::resolve_bank,
|
|
10
10
|
call::resolve_call,
|
|
11
11
|
condition::resolve_condition,
|
|
12
|
+
function::resolve_function,
|
|
12
13
|
group::resolve_group,
|
|
13
14
|
let_::resolve_let,
|
|
14
15
|
loop_::resolve_loop,
|
|
@@ -36,12 +37,22 @@ pub fn resolve_statement(
|
|
|
36
37
|
global_store: &mut GlobalStore
|
|
37
38
|
) -> Statement {
|
|
38
39
|
match &stmt.kind {
|
|
39
|
-
StatementKind::Trigger { entity, duration } =>
|
|
40
|
-
resolve_trigger(
|
|
40
|
+
StatementKind::Trigger { entity, duration, effects } =>
|
|
41
|
+
resolve_trigger(
|
|
42
|
+
stmt,
|
|
43
|
+
entity,
|
|
44
|
+
&mut duration.clone(),
|
|
45
|
+
effects.clone(),
|
|
46
|
+
module,
|
|
47
|
+
path,
|
|
48
|
+
global_store
|
|
49
|
+
),
|
|
41
50
|
StatementKind::If => resolve_condition(stmt, module, path, global_store),
|
|
42
51
|
StatementKind::Group => resolve_group(stmt, module, path, global_store),
|
|
43
|
-
StatementKind::Call
|
|
44
|
-
|
|
52
|
+
StatementKind::Call { name, args } =>
|
|
53
|
+
resolve_call(stmt, name.clone(), args.clone(), module, path, global_store),
|
|
54
|
+
StatementKind::Spawn { name, args } =>
|
|
55
|
+
resolve_spawn(stmt, name.clone(), args.clone(), module, path, global_store),
|
|
45
56
|
StatementKind::Bank => resolve_bank(stmt, module, path, global_store),
|
|
46
57
|
StatementKind::Tempo => resolve_tempo(stmt, module, path, global_store),
|
|
47
58
|
StatementKind::Loop => resolve_loop(stmt, module, path, global_store),
|
|
@@ -180,14 +191,20 @@ pub fn resolve_and_flatten_all_modules(
|
|
|
180
191
|
let mut resolved = Vec::new();
|
|
181
192
|
|
|
182
193
|
for stmt in &module.statements {
|
|
183
|
-
let
|
|
194
|
+
let stmt = stmt.clone();
|
|
184
195
|
|
|
185
196
|
match &stmt.kind {
|
|
186
|
-
StatementKind::
|
|
197
|
+
StatementKind::Let { name } => {
|
|
198
|
+
let resolved_stmt = resolve_let(&stmt, name, &module, &path, global_store);
|
|
199
|
+
resolved.push(resolved_stmt);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
StatementKind::Trigger { entity, duration, effects } => {
|
|
187
203
|
let resolved_stmt = resolve_trigger(
|
|
188
204
|
&stmt,
|
|
189
205
|
entity.as_str(),
|
|
190
206
|
&mut duration.clone(),
|
|
207
|
+
effects.clone(),
|
|
191
208
|
&module,
|
|
192
209
|
&path,
|
|
193
210
|
global_store
|
|
@@ -214,11 +231,40 @@ pub fn resolve_and_flatten_all_modules(
|
|
|
214
231
|
resolved.push(stmt.clone());
|
|
215
232
|
}
|
|
216
233
|
|
|
234
|
+
StatementKind::Call { name, args } => {
|
|
235
|
+
let resolved_stmt = resolve_call(
|
|
236
|
+
&stmt,
|
|
237
|
+
name.clone(),
|
|
238
|
+
args.clone(),
|
|
239
|
+
&module,
|
|
240
|
+
&path,
|
|
241
|
+
global_store
|
|
242
|
+
);
|
|
243
|
+
resolved.push(resolved_stmt);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
StatementKind::Spawn { name, args } => {
|
|
247
|
+
let resolved_stmt = resolve_spawn(
|
|
248
|
+
&stmt,
|
|
249
|
+
name.clone(),
|
|
250
|
+
args.clone(),
|
|
251
|
+
&module,
|
|
252
|
+
&path,
|
|
253
|
+
global_store
|
|
254
|
+
);
|
|
255
|
+
resolved.push(resolved_stmt);
|
|
256
|
+
}
|
|
257
|
+
|
|
217
258
|
StatementKind::Group => {
|
|
218
259
|
let resolved_stmt = resolve_group(&stmt, &module, &path, global_store);
|
|
219
260
|
resolved.push(resolved_stmt);
|
|
220
261
|
}
|
|
221
262
|
|
|
263
|
+
StatementKind::Function { name, parameters, body } => {
|
|
264
|
+
let resolved_function = resolve_function(&stmt, &module, &path, global_store);
|
|
265
|
+
resolved.push(resolved_function);
|
|
266
|
+
}
|
|
267
|
+
|
|
222
268
|
_ => {
|
|
223
269
|
resolved.push(stmt);
|
|
224
270
|
}
|
|
@@ -0,0 +1,78 @@
|
|
|
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::{ function::FunctionDef, global::GlobalStore, variable::VariableTable },
|
|
9
|
+
},
|
|
10
|
+
utils::logger::{ LogLevel, Logger },
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
pub fn resolve_function(
|
|
14
|
+
stmt: &Statement,
|
|
15
|
+
module: &Module,
|
|
16
|
+
path: &str,
|
|
17
|
+
global_store: &mut GlobalStore
|
|
18
|
+
) -> Statement {
|
|
19
|
+
if let StatementKind::Function { name, parameters, body } = &stmt.kind {
|
|
20
|
+
let resolved_body = resolve_block_statements(body, &module, path, global_store);
|
|
21
|
+
|
|
22
|
+
global_store.functions.add_function(FunctionDef {
|
|
23
|
+
name: name.clone(),
|
|
24
|
+
parameters: parameters.clone(),
|
|
25
|
+
body: resolved_body.clone(),
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
if let Some(current_mod) = global_store.modules.get_mut(path) {
|
|
29
|
+
current_mod.function_table.add_function(FunctionDef {
|
|
30
|
+
name: name.clone(),
|
|
31
|
+
parameters: parameters.clone(),
|
|
32
|
+
body: resolved_body.clone(),
|
|
33
|
+
});
|
|
34
|
+
} else {
|
|
35
|
+
eprintln!("[resolve_statement] ❌ Module path not found: {path}");
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return Statement {
|
|
39
|
+
kind: StatementKind::Function {
|
|
40
|
+
name: name.clone(),
|
|
41
|
+
parameters: parameters.clone(),
|
|
42
|
+
body: resolved_body,
|
|
43
|
+
},
|
|
44
|
+
value: Value::Null,
|
|
45
|
+
..stmt.clone()
|
|
46
|
+
};
|
|
47
|
+
} else {
|
|
48
|
+
return Statement {
|
|
49
|
+
kind: StatementKind::Error {
|
|
50
|
+
message: "Expected a function statement".to_string(),
|
|
51
|
+
},
|
|
52
|
+
value: Value::Null,
|
|
53
|
+
..stmt.clone()
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
fn resolve_block_statements(
|
|
59
|
+
body: &[Statement],
|
|
60
|
+
module: &Module,
|
|
61
|
+
path: &str,
|
|
62
|
+
global_store: &mut GlobalStore
|
|
63
|
+
) -> Vec<Statement> {
|
|
64
|
+
body.iter()
|
|
65
|
+
.map(|stmt| resolve_statement(stmt, module, path, global_store))
|
|
66
|
+
.collect()
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
fn type_error(logger: &Logger, module: &Module, stmt: &Statement, message: String) -> Statement {
|
|
70
|
+
let stacktrace = format!("{}:{}:{}", module.path, stmt.line, stmt.column);
|
|
71
|
+
logger.log_error_with_stacktrace(&message, &stacktrace);
|
|
72
|
+
|
|
73
|
+
Statement {
|
|
74
|
+
kind: StatementKind::Error { message },
|
|
75
|
+
value: Value::Null,
|
|
76
|
+
..stmt.clone()
|
|
77
|
+
}
|
|
78
|
+
}
|