@devaloop/devalang 0.0.1-alpha.11 → 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/.devalang +8 -8
- package/Cargo.toml +8 -8
- package/README.md +1 -14
- package/docs/CHANGELOG.md +44 -0
- package/docs/TODO.md +1 -1
- package/examples/index.deva +10 -11
- package/out-tsc/bin/devalang.exe +0 -0
- package/package.json +2 -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 +207 -41
- 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 +169 -61
- 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 +31 -3
- package/rust/core/parser/handler/dot.rs +65 -129
- 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/installer/bank.rs +1 -1
- package/rust/installer/mod.rs +2 -1
- package/rust/lib.rs +10 -8
- package/rust/utils/mod.rs +44 -1
- /package/rust/{utils/installer.rs → installer/utils.rs} +0 -0
|
@@ -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
|
+
}
|
|
@@ -1,20 +1,18 @@
|
|
|
1
|
-
use std::collections::HashMap;
|
|
2
|
-
|
|
3
1
|
use crate::{
|
|
4
2
|
core::{
|
|
5
|
-
parser::statement::{
|
|
6
|
-
preprocessor::{
|
|
3
|
+
parser::statement::{Statement, StatementKind},
|
|
4
|
+
preprocessor::{module::Module, resolver::driver::resolve_statement},
|
|
7
5
|
shared::value::Value,
|
|
8
|
-
store::
|
|
6
|
+
store::global::GlobalStore,
|
|
9
7
|
},
|
|
10
|
-
utils::logger::{
|
|
8
|
+
utils::logger::{LogLevel, Logger},
|
|
11
9
|
};
|
|
12
10
|
|
|
13
11
|
pub fn resolve_group(
|
|
14
12
|
stmt: &Statement,
|
|
15
13
|
module: &Module,
|
|
16
14
|
path: &str,
|
|
17
|
-
global_store: &mut GlobalStore
|
|
15
|
+
global_store: &mut GlobalStore,
|
|
18
16
|
) -> Statement {
|
|
19
17
|
let logger = Logger::new();
|
|
20
18
|
|
|
@@ -22,27 +20,59 @@ pub fn resolve_group(
|
|
|
22
20
|
return type_error(&logger, module, stmt, "Expected a map in group statement".to_string());
|
|
23
21
|
};
|
|
24
22
|
|
|
25
|
-
|
|
23
|
+
// Check for the presence of the identifier field
|
|
24
|
+
let identifier = match group_map.get("identifier") {
|
|
25
|
+
Some(Value::String(id)) => id.clone(),
|
|
26
|
+
_ => {
|
|
27
|
+
return type_error(
|
|
28
|
+
&logger,
|
|
29
|
+
module,
|
|
30
|
+
stmt,
|
|
31
|
+
"Group statement must have an 'identifier' field".to_string(),
|
|
32
|
+
)
|
|
33
|
+
}
|
|
34
|
+
};
|
|
26
35
|
|
|
36
|
+
// Ensure the identifier does not already exist
|
|
37
|
+
if global_store.variables.variables.contains_key(&identifier) {
|
|
38
|
+
return type_error(
|
|
39
|
+
&logger,
|
|
40
|
+
module,
|
|
41
|
+
stmt,
|
|
42
|
+
format!("Group identifier '{}' already exists", identifier),
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Resolve statements in the body
|
|
47
|
+
let mut resolved_map = group_map.clone();
|
|
27
48
|
if let Some(Value::Block(body)) = group_map.get("body") {
|
|
28
49
|
let resolved_body = resolve_block_statements(body, module, path, global_store);
|
|
29
50
|
resolved_map.insert("body".to_string(), Value::Block(resolved_body));
|
|
30
51
|
} else {
|
|
31
|
-
logger.log_message(LogLevel::Warning, "
|
|
52
|
+
logger.log_message(LogLevel::Warning, "Group without a body");
|
|
32
53
|
}
|
|
33
54
|
|
|
34
|
-
Statement
|
|
55
|
+
// Build a complete Statement for the group
|
|
56
|
+
let resolved_group_stmt = Statement {
|
|
35
57
|
kind: StatementKind::Group,
|
|
36
|
-
value: Value::Map(resolved_map),
|
|
58
|
+
value: Value::Map(resolved_map.clone()),
|
|
37
59
|
..stmt.clone()
|
|
38
|
-
}
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
// Store the Statement directly in the global variable_table
|
|
63
|
+
global_store
|
|
64
|
+
.variables
|
|
65
|
+
.variables
|
|
66
|
+
.insert(identifier.clone(), Value::Statement(Box::new(resolved_group_stmt.clone())));
|
|
67
|
+
|
|
68
|
+
resolved_group_stmt
|
|
39
69
|
}
|
|
40
70
|
|
|
41
71
|
fn resolve_block_statements(
|
|
42
72
|
body: &[Statement],
|
|
43
73
|
module: &Module,
|
|
44
74
|
path: &str,
|
|
45
|
-
global_store: &mut GlobalStore
|
|
75
|
+
global_store: &mut GlobalStore,
|
|
46
76
|
) -> Vec<Statement> {
|
|
47
77
|
body.iter()
|
|
48
78
|
.map(|stmt| resolve_statement(stmt, module, path, global_store))
|
|
@@ -1,13 +1,8 @@
|
|
|
1
|
-
use crate::
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
resolver:: value::resolve_value ,
|
|
7
|
-
},
|
|
8
|
-
store:: global::GlobalStore ,
|
|
9
|
-
}
|
|
10
|
-
;
|
|
1
|
+
use crate::core::{
|
|
2
|
+
parser::statement::Statement,
|
|
3
|
+
preprocessor::{ module::Module, resolver::value::resolve_value },
|
|
4
|
+
store::global::GlobalStore,
|
|
5
|
+
};
|
|
11
6
|
|
|
12
7
|
pub fn resolve_let(
|
|
13
8
|
stmt: &Statement,
|
|
@@ -18,6 +13,8 @@ pub fn resolve_let(
|
|
|
18
13
|
) -> Statement {
|
|
19
14
|
let resolved_value = resolve_value(&stmt.value, module, global_store);
|
|
20
15
|
|
|
16
|
+
global_store.variables.set(name.to_string(), resolved_value.clone());
|
|
17
|
+
|
|
21
18
|
if let Some(current_mod) = global_store.modules.get_mut(path) {
|
|
22
19
|
current_mod.variable_table.set(name.to_string(), resolved_value.clone());
|
|
23
20
|
} else {
|
|
@@ -14,45 +14,79 @@ use crate::{
|
|
|
14
14
|
|
|
15
15
|
pub fn resolve_spawn(
|
|
16
16
|
stmt: &Statement,
|
|
17
|
+
name: String,
|
|
18
|
+
args: Vec<Value>,
|
|
17
19
|
module: &Module,
|
|
18
20
|
path: &str,
|
|
19
21
|
global_store: &mut GlobalStore
|
|
20
22
|
) -> Statement {
|
|
21
23
|
let logger = Logger::new();
|
|
22
24
|
|
|
23
|
-
|
|
25
|
+
// ✅ Si c'est une fonction
|
|
26
|
+
if let Some(func) = global_store.functions.functions.get(&name) {
|
|
27
|
+
let mut resolved_map = std::collections::HashMap::new();
|
|
28
|
+
resolved_map.insert("name".to_string(), Value::String(name.clone()));
|
|
29
|
+
resolved_map.insert("args".to_string(), Value::Array(args.clone()));
|
|
30
|
+
resolved_map.insert("body".to_string(), Value::Block(func.body.clone()));
|
|
24
31
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
.collect();
|
|
32
|
-
map.insert("body".to_string(), Value::Block(resolved_block));
|
|
33
|
-
}
|
|
32
|
+
return Statement {
|
|
33
|
+
kind: StatementKind::Spawn { name, args },
|
|
34
|
+
value: Value::Map(resolved_map),
|
|
35
|
+
..stmt.clone()
|
|
36
|
+
};
|
|
37
|
+
}
|
|
34
38
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
// ✅ Si c'est un group dans les variables
|
|
40
|
+
if let Some(variable) = global_store.variables.variables.get(&name) {
|
|
41
|
+
if let Value::Statement(stmt_box) = variable {
|
|
42
|
+
if let StatementKind::Group = stmt_box.kind {
|
|
43
|
+
if let Value::Map(map) = &stmt_box.value {
|
|
44
|
+
if let Some(Value::Block(body)) = map.get("body") {
|
|
45
|
+
let mut resolved_map = std::collections::HashMap::new();
|
|
46
|
+
resolved_map.insert("identifier".to_string(), Value::String(name.clone()));
|
|
47
|
+
resolved_map.insert("args".to_string(), Value::Array(args.clone()));
|
|
48
|
+
resolved_map.insert("body".to_string(), Value::Block(body.clone()));
|
|
41
49
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
Statement {
|
|
50
|
-
kind: StatementKind::Error {
|
|
51
|
-
message: "Invalid spawn value".to_string(),
|
|
52
|
-
},
|
|
53
|
-
value: Value::Null,
|
|
54
|
-
..stmt.clone()
|
|
50
|
+
return Statement {
|
|
51
|
+
kind: StatementKind::Spawn { name, args },
|
|
52
|
+
value: Value::Map(resolved_map),
|
|
53
|
+
..stmt.clone()
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
}
|
|
55
57
|
}
|
|
56
58
|
}
|
|
57
59
|
}
|
|
58
|
-
|
|
60
|
+
|
|
61
|
+
// ❌ Sinon erreur
|
|
62
|
+
let stacktrace = format!("{}:{}:{}", module.path, stmt.line, stmt.column);
|
|
63
|
+
logger.log_message(
|
|
64
|
+
LogLevel::Error,
|
|
65
|
+
&format!("Function or group '{}' not found for spawn\n → at {stacktrace}", name)
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
Statement {
|
|
69
|
+
kind: StatementKind::Error {
|
|
70
|
+
message: format!("Function or group '{}' not found for spawn", name),
|
|
71
|
+
},
|
|
72
|
+
value: Value::Null,
|
|
73
|
+
..stmt.clone()
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
fn get_group_body(stmt_box: &Statement) -> Vec<Statement> {
|
|
78
|
+
if let Value::Block(body) = &stmt_box.value { body.clone() } else { vec![] }
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
fn error_stmt(logger: &Logger, module: &Module, stmt: &Statement, message: &str) -> Statement {
|
|
82
|
+
let stacktrace = format!("{}:{}:{}", module.path, stmt.line, stmt.column);
|
|
83
|
+
logger.log_message(LogLevel::Error, &format!("{message}\n → at {stacktrace}"));
|
|
84
|
+
|
|
85
|
+
Statement {
|
|
86
|
+
kind: StatementKind::Error {
|
|
87
|
+
message: message.to_string(),
|
|
88
|
+
},
|
|
89
|
+
value: Value::Null,
|
|
90
|
+
..stmt.clone()
|
|
91
|
+
}
|
|
92
|
+
}
|
|
@@ -14,6 +14,7 @@ pub fn resolve_trigger(
|
|
|
14
14
|
stmt: &Statement,
|
|
15
15
|
entity: &str,
|
|
16
16
|
duration: &mut Duration,
|
|
17
|
+
effects: Option<Value>,
|
|
17
18
|
module: &Module,
|
|
18
19
|
path: &str,
|
|
19
20
|
global_store: &GlobalStore
|
|
@@ -44,6 +45,8 @@ pub fn resolve_trigger(
|
|
|
44
45
|
// Params value resolution
|
|
45
46
|
final_value = match &stmt.value {
|
|
46
47
|
Value::Identifier(ident) => {
|
|
48
|
+
println!("Resolving identifier: {}", ident);
|
|
49
|
+
|
|
47
50
|
resolve_identifier(ident, module, global_store).unwrap_or_else(|| {
|
|
48
51
|
logger.log_error_with_stacktrace(
|
|
49
52
|
&format!("'{path}': value identifier '{ident}' not found"),
|
|
@@ -71,9 +74,10 @@ pub fn resolve_trigger(
|
|
|
71
74
|
Statement {
|
|
72
75
|
kind: StatementKind::Trigger {
|
|
73
76
|
entity: entity.to_string(),
|
|
74
|
-
duration: final_duration,
|
|
77
|
+
duration: final_duration.clone(),
|
|
78
|
+
effects: Some(final_value.clone()),
|
|
75
79
|
},
|
|
76
|
-
value:
|
|
80
|
+
value: Value::Null,
|
|
77
81
|
line: stmt.line,
|
|
78
82
|
column: stmt.column,
|
|
79
83
|
indent: stmt.indent,
|
|
@@ -86,7 +90,7 @@ fn resolve_identifier(ident: &str, module: &Module, global_store: &GlobalStore)
|
|
|
86
90
|
}
|
|
87
91
|
|
|
88
92
|
for (_, other_mod) in &global_store.modules {
|
|
89
|
-
if let Some(val) = other_mod.
|
|
93
|
+
if let Some(val) = other_mod.variable_table.get(ident) {
|
|
90
94
|
return Some(resolve_value(val, other_mod, global_store));
|
|
91
95
|
}
|
|
92
96
|
}
|
|
@@ -16,11 +16,18 @@ fn find_export_value(name: &str, global_store: &GlobalStore) -> Option<Value> {
|
|
|
16
16
|
return Some(val.clone());
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
|
+
|
|
19
20
|
None
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
pub fn resolve_value(value: &Value, module: &Module, global_store: &mut GlobalStore) -> Value {
|
|
23
24
|
match value {
|
|
25
|
+
Value::String(s) => {
|
|
26
|
+
println!("Resolving value: {}", s);
|
|
27
|
+
|
|
28
|
+
Value::String(s.clone())
|
|
29
|
+
},
|
|
30
|
+
|
|
24
31
|
Value::Identifier(name) => {
|
|
25
32
|
if let Some(original_val) = module.variable_table.get(name) {
|
|
26
33
|
return resolve_value(original_val, module, global_store);
|
|
@@ -30,7 +37,8 @@ pub fn resolve_value(value: &Value, module: &Module, global_store: &mut GlobalSt
|
|
|
30
37
|
return resolve_value(&export_val, module, global_store);
|
|
31
38
|
}
|
|
32
39
|
|
|
33
|
-
|
|
40
|
+
println!("⚠️ Unresolved identifier '{}'", name);
|
|
41
|
+
|
|
34
42
|
Value::Null
|
|
35
43
|
}
|
|
36
44
|
|
|
@@ -62,6 +70,7 @@ pub fn resolve_value(value: &Value, module: &Module, global_store: &mut GlobalSt
|
|
|
62
70
|
for (k, v) in map {
|
|
63
71
|
resolved.insert(k.clone(), resolve_value(v, module, global_store));
|
|
64
72
|
}
|
|
73
|
+
|
|
65
74
|
Value::Map(resolved)
|
|
66
75
|
}
|
|
67
76
|
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
use std::collections::HashMap;
|
|
2
2
|
use serde::{ Deserialize, Serialize };
|
|
3
3
|
|
|
4
|
-
use crate::core::parser::statement::Statement;
|
|
4
|
+
use crate::core::{parser::statement::{Statement, StatementKind}, shared::duration::Duration};
|
|
5
5
|
|
|
6
6
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
|
7
7
|
pub enum Value {
|
|
8
8
|
Boolean(bool),
|
|
9
9
|
Number(f32),
|
|
10
|
+
Duration(Duration),
|
|
10
11
|
Identifier(String),
|
|
11
12
|
String(String),
|
|
12
13
|
Array(Vec<Value>),
|
|
@@ -14,6 +15,8 @@ pub enum Value {
|
|
|
14
15
|
Block(Vec<Statement>),
|
|
15
16
|
Sample(String),
|
|
16
17
|
Beat(String),
|
|
18
|
+
Statement(Box<Statement>),
|
|
19
|
+
StatementKind(Box<StatementKind>),
|
|
17
20
|
Unknown,
|
|
18
21
|
Null,
|
|
19
22
|
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
use std::collections::HashMap;
|
|
2
|
+
use crate::core::parser::statement::Statement;
|
|
3
|
+
|
|
4
|
+
#[derive(Debug, Clone)]
|
|
5
|
+
pub struct FunctionDef {
|
|
6
|
+
pub name: String,
|
|
7
|
+
pub parameters: Vec<String>,
|
|
8
|
+
pub body: Vec<Statement>,
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
#[derive(Debug, Clone)]
|
|
12
|
+
pub struct FunctionTable {
|
|
13
|
+
pub functions: HashMap<String, FunctionDef>,
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
impl FunctionTable {
|
|
17
|
+
pub fn new() -> Self {
|
|
18
|
+
FunctionTable {
|
|
19
|
+
functions: HashMap::new(),
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
pub fn add_function(&mut self, function: FunctionDef) {
|
|
24
|
+
self.functions.insert(function.name.clone(), function);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
pub fn get_function(&self, name: &str) -> Option<&FunctionDef> {
|
|
28
|
+
self.functions.get(name)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
pub fn remove_function(&mut self, name: &str) -> Option<FunctionDef> {
|
|
32
|
+
self.functions.remove(name)
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -1,23 +1,22 @@
|
|
|
1
1
|
use std::collections::HashMap;
|
|
2
|
-
use crate::core::
|
|
2
|
+
use crate::core::{
|
|
3
|
+
preprocessor::module::Module,
|
|
4
|
+
store::{ function::FunctionTable, variable::VariableTable },
|
|
5
|
+
};
|
|
3
6
|
|
|
4
|
-
#[derive(Debug,
|
|
7
|
+
#[derive(Debug, Clone)]
|
|
5
8
|
pub struct GlobalStore {
|
|
6
9
|
pub modules: HashMap<String, Module>,
|
|
10
|
+
pub variables: VariableTable,
|
|
11
|
+
pub functions: FunctionTable,
|
|
7
12
|
}
|
|
8
13
|
|
|
9
14
|
impl GlobalStore {
|
|
10
15
|
pub fn new() -> Self {
|
|
11
16
|
GlobalStore {
|
|
12
17
|
modules: HashMap::new(),
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
pub fn resolve_all_imports(&mut self) {
|
|
17
|
-
for module in self.modules.values_mut() {
|
|
18
|
-
for (name, source_path) in &module.import_table.imports {
|
|
19
|
-
println!("Resolving import: {} from {:?}", name, source_path);
|
|
20
|
-
}
|
|
18
|
+
functions: FunctionTable::new(),
|
|
19
|
+
variables: VariableTable::new(),
|
|
21
20
|
}
|
|
22
21
|
}
|
|
23
22
|
|
package/rust/core/store/mod.rs
CHANGED
|
@@ -5,12 +5,14 @@ use crate::core::shared::value::Value;
|
|
|
5
5
|
#[derive(Debug, Default, Clone, PartialEq)]
|
|
6
6
|
pub struct VariableTable {
|
|
7
7
|
pub variables: HashMap<String, Value>,
|
|
8
|
+
pub parent: Option<Box<VariableTable>>,
|
|
8
9
|
}
|
|
9
10
|
|
|
10
11
|
impl VariableTable {
|
|
11
12
|
pub fn new() -> Self {
|
|
12
13
|
VariableTable {
|
|
13
14
|
variables: HashMap::new(),
|
|
15
|
+
parent: None,
|
|
14
16
|
}
|
|
15
17
|
}
|
|
16
18
|
|
|
@@ -18,6 +20,10 @@ impl VariableTable {
|
|
|
18
20
|
self.variables.insert(name, value);
|
|
19
21
|
}
|
|
20
22
|
|
|
23
|
+
pub fn with_parent(parent: VariableTable) -> Self {
|
|
24
|
+
Self { variables: HashMap::new(), parent: Some(Box::new(parent)) }
|
|
25
|
+
}
|
|
26
|
+
|
|
21
27
|
pub fn get(&self, name: &str) -> Option<&Value> {
|
|
22
28
|
self.variables.get(name)
|
|
23
29
|
}
|
package/rust/installer/bank.rs
CHANGED
|
@@ -2,7 +2,7 @@ use std::path::{ Path, PathBuf };
|
|
|
2
2
|
use crate::{
|
|
3
3
|
common::cdn::get_cdn_url,
|
|
4
4
|
config::loader::{ add_bank_to_config, load_config },
|
|
5
|
-
utils::
|
|
5
|
+
installer::utils::{ download_file, extract_archive },
|
|
6
6
|
};
|
|
7
7
|
|
|
8
8
|
pub async fn install_bank(name: &str, target_dir: &Path) -> Result<(), String> {
|
package/rust/installer/mod.rs
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
pub mod bank;
|
|
1
|
+
pub mod bank;
|
|
2
|
+
pub mod utils;
|
package/rust/lib.rs
CHANGED
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
pub mod core;
|
|
2
2
|
pub mod utils;
|
|
3
3
|
pub mod config;
|
|
4
|
-
pub mod common;
|
|
5
4
|
|
|
6
5
|
use serde::{ Deserialize, Serialize };
|
|
7
6
|
use wasm_bindgen::prelude::*;
|
|
8
7
|
use serde_wasm_bindgen::to_value;
|
|
9
8
|
|
|
10
9
|
use crate::core::{
|
|
11
|
-
audio::{ engine::AudioEngine, interpreter::driver::
|
|
10
|
+
audio::{ engine::AudioEngine, interpreter::driver::run_audio_program },
|
|
12
11
|
parser::statement::{ Statement, StatementKind },
|
|
13
12
|
preprocessor::loader::ModuleLoader,
|
|
14
13
|
shared::value::Value,
|
|
15
|
-
store::global::GlobalStore,
|
|
14
|
+
store::{ function::FunctionTable, global::GlobalStore, variable::VariableTable },
|
|
16
15
|
utils::path::normalize_path,
|
|
17
16
|
};
|
|
18
17
|
|
|
@@ -70,16 +69,19 @@ pub fn render_audio(user_code: &str) -> Result<js_sys::Float32Array, JsValue> {
|
|
|
70
69
|
.ok_or(JsValue::from_str("❌ No statements found for entry module"))?
|
|
71
70
|
.clone();
|
|
72
71
|
|
|
73
|
-
let audio_engine = AudioEngine::new("wasm_output".to_string());
|
|
72
|
+
let mut audio_engine = AudioEngine::new("wasm_output".to_string());
|
|
74
73
|
|
|
75
|
-
let
|
|
74
|
+
let _ = run_audio_program(
|
|
76
75
|
&main_statements,
|
|
77
|
-
audio_engine,
|
|
76
|
+
&mut audio_engine,
|
|
78
77
|
"playground".to_string(),
|
|
79
|
-
"wasm_output".to_string()
|
|
78
|
+
"wasm_output".to_string(),
|
|
79
|
+
VariableTable::new(),
|
|
80
|
+
FunctionTable::new(),
|
|
81
|
+
&mut global_store
|
|
80
82
|
);
|
|
81
83
|
|
|
82
|
-
let samples =
|
|
84
|
+
let samples = audio_engine.get_normalized_buffer();
|
|
83
85
|
|
|
84
86
|
if samples.is_empty() {
|
|
85
87
|
return Err(JsValue::from_str("❌ Audio buffer is empty"));
|