@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.
- package/Cargo.toml +1 -1
- package/README.md +4 -8
- package/docs/CHANGELOG.md +27 -0
- package/examples/condition.deva +8 -12
- package/examples/group.deva +3 -3
- package/examples/index.deva +10 -8
- package/examples/loop.deva +10 -8
- package/examples/synth.deva +14 -0
- package/examples/variables.deva +1 -1
- package/out-tsc/bin/devalang.exe +0 -0
- package/out-tsc/scripts/version/fetch.js +1 -5
- package/package.json +1 -1
- package/project-version.json +3 -3
- package/rust/core/audio/engine.rs +89 -12
- package/rust/core/audio/interpreter/arrow_call.rs +129 -0
- package/rust/core/audio/interpreter/call.rs +29 -7
- package/rust/core/audio/interpreter/condition.rs +5 -1
- package/rust/core/audio/interpreter/driver.rs +41 -29
- package/rust/core/audio/interpreter/loop_.rs +11 -3
- package/rust/core/audio/interpreter/mod.rs +1 -0
- package/rust/core/audio/interpreter/spawn.rs +43 -42
- package/rust/core/audio/interpreter/trigger.rs +1 -1
- package/rust/core/audio/renderer.rs +15 -18
- package/rust/core/lexer/handler/arrow.rs +31 -0
- package/rust/core/lexer/handler/driver.rs +12 -1
- package/rust/core/lexer/handler/identifier.rs +1 -0
- package/rust/core/lexer/handler/mod.rs +1 -0
- package/rust/core/lexer/mod.rs +24 -3
- package/rust/core/lexer/token.rs +4 -0
- package/rust/core/parser/driver.rs +23 -4
- package/rust/core/parser/handler/arrow_call.rs +126 -0
- package/rust/core/parser/handler/identifier/call.rs +41 -0
- package/rust/core/parser/handler/identifier/group.rs +75 -0
- package/rust/core/parser/handler/identifier/let_.rs +133 -0
- package/rust/core/parser/handler/identifier/mod.rs +51 -0
- package/rust/core/parser/handler/identifier/sleep.rs +33 -0
- package/rust/core/parser/handler/identifier/spawn.rs +41 -0
- package/rust/core/parser/handler/identifier/synth.rs +65 -0
- package/rust/core/parser/handler/loop_.rs +24 -18
- package/rust/core/parser/handler/mod.rs +2 -1
- package/rust/core/parser/statement.rs +8 -0
- package/rust/core/preprocessor/loader.rs +57 -43
- package/rust/core/preprocessor/module.rs +3 -6
- package/rust/core/preprocessor/processor.rs +13 -4
- package/rust/core/preprocessor/resolver/call.rs +99 -29
- package/rust/core/preprocessor/resolver/condition.rs +38 -12
- package/rust/core/preprocessor/resolver/driver.rs +74 -29
- package/rust/core/preprocessor/resolver/group.rs +24 -81
- package/rust/core/preprocessor/resolver/let_.rs +31 -0
- package/rust/core/preprocessor/resolver/loop_.rs +62 -116
- package/rust/core/preprocessor/resolver/mod.rs +5 -1
- package/rust/core/preprocessor/resolver/spawn.rs +41 -36
- package/rust/core/preprocessor/resolver/synth.rs +50 -0
- package/rust/core/preprocessor/resolver/trigger.rs +51 -50
- package/rust/core/preprocessor/resolver/value.rs +78 -0
- package/rust/core/utils/path.rs +17 -32
- package/rust/core/utils/validation.rs +30 -28
- package/typescript/scripts/version/fetch.ts +1 -6
- 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
|
-
|
|
119
|
+
raw_path: &str,
|
|
112
120
|
global_store: &mut GlobalStore
|
|
113
121
|
) -> HashMap<String, Vec<Token>> {
|
|
114
|
-
|
|
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.
|
|
133
|
+
parser.set_current_module(path.clone());
|
|
123
134
|
|
|
124
135
|
let statements = parser.parse_tokens(tokens.clone(), global_store);
|
|
125
136
|
|
|
126
|
-
//
|
|
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()
|
|
141
|
+
if error_handler.has_errors() {
|
|
131
142
|
let logger = Logger::new();
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
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
|
-
//
|
|
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
|
-
|
|
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
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
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
|
|
163
|
-
.get(path)
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
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
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
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::{
|
|
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(
|
|
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(
|
|
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
|
-
|
|
15
|
-
|
|
14
|
+
path: &str,
|
|
15
|
+
global_store: &mut GlobalStore
|
|
16
16
|
) -> Statement {
|
|
17
17
|
let logger = Logger::new();
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
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
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
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
|
|
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.
|
|
114
|
+
logger.log_message(LogLevel::Error, &format!("{message}\n → at {stacktrace}"));
|
|
47
115
|
|
|
48
116
|
Statement {
|
|
49
|
-
kind: StatementKind::Error {
|
|
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::{
|
|
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
|
-
//
|
|
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
|
-
//
|
|
36
|
-
if let Some(Value::Map(
|
|
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(
|
|
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::{
|
|
4
|
+
parser::statement::{ Statement, StatementKind },
|
|
5
5
|
preprocessor::{
|
|
6
6
|
loader::ModuleLoader,
|
|
7
7
|
module::Module,
|
|
8
8
|
resolver::{
|
|
9
|
-
bank::resolve_bank,
|
|
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::
|
|
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
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
72
|
+
eprintln!("⚠️ Unresolved identifier '{}'", name);
|
|
73
|
+
Value::Null
|
|
74
|
+
}
|
|
48
75
|
|
|
49
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
213
|
+
let resolved_stmt = resolve_group(&stmt, &module, &path, global_store);
|
|
169
214
|
resolved.push(resolved_stmt);
|
|
170
215
|
}
|
|
171
216
|
|