@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
|
@@ -4,7 +4,7 @@ use crate::core::{
|
|
|
4
4
|
lexer::token::{ Token, TokenKind },
|
|
5
5
|
parser::{
|
|
6
6
|
driver::Parser,
|
|
7
|
-
handler::identifier::synth::parse_synth_token,
|
|
7
|
+
handler::{ dot::parse_dot_token, identifier::synth::parse_synth_token },
|
|
8
8
|
statement::{ Statement, StatementKind },
|
|
9
9
|
},
|
|
10
10
|
shared::value::Value,
|
|
@@ -33,21 +33,15 @@ pub fn parse_let_token(
|
|
|
33
33
|
return Statement::error(current_token, "Expected '=' after identifier".to_string());
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
if token.kind == TokenKind::
|
|
36
|
+
let value = match parser.peek_clone() {
|
|
37
|
+
Some(token) if token.kind == TokenKind::Dot => {
|
|
38
|
+
let dot_stmt = parse_dot_token(parser, global_store);
|
|
39
|
+
Value::Statement(Box::new(dot_stmt))
|
|
40
|
+
}
|
|
41
|
+
Some(token) if token.kind == TokenKind::Synth => {
|
|
38
42
|
let synth_stmt = parse_synth_token(parser, token.clone(), global_store);
|
|
39
|
-
|
|
40
|
-
return Statement {
|
|
41
|
-
kind: StatementKind::Let { name: identifier },
|
|
42
|
-
value: synth_stmt.value,
|
|
43
|
-
indent: current_token.indent,
|
|
44
|
-
line: current_token.line,
|
|
45
|
-
column: current_token.column,
|
|
46
|
-
};
|
|
43
|
+
Value::Statement(Box::new(synth_stmt))
|
|
47
44
|
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
let value = match parser.peek_clone() {
|
|
51
45
|
Some(token) if token.kind == TokenKind::Identifier => {
|
|
52
46
|
parser.advance();
|
|
53
47
|
Value::Identifier(token.lexeme.clone())
|
|
@@ -65,7 +59,8 @@ pub fn parse_let_token(
|
|
|
65
59
|
Value::Boolean(token.lexeme.parse().unwrap_or(false))
|
|
66
60
|
}
|
|
67
61
|
Some(token) if token.kind == TokenKind::LBrace => {
|
|
68
|
-
parser.advance();
|
|
62
|
+
parser.advance();
|
|
63
|
+
|
|
69
64
|
let mut map = HashMap::new();
|
|
70
65
|
|
|
71
66
|
while let Some(key_token) = parser.peek_clone() {
|
|
@@ -117,15 +112,14 @@ pub fn parse_let_token(
|
|
|
117
112
|
|
|
118
113
|
Value::Map(map)
|
|
119
114
|
}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
return Statement::error(current_token, message);
|
|
115
|
+
_ => {
|
|
116
|
+
return Statement::error(current_token, "Unhandled value type after '='".to_string());
|
|
123
117
|
}
|
|
124
118
|
};
|
|
125
119
|
|
|
126
120
|
Statement {
|
|
127
121
|
kind: StatementKind::Let { name: identifier },
|
|
128
|
-
value,
|
|
122
|
+
value: value,
|
|
129
123
|
indent: current_token.indent,
|
|
130
124
|
line: current_token.line,
|
|
131
125
|
column: current_token.column,
|
|
@@ -8,34 +8,81 @@ use crate::core::{
|
|
|
8
8
|
pub fn parse_spawn_token(
|
|
9
9
|
parser: &mut Parser,
|
|
10
10
|
current_token: Token,
|
|
11
|
-
|
|
11
|
+
_global_store: &mut GlobalStore
|
|
12
12
|
) -> Statement {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
TokenKind::String => Value::String(token.lexeme.clone()),
|
|
20
|
-
_ => {
|
|
21
|
-
return Statement::error(
|
|
22
|
-
token,
|
|
23
|
-
"Expected identifier or string after 'spawn'".to_string()
|
|
24
|
-
);
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
} else {
|
|
13
|
+
parser.advance(); // consume "spawn"
|
|
14
|
+
|
|
15
|
+
// Expect function name
|
|
16
|
+
let name_token = match parser.peek_clone() {
|
|
17
|
+
Some(t) => t,
|
|
18
|
+
None => {
|
|
28
19
|
return Statement::error(
|
|
29
20
|
current_token,
|
|
30
|
-
"Expected
|
|
21
|
+
"Expected function name after 'spawn'".to_string()
|
|
31
22
|
);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
if name_token.kind != TokenKind::Identifier {
|
|
27
|
+
return Statement::error(
|
|
28
|
+
name_token,
|
|
29
|
+
"Expected function name to be an identifier".to_string()
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
let func_name = name_token.lexeme.clone();
|
|
34
|
+
parser.advance(); // consume function name
|
|
35
|
+
|
|
36
|
+
// Expect '('
|
|
37
|
+
let mut args: Vec<Value> = Vec::new();
|
|
38
|
+
if let Some(open_paren) = parser.peek_clone() {
|
|
39
|
+
if open_paren.kind == TokenKind::LParen {
|
|
40
|
+
parser.advance(); // consume '('
|
|
41
|
+
|
|
42
|
+
// Collect args until ')'
|
|
43
|
+
while let Some(token) = parser.peek_clone() {
|
|
44
|
+
if token.kind == TokenKind::RParen {
|
|
45
|
+
parser.advance(); // consume ')'
|
|
46
|
+
break;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
match token.kind {
|
|
50
|
+
TokenKind::Number => {
|
|
51
|
+
if let Ok(num) = token.lexeme.parse::<f32>() {
|
|
52
|
+
args.push(Value::Number(num));
|
|
53
|
+
}
|
|
54
|
+
parser.advance();
|
|
55
|
+
}
|
|
56
|
+
TokenKind::String => {
|
|
57
|
+
args.push(Value::String(token.lexeme.clone()));
|
|
58
|
+
parser.advance();
|
|
59
|
+
}
|
|
60
|
+
TokenKind::Identifier => {
|
|
61
|
+
args.push(Value::Identifier(token.lexeme.clone()));
|
|
62
|
+
parser.advance();
|
|
63
|
+
}
|
|
64
|
+
TokenKind::Comma => {
|
|
65
|
+
parser.advance(); // skip comma
|
|
66
|
+
}
|
|
67
|
+
_ => {
|
|
68
|
+
return Statement::error(
|
|
69
|
+
token,
|
|
70
|
+
"Unexpected token in spawn arguments".to_string()
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
Statement {
|
|
79
|
+
kind: StatementKind::Spawn {
|
|
80
|
+
name: func_name,
|
|
81
|
+
args,
|
|
82
|
+
},
|
|
83
|
+
value: Value::Null,
|
|
84
|
+
indent: current_token.indent,
|
|
85
|
+
line: current_token.line,
|
|
86
|
+
column: current_token.column,
|
|
87
|
+
}
|
|
88
|
+
}
|
|
@@ -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()
|