@devaloop/devalang 0.0.1-alpha.9 → 0.0.1-beta.2
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 +6 -1
- package/.github/workflows/ci.yml +103 -0
- package/Cargo.toml +81 -48
- package/README.md +137 -154
- package/docs/CHANGELOG.md +428 -1
- package/docs/CONTRIBUTING.md +101 -0
- package/docs/ROADMAP.md +14 -7
- package/docs/TODO.md +16 -15
- package/examples/automation.deva +42 -0
- package/examples/bank.deva +7 -0
- package/examples/bus.deva +10 -0
- package/examples/duration.deva +9 -0
- package/examples/effect.deva +2 -0
- package/examples/events.deva +12 -0
- package/examples/filter.deva +11 -0
- package/examples/function.deva +15 -0
- package/examples/index.deva +57 -12
- package/examples/lfo.deva +9 -0
- package/examples/loop.deva +5 -12
- package/examples/pattern.deva +8 -0
- package/examples/plugin.deva +16 -0
- package/examples/synth.deva +11 -1
- package/examples/synth_types.deva +17 -0
- package/examples/variables.deva +1 -1
- package/out-tsc/bin/index.d.ts +2 -0
- package/out-tsc/bin/index.js +51 -7
- package/out-tsc/core/functions/index.d.ts +42 -0
- package/out-tsc/core/functions/index.js +87 -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 +42 -1
- package/out-tsc/pkg/devalang_core.d.ts +15 -0
- package/out-tsc/pkg/devalang_core.js +65 -0
- package/out-tsc/pkg/devalang_core_bg.wasm.d.ts +34 -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 +83 -0
- 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 +28 -7
- package/project-version.json +4 -4
- package/rust/cli/bank/api.rs +122 -0
- package/rust/cli/bank/commands.rs +306 -0
- package/rust/cli/bank/mod.rs +29 -0
- package/rust/cli/build/commands.rs +153 -0
- package/rust/cli/build/mod.rs +2 -0
- package/rust/cli/build/process.rs +165 -0
- package/rust/cli/check/mod.rs +208 -0
- 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} +32 -23
- package/rust/cli/init/mod.rs +1 -0
- package/rust/cli/install/addon.rs +118 -0
- package/rust/cli/install/bank.rs +72 -0
- package/rust/cli/install/commands.rs +35 -0
- package/rust/cli/install/mod.rs +4 -0
- package/rust/cli/install/plugin.rs +80 -0
- package/rust/cli/login/commands.rs +124 -0
- package/rust/cli/login/mod.rs +1 -0
- package/rust/cli/mod.rs +9 -202
- package/rust/cli/parser.rs +359 -0
- package/rust/cli/play/commands.rs +375 -0
- package/rust/cli/play/io.rs +17 -0
- package/rust/cli/play/mod.rs +5 -0
- package/rust/cli/play/process.rs +159 -0
- package/rust/cli/play/realtime.rs +91 -0
- package/rust/cli/play/utils.rs +23 -0
- package/rust/cli/telemetry/commands.rs +22 -0
- 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} +17 -5
- package/rust/cli/template/mod.rs +1 -0
- package/rust/cli/update/commands.rs +6 -0
- package/rust/cli/update/mod.rs +1 -0
- package/rust/config/driver.rs +112 -0
- package/rust/config/mod.rs +3 -16
- package/rust/config/ops.rs +26 -0
- package/rust/config/settings.rs +101 -0
- package/rust/core/audio/engine/driver.rs +220 -0
- package/rust/core/audio/engine/export.rs +169 -0
- package/rust/core/audio/engine/helpers.rs +178 -0
- package/rust/core/audio/engine/mod.rs +56 -0
- package/rust/core/audio/engine/notes/dsp.rs +85 -0
- package/rust/core/audio/engine/notes/mod.rs +44 -0
- package/rust/core/audio/engine/notes/params.rs +294 -0
- package/rust/core/audio/engine/sample/insert.rs +199 -0
- package/rust/core/audio/engine/sample/mod.rs +40 -0
- package/rust/core/audio/engine/sample/padding.rs +170 -0
- package/rust/core/audio/evaluator/condition.rs +61 -0
- package/rust/core/audio/evaluator/mod.rs +9 -0
- package/rust/core/audio/evaluator/numeric.rs +152 -0
- package/rust/core/audio/evaluator/rhs.rs +16 -0
- package/rust/core/audio/evaluator/string_expr.rs +94 -0
- package/rust/core/audio/interpreter/driver.rs +574 -216
- package/rust/core/audio/interpreter/mod.rs +2 -12
- package/rust/core/audio/interpreter/statements/arrow_call/interprete.rs +175 -0
- package/rust/core/audio/interpreter/statements/arrow_call/methods/chord.rs +384 -0
- package/rust/core/audio/interpreter/statements/arrow_call/methods/mod.rs +2 -0
- package/rust/core/audio/interpreter/statements/arrow_call/methods/note.rs +316 -0
- package/rust/core/audio/interpreter/statements/arrow_call/mod.rs +3 -0
- package/rust/core/audio/interpreter/statements/arrow_call/types/arp.rs +192 -0
- package/rust/core/audio/interpreter/statements/arrow_call/types/mod.rs +24 -0
- package/rust/core/audio/interpreter/statements/arrow_call/types/pad.rs +116 -0
- package/rust/core/audio/interpreter/statements/arrow_call/types/pluck.rs +97 -0
- package/rust/core/audio/interpreter/statements/arrow_call/types/sub.rs +100 -0
- package/rust/core/audio/interpreter/statements/automate.rs +16 -0
- package/rust/core/audio/interpreter/statements/call.rs +295 -0
- package/rust/core/audio/interpreter/{condition.rs → statements/condition.rs} +72 -69
- package/rust/core/audio/interpreter/statements/function.rs +24 -0
- package/rust/core/audio/interpreter/statements/let_.rs +36 -0
- package/rust/core/audio/interpreter/statements/load.rs +17 -0
- package/rust/core/audio/interpreter/statements/loop_.rs +115 -0
- package/rust/core/audio/interpreter/statements/mod.rs +12 -0
- package/rust/core/audio/interpreter/statements/sleep.rs +28 -0
- package/rust/core/audio/interpreter/statements/spawn.rs +253 -0
- package/rust/core/audio/interpreter/statements/tempo.rs +40 -0
- package/rust/core/audio/interpreter/statements/trigger.rs +239 -0
- package/rust/core/audio/loader/mod.rs +1 -1
- package/rust/core/audio/loader/trigger.rs +98 -52
- package/rust/core/audio/mod.rs +2 -2
- package/rust/core/audio/player.rs +28 -12
- package/rust/core/audio/special/easing.rs +189 -0
- package/rust/core/audio/special/env.rs +45 -0
- package/rust/core/audio/special/math.rs +134 -0
- package/rust/core/audio/special/mod.rs +9 -0
- package/rust/core/audio/special/modulator.rs +143 -0
- package/rust/core/builder/mod.rs +129 -80
- package/rust/core/debugger/lexer.rs +4 -4
- package/rust/core/debugger/logs.rs +52 -0
- package/rust/core/debugger/mod.rs +11 -2
- package/rust/core/debugger/preprocessor.rs +4 -4
- package/rust/core/debugger/store.rs +38 -25
- package/rust/core/error/mod.rs +221 -12
- package/rust/core/lexer/driver.rs +59 -0
- package/rust/core/lexer/handler/arrow.rs +62 -11
- package/rust/core/lexer/handler/at.rs +5 -5
- package/rust/core/lexer/handler/brace.rs +11 -11
- package/rust/core/lexer/handler/colon.rs +5 -5
- package/rust/core/lexer/handler/comment.rs +3 -3
- package/rust/core/lexer/handler/dot.rs +6 -6
- package/rust/core/lexer/handler/driver.rs +143 -32
- package/rust/core/lexer/handler/identifier.rs +11 -5
- package/rust/core/lexer/handler/indent.rs +18 -4
- package/rust/core/lexer/handler/mod.rs +6 -5
- package/rust/core/lexer/handler/newline.rs +3 -3
- package/rust/core/lexer/handler/number.rs +5 -5
- package/rust/core/lexer/handler/operator.rs +5 -3
- package/rust/core/lexer/handler/parenthesis.rs +41 -0
- package/rust/core/lexer/handler/slash.rs +21 -0
- package/rust/core/lexer/handler/string.rs +3 -3
- package/rust/core/lexer/mod.rs +1 -49
- package/rust/core/lexer/token.rs +17 -12
- package/rust/core/mod.rs +9 -10
- package/rust/core/parser/driver/block.rs +111 -0
- package/rust/core/parser/driver/cursor.rs +82 -0
- package/rust/core/parser/driver/driver_impl.rs +139 -0
- package/rust/core/parser/driver/mod.rs +6 -0
- package/rust/core/parser/driver/parse_array.rs +120 -0
- package/rust/core/parser/driver/parse_map.rs +223 -0
- package/rust/core/parser/driver/parser.rs +160 -0
- package/rust/core/parser/handler/arrow_call.rs +277 -126
- package/rust/core/parser/handler/at.rs +142 -25
- package/rust/core/parser/handler/bank.rs +83 -20
- package/rust/core/parser/handler/condition.rs +14 -5
- package/rust/core/parser/handler/dot.rs +111 -75
- package/rust/core/parser/handler/identifier/automate.rs +254 -0
- package/rust/core/parser/handler/identifier/call.rs +74 -24
- package/rust/core/parser/handler/identifier/emit.rs +70 -0
- package/rust/core/parser/handler/identifier/function.rs +113 -0
- package/rust/core/parser/handler/identifier/group.rs +28 -14
- package/rust/core/parser/handler/identifier/let_.rs +61 -21
- package/rust/core/parser/handler/identifier/mod.rs +24 -20
- package/rust/core/parser/handler/identifier/on.rs +107 -0
- package/rust/core/parser/handler/identifier/print.rs +49 -0
- package/rust/core/parser/handler/identifier/sleep.rs +77 -14
- package/rust/core/parser/handler/identifier/spawn.rs +81 -31
- package/rust/core/parser/handler/identifier/synth.rs +102 -32
- package/rust/core/parser/handler/loop_.rs +144 -22
- package/rust/core/parser/handler/mod.rs +6 -5
- package/rust/core/parser/handler/pattern.rs +74 -0
- package/rust/core/parser/handler/tempo.rs +67 -9
- package/rust/core/parser/mod.rs +3 -4
- package/rust/core/parser/statement.rs +6 -92
- package/rust/core/plugin/loader.rs +137 -0
- package/rust/core/plugin/mod.rs +2 -0
- package/rust/core/plugin/runner/mod.rs +11 -0
- package/rust/core/plugin/runner/non_wasm.rs +297 -0
- package/rust/core/plugin/runner/wasm32.rs +43 -0
- package/rust/core/preprocessor/loader/inject.rs +278 -0
- package/rust/core/preprocessor/loader/loader_helpers.rs +110 -0
- package/rust/core/preprocessor/loader/mod.rs +235 -0
- package/rust/core/preprocessor/mod.rs +4 -4
- package/rust/core/preprocessor/module.rs +55 -50
- package/rust/core/preprocessor/processor/handlers.rs +107 -0
- package/rust/core/preprocessor/processor/mod.rs +1 -0
- package/rust/core/preprocessor/resolver/bank.rs +14 -12
- package/rust/core/preprocessor/resolver/call.rs +106 -105
- package/rust/core/preprocessor/resolver/condition.rs +13 -10
- package/rust/core/preprocessor/resolver/driver.rs +145 -48
- package/rust/core/preprocessor/resolver/function.rs +69 -0
- package/rust/core/preprocessor/resolver/group.rs +122 -61
- package/rust/core/preprocessor/resolver/let_.rs +13 -12
- package/rust/core/preprocessor/resolver/loop_.rs +240 -13
- package/rust/core/preprocessor/resolver/mod.rs +8 -6
- package/rust/core/preprocessor/resolver/pattern.rs +83 -0
- package/rust/core/preprocessor/resolver/spawn.rs +83 -42
- package/rust/core/preprocessor/resolver/synth.rs +15 -11
- package/rust/core/preprocessor/resolver/tempo.rs +13 -14
- package/rust/core/preprocessor/resolver/trigger.rs +32 -28
- package/rust/core/preprocessor/resolver/value.rs +111 -13
- package/rust/core/store/global.rs +57 -39
- package/rust/core/store/mod.rs +0 -3
- package/rust/lib.rs +323 -117
- package/rust/main.rs +388 -65
- 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 +84 -0
- package/rust/types/src/lib.rs +15 -0
- package/rust/types/src/plugin.rs +20 -0
- package/rust/types/src/store.rs +139 -0
- package/rust/types/src/telemetry.rs +85 -0
- package/rust/utils/Cargo.toml +26 -0
- package/rust/utils/src/error.rs +186 -0
- 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} +6 -3
- package/rust/utils/{logger.rs → src/logger.rs} +94 -17
- package/rust/utils/src/path.rs +129 -0
- package/rust/utils/src/signature.rs +41 -0
- package/rust/utils/{spinner.rs → src/spinner.rs} +7 -8
- package/rust/utils/src/version.rs +27 -0
- package/rust/utils/{watcher.rs → src/watcher.rs} +17 -4
- package/rust/web/api.rs +5 -0
- package/rust/web/cdn.rs +34 -0
- package/rust/web/mod.rs +3 -0
- package/rust/web/sso.rs +5 -0
- package/templates/minimal/README.md +143 -127
- package/templates/welcome/README.md +143 -127
- package/templates/welcome/src/index.deva +56 -8
- package/templates/welcome/src/variables.deva +2 -4
- package/tests/integration.rs +21 -0
- package/tests/rust/cli_check_build.rs +21 -0
- package/tests/rust/cli_help.rs +12 -0
- package/tests/rust/cli_template_list.rs +10 -0
- package/tests/rust/cli_version.rs +11 -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 +12 -10
- package/typescript/bin/index.ts +19 -5
- package/typescript/core/functions/index.ts +94 -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 +8 -1
- package/typescript/pkg/devalang_core.d.ts +4 -0
- package/typescript/pkg/devalang_core.ts +65 -0
- package/typescript/scripts/copy-wasm-dts.ts +41 -0
- package/typescript/scripts/postinstall.ts +85 -0
- package/typescript/scripts/version/bump.ts +0 -1
- package/typescript/scripts/version/index.ts +0 -1
- package/docs/COMMANDS.md +0 -85
- package/docs/CONFIG.md +0 -30
- package/docs/SYNTAX.md +0 -210
- package/out-tsc/bin/devalang.exe +0 -0
- package/out-tsc/scripts/postbuild.js +0 -11
- package/rust/cli/build.rs +0 -137
- package/rust/cli/check.rs +0 -117
- package/rust/cli/play.rs +0 -193
- package/rust/config/loader.rs +0 -13
- package/rust/core/audio/engine.rs +0 -203
- package/rust/core/audio/evaluator.rs +0 -31
- package/rust/core/audio/interpreter/arrow_call.rs +0 -129
- package/rust/core/audio/interpreter/call.rs +0 -64
- package/rust/core/audio/interpreter/let_.rs +0 -19
- package/rust/core/audio/interpreter/load.rs +0 -18
- package/rust/core/audio/interpreter/loop_.rs +0 -67
- package/rust/core/audio/interpreter/sleep.rs +0 -36
- package/rust/core/audio/interpreter/spawn.rs +0 -66
- package/rust/core/audio/interpreter/tempo.rs +0 -16
- package/rust/core/audio/interpreter/trigger.rs +0 -69
- package/rust/core/audio/renderer.rs +0 -54
- package/rust/core/parser/driver.rs +0 -331
- package/rust/core/preprocessor/loader.rs +0 -193
- package/rust/core/preprocessor/processor.rs +0 -76
- package/rust/core/shared/duration.rs +0 -8
- package/rust/core/shared/mod.rs +0 -2
- package/rust/core/shared/value.rs +0 -18
- package/rust/core/store/export.rs +0 -28
- package/rust/core/store/import.rs +0 -28
- package/rust/core/store/variable.rs +0 -28
- package/rust/core/utils/mod.rs +0 -2
- package/rust/core/utils/path.rs +0 -31
- package/rust/core/utils/validation.rs +0 -37
- package/rust/utils/file.rs +0 -35
- package/rust/utils/signature.rs +0 -17
- package/rust/utils/version.rs +0 -15
- package/typescript/scripts/postbuild.ts +0 -8
|
@@ -1,10 +1,14 @@
|
|
|
1
|
+
use devalang_types::Value;
|
|
2
|
+
|
|
1
3
|
use crate::core::{
|
|
2
4
|
lexer::token::TokenKind,
|
|
3
|
-
parser::{
|
|
4
|
-
|
|
5
|
+
parser::{
|
|
6
|
+
driver::parser::Parser,
|
|
7
|
+
statement::{Statement, StatementKind},
|
|
8
|
+
},
|
|
5
9
|
store::global::GlobalStore,
|
|
6
10
|
};
|
|
7
|
-
pub fn parse_at_token(parser: &mut Parser,
|
|
11
|
+
pub fn parse_at_token(parser: &mut Parser, _global_store: &mut GlobalStore) -> Statement {
|
|
8
12
|
parser.advance(); // consume '@'
|
|
9
13
|
|
|
10
14
|
let Some(token) = parser.peek_clone() else {
|
|
@@ -14,11 +18,96 @@ pub fn parse_at_token(parser: &mut Parser, global_store: &mut GlobalStore) -> St
|
|
|
14
18
|
let keyword = token.lexeme.as_str();
|
|
15
19
|
|
|
16
20
|
match keyword {
|
|
21
|
+
"use" => {
|
|
22
|
+
parser.advance(); // consume 'use'
|
|
23
|
+
let Some(use_token) = parser.previous_clone() else {
|
|
24
|
+
return Statement::unknown();
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
// Expect plugin author
|
|
28
|
+
let Some(author_token) = parser.peek_clone() else {
|
|
29
|
+
return crate::core::parser::statement::error_from_token(
|
|
30
|
+
use_token,
|
|
31
|
+
"Expected plugin author".to_string(),
|
|
32
|
+
);
|
|
33
|
+
};
|
|
34
|
+
if author_token.kind != TokenKind::Identifier {
|
|
35
|
+
return crate::core::parser::statement::error_from_token(
|
|
36
|
+
author_token,
|
|
37
|
+
"Expected identifier for plugin author".to_string(),
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
parser.advance(); // consume author
|
|
41
|
+
|
|
42
|
+
// Expect '.'
|
|
43
|
+
if !parser.match_token(TokenKind::Dot) {
|
|
44
|
+
return crate::core::parser::statement::error_from_token(
|
|
45
|
+
author_token,
|
|
46
|
+
"Expected '.' after plugin author".to_string(),
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Expect plugin name
|
|
51
|
+
let Some(plugin_token) = parser.peek_clone() else {
|
|
52
|
+
return crate::core::parser::statement::error_from_token(
|
|
53
|
+
author_token,
|
|
54
|
+
"Expected plugin name".to_string(),
|
|
55
|
+
);
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
let name = match plugin_token.kind {
|
|
59
|
+
TokenKind::Identifier | TokenKind::Number => {
|
|
60
|
+
parser.advance();
|
|
61
|
+
format!("{}.{}", author_token.lexeme, plugin_token.lexeme)
|
|
62
|
+
}
|
|
63
|
+
_ => {
|
|
64
|
+
return crate::core::parser::statement::error_from_token(
|
|
65
|
+
plugin_token,
|
|
66
|
+
"Expected identifier or number for plugin name".to_string(),
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
// Optional alias
|
|
72
|
+
let alias = if parser.match_token(TokenKind::As) {
|
|
73
|
+
let Some(alias_token) = parser.peek_clone() else {
|
|
74
|
+
return crate::core::parser::statement::error_from_token(
|
|
75
|
+
use_token,
|
|
76
|
+
"Expected identifier after 'as'".to_string(),
|
|
77
|
+
);
|
|
78
|
+
};
|
|
79
|
+
if alias_token.kind != TokenKind::Identifier {
|
|
80
|
+
return crate::core::parser::statement::error_from_token(
|
|
81
|
+
alias_token,
|
|
82
|
+
"Expected identifier after 'as'".to_string(),
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
parser.advance();
|
|
86
|
+
Some(alias_token.lexeme.clone())
|
|
87
|
+
} else {
|
|
88
|
+
None
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
Statement {
|
|
92
|
+
kind: StatementKind::Use {
|
|
93
|
+
name: name.clone(),
|
|
94
|
+
alias,
|
|
95
|
+
},
|
|
96
|
+
value: Value::Null,
|
|
97
|
+
indent: use_token.indent,
|
|
98
|
+
line: use_token.line,
|
|
99
|
+
column: use_token.column,
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
17
103
|
"import" => {
|
|
18
104
|
parser.advance(); // consume 'import'
|
|
19
105
|
|
|
20
106
|
if !parser.match_token(TokenKind::LBrace) {
|
|
21
|
-
return
|
|
107
|
+
return crate::core::parser::statement::error_from_token(
|
|
108
|
+
token,
|
|
109
|
+
"Expected '{{' after 'import'".to_string(),
|
|
110
|
+
);
|
|
22
111
|
}
|
|
23
112
|
|
|
24
113
|
let mut names = Vec::new();
|
|
@@ -36,31 +125,44 @@ pub fn parse_at_token(parser: &mut Parser, global_store: &mut GlobalStore) -> St
|
|
|
36
125
|
break;
|
|
37
126
|
}
|
|
38
127
|
_ => {
|
|
39
|
-
let message =
|
|
40
|
-
"Unexpected token in import list: {:?}",
|
|
41
|
-
|
|
128
|
+
let message =
|
|
129
|
+
format!("Unexpected token in import list: {:?}", token.kind.clone());
|
|
130
|
+
return crate::core::parser::statement::error_from_token(
|
|
131
|
+
token.clone(),
|
|
132
|
+
message,
|
|
42
133
|
);
|
|
43
|
-
return Statement::error(token.clone(), message);
|
|
44
134
|
}
|
|
45
135
|
}
|
|
46
136
|
}
|
|
47
137
|
|
|
48
138
|
let Some(from_token) = parser.peek_clone() else {
|
|
49
|
-
return
|
|
139
|
+
return crate::core::parser::statement::error_from_token(
|
|
140
|
+
token,
|
|
141
|
+
"Expected 'from' after import list".to_string(),
|
|
142
|
+
);
|
|
50
143
|
};
|
|
51
144
|
|
|
52
145
|
if from_token.lexeme != "from" {
|
|
53
|
-
return
|
|
146
|
+
return crate::core::parser::statement::error_from_token(
|
|
147
|
+
token,
|
|
148
|
+
"Expected keyword 'from'".to_string(),
|
|
149
|
+
);
|
|
54
150
|
}
|
|
55
151
|
|
|
56
152
|
parser.advance(); // consume 'from'
|
|
57
153
|
|
|
58
154
|
let Some(source_token) = parser.peek() else {
|
|
59
|
-
return
|
|
155
|
+
return crate::core::parser::statement::error_from_token(
|
|
156
|
+
token,
|
|
157
|
+
"Expected string after 'from'".to_string(),
|
|
158
|
+
);
|
|
60
159
|
};
|
|
61
160
|
|
|
62
161
|
if source_token.kind != TokenKind::String {
|
|
63
|
-
return
|
|
162
|
+
return crate::core::parser::statement::error_from_token(
|
|
163
|
+
token,
|
|
164
|
+
"Expected string after 'from'".to_string(),
|
|
165
|
+
);
|
|
64
166
|
}
|
|
65
167
|
|
|
66
168
|
let source = source_token.lexeme.clone();
|
|
@@ -91,7 +193,10 @@ pub fn parse_at_token(parser: &mut Parser, global_store: &mut GlobalStore) -> St
|
|
|
91
193
|
} else if token.kind == TokenKind::RBrace {
|
|
92
194
|
break; // Stop at the closing brace
|
|
93
195
|
} else {
|
|
94
|
-
return
|
|
196
|
+
return crate::core::parser::statement::error_from_token(
|
|
197
|
+
token,
|
|
198
|
+
"Unexpected token in export list".to_string(),
|
|
199
|
+
);
|
|
95
200
|
}
|
|
96
201
|
}
|
|
97
202
|
|
|
@@ -110,35 +215,47 @@ pub fn parse_at_token(parser: &mut Parser, global_store: &mut GlobalStore) -> St
|
|
|
110
215
|
"load" => {
|
|
111
216
|
parser.advance(); // consume 'load'
|
|
112
217
|
|
|
113
|
-
//
|
|
218
|
+
// Example: @load "preset.mydeva"
|
|
114
219
|
let Some(path_token) = parser.peek() else {
|
|
115
|
-
return
|
|
220
|
+
return crate::core::parser::statement::error_from_token(
|
|
221
|
+
token,
|
|
222
|
+
"Expected string after 'load'".to_string(),
|
|
223
|
+
);
|
|
116
224
|
};
|
|
117
225
|
|
|
118
226
|
if path_token.kind != TokenKind::String {
|
|
119
|
-
return
|
|
227
|
+
return crate::core::parser::statement::error_from_token(
|
|
228
|
+
token,
|
|
229
|
+
"Expected string after 'load'".to_string(),
|
|
230
|
+
);
|
|
120
231
|
}
|
|
121
232
|
|
|
122
233
|
let path = path_token.lexeme.clone();
|
|
123
234
|
|
|
124
235
|
parser.advance(); // consume string
|
|
125
|
-
parser.advance(); // consume 'as'
|
|
126
236
|
|
|
127
|
-
|
|
128
|
-
return
|
|
237
|
+
if !parser.match_token(TokenKind::As) {
|
|
238
|
+
return crate::core::parser::statement::error_from_token(
|
|
239
|
+
token,
|
|
240
|
+
"Expected 'as' after path in load statement".to_string(),
|
|
241
|
+
);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
let Some(alias_token) = parser.peek_clone() else {
|
|
245
|
+
return crate::core::parser::statement::error_from_token(
|
|
129
246
|
token,
|
|
130
|
-
"Expected 'as'
|
|
247
|
+
"Expected identifier after 'as' in load statement".to_string(),
|
|
131
248
|
);
|
|
132
249
|
};
|
|
133
250
|
|
|
134
|
-
if
|
|
135
|
-
return
|
|
251
|
+
if alias_token.kind != TokenKind::Identifier {
|
|
252
|
+
return crate::core::parser::statement::error_from_token(
|
|
136
253
|
token,
|
|
137
|
-
"Expected identifier after 'as' in load statement".to_string()
|
|
254
|
+
"Expected identifier after 'as' in load statement".to_string(),
|
|
138
255
|
);
|
|
139
256
|
}
|
|
140
257
|
|
|
141
|
-
let alias =
|
|
258
|
+
let alias = alias_token.lexeme.clone();
|
|
142
259
|
|
|
143
260
|
parser.advance(); // consume identifier
|
|
144
261
|
|
|
@@ -156,7 +273,7 @@ pub fn parse_at_token(parser: &mut Parser, global_store: &mut GlobalStore) -> St
|
|
|
156
273
|
|
|
157
274
|
_ => {
|
|
158
275
|
let message = format!("Unknown keyword after '@' : {}", keyword);
|
|
159
|
-
|
|
276
|
+
crate::core::parser::statement::error_from_token(token, message)
|
|
160
277
|
}
|
|
161
278
|
}
|
|
162
279
|
}
|
|
@@ -1,41 +1,104 @@
|
|
|
1
|
+
use devalang_types::Value;
|
|
2
|
+
|
|
1
3
|
use crate::core::{
|
|
2
4
|
lexer::token::TokenKind,
|
|
3
|
-
parser::{
|
|
4
|
-
|
|
5
|
+
parser::{
|
|
6
|
+
driver::parser::Parser,
|
|
7
|
+
statement::{Statement, StatementKind},
|
|
8
|
+
},
|
|
5
9
|
store::global::GlobalStore,
|
|
6
10
|
};
|
|
7
11
|
|
|
8
12
|
pub fn parse_bank_token(parser: &mut Parser, _global_store: &mut GlobalStore) -> Statement {
|
|
9
|
-
|
|
13
|
+
// consume 'bank'
|
|
14
|
+
parser.advance();
|
|
10
15
|
|
|
11
|
-
let Some(
|
|
16
|
+
let Some(bank_tok) = parser.previous_clone() else {
|
|
12
17
|
return Statement::unknown();
|
|
13
18
|
};
|
|
14
19
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
20
|
+
// Parse bank name
|
|
21
|
+
let bank_value: Value = match parser.peek_clone() {
|
|
22
|
+
Some(tok) => match tok.kind {
|
|
23
|
+
TokenKind::Identifier | TokenKind::Number => {
|
|
24
|
+
// base name
|
|
18
25
|
parser.advance();
|
|
19
|
-
|
|
26
|
+
let mut base = tok.lexeme.clone();
|
|
27
|
+
// optional .suffix (identifier or number)
|
|
28
|
+
if let Some(dot) = parser.peek_clone() {
|
|
29
|
+
if dot.kind == TokenKind::Dot {
|
|
30
|
+
// consume '.' and the following ident/number
|
|
31
|
+
parser.advance();
|
|
32
|
+
if let Some(suffix) = parser.peek_clone() {
|
|
33
|
+
match suffix.kind {
|
|
34
|
+
TokenKind::Identifier | TokenKind::Number => {
|
|
35
|
+
parser.advance();
|
|
36
|
+
base.push('.');
|
|
37
|
+
base.push_str(&suffix.lexeme);
|
|
38
|
+
Value::String(base)
|
|
39
|
+
}
|
|
40
|
+
_ => Value::Identifier(base),
|
|
41
|
+
}
|
|
42
|
+
} else {
|
|
43
|
+
Value::Identifier(base)
|
|
44
|
+
}
|
|
45
|
+
} else {
|
|
46
|
+
match tok.kind {
|
|
47
|
+
TokenKind::Identifier => Value::String(base),
|
|
48
|
+
TokenKind::Number => Value::Number(base.parse::<f32>().unwrap_or(0.0)),
|
|
49
|
+
_ => Value::Unknown,
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
} else {
|
|
53
|
+
match tok.kind {
|
|
54
|
+
TokenKind::Identifier => Value::String(base),
|
|
55
|
+
TokenKind::Number => Value::Number(base.parse::<f32>().unwrap_or(0.0)),
|
|
56
|
+
_ => Value::Unknown,
|
|
57
|
+
}
|
|
58
|
+
}
|
|
20
59
|
}
|
|
21
|
-
TokenKind::
|
|
60
|
+
TokenKind::String => {
|
|
22
61
|
parser.advance();
|
|
23
|
-
Value::
|
|
62
|
+
Value::String(tok.lexeme.clone())
|
|
24
63
|
}
|
|
25
64
|
_ => Value::Unknown,
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
return Statement::error(
|
|
29
|
-
bank_token,
|
|
30
|
-
"Expected identifier or number after 'bank'".to_string()
|
|
31
|
-
);
|
|
65
|
+
},
|
|
66
|
+
None => Value::Unknown,
|
|
32
67
|
};
|
|
33
68
|
|
|
69
|
+
if matches!(bank_value, Value::Unknown | Value::Null) {
|
|
70
|
+
return crate::core::parser::statement::error_from_token(
|
|
71
|
+
bank_tok,
|
|
72
|
+
"Expected a bank name".to_string(),
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Optional alias: as <identifier>
|
|
77
|
+
let mut alias: Option<String> = None;
|
|
78
|
+
if parser.peek_is("as") {
|
|
79
|
+
// consume 'as'
|
|
80
|
+
parser.advance();
|
|
81
|
+
let Some(next) = parser.peek_clone() else {
|
|
82
|
+
return crate::core::parser::statement::error_from_token(
|
|
83
|
+
bank_tok,
|
|
84
|
+
"Expected identifier after 'as'".to_string(),
|
|
85
|
+
);
|
|
86
|
+
};
|
|
87
|
+
if next.kind != TokenKind::Identifier {
|
|
88
|
+
return crate::core::parser::statement::error_from_token(
|
|
89
|
+
next,
|
|
90
|
+
"Expected identifier after 'as'".to_string(),
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
parser.advance();
|
|
94
|
+
alias = Some(next.lexeme.clone());
|
|
95
|
+
}
|
|
96
|
+
|
|
34
97
|
Statement {
|
|
35
|
-
kind: StatementKind::Bank,
|
|
98
|
+
kind: StatementKind::Bank { alias },
|
|
36
99
|
value: bank_value,
|
|
37
|
-
indent:
|
|
38
|
-
line:
|
|
39
|
-
column:
|
|
100
|
+
indent: bank_tok.indent,
|
|
101
|
+
line: bank_tok.line,
|
|
102
|
+
column: bank_tok.column,
|
|
40
103
|
}
|
|
41
104
|
}
|
|
@@ -1,10 +1,13 @@
|
|
|
1
|
-
use std::collections::HashMap;
|
|
2
1
|
use crate::core::{
|
|
3
2
|
lexer::token::TokenKind,
|
|
4
|
-
parser::{
|
|
5
|
-
|
|
3
|
+
parser::{
|
|
4
|
+
driver::parser::Parser,
|
|
5
|
+
statement::{Statement, StatementKind},
|
|
6
|
+
},
|
|
6
7
|
store::global::GlobalStore,
|
|
7
8
|
};
|
|
9
|
+
use devalang_types::Value;
|
|
10
|
+
use std::collections::HashMap;
|
|
8
11
|
|
|
9
12
|
pub fn parse_condition_token(parser: &mut Parser, global_store: &mut GlobalStore) -> Statement {
|
|
10
13
|
parser.advance(); // consume 'if'
|
|
@@ -13,7 +16,10 @@ pub fn parse_condition_token(parser: &mut Parser, global_store: &mut GlobalStore
|
|
|
13
16
|
};
|
|
14
17
|
|
|
15
18
|
let Some(condition) = parser.parse_condition_until_colon() else {
|
|
16
|
-
return
|
|
19
|
+
return crate::core::parser::statement::error_from_token(
|
|
20
|
+
if_token,
|
|
21
|
+
"Expected condition after 'if'".to_string(),
|
|
22
|
+
);
|
|
17
23
|
};
|
|
18
24
|
|
|
19
25
|
parser.advance_if(TokenKind::Colon);
|
|
@@ -40,7 +46,10 @@ pub fn parse_condition_token(parser: &mut Parser, global_store: &mut GlobalStore
|
|
|
40
46
|
let next_condition = if parser.peek_is("if") {
|
|
41
47
|
parser.advance(); // consume 'if'
|
|
42
48
|
let Some(cond) = parser.parse_condition_until_colon() else {
|
|
43
|
-
return
|
|
49
|
+
return crate::core::parser::statement::error_from_token(
|
|
50
|
+
tok.clone(),
|
|
51
|
+
"Expected condition after 'else if'".to_string(),
|
|
52
|
+
);
|
|
44
53
|
};
|
|
45
54
|
parser.advance_if(TokenKind::Colon);
|
|
46
55
|
Some(cond)
|
|
@@ -1,100 +1,136 @@
|
|
|
1
|
+
use devalang_types::{Duration, Value};
|
|
2
|
+
|
|
1
3
|
use crate::core::{
|
|
2
4
|
lexer::token::TokenKind,
|
|
3
|
-
parser::{
|
|
4
|
-
|
|
5
|
-
|
|
5
|
+
parser::{
|
|
6
|
+
driver::parser::Parser,
|
|
7
|
+
statement::{Statement, StatementKind},
|
|
8
|
+
},
|
|
6
9
|
};
|
|
7
10
|
|
|
8
|
-
pub fn parse_dot_token(
|
|
9
|
-
parser
|
|
10
|
-
|
|
11
|
+
pub fn parse_dot_token(
|
|
12
|
+
parser: &mut Parser,
|
|
13
|
+
_global_store: &mut crate::core::store::global::GlobalStore,
|
|
14
|
+
) -> Statement {
|
|
15
|
+
parser.advance(); // consume '.'
|
|
16
|
+
let logger = devalang_utils::logger::Logger::new();
|
|
17
|
+
use devalang_utils::logger::LogLevel;
|
|
11
18
|
let Some(dot_token) = parser.previous_clone() else {
|
|
12
19
|
return Statement::unknown();
|
|
13
20
|
};
|
|
14
21
|
|
|
15
|
-
//
|
|
16
|
-
let
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
22
|
+
// Parse a single entity (namespace-friendly, stops at newline)
|
|
23
|
+
let mut parts = Vec::new();
|
|
24
|
+
let current_line = dot_token.line;
|
|
25
|
+
|
|
26
|
+
while let Some(token) = parser.peek_clone() {
|
|
27
|
+
// Never cross a newline
|
|
28
|
+
if token.line != current_line {
|
|
29
|
+
break;
|
|
30
|
+
}
|
|
31
|
+
match token.kind {
|
|
32
|
+
TokenKind::Identifier | TokenKind::Number => {
|
|
33
|
+
parts.push(token.lexeme.clone());
|
|
34
|
+
parser.advance();
|
|
35
|
+
// The separator must be a '.' on the same line, otherwise stop
|
|
36
|
+
if let Some(next) = parser.peek_clone() {
|
|
37
|
+
if next.line != current_line || next.kind != TokenKind::Dot {
|
|
38
|
+
break;
|
|
39
|
+
}
|
|
40
|
+
} else {
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
TokenKind::Dot => {
|
|
45
|
+
parser.advance();
|
|
46
|
+
}
|
|
47
|
+
TokenKind::Newline | TokenKind::EOF | TokenKind::Indent | TokenKind::Dedent => {
|
|
48
|
+
break; // Stop at newline or dedent
|
|
49
|
+
}
|
|
50
|
+
_ => {
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
31
55
|
|
|
32
|
-
//
|
|
33
|
-
let
|
|
56
|
+
// Build entity name properly
|
|
57
|
+
let entity = if !parts.is_empty() {
|
|
58
|
+
parts.join(".") // only join within the same line
|
|
59
|
+
} else {
|
|
60
|
+
logger.log_message(
|
|
61
|
+
LogLevel::Warning,
|
|
62
|
+
&format!("Empty entity after '.' at line {}", dot_token.line),
|
|
63
|
+
);
|
|
64
|
+
String::new()
|
|
65
|
+
};
|
|
34
66
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
67
|
+
// Optional duration and effects map
|
|
68
|
+
let mut duration = Duration::Auto;
|
|
69
|
+
let mut value = Value::Null;
|
|
38
70
|
|
|
39
|
-
|
|
71
|
+
if let Some(token) = parser.peek_clone() {
|
|
72
|
+
// Duration and effects map are only valid on the same line
|
|
73
|
+
if token.line == current_line {
|
|
40
74
|
match token.kind {
|
|
41
|
-
TokenKind::Newline | TokenKind::EOF => { (Duration::Auto, Value::Null) }
|
|
42
|
-
|
|
43
75
|
TokenKind::Number => {
|
|
44
|
-
let
|
|
45
|
-
parser.advance();
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
76
|
+
let numerator = token.lexeme.clone();
|
|
77
|
+
parser.advance();
|
|
78
|
+
if let Some(peek) = parser.peek_clone() {
|
|
79
|
+
if peek.line == current_line {
|
|
80
|
+
if let Some(TokenKind::Slash) = parser.peek_kind() {
|
|
81
|
+
parser.advance();
|
|
82
|
+
if let Some(denominator_token) = parser.peek_clone() {
|
|
83
|
+
if denominator_token.line == current_line
|
|
84
|
+
&& denominator_token.kind == TokenKind::Number
|
|
85
|
+
{
|
|
86
|
+
let denominator = denominator_token.lexeme.clone();
|
|
87
|
+
parser.advance();
|
|
88
|
+
duration = Duration::Beat(format!(
|
|
89
|
+
"{}/{}",
|
|
90
|
+
numerator, denominator
|
|
91
|
+
));
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
} else {
|
|
95
|
+
duration = parse_duration(numerator);
|
|
96
|
+
}
|
|
97
|
+
} else {
|
|
98
|
+
duration = parse_duration(numerator);
|
|
55
99
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
100
|
+
} else {
|
|
101
|
+
duration = parse_duration(numerator);
|
|
102
|
+
}
|
|
103
|
+
if let Some(next) = parser.peek_clone() {
|
|
104
|
+
if next.line == current_line && next.kind == TokenKind::LBrace {
|
|
105
|
+
value = parser.parse_map_value().unwrap_or(Value::Null);
|
|
61
106
|
}
|
|
62
|
-
|
|
63
|
-
_ => (parse_duration(duration_lexeme), Value::Null),
|
|
64
107
|
}
|
|
65
108
|
}
|
|
66
|
-
|
|
67
109
|
TokenKind::Identifier => {
|
|
68
|
-
let
|
|
69
|
-
parser.advance();
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
parser.advance();
|
|
75
|
-
(
|
|
76
|
-
parse_duration(duration_lexeme),
|
|
77
|
-
Value::Identifier(param_token.lexeme.clone()),
|
|
78
|
-
)
|
|
110
|
+
let id = token.lexeme.clone();
|
|
111
|
+
parser.advance();
|
|
112
|
+
duration = parse_duration(id);
|
|
113
|
+
if let Some(next) = parser.peek_clone() {
|
|
114
|
+
if next.line == current_line && next.kind == TokenKind::LBrace {
|
|
115
|
+
value = parser.parse_map_value().unwrap_or(Value::Null);
|
|
79
116
|
}
|
|
80
|
-
|
|
81
|
-
Some(param_token) if param_token.kind == TokenKind::LBrace => {
|
|
82
|
-
// Handle value as Map
|
|
83
|
-
let map = parser.parse_map_value(); // Assumes you have a helper for map
|
|
84
|
-
(parse_duration(duration_lexeme), map.unwrap_or(Value::Null))
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
_ => (parse_duration(duration_lexeme), Value::Null),
|
|
88
117
|
}
|
|
89
118
|
}
|
|
90
|
-
|
|
91
|
-
|
|
119
|
+
TokenKind::LBrace => {
|
|
120
|
+
value = parser.parse_map_value().unwrap_or(Value::Null);
|
|
121
|
+
}
|
|
122
|
+
_ => {}
|
|
92
123
|
}
|
|
93
|
-
|
|
124
|
+
}
|
|
125
|
+
}
|
|
94
126
|
|
|
95
127
|
Statement {
|
|
96
|
-
kind: StatementKind::Trigger {
|
|
97
|
-
|
|
128
|
+
kind: StatementKind::Trigger {
|
|
129
|
+
entity,
|
|
130
|
+
duration,
|
|
131
|
+
effects: Some(value.clone()),
|
|
132
|
+
},
|
|
133
|
+
value: Value::Null,
|
|
98
134
|
indent: dot_token.indent,
|
|
99
135
|
line: dot_token.line,
|
|
100
136
|
column: dot_token.column,
|
|
@@ -104,8 +140,8 @@ pub fn parse_dot_token(parser: &mut Parser, _global_store: &mut GlobalStore) ->
|
|
|
104
140
|
fn parse_duration(s: String) -> Duration {
|
|
105
141
|
if s == "auto" {
|
|
106
142
|
Duration::Auto
|
|
107
|
-
} else if s.parse::<f32>()
|
|
108
|
-
Duration::Number(
|
|
143
|
+
} else if let Ok(num) = s.parse::<f32>() {
|
|
144
|
+
Duration::Number(num)
|
|
109
145
|
} else {
|
|
110
146
|
Duration::Identifier(s)
|
|
111
147
|
}
|