@devaloop/devalang 0.0.1-alpha.3 → 0.0.1-alpha.4
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 +1 -1
- package/Cargo.toml +3 -3
- package/README.md +42 -25
- package/docs/CHANGELOG.md +17 -0
- package/docs/COMMANDS.md +31 -0
- package/docs/CONFIG.md +6 -4
- package/docs/ROADMAP.md +1 -1
- package/docs/TODO.md +4 -4
- package/examples/index.deva +7 -1
- package/examples/samples/hat-808.wav +0 -0
- package/out-tsc/bin/devalang.exe +0 -0
- package/package.json +41 -41
- package/project-version.json +6 -6
- package/rust/audio/engine.rs +130 -0
- package/rust/audio/interpreter.rs +143 -0
- package/rust/audio/loader.rs +46 -0
- package/rust/audio/mod.rs +5 -0
- package/rust/audio/player.rs +54 -0
- package/rust/audio/render.rs +57 -0
- package/rust/cli/build.rs +17 -6
- package/rust/cli/mod.rs +29 -0
- package/rust/cli/play.rs +191 -0
- package/rust/config/mod.rs +3 -2
- package/rust/core/builder/mod.rs +48 -0
- package/rust/core/debugger/lexer.rs +20 -5
- package/rust/core/debugger/preprocessor.rs +9 -5
- package/rust/core/preprocessor/loader.rs +26 -15
- package/rust/core/preprocessor/resolver/bank.rs +46 -0
- package/rust/core/preprocessor/resolver/loop_.rs +143 -0
- package/rust/core/preprocessor/resolver/mod.rs +152 -0
- package/rust/core/preprocessor/resolver/tempo.rs +49 -0
- package/rust/core/preprocessor/resolver/trigger.rs +114 -0
- package/rust/main.rs +6 -0
- package/rust/utils/watcher.rs +10 -2
- package/rust/core/preprocessor/resolver.rs +0 -372
|
@@ -1,372 +0,0 @@
|
|
|
1
|
-
use std::collections::HashMap;
|
|
2
|
-
|
|
3
|
-
use crate::{
|
|
4
|
-
core::{
|
|
5
|
-
parser::statement::{ self, Statement, StatementKind },
|
|
6
|
-
preprocessor::loader::ModuleLoader,
|
|
7
|
-
shared::{ duration::Duration, value::Value },
|
|
8
|
-
store::global::GlobalStore,
|
|
9
|
-
utils::validation::{ is_valid_entity, is_valid_identifier },
|
|
10
|
-
},
|
|
11
|
-
utils::logger::Logger,
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
pub fn resolve_all_modules(module_loader: &ModuleLoader, global_store: &mut GlobalStore) {
|
|
15
|
-
for module in global_store.clone().modules.values_mut() {
|
|
16
|
-
resolve_imports(module_loader, global_store);
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
pub fn resolve_imports(module_loader: &ModuleLoader, global_store: &mut GlobalStore) {
|
|
21
|
-
for (module_path, module) in global_store.clone().modules.iter_mut() {
|
|
22
|
-
for (name, source_path) in &module.import_table.imports {
|
|
23
|
-
match source_path {
|
|
24
|
-
Value::String(source_path) => {
|
|
25
|
-
if let Some(source_module) = global_store.modules.get(source_path) {
|
|
26
|
-
if let Some(value) = source_module.export_table.get_export(name) {
|
|
27
|
-
module.variable_table.set(name.clone(), value.clone());
|
|
28
|
-
} else {
|
|
29
|
-
println!(
|
|
30
|
-
"[warn] '{module_path}': '{name}' not found in exports of '{source_path}'"
|
|
31
|
-
);
|
|
32
|
-
}
|
|
33
|
-
} else {
|
|
34
|
-
println!(
|
|
35
|
-
"[warn] '{module_path}': cannot find source module '{source_path}'"
|
|
36
|
-
);
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
_ => {
|
|
40
|
-
println!(
|
|
41
|
-
"[warn] '{module_path}': expected string for import source, found {:?}",
|
|
42
|
-
source_path
|
|
43
|
-
);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
pub fn resolve_and_flatten_all_modules(
|
|
51
|
-
global_store: &mut GlobalStore
|
|
52
|
-
) -> HashMap<String, Vec<Statement>> {
|
|
53
|
-
let logger = Logger::new();
|
|
54
|
-
|
|
55
|
-
// 1. Imports resolving
|
|
56
|
-
let global_store_clone = global_store.clone();
|
|
57
|
-
for (module_path, module) in global_store.modules.iter_mut() {
|
|
58
|
-
for (name, source_path) in &module.import_table.imports {
|
|
59
|
-
match source_path {
|
|
60
|
-
Value::String(source_path) => {
|
|
61
|
-
if let Some(source_module) = global_store_clone.modules.get(source_path) {
|
|
62
|
-
if let Some(value) = source_module.export_table.get_export(name) {
|
|
63
|
-
module.variable_table.set(name.clone(), value.clone());
|
|
64
|
-
} else {
|
|
65
|
-
let message = format!(
|
|
66
|
-
"'{name}' not found in exports of '{source_path}'"
|
|
67
|
-
);
|
|
68
|
-
logger.log_error_with_stacktrace(&message, module_path);
|
|
69
|
-
}
|
|
70
|
-
} else {
|
|
71
|
-
let message = format!("cannot find source module '{source_path}'");
|
|
72
|
-
logger.log_error_with_stacktrace(&message, module_path);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
_ => {
|
|
76
|
-
let message = format!(
|
|
77
|
-
"expected string for import source, found {:?}",
|
|
78
|
-
source_path
|
|
79
|
-
);
|
|
80
|
-
logger.log_error_with_stacktrace(&message, module_path);
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// 2. Full statement resolution
|
|
87
|
-
let mut resolved_map = HashMap::new();
|
|
88
|
-
|
|
89
|
-
for (path, module) in &global_store.modules {
|
|
90
|
-
let mut resolved = Vec::new();
|
|
91
|
-
|
|
92
|
-
for mut stmt in module.statements.clone() {
|
|
93
|
-
match &mut stmt.kind {
|
|
94
|
-
StatementKind::Bank => {
|
|
95
|
-
if let Value::Identifier(ident) = &stmt.value {
|
|
96
|
-
if let Some(val) = module.variable_table.get(ident) {
|
|
97
|
-
stmt.value = val.clone();
|
|
98
|
-
} else {
|
|
99
|
-
let message = format!(
|
|
100
|
-
"Bank identifier '{ident}' not found in variable table"
|
|
101
|
-
);
|
|
102
|
-
|
|
103
|
-
logger.log_error_with_stacktrace(&message, &module.path);
|
|
104
|
-
|
|
105
|
-
stmt.kind = StatementKind::Error {
|
|
106
|
-
message: format!(
|
|
107
|
-
"Bank identifier '{ident}' not found in variable table"
|
|
108
|
-
),
|
|
109
|
-
};
|
|
110
|
-
stmt.value = Value::Null;
|
|
111
|
-
}
|
|
112
|
-
} else if let Value::String(_) = &stmt.value {
|
|
113
|
-
// Value is already a string, no need to modify
|
|
114
|
-
} else {
|
|
115
|
-
let message = format!(
|
|
116
|
-
"Expected a string or identifier for bank, found {:?}",
|
|
117
|
-
stmt.value
|
|
118
|
-
);
|
|
119
|
-
|
|
120
|
-
logger.log_error_with_stacktrace(&message, &module.path);
|
|
121
|
-
|
|
122
|
-
stmt.kind = StatementKind::Error {
|
|
123
|
-
message: "Expected a string or identifier for bank".to_string(),
|
|
124
|
-
};
|
|
125
|
-
stmt.value = Value::Null;
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
StatementKind::Tempo => {
|
|
130
|
-
if let Value::Identifier(ident) = &stmt.value {
|
|
131
|
-
if let Some(val) = module.variable_table.get(ident) {
|
|
132
|
-
stmt.value = val.clone();
|
|
133
|
-
} else {
|
|
134
|
-
let message = format!(
|
|
135
|
-
"Tempo identifier '{ident}' not found in variable table"
|
|
136
|
-
);
|
|
137
|
-
|
|
138
|
-
logger.log_error_with_stacktrace(&message, &module.path);
|
|
139
|
-
|
|
140
|
-
stmt.kind = StatementKind::Error {
|
|
141
|
-
message: format!(
|
|
142
|
-
"Tempo identifier '{ident}' not found in variable table"
|
|
143
|
-
),
|
|
144
|
-
};
|
|
145
|
-
stmt.value = Value::Null;
|
|
146
|
-
}
|
|
147
|
-
} else if let Value::Number(_) = &stmt.value {
|
|
148
|
-
// Value is already a number, no need to modify
|
|
149
|
-
} else {
|
|
150
|
-
let message = format!(
|
|
151
|
-
"Expected a number or identifier for tempo, found {:?}",
|
|
152
|
-
stmt.value
|
|
153
|
-
);
|
|
154
|
-
|
|
155
|
-
logger.log_error_with_stacktrace(&message, &module.path);
|
|
156
|
-
|
|
157
|
-
stmt.kind = StatementKind::Error {
|
|
158
|
-
message: "Expected a number or identifier for tempo".to_string(),
|
|
159
|
-
};
|
|
160
|
-
stmt.value = Value::Null;
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
StatementKind::Trigger { entity, duration } => {
|
|
165
|
-
if !is_valid_entity(entity, module, global_store) {
|
|
166
|
-
let message =
|
|
167
|
-
format!("Invalid entity '{}', expected a valid identifier", entity);
|
|
168
|
-
|
|
169
|
-
let stacktrace = format!("{}:{}:{}", module.path, stmt.line, stmt.column);
|
|
170
|
-
logger.log_error_with_stacktrace(&message, &stacktrace);
|
|
171
|
-
|
|
172
|
-
stmt.kind = StatementKind::Error {
|
|
173
|
-
message: format!("Invalid entity '{}'", entity),
|
|
174
|
-
};
|
|
175
|
-
stmt.value = Value::Null;
|
|
176
|
-
|
|
177
|
-
resolved.push(stmt);
|
|
178
|
-
continue;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
// Duration resolution
|
|
182
|
-
if let Duration::Identifier(ident) = duration {
|
|
183
|
-
if let Some(val) = module.variable_table.get(ident) {
|
|
184
|
-
match val {
|
|
185
|
-
Value::Number(num) => {
|
|
186
|
-
*duration = Duration::Number(*num);
|
|
187
|
-
}
|
|
188
|
-
Value::String(s) => {
|
|
189
|
-
*duration = Duration::Identifier(s.clone());
|
|
190
|
-
}
|
|
191
|
-
Value::Identifier(id) if id == "auto" => {
|
|
192
|
-
*duration = Duration::Auto;
|
|
193
|
-
}
|
|
194
|
-
_ => {}
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
// Associated value resolution
|
|
200
|
-
if let Value::Identifier(ident) = &stmt.value {
|
|
201
|
-
if let Some(val) = module.variable_table.get(ident) {
|
|
202
|
-
stmt.value = val.clone();
|
|
203
|
-
} else {
|
|
204
|
-
let stacktrace = format!(
|
|
205
|
-
"{}:{}:{}",
|
|
206
|
-
module.path,
|
|
207
|
-
stmt.line,
|
|
208
|
-
stmt.column
|
|
209
|
-
);
|
|
210
|
-
let message = format!(
|
|
211
|
-
"'{path}': value identifier '{ident}' not found in variable table"
|
|
212
|
-
);
|
|
213
|
-
|
|
214
|
-
logger.log_error_with_stacktrace(&message, &stacktrace);
|
|
215
|
-
|
|
216
|
-
stmt.kind = StatementKind::Error {
|
|
217
|
-
message: format!(
|
|
218
|
-
"Value identifier '{ident}' not found in variable table"
|
|
219
|
-
),
|
|
220
|
-
};
|
|
221
|
-
stmt.value = Value::Null;
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
StatementKind::Let { .. } => {
|
|
227
|
-
if let Value::Identifier(ident) = &stmt.value {
|
|
228
|
-
if let Some(val) = module.variable_table.get(ident) {
|
|
229
|
-
stmt.value = val.clone();
|
|
230
|
-
} else {
|
|
231
|
-
if !is_valid_identifier(ident, module) {
|
|
232
|
-
let message = format!(
|
|
233
|
-
"'{path}': value identifier '{ident}' not found in variable table"
|
|
234
|
-
);
|
|
235
|
-
|
|
236
|
-
logger.log_error_with_stacktrace(&message, &module.path);
|
|
237
|
-
|
|
238
|
-
stmt.kind = StatementKind::Error {
|
|
239
|
-
message: format!(
|
|
240
|
-
"Value identifier '{ident}' not found in variable table"
|
|
241
|
-
),
|
|
242
|
-
};
|
|
243
|
-
stmt.value = Value::Null;
|
|
244
|
-
} else {
|
|
245
|
-
stmt.value = Value::Identifier(ident.clone());
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
StatementKind::Loop => {
|
|
252
|
-
if let Value::Map(value_map) = &stmt.value {
|
|
253
|
-
let iterator_value = match value_map.get("iterator") {
|
|
254
|
-
Some(Value::Identifier(ident)) => {
|
|
255
|
-
if let Some(val) = module.variable_table.get(ident) {
|
|
256
|
-
match val {
|
|
257
|
-
Value::Number(n) => Value::Number(*n),
|
|
258
|
-
_ => {
|
|
259
|
-
let message = format!(
|
|
260
|
-
"Loop iterator '{ident}' must resolve to a number"
|
|
261
|
-
);
|
|
262
|
-
let stacktrace = format!(
|
|
263
|
-
"{}:{}:{}",
|
|
264
|
-
module.path,
|
|
265
|
-
stmt.line,
|
|
266
|
-
stmt.column
|
|
267
|
-
);
|
|
268
|
-
logger.log_error_with_stacktrace(&message, &stacktrace);
|
|
269
|
-
|
|
270
|
-
stmt.kind = StatementKind::Error {
|
|
271
|
-
message,
|
|
272
|
-
};
|
|
273
|
-
Value::Null
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
} else {
|
|
277
|
-
let message = format!(
|
|
278
|
-
"'{path}': loop iterator '{ident}' not found in variable table"
|
|
279
|
-
);
|
|
280
|
-
let stacktrace = format!(
|
|
281
|
-
"{}:{}:{}",
|
|
282
|
-
module.path,
|
|
283
|
-
stmt.line,
|
|
284
|
-
stmt.column
|
|
285
|
-
);
|
|
286
|
-
logger.log_error_with_stacktrace(&message, &stacktrace);
|
|
287
|
-
|
|
288
|
-
stmt.kind = StatementKind::Error {
|
|
289
|
-
message: format!("Loop iterator '{ident}' not found"),
|
|
290
|
-
};
|
|
291
|
-
Value::Null
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
Some(Value::Number(n)) => Value::Number(*n),
|
|
296
|
-
|
|
297
|
-
Some(v) => {
|
|
298
|
-
let message = format!(
|
|
299
|
-
"Unexpected value for loop iterator: {:?}, expected number or identifier",
|
|
300
|
-
v
|
|
301
|
-
);
|
|
302
|
-
let stacktrace = format!(
|
|
303
|
-
"{}:{}:{}",
|
|
304
|
-
module.path,
|
|
305
|
-
stmt.line,
|
|
306
|
-
stmt.column
|
|
307
|
-
);
|
|
308
|
-
logger.log_error_with_stacktrace(&message, &stacktrace);
|
|
309
|
-
|
|
310
|
-
stmt.kind = StatementKind::Error {
|
|
311
|
-
message,
|
|
312
|
-
};
|
|
313
|
-
Value::Null
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
None => {
|
|
317
|
-
let message = format!(
|
|
318
|
-
"Missing 'iterator' key in loop statement map"
|
|
319
|
-
);
|
|
320
|
-
let stacktrace = format!(
|
|
321
|
-
"{}:{}:{}",
|
|
322
|
-
module.path,
|
|
323
|
-
stmt.line,
|
|
324
|
-
stmt.column
|
|
325
|
-
);
|
|
326
|
-
logger.log_error_with_stacktrace(&message, &stacktrace);
|
|
327
|
-
|
|
328
|
-
stmt.kind = StatementKind::Error {
|
|
329
|
-
message,
|
|
330
|
-
};
|
|
331
|
-
Value::Null
|
|
332
|
-
}
|
|
333
|
-
};
|
|
334
|
-
|
|
335
|
-
let body_value = value_map.get("body").cloned().unwrap_or(Value::Null);
|
|
336
|
-
|
|
337
|
-
let mut loop_map = std::collections::HashMap::new();
|
|
338
|
-
loop_map.insert("iterator".to_string(), iterator_value);
|
|
339
|
-
loop_map.insert("body".to_string(), body_value);
|
|
340
|
-
|
|
341
|
-
stmt.value = Value::Map(loop_map);
|
|
342
|
-
} else {
|
|
343
|
-
let message = format!(
|
|
344
|
-
"'{path}': expected a map for loop value, found {:?}",
|
|
345
|
-
stmt.value
|
|
346
|
-
);
|
|
347
|
-
let stacktrace = format!("{}:{}:{}", module.path, stmt.line, stmt.column);
|
|
348
|
-
|
|
349
|
-
logger.log_error_with_stacktrace(&message, &stacktrace);
|
|
350
|
-
|
|
351
|
-
stmt.kind = StatementKind::Error {
|
|
352
|
-
message: "Expected a map for loop value".to_string(),
|
|
353
|
-
};
|
|
354
|
-
stmt.value = Value::Null;
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
StatementKind::Import { names, source } => {}
|
|
359
|
-
|
|
360
|
-
StatementKind::Export { names, source } => {}
|
|
361
|
-
|
|
362
|
-
_ => {}
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
resolved.push(stmt);
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
resolved_map.insert(path.clone(), resolved);
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
resolved_map
|
|
372
|
-
}
|