@devaloop/devalang 0.0.1-alpha.16-hotfix.3 → 0.0.1-alpha.18
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/config.toml +2 -0
- package/.devalang +10 -10
- package/.github/workflows/ci.yml +0 -1
- package/Cargo.toml +18 -2
- package/README.md +82 -34
- package/docs/CHANGELOG.md +91 -0
- package/docs/ROADMAP.md +7 -4
- package/docs/TODO.md +1 -1
- package/examples/index.deva +55 -35
- package/examples/pattern.deva +5 -5
- package/out-tsc/bin/index.d.ts +2 -0
- package/out-tsc/core/functions/index.d.ts +37 -0
- package/out-tsc/core/functions/index.js +76 -0
- package/out-tsc/core/index.d.ts +6 -0
- package/out-tsc/core/index.js +22 -0
- package/out-tsc/core/types/index.d.ts +4 -0
- package/out-tsc/core/types/index.js +20 -0
- package/out-tsc/core/types/plugin.d.ts +18 -0
- package/out-tsc/core/types/plugin.js +2 -0
- package/out-tsc/core/types/result.d.ts +27 -0
- package/out-tsc/core/types/result.js +2 -0
- package/out-tsc/core/types/statement.d.ts +106 -0
- package/out-tsc/core/types/statement.js +2 -0
- package/out-tsc/core/types/value.d.ts +43 -0
- package/out-tsc/core/types/value.js +2 -0
- package/out-tsc/index.d.ts +7 -0
- package/out-tsc/index.js +41 -2
- package/out-tsc/pkg/devalang_core.d.ts +7 -0
- package/out-tsc/pkg/devalang_core_bg.wasm.d.ts +33 -0
- package/out-tsc/scripts/copy-wasm-dts.d.ts +1 -0
- package/out-tsc/scripts/copy-wasm-dts.js +73 -0
- package/out-tsc/scripts/postinstall.d.ts +1 -0
- package/out-tsc/scripts/postinstall.js +33 -23
- package/out-tsc/scripts/version/bump.d.ts +1 -0
- package/out-tsc/scripts/version/fetch.d.ts +1 -0
- package/out-tsc/scripts/version/index.d.ts +1 -0
- package/out-tsc/scripts/version/sync.d.ts +1 -0
- package/package.json +16 -4
- package/project-version.json +3 -3
- package/rust/cli/bank/api.rs +122 -0
- package/rust/cli/bank/commands.rs +275 -0
- package/rust/cli/bank/mod.rs +29 -0
- package/rust/cli/build/commands.rs +107 -0
- package/rust/cli/build/mod.rs +2 -0
- package/rust/cli/build/process.rs +146 -0
- package/rust/cli/{check.rs → check/mod.rs} +18 -31
- package/rust/cli/discover/commands.rs +253 -0
- package/rust/cli/discover/config.rs +111 -0
- package/rust/cli/discover/fs.rs +19 -0
- package/rust/cli/discover/install.rs +103 -0
- package/rust/cli/discover/metadata.rs +48 -0
- package/rust/cli/discover/mod.rs +5 -0
- package/rust/cli/{init.rs → init/commands.rs} +88 -87
- package/rust/cli/init/mod.rs +1 -0
- package/rust/cli/install/addon.rs +126 -0
- package/rust/cli/install/bank.rs +53 -0
- package/rust/cli/{install.rs → install/commands.rs} +9 -9
- package/rust/{installer → cli/install}/mod.rs +2 -3
- package/rust/cli/install/plugin.rs +61 -0
- package/rust/cli/{login.rs → login/commands.rs} +8 -11
- package/rust/cli/login/mod.rs +1 -0
- package/rust/cli/mod.rs +2 -2
- package/rust/cli/{driver.rs → parser.rs} +7 -2
- package/rust/cli/play/commands.rs +324 -0
- package/rust/cli/play/io.rs +17 -0
- package/rust/cli/play/mod.rs +5 -0
- package/rust/cli/play/process.rs +150 -0
- package/rust/cli/play/realtime.rs +91 -0
- package/rust/cli/play/utils.rs +23 -0
- package/rust/cli/{telemetry.rs → telemetry/commands.rs} +4 -4
- package/rust/cli/telemetry/event_creator.rs +80 -0
- package/rust/cli/telemetry/mod.rs +3 -0
- package/rust/cli/telemetry/send.rs +51 -0
- package/rust/cli/{template.rs → template/commands.rs} +1 -1
- package/rust/cli/template/mod.rs +1 -0
- package/rust/cli/{update.rs → update/commands.rs} +6 -6
- package/rust/cli/update/mod.rs +1 -0
- package/rust/config/driver.rs +57 -72
- package/rust/config/mod.rs +1 -2
- package/rust/config/ops.rs +26 -0
- package/rust/config/settings.rs +40 -42
- package/rust/core/audio/engine/helpers.rs +158 -0
- package/rust/core/audio/engine/mod.rs +7 -0
- package/rust/core/audio/engine/sample.rs +359 -0
- package/rust/core/audio/engine/synth.rs +325 -0
- package/rust/core/audio/evaluator.rs +68 -27
- package/rust/core/audio/interpreter/arrow_call.rs +113 -33
- package/rust/core/audio/interpreter/call.rs +232 -56
- package/rust/core/audio/interpreter/condition.rs +3 -2
- package/rust/core/audio/interpreter/driver.rs +206 -151
- package/rust/core/audio/interpreter/let_.rs +1 -1
- package/rust/core/audio/interpreter/load.rs +2 -1
- package/rust/core/audio/interpreter/loop_.rs +7 -6
- package/rust/core/audio/interpreter/sleep.rs +2 -1
- package/rust/core/audio/interpreter/spawn.rs +186 -54
- package/rust/core/audio/interpreter/tempo.rs +31 -10
- package/rust/core/audio/interpreter/trigger.rs +2 -2
- package/rust/core/audio/loader/trigger.rs +4 -7
- package/rust/core/audio/player.rs +6 -0
- package/rust/core/audio/renderer.rs +5 -7
- package/rust/core/audio/special/env.rs +3 -1
- package/rust/core/audio/special/math.rs +26 -6
- package/rust/core/audio/special/modulator.rs +2 -2
- package/rust/core/builder/mod.rs +9 -3
- package/rust/core/debugger/lexer.rs +1 -1
- package/rust/core/debugger/mod.rs +6 -0
- package/rust/core/debugger/module.rs +4 -4
- package/rust/core/debugger/preprocessor.rs +1 -1
- package/rust/core/debugger/store.rs +2 -2
- package/rust/core/error/mod.rs +189 -0
- package/rust/core/lexer/driver.rs +61 -0
- package/rust/core/lexer/handler/arrow.rs +1 -1
- package/rust/core/lexer/handler/at.rs +1 -1
- package/rust/core/lexer/handler/brace.rs +2 -2
- package/rust/core/lexer/handler/colon.rs +1 -1
- package/rust/core/lexer/handler/comment.rs +1 -1
- package/rust/core/lexer/handler/dot.rs +1 -1
- package/rust/core/lexer/handler/driver.rs +1 -1
- package/rust/core/lexer/handler/identifier.rs +4 -3
- package/rust/core/lexer/handler/mod.rs +1 -2
- package/rust/core/lexer/handler/number.rs +1 -1
- package/rust/core/lexer/handler/operator.rs +1 -1
- package/rust/core/lexer/handler/parenthesis.rs +2 -2
- package/rust/core/lexer/handler/slash.rs +1 -1
- package/rust/core/lexer/handler/string.rs +1 -1
- package/rust/core/lexer/mod.rs +1 -52
- package/rust/core/lexer/token.rs +91 -97
- package/rust/core/mod.rs +0 -1
- package/rust/core/parser/driver.rs +78 -22
- package/rust/core/parser/handler/arrow_call.rs +28 -8
- package/rust/core/parser/handler/at.rs +55 -21
- package/rust/core/parser/handler/bank.rs +14 -4
- package/rust/core/parser/handler/condition.rs +6 -3
- package/rust/core/parser/handler/dot.rs +5 -3
- package/rust/core/parser/handler/identifier/automate.rs +13 -16
- package/rust/core/parser/handler/identifier/call.rs +4 -4
- package/rust/core/parser/handler/identifier/emit.rs +9 -5
- package/rust/core/parser/handler/identifier/function.rs +20 -7
- package/rust/core/parser/handler/identifier/group.rs +11 -7
- package/rust/core/parser/handler/identifier/let_.rs +24 -9
- package/rust/core/parser/handler/identifier/mod.rs +6 -5
- package/rust/core/parser/handler/identifier/on.rs +16 -7
- package/rust/core/parser/handler/identifier/print.rs +6 -9
- package/rust/core/parser/handler/identifier/sleep.rs +12 -5
- package/rust/core/parser/handler/identifier/spawn.rs +4 -4
- package/rust/core/parser/handler/identifier/synth.rs +79 -9
- package/rust/core/parser/handler/loop_.rs +38 -13
- package/rust/core/parser/handler/mod.rs +1 -0
- package/rust/core/parser/handler/pattern.rs +74 -0
- package/rust/core/parser/handler/tempo.rs +9 -5
- package/rust/core/parser/mod.rs +0 -1
- package/rust/core/parser/statement.rs +6 -137
- package/rust/core/plugin/loader.rs +41 -27
- package/rust/core/plugin/runner.rs +68 -17
- package/rust/core/preprocessor/loader.rs +181 -99
- package/rust/core/preprocessor/processor.rs +9 -9
- package/rust/core/preprocessor/resolver/bank.rs +6 -8
- package/rust/core/preprocessor/resolver/call.rs +47 -23
- package/rust/core/preprocessor/resolver/condition.rs +6 -8
- package/rust/core/preprocessor/resolver/driver.rs +28 -28
- package/rust/core/preprocessor/resolver/function.rs +6 -6
- package/rust/core/preprocessor/resolver/group.rs +6 -8
- package/rust/core/preprocessor/resolver/loop_.rs +8 -10
- package/rust/core/preprocessor/resolver/mod.rs +1 -0
- package/rust/core/preprocessor/resolver/pattern.rs +75 -0
- package/rust/core/preprocessor/resolver/spawn.rs +45 -22
- package/rust/core/preprocessor/resolver/synth.rs +6 -8
- package/rust/core/preprocessor/resolver/tempo.rs +6 -8
- package/rust/core/preprocessor/resolver/trigger.rs +22 -19
- package/rust/core/preprocessor/resolver/value.rs +99 -4
- package/rust/core/store/export.rs +28 -28
- package/rust/core/store/function.rs +6 -0
- package/rust/core/store/global.rs +7 -1
- package/rust/core/store/import.rs +28 -28
- package/rust/core/store/variable.rs +16 -2
- package/rust/core/utils/mod.rs +0 -1
- package/rust/lib.rs +102 -9
- package/rust/main.rs +159 -45
- package/rust/types/Cargo.toml +11 -0
- package/rust/types/src/addons.rs +55 -0
- package/rust/types/src/ast.rs +202 -0
- package/rust/types/src/config.rs +74 -0
- package/rust/types/src/lib.rs +12 -0
- package/rust/types/src/telemetry.rs +85 -0
- package/rust/utils/Cargo.toml +26 -0
- package/rust/utils/{error.rs → src/error.rs} +186 -200
- package/rust/utils/src/file.rs +94 -0
- package/rust/utils/src/first_usage.rs +97 -0
- package/rust/utils/{mod.rs → src/lib.rs} +1 -1
- package/rust/utils/{logger.rs → src/logger.rs} +17 -12
- package/rust/utils/src/path.rs +88 -0
- package/rust/utils/src/signature.rs +41 -0
- package/rust/utils/{spinner.rs → src/spinner.rs} +3 -5
- package/rust/utils/src/version.rs +27 -0
- package/rust/utils/{watcher.rs → src/watcher.rs} +13 -1
- package/rust/web/cdn.rs +34 -0
- package/templates/minimal/README.md +98 -54
- package/templates/welcome/README.md +98 -54
- package/templates/welcome/src/index.deva +56 -8
- package/templates/welcome/src/variables.deva +2 -4
- package/tests/rust/TODO.md +0 -0
- package/tests/typescript/index.spec.ts +136 -0
- package/tests/typescript/playhead.spec.ts +36 -0
- package/tests/typescript/render_e2e.spec.ts +77 -0
- package/tsconfig.json +1 -1
- package/typescript/core/functions/index.ts +83 -0
- package/typescript/core/index.ts +6 -0
- package/typescript/core/types/index.ts +4 -0
- package/typescript/core/types/plugin.ts +19 -0
- package/typescript/core/types/result.ts +29 -0
- package/typescript/core/types/statement.ts +47 -0
- package/typescript/core/types/value.ts +29 -0
- package/typescript/index.ts +7 -2
- package/typescript/pkg/devalang_core.d.ts +4 -0
- package/typescript/scripts/copy-wasm-dts.ts +41 -0
- package/rust/cli/bank.rs +0 -462
- package/rust/cli/build.rs +0 -252
- package/rust/cli/play.rs +0 -1123
- package/rust/common/cdn.rs +0 -5
- package/rust/config/loader.rs +0 -165
- package/rust/config/stats.rs +0 -257
- package/rust/core/audio/engine.rs +0 -696
- package/rust/core/shared/bank.rs +0 -21
- package/rust/core/shared/duration.rs +0 -9
- package/rust/core/shared/mod.rs +0 -3
- package/rust/core/shared/value.rs +0 -35
- package/rust/core/utils/validation.rs +0 -35
- package/rust/installer/addon.rs +0 -84
- package/rust/installer/bank.rs +0 -62
- package/rust/installer/plugin.rs +0 -54
- package/rust/installer/utils.rs +0 -56
- package/rust/utils/file.rs +0 -38
- package/rust/utils/first_usage.rs +0 -83
- package/rust/utils/signature.rs +0 -19
- package/rust/utils/telemetry.rs +0 -292
- package/rust/utils/version.rs +0 -15
- /package/rust/{common → web}/api.rs +0 -0
- /package/rust/{common → web}/mod.rs +0 -0
- /package/rust/{common → web}/sso.rs +0 -0
|
@@ -1,25 +1,23 @@
|
|
|
1
|
+
#[cfg(feature = "cli")]
|
|
1
2
|
use crate::core::preprocessor::resolver::driver::{
|
|
2
|
-
resolve_all_modules,
|
|
3
|
+
resolve_all_modules,
|
|
4
|
+
resolve_and_flatten_all_modules,
|
|
3
5
|
};
|
|
6
|
+
#[cfg(feature = "cli")]
|
|
4
7
|
use crate::core::utils::path::resolve_relative_path;
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
plugin::loader::load_plugin,
|
|
15
|
-
preprocessor::{module::Module, processor::process_modules},
|
|
16
|
-
shared::{bank::BankFile, value::Value},
|
|
17
|
-
store::global::GlobalStore,
|
|
18
|
-
utils::path::normalize_path,
|
|
19
|
-
},
|
|
20
|
-
utils::logger::Logger,
|
|
8
|
+
#[cfg_attr(not(feature = "cli"), allow(unused_imports))]
|
|
9
|
+
use crate::core::{
|
|
10
|
+
error::ErrorHandler,
|
|
11
|
+
lexer::{ token::Token, driver::Lexer },
|
|
12
|
+
parser::{ driver::Parser, statement::{ Statement, StatementKind } },
|
|
13
|
+
plugin::loader::load_plugin,
|
|
14
|
+
preprocessor::{ module::Module, processor::process_modules },
|
|
15
|
+
store::global::GlobalStore,
|
|
16
|
+
utils::path::normalize_path,
|
|
21
17
|
};
|
|
22
|
-
use
|
|
18
|
+
use devalang_types::{ BankFile, Value };
|
|
19
|
+
use devalang_utils::logger::{ LogLevel, Logger };
|
|
20
|
+
use std::{ collections::HashMap, path::Path };
|
|
23
21
|
|
|
24
22
|
pub struct ModuleLoader {
|
|
25
23
|
pub entry: String,
|
|
@@ -38,7 +36,7 @@ impl ModuleLoader {
|
|
|
38
36
|
Self {
|
|
39
37
|
entry: entry.to_string(),
|
|
40
38
|
output: output.to_string(),
|
|
41
|
-
base_dir
|
|
39
|
+
base_dir,
|
|
42
40
|
}
|
|
43
41
|
}
|
|
44
42
|
|
|
@@ -46,13 +44,16 @@ impl ModuleLoader {
|
|
|
46
44
|
entry_path: &str,
|
|
47
45
|
output_path: &str,
|
|
48
46
|
content: &str,
|
|
49
|
-
global_store: &mut GlobalStore
|
|
47
|
+
global_store: &mut GlobalStore
|
|
50
48
|
) -> Self {
|
|
51
49
|
let normalized_entry_path = normalize_path(entry_path);
|
|
52
50
|
|
|
53
|
-
let mut module = Module::new(
|
|
51
|
+
let mut module = Module::new(entry_path);
|
|
54
52
|
module.content = content.to_string();
|
|
55
53
|
|
|
54
|
+
// Insert a module stub containing the provided content into the
|
|
55
|
+
// global store. This is used by the WASM APIs and tests which
|
|
56
|
+
// operate on in-memory sources instead of files on disk.
|
|
56
57
|
global_store.insert_module(normalized_entry_path.to_string(), module);
|
|
57
58
|
|
|
58
59
|
Self {
|
|
@@ -64,18 +65,16 @@ impl ModuleLoader {
|
|
|
64
65
|
|
|
65
66
|
pub fn extract_statements_map(
|
|
66
67
|
&self,
|
|
67
|
-
global_store: &GlobalStore
|
|
68
|
+
global_store: &GlobalStore
|
|
68
69
|
) -> HashMap<String, Vec<Statement>> {
|
|
69
|
-
global_store
|
|
70
|
-
.modules
|
|
70
|
+
global_store.modules
|
|
71
71
|
.iter()
|
|
72
72
|
.map(|(path, module)| (path.clone(), module.statements.clone()))
|
|
73
73
|
.collect()
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
pub fn load_single_module(&self, global_store: &mut GlobalStore) -> Result<Module, String> {
|
|
77
|
-
let mut module = global_store
|
|
78
|
-
.modules
|
|
77
|
+
let mut module = global_store.modules
|
|
79
78
|
.remove(&self.entry)
|
|
80
79
|
.ok_or_else(|| format!("Module not found in store for path: {}", self.entry))?;
|
|
81
80
|
|
|
@@ -102,9 +101,7 @@ impl ModuleLoader {
|
|
|
102
101
|
self.load_plugin_and_register(&mut module, &plugin_name, &alias, global_store);
|
|
103
102
|
}
|
|
104
103
|
|
|
105
|
-
global_store
|
|
106
|
-
.modules
|
|
107
|
-
.insert(self.entry.clone(), module.clone());
|
|
104
|
+
global_store.modules.insert(self.entry.clone(), module.clone());
|
|
108
105
|
|
|
109
106
|
// SECTION Error handling
|
|
110
107
|
let mut error_handler = ErrorHandler::new();
|
|
@@ -116,8 +113,7 @@ impl ModuleLoader {
|
|
|
116
113
|
pub fn load_wasm_module(&self, global_store: &mut GlobalStore) -> Result<(), String> {
|
|
117
114
|
// Step one : Load the module from the global store
|
|
118
115
|
let module = {
|
|
119
|
-
let module_ref = global_store
|
|
120
|
-
.modules
|
|
116
|
+
let module_ref = global_store.modules
|
|
121
117
|
.get(&self.entry)
|
|
122
118
|
.ok_or_else(|| format!("❌ Module not found for path: {}", self.entry))?;
|
|
123
119
|
|
|
@@ -145,6 +141,15 @@ impl ModuleLoader {
|
|
|
145
141
|
return Err(format!("Failed to inject bank triggers: {}", e));
|
|
146
142
|
}
|
|
147
143
|
|
|
144
|
+
// Insert the updated module into the global store before processing so
|
|
145
|
+
// process_modules can operate on it and populate variable_table, imports,
|
|
146
|
+
// and other derived structures.
|
|
147
|
+
global_store.modules.insert(self.entry.clone(), updated_module.clone());
|
|
148
|
+
|
|
149
|
+
// Process modules to populate module.variable_table, import/export tables,
|
|
150
|
+
// and other derived structures so runtime execution can resolve groups/synths.
|
|
151
|
+
process_modules(self, global_store);
|
|
152
|
+
|
|
148
153
|
for (plugin_name, alias) in self.extract_plugin_uses(&updated_module.statements) {
|
|
149
154
|
self.load_plugin_and_register(&mut updated_module, &plugin_name, &alias, global_store);
|
|
150
155
|
}
|
|
@@ -153,10 +158,24 @@ impl ModuleLoader {
|
|
|
153
158
|
let mut error_handler = ErrorHandler::new();
|
|
154
159
|
error_handler.detect_from_statements(&mut parser, &updated_module.statements);
|
|
155
160
|
|
|
156
|
-
// Final step :
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
161
|
+
// Final step : also expose module-level variables and functions into the global store
|
|
162
|
+
// so runtime evaluation (render_audio) can find group/synth definitions.
|
|
163
|
+
// Use the module instance that was actually processed by `process_modules`
|
|
164
|
+
// (it lives in `global_store.modules`) because `updated_module` is a local
|
|
165
|
+
// clone and won't contain the mutations applied by `process_modules`.
|
|
166
|
+
if let Some(stored_module) = global_store.modules.get(&self.entry) {
|
|
167
|
+
global_store.variables.variables.extend(stored_module.variable_table.variables.clone());
|
|
168
|
+
global_store.functions.functions.extend(stored_module.function_table.functions.clone());
|
|
169
|
+
} else {
|
|
170
|
+
// Fallback to the local updated_module if for any reason the module
|
|
171
|
+
// wasn't inserted into the store (defensive programming).
|
|
172
|
+
global_store.variables.variables.extend(
|
|
173
|
+
updated_module.variable_table.variables.clone()
|
|
174
|
+
);
|
|
175
|
+
global_store.functions.functions.extend(
|
|
176
|
+
updated_module.function_table.functions.clone()
|
|
177
|
+
);
|
|
178
|
+
}
|
|
160
179
|
|
|
161
180
|
Ok(())
|
|
162
181
|
}
|
|
@@ -164,7 +183,7 @@ impl ModuleLoader {
|
|
|
164
183
|
#[cfg(feature = "cli")]
|
|
165
184
|
pub fn load_all_modules(
|
|
166
185
|
&self,
|
|
167
|
-
global_store: &mut GlobalStore
|
|
186
|
+
global_store: &mut GlobalStore
|
|
168
187
|
) -> (HashMap<String, Vec<Token>>, HashMap<String, Vec<Statement>>) {
|
|
169
188
|
// SECTION Load the entry module and its dependencies
|
|
170
189
|
let tokens_by_module = self.load_module_recursively(&self.entry, global_store);
|
|
@@ -183,7 +202,7 @@ impl ModuleLoader {
|
|
|
183
202
|
fn load_module_recursively(
|
|
184
203
|
&self,
|
|
185
204
|
raw_path: &str,
|
|
186
|
-
global_store: &mut GlobalStore
|
|
205
|
+
global_store: &mut GlobalStore
|
|
187
206
|
) -> HashMap<String, Vec<Token>> {
|
|
188
207
|
let path = normalize_path(raw_path);
|
|
189
208
|
|
|
@@ -193,7 +212,14 @@ impl ModuleLoader {
|
|
|
193
212
|
}
|
|
194
213
|
|
|
195
214
|
let lexer = Lexer::new();
|
|
196
|
-
let tokens = lexer.lex_tokens(&path)
|
|
215
|
+
let tokens = match lexer.lex_tokens(&path) {
|
|
216
|
+
Ok(t) => t,
|
|
217
|
+
Err(e) => {
|
|
218
|
+
let logger = Logger::new();
|
|
219
|
+
logger.log_message(LogLevel::Error, &format!("Failed to lex '{}': {}", path, e));
|
|
220
|
+
return HashMap::new();
|
|
221
|
+
}
|
|
222
|
+
};
|
|
197
223
|
|
|
198
224
|
let mut parser = Parser::new();
|
|
199
225
|
parser.set_current_module(path.clone());
|
|
@@ -217,14 +243,8 @@ impl ModuleLoader {
|
|
|
217
243
|
}
|
|
218
244
|
|
|
219
245
|
// Inject module variables and functions into global store
|
|
220
|
-
global_store
|
|
221
|
-
|
|
222
|
-
.variables
|
|
223
|
-
.extend(module.variable_table.variables.clone());
|
|
224
|
-
global_store
|
|
225
|
-
.functions
|
|
226
|
-
.functions
|
|
227
|
-
.extend(module.function_table.functions.clone());
|
|
246
|
+
global_store.variables.variables.extend(module.variable_table.variables.clone());
|
|
247
|
+
global_store.functions.functions.extend(module.function_table.functions.clone());
|
|
228
248
|
|
|
229
249
|
// Inject the module into the global store
|
|
230
250
|
global_store.insert_module(path.clone(), module);
|
|
@@ -249,8 +269,7 @@ impl ModuleLoader {
|
|
|
249
269
|
}
|
|
250
270
|
|
|
251
271
|
// Return tokens per module
|
|
252
|
-
global_store
|
|
253
|
-
.modules
|
|
272
|
+
global_store.modules
|
|
254
273
|
.iter()
|
|
255
274
|
.map(|(p, m)| (p.clone(), m.tokens.clone()))
|
|
256
275
|
.collect()
|
|
@@ -262,16 +281,12 @@ impl ModuleLoader {
|
|
|
262
281
|
let current_module = match global_store.modules.get(path) {
|
|
263
282
|
Some(module) => module,
|
|
264
283
|
None => {
|
|
265
|
-
eprintln!(
|
|
266
|
-
"[warn] Cannot resolve imports: module '{}' not found in store",
|
|
267
|
-
path
|
|
268
|
-
);
|
|
284
|
+
eprintln!("[warn] Cannot resolve imports: module '{}' not found in store", path);
|
|
269
285
|
return;
|
|
270
286
|
}
|
|
271
287
|
};
|
|
272
288
|
|
|
273
|
-
current_module
|
|
274
|
-
.statements
|
|
289
|
+
current_module.statements
|
|
275
290
|
.iter()
|
|
276
291
|
.filter_map(|stmt| {
|
|
277
292
|
if let StatementKind::Import { source, .. } = &stmt.kind {
|
|
@@ -293,57 +308,64 @@ impl ModuleLoader {
|
|
|
293
308
|
&self,
|
|
294
309
|
module: &mut Module,
|
|
295
310
|
bank_name: &str,
|
|
296
|
-
alias_override: Option<String
|
|
311
|
+
alias_override: Option<String>
|
|
297
312
|
) -> Result<Module, String> {
|
|
298
|
-
let default_alias = bank_name.split('.').
|
|
313
|
+
let default_alias = bank_name.split('.').next_back().unwrap_or(bank_name).to_string();
|
|
299
314
|
let alias_ref = alias_override.as_deref().unwrap_or(&default_alias);
|
|
300
315
|
|
|
301
|
-
let bank_path =
|
|
316
|
+
let bank_path = match devalang_utils::path::get_deva_dir() {
|
|
317
|
+
Ok(dir) => dir.join("banks").join(bank_name),
|
|
318
|
+
Err(_) => Path::new("./.deva").join("banks").join(bank_name),
|
|
319
|
+
};
|
|
302
320
|
let bank_toml_path = bank_path.join("bank.toml");
|
|
303
321
|
|
|
304
322
|
if !bank_toml_path.exists() {
|
|
305
323
|
return Ok(module.clone());
|
|
306
324
|
}
|
|
307
325
|
|
|
308
|
-
let content = std::fs
|
|
326
|
+
let content = std::fs
|
|
327
|
+
::read_to_string(&bank_toml_path)
|
|
309
328
|
.map_err(|e| format!("Failed to read '{}': {}", bank_toml_path.display(), e))?;
|
|
310
329
|
|
|
311
|
-
let parsed_bankfile: BankFile = toml
|
|
330
|
+
let parsed_bankfile: BankFile = toml
|
|
331
|
+
::from_str(&content)
|
|
312
332
|
.map_err(|e| format!("Failed to parse '{}': {}", bank_toml_path.display(), e))?;
|
|
313
333
|
|
|
314
334
|
let mut bank_map = HashMap::new();
|
|
315
335
|
|
|
316
336
|
for bank_trigger in parsed_bankfile.triggers.unwrap_or_default() {
|
|
317
|
-
|
|
318
|
-
|
|
337
|
+
// Use the configured path from the bank file as the entity reference so
|
|
338
|
+
// that bank entries can point to files or nested paths. Clean common
|
|
339
|
+
// local prefixes like "./" to keep the URI tidy.
|
|
340
|
+
let entity_ref = bank_trigger.path.clone().replace("\\", "/").replace("./", "");
|
|
341
|
+
let bank_trigger_path = format!("devalang://bank/{}/{}", bank_name, entity_ref);
|
|
319
342
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
);
|
|
343
|
+
// Keep the trigger key as declared (bank_trigger.name) but expose its
|
|
344
|
+
// value as a devalang://bank URI pointing to the configured path.
|
|
345
|
+
bank_map.insert(bank_trigger.name.clone(), Value::String(bank_trigger_path.clone()));
|
|
324
346
|
|
|
325
347
|
if module.variable_table.variables.contains_key(alias_ref) {
|
|
326
348
|
eprintln!(
|
|
327
349
|
"⚠️ Trigger '{}' already defined in module '{}', skipping injection.",
|
|
328
|
-
alias_ref,
|
|
350
|
+
alias_ref,
|
|
351
|
+
module.path
|
|
329
352
|
);
|
|
330
353
|
continue;
|
|
331
354
|
}
|
|
332
355
|
|
|
333
356
|
module.variable_table.set(
|
|
334
357
|
format!("{}.{}", alias_ref, bank_trigger.name),
|
|
335
|
-
Value::String(bank_trigger_path.clone())
|
|
358
|
+
Value::String(bank_trigger_path.clone())
|
|
336
359
|
);
|
|
337
360
|
}
|
|
338
361
|
|
|
339
362
|
// Inject the map under the bank name
|
|
340
|
-
module
|
|
341
|
-
.variable_table
|
|
342
|
-
.set(alias_ref.to_string(), Value::Map(bank_map));
|
|
363
|
+
module.variable_table.set(alias_ref.to_string(), Value::Map(bank_map));
|
|
343
364
|
|
|
344
365
|
Ok(module.clone())
|
|
345
366
|
}
|
|
346
367
|
|
|
368
|
+
#[cfg_attr(not(feature = "cli"), allow(dead_code))]
|
|
347
369
|
fn extract_bank_decls(&self, statements: &[Statement]) -> Vec<(String, Option<String>)> {
|
|
348
370
|
let mut banks = Vec::new();
|
|
349
371
|
|
|
@@ -371,7 +393,7 @@ impl ModuleLoader {
|
|
|
371
393
|
if let StatementKind::Use { name, alias } = &stmt.kind {
|
|
372
394
|
let alias_name = alias
|
|
373
395
|
.clone()
|
|
374
|
-
.unwrap_or_else(|| name.split('.').
|
|
396
|
+
.unwrap_or_else(|| name.split('.').next_back().unwrap_or(name).to_string());
|
|
375
397
|
plugins.push((name.clone(), alias_name));
|
|
376
398
|
}
|
|
377
399
|
}
|
|
@@ -384,7 +406,7 @@ impl ModuleLoader {
|
|
|
384
406
|
module: &mut Module,
|
|
385
407
|
plugin_name: &str,
|
|
386
408
|
alias: &str,
|
|
387
|
-
global_store: &mut GlobalStore
|
|
409
|
+
global_store: &mut GlobalStore
|
|
388
410
|
) {
|
|
389
411
|
// plugin_name expected format: "author.name"
|
|
390
412
|
let mut parts = plugin_name.split('.');
|
|
@@ -403,10 +425,7 @@ impl ModuleLoader {
|
|
|
403
425
|
}
|
|
404
426
|
};
|
|
405
427
|
if parts.next().is_some() {
|
|
406
|
-
eprintln!(
|
|
407
|
-
"Invalid plugin name '{}': expected <author>.<name>",
|
|
408
|
-
plugin_name
|
|
409
|
-
);
|
|
428
|
+
eprintln!("Invalid plugin name '{}': expected <author>.<name>", plugin_name);
|
|
410
429
|
return;
|
|
411
430
|
}
|
|
412
431
|
|
|
@@ -415,16 +434,19 @@ impl ModuleLoader {
|
|
|
415
434
|
let expected_uri = format!("devalang://plugin/{}.{}", author, name);
|
|
416
435
|
|
|
417
436
|
// Detect local presence (preferred and legacy layouts)
|
|
418
|
-
let root =
|
|
419
|
-
|
|
437
|
+
let root = match devalang_utils::path::get_deva_dir() {
|
|
438
|
+
Ok(dir) => dir,
|
|
439
|
+
Err(_) => Path::new("./.deva").to_path_buf(),
|
|
440
|
+
};
|
|
441
|
+
let plugin_dir_preferred = root.join("plugins").join(format!("{}.{}", author, name));
|
|
420
442
|
let toml_path_preferred = plugin_dir_preferred.join("plugin.toml");
|
|
421
|
-
let plugin_dir_fallback = root.join("
|
|
443
|
+
let plugin_dir_fallback = root.join("plugins").join(author).join(name);
|
|
422
444
|
let toml_path_fallback = plugin_dir_fallback.join("plugin.toml");
|
|
423
445
|
let exists_locally = toml_path_preferred.exists() || toml_path_fallback.exists();
|
|
424
446
|
|
|
425
447
|
if exists_locally {
|
|
426
448
|
// Load config and verify plugin is declared
|
|
427
|
-
let cfg_opt = load_config(None);
|
|
449
|
+
let cfg_opt = crate::config::ops::load_config(None);
|
|
428
450
|
let mut declared = false;
|
|
429
451
|
if let Some(cfg) = cfg_opt {
|
|
430
452
|
if let Some(list) = cfg.plugins {
|
|
@@ -435,8 +457,7 @@ impl ModuleLoader {
|
|
|
435
457
|
// Inject a single, clear error into the module so it is reported once by the error handler
|
|
436
458
|
module.statements.push(Statement {
|
|
437
459
|
kind: StatementKind::Error {
|
|
438
|
-
message: "plugin present in local files but missing in .devalang config"
|
|
439
|
-
.to_string(),
|
|
460
|
+
message: "plugin present in local files but missing in .devalang config".to_string(),
|
|
440
461
|
},
|
|
441
462
|
value: Value::Null,
|
|
442
463
|
indent: 0,
|
|
@@ -450,15 +471,16 @@ impl ModuleLoader {
|
|
|
450
471
|
match load_plugin(author, name) {
|
|
451
472
|
Ok((info, wasm)) => {
|
|
452
473
|
let uri = format!("devalang://plugin/{}.{}", author, name);
|
|
453
|
-
global_store
|
|
454
|
-
.plugins
|
|
455
|
-
.insert(format!("{}:{}", author, name), (info, wasm));
|
|
474
|
+
global_store.plugins.insert(format!("{}:{}", author, name), (info, wasm));
|
|
456
475
|
// Set alias to URI, and inject exported variables
|
|
457
|
-
module
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
476
|
+
module.variable_table.set(alias.to_string(), Value::String(uri.clone()));
|
|
477
|
+
// Also expose alias at global level so runtime can resolve it
|
|
478
|
+
global_store.variables.set(alias.to_string(), Value::String(uri.clone()));
|
|
479
|
+
|
|
480
|
+
if
|
|
481
|
+
let Some((plugin_info, _)) = global_store.plugins.get(
|
|
482
|
+
&format!("{}:{}", author, name)
|
|
483
|
+
)
|
|
462
484
|
{
|
|
463
485
|
for exp in &plugin_info.exports {
|
|
464
486
|
match exp.kind.as_str() {
|
|
@@ -467,18 +489,18 @@ impl ModuleLoader {
|
|
|
467
489
|
if let Ok(n) = s.parse::<f32>() {
|
|
468
490
|
module.variable_table.set(
|
|
469
491
|
format!("{}.{}", alias, exp.name),
|
|
470
|
-
Value::Number(n)
|
|
492
|
+
Value::Number(n)
|
|
471
493
|
);
|
|
472
494
|
}
|
|
473
495
|
} else if let Some(toml::Value::Integer(i)) = &exp.default {
|
|
474
496
|
module.variable_table.set(
|
|
475
497
|
format!("{}.{}", alias, exp.name),
|
|
476
|
-
Value::Number(*i as f32)
|
|
498
|
+
Value::Number(*i as f32)
|
|
477
499
|
);
|
|
478
500
|
} else if let Some(toml::Value::Float(f)) = &exp.default {
|
|
479
501
|
module.variable_table.set(
|
|
480
502
|
format!("{}.{}", alias, exp.name),
|
|
481
|
-
Value::Number(*f as f32)
|
|
503
|
+
Value::Number(*f as f32)
|
|
482
504
|
);
|
|
483
505
|
}
|
|
484
506
|
}
|
|
@@ -486,25 +508,85 @@ impl ModuleLoader {
|
|
|
486
508
|
if let Some(toml::Value::String(s)) = &exp.default {
|
|
487
509
|
module.variable_table.set(
|
|
488
510
|
format!("{}.{}", alias, exp.name),
|
|
489
|
-
Value::String(s.clone())
|
|
511
|
+
Value::String(s.clone())
|
|
490
512
|
);
|
|
491
513
|
}
|
|
492
514
|
}
|
|
493
515
|
"bool" => {
|
|
494
516
|
if let Some(toml::Value::Boolean(b)) = &exp.default {
|
|
495
|
-
module
|
|
496
|
-
.
|
|
497
|
-
|
|
517
|
+
module.variable_table.set(
|
|
518
|
+
format!("{}.{}", alias, exp.name),
|
|
519
|
+
Value::Boolean(*b)
|
|
520
|
+
);
|
|
498
521
|
}
|
|
499
522
|
}
|
|
500
523
|
"synth" => {
|
|
501
524
|
// Provide a discoverable marker: alias.<synthName> resolves to alias.synthName waveform string
|
|
502
525
|
module.variable_table.set(
|
|
503
526
|
format!("{}.{}", alias, exp.name),
|
|
504
|
-
Value::String(format!("{}.{}", alias, exp.name))
|
|
527
|
+
Value::String(format!("{}.{}", alias, exp.name))
|
|
505
528
|
);
|
|
506
529
|
}
|
|
507
|
-
_ => {
|
|
530
|
+
_ => {
|
|
531
|
+
// Fallback: if default is present, map it to a Value dynamically
|
|
532
|
+
if let Some(def) = &exp.default {
|
|
533
|
+
let val = match def {
|
|
534
|
+
toml::Value::String(s) => Value::String(s.clone()),
|
|
535
|
+
toml::Value::Integer(i) => Value::Number(*i as f32),
|
|
536
|
+
toml::Value::Float(f) => Value::Number(*f as f32),
|
|
537
|
+
toml::Value::Boolean(b) => Value::Boolean(*b),
|
|
538
|
+
toml::Value::Array(arr) =>
|
|
539
|
+
Value::Array(
|
|
540
|
+
arr
|
|
541
|
+
.iter()
|
|
542
|
+
.map(|v| {
|
|
543
|
+
match v {
|
|
544
|
+
toml::Value::String(s) => {
|
|
545
|
+
Value::String(s.clone())
|
|
546
|
+
}
|
|
547
|
+
toml::Value::Integer(i) => {
|
|
548
|
+
Value::Number(*i as f32)
|
|
549
|
+
}
|
|
550
|
+
toml::Value::Float(f) => {
|
|
551
|
+
Value::Number(*f as f32)
|
|
552
|
+
}
|
|
553
|
+
toml::Value::Boolean(b) =>
|
|
554
|
+
Value::Boolean(*b),
|
|
555
|
+
_ => Value::Null,
|
|
556
|
+
}
|
|
557
|
+
})
|
|
558
|
+
.collect()
|
|
559
|
+
),
|
|
560
|
+
toml::Value::Table(t) => {
|
|
561
|
+
let mut m = std::collections::HashMap::new();
|
|
562
|
+
for (k, v) in t.iter() {
|
|
563
|
+
let vv = match v {
|
|
564
|
+
toml::Value::String(s) => {
|
|
565
|
+
Value::String(s.clone())
|
|
566
|
+
}
|
|
567
|
+
toml::Value::Integer(i) => {
|
|
568
|
+
Value::Number(*i as f32)
|
|
569
|
+
}
|
|
570
|
+
toml::Value::Float(f) => {
|
|
571
|
+
Value::Number(*f as f32)
|
|
572
|
+
}
|
|
573
|
+
toml::Value::Boolean(b) => Value::Boolean(*b),
|
|
574
|
+
_ => Value::Null,
|
|
575
|
+
};
|
|
576
|
+
m.insert(k.clone(), vv);
|
|
577
|
+
}
|
|
578
|
+
Value::Map(m)
|
|
579
|
+
}
|
|
580
|
+
_ => Value::Null,
|
|
581
|
+
};
|
|
582
|
+
if val != Value::Null {
|
|
583
|
+
module.variable_table.set(
|
|
584
|
+
format!("{}.{}", alias, exp.name),
|
|
585
|
+
val
|
|
586
|
+
);
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
}
|
|
508
590
|
}
|
|
509
591
|
}
|
|
510
592
|
}
|
|
@@ -3,18 +3,21 @@ use std::{collections::HashMap, path::Path};
|
|
|
3
3
|
use crate::core::{
|
|
4
4
|
parser::statement::StatementKind,
|
|
5
5
|
preprocessor::loader::ModuleLoader,
|
|
6
|
-
shared::value::Value,
|
|
7
6
|
store::global::GlobalStore,
|
|
8
7
|
utils::path::{normalize_path, resolve_relative_path},
|
|
9
8
|
};
|
|
9
|
+
use devalang_types::Value;
|
|
10
10
|
|
|
11
11
|
pub fn process_modules(_module_loader: &ModuleLoader, global_store: &mut GlobalStore) {
|
|
12
12
|
for module in global_store.modules.values_mut() {
|
|
13
|
+
let logger = devalang_utils::logger::Logger::new();
|
|
14
|
+
use devalang_utils::logger::LogLevel;
|
|
15
|
+
|
|
13
16
|
for stmt in &module.statements {
|
|
14
17
|
match &stmt.kind {
|
|
15
18
|
StatementKind::Let { name } => {
|
|
16
19
|
if let Value::Null = stmt.value {
|
|
17
|
-
|
|
20
|
+
logger.log_message(LogLevel::Error, &format!("Variable '{}' is declared but not initialized.", name));
|
|
18
21
|
|
|
19
22
|
module.variable_table.variables.insert(
|
|
20
23
|
name.clone(),
|
|
@@ -25,15 +28,12 @@ pub fn process_modules(_module_loader: &ModuleLoader, global_store: &mut GlobalS
|
|
|
25
28
|
}
|
|
26
29
|
|
|
27
30
|
if module.variable_table.get(name).is_some() {
|
|
28
|
-
|
|
31
|
+
logger.log_message(LogLevel::Error, &format!("Variable '{}' is already defined in this scope.", name));
|
|
29
32
|
continue;
|
|
30
33
|
}
|
|
31
34
|
|
|
32
35
|
if let Some(module_variable) = module.variable_table.variables.get(name) {
|
|
33
|
-
|
|
34
|
-
"❌ Variable '{}' is already defined globally with value: {:?}",
|
|
35
|
-
name, module_variable
|
|
36
|
-
);
|
|
36
|
+
logger.log_message(LogLevel::Error, &format!("Variable '{}' is already defined globally with value: {:?}", name, module_variable));
|
|
37
37
|
continue;
|
|
38
38
|
}
|
|
39
39
|
|
|
@@ -46,7 +46,7 @@ pub fn process_modules(_module_loader: &ModuleLoader, global_store: &mut GlobalS
|
|
|
46
46
|
StatementKind::Load { source, alias } => {
|
|
47
47
|
let module_dir = Path::new(&module.path).parent().unwrap_or(Path::new(""));
|
|
48
48
|
|
|
49
|
-
let resolved_path = normalize_path(
|
|
49
|
+
let resolved_path = normalize_path(module_dir.join(source));
|
|
50
50
|
|
|
51
51
|
module
|
|
52
52
|
.variable_table
|
|
@@ -87,7 +87,7 @@ pub fn process_modules(_module_loader: &ModuleLoader, global_store: &mut GlobalS
|
|
|
87
87
|
.variable_table
|
|
88
88
|
.set(name.to_string(), Value::Map(stored_map));
|
|
89
89
|
} else {
|
|
90
|
-
|
|
90
|
+
logger.log_message(LogLevel::Error, &format!("Invalid group definition: {:?}", stmt.value));
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
93
|
}
|
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
use crate::{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
shared::value::Value,
|
|
6
|
-
store::global::GlobalStore,
|
|
7
|
-
},
|
|
8
|
-
utils::logger::Logger,
|
|
1
|
+
use crate::core::{
|
|
2
|
+
parser::statement::{Statement, StatementKind},
|
|
3
|
+
preprocessor::module::Module,
|
|
4
|
+
store::global::GlobalStore,
|
|
9
5
|
};
|
|
6
|
+
use devalang_types::Value;
|
|
7
|
+
use devalang_utils::logger::Logger;
|
|
10
8
|
|
|
11
9
|
pub fn resolve_bank(
|
|
12
10
|
stmt: &Statement,
|