@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
|
@@ -7,9 +7,9 @@ use crate::core::{
|
|
|
7
7
|
handler::{dot::parse_dot_token, identifier::synth::parse_synth_token},
|
|
8
8
|
statement::{Statement, StatementKind},
|
|
9
9
|
},
|
|
10
|
-
shared::value::Value,
|
|
11
10
|
store::global::GlobalStore,
|
|
12
11
|
};
|
|
12
|
+
use devalang_types::Value;
|
|
13
13
|
|
|
14
14
|
pub fn parse_let_token(
|
|
15
15
|
parser: &mut Parser,
|
|
@@ -23,14 +23,23 @@ pub fn parse_let_token(
|
|
|
23
23
|
parser.advance();
|
|
24
24
|
token.lexeme.clone()
|
|
25
25
|
} else {
|
|
26
|
-
return
|
|
26
|
+
return crate::core::parser::statement::error_from_token(
|
|
27
|
+
token,
|
|
28
|
+
"Expected identifier after 'let'".to_string(),
|
|
29
|
+
);
|
|
27
30
|
}
|
|
28
31
|
} else {
|
|
29
|
-
return
|
|
32
|
+
return crate::core::parser::statement::error_from_token(
|
|
33
|
+
current_token,
|
|
34
|
+
"Expected identifier after 'let'".to_string(),
|
|
35
|
+
);
|
|
30
36
|
};
|
|
31
37
|
|
|
32
38
|
if !parser.match_token(TokenKind::Equals) {
|
|
33
|
-
return
|
|
39
|
+
return crate::core::parser::statement::error_from_token(
|
|
40
|
+
current_token,
|
|
41
|
+
"Expected '=' after identifier".to_string(),
|
|
42
|
+
);
|
|
34
43
|
}
|
|
35
44
|
|
|
36
45
|
// If RHS begins with '$' or contains expression tokens ('+', '-', '*', '/', '(', '['),
|
|
@@ -101,14 +110,17 @@ pub fn parse_let_token(
|
|
|
101
110
|
}
|
|
102
111
|
|
|
103
112
|
if key_token.kind != TokenKind::Identifier {
|
|
104
|
-
return
|
|
113
|
+
return crate::core::parser::statement::error_from_token(
|
|
114
|
+
token,
|
|
115
|
+
"Expected key identifier in map".to_string(),
|
|
116
|
+
);
|
|
105
117
|
}
|
|
106
118
|
parser.advance();
|
|
107
119
|
let key = key_token.lexeme.clone();
|
|
108
120
|
|
|
109
121
|
if !parser.match_token(TokenKind::Colon) {
|
|
110
122
|
let message = format!("Expected ':' after key '{}'", key);
|
|
111
|
-
return
|
|
123
|
+
return crate::core::parser::statement::error_from_token(token, message);
|
|
112
124
|
}
|
|
113
125
|
|
|
114
126
|
let val = match parser.peek_clone() {
|
|
@@ -129,7 +141,7 @@ pub fn parse_let_token(
|
|
|
129
141
|
|
|
130
142
|
if val == Value::Null {
|
|
131
143
|
let message = format!("Invalid value for key '{}'", key);
|
|
132
|
-
return
|
|
144
|
+
return crate::core::parser::statement::error_from_token(token, message);
|
|
133
145
|
}
|
|
134
146
|
|
|
135
147
|
map.insert(key, val);
|
|
@@ -144,13 +156,16 @@ pub fn parse_let_token(
|
|
|
144
156
|
Value::Map(map)
|
|
145
157
|
}
|
|
146
158
|
_ => {
|
|
147
|
-
return
|
|
159
|
+
return crate::core::parser::statement::error_from_token(
|
|
160
|
+
current_token,
|
|
161
|
+
"Unhandled value type after '='".to_string(),
|
|
162
|
+
);
|
|
148
163
|
}
|
|
149
164
|
};
|
|
150
165
|
|
|
151
166
|
Statement {
|
|
152
167
|
kind: StatementKind::Let { name: identifier },
|
|
153
|
-
value
|
|
168
|
+
value,
|
|
154
169
|
indent: current_token.indent,
|
|
155
170
|
line: current_token.line,
|
|
156
171
|
column: current_token.column,
|
|
@@ -32,7 +32,7 @@ pub fn parse_identifier_token(parser: &mut Parser, global_store: &mut GlobalStor
|
|
|
32
32
|
let current_token_clone = current_token.clone();
|
|
33
33
|
let current_token_lexeme = current_token_clone.lexeme.clone();
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
match current_token_lexeme.as_str() {
|
|
36
36
|
"let" => parse_let_token(parser, current_token_clone, global_store),
|
|
37
37
|
"group" => parse_group_token(parser, current_token_clone, global_store),
|
|
38
38
|
"call" => parse_call_token(parser, current_token_clone, global_store),
|
|
@@ -46,9 +46,10 @@ pub fn parse_identifier_token(parser: &mut Parser, global_store: &mut GlobalStor
|
|
|
46
46
|
_ => {
|
|
47
47
|
parser.advance(); // consume identifier
|
|
48
48
|
|
|
49
|
-
|
|
49
|
+
crate::core::parser::statement::error_from_token(
|
|
50
|
+
current_token_clone,
|
|
51
|
+
"Unexpected identifier".to_string(),
|
|
52
|
+
)
|
|
50
53
|
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
return statement;
|
|
54
|
+
}
|
|
54
55
|
}
|
|
@@ -1,16 +1,14 @@
|
|
|
1
|
+
use devalang_types::Value;
|
|
2
|
+
|
|
1
3
|
use crate::core::{
|
|
2
4
|
lexer::token::TokenKind,
|
|
3
5
|
parser::{
|
|
4
6
|
driver::Parser,
|
|
5
7
|
statement::{Statement, StatementKind},
|
|
6
8
|
},
|
|
7
|
-
shared::value::Value,
|
|
8
9
|
store::global::GlobalStore,
|
|
9
10
|
};
|
|
10
11
|
|
|
11
|
-
// Syntax:
|
|
12
|
-
// on <identifier>:
|
|
13
|
-
// <indented block>
|
|
14
12
|
pub fn parse_on_token(parser: &mut Parser, _global_store: &mut GlobalStore) -> Statement {
|
|
15
13
|
// consume 'on'
|
|
16
14
|
let on_tok = match parser.peek_clone() {
|
|
@@ -23,9 +21,17 @@ pub fn parse_on_token(parser: &mut Parser, _global_store: &mut GlobalStore) -> S
|
|
|
23
21
|
let event_tok = match parser.peek_clone() {
|
|
24
22
|
Some(tok) if tok.kind == TokenKind::Identifier => tok,
|
|
25
23
|
Some(other) => {
|
|
26
|
-
return
|
|
24
|
+
return crate::core::parser::statement::error_from_token(
|
|
25
|
+
other,
|
|
26
|
+
"Expected event name after 'on'".to_string(),
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
None => {
|
|
30
|
+
return crate::core::parser::statement::error_from_token(
|
|
31
|
+
on_tok,
|
|
32
|
+
"Expected event name after 'on'".to_string(),
|
|
33
|
+
);
|
|
27
34
|
}
|
|
28
|
-
None => return Statement::error(on_tok, "Expected event name after 'on'".to_string()),
|
|
29
35
|
};
|
|
30
36
|
let event_name = event_tok.lexeme.clone();
|
|
31
37
|
parser.advance();
|
|
@@ -68,7 +74,10 @@ pub fn parse_on_token(parser: &mut Parser, _global_store: &mut GlobalStore) -> S
|
|
|
68
74
|
|
|
69
75
|
// Expect ':' then block
|
|
70
76
|
if parser.peek_kind() != Some(TokenKind::Colon) {
|
|
71
|
-
return
|
|
77
|
+
return crate::core::parser::statement::error_from_token(
|
|
78
|
+
event_tok,
|
|
79
|
+
"Expected ':' after event name".to_string(),
|
|
80
|
+
);
|
|
72
81
|
}
|
|
73
82
|
parser.advance(); // consume ':'
|
|
74
83
|
|
|
@@ -6,6 +6,7 @@ use crate::core::{
|
|
|
6
6
|
},
|
|
7
7
|
store::global::GlobalStore,
|
|
8
8
|
};
|
|
9
|
+
use devalang_types::Value;
|
|
9
10
|
|
|
10
11
|
pub fn parse_print_token(
|
|
11
12
|
parser: &mut Parser,
|
|
@@ -19,17 +20,13 @@ pub fn parse_print_token(
|
|
|
19
20
|
// Accept: print <identifier|string|number|expression>
|
|
20
21
|
let value = if collected.len() == 1 {
|
|
21
22
|
match collected[0].kind {
|
|
22
|
-
TokenKind::Identifier =>
|
|
23
|
-
|
|
24
|
-
}
|
|
25
|
-
TokenKind::String => {
|
|
26
|
-
crate::core::shared::value::Value::String(collected[0].lexeme.clone())
|
|
27
|
-
}
|
|
23
|
+
TokenKind::Identifier => Value::Identifier(collected[0].lexeme.clone()),
|
|
24
|
+
TokenKind::String => Value::String(collected[0].lexeme.clone()),
|
|
28
25
|
TokenKind::Number => {
|
|
29
26
|
let n = collected[0].lexeme.parse::<f32>().unwrap_or(0.0);
|
|
30
|
-
|
|
27
|
+
Value::Number(n)
|
|
31
28
|
}
|
|
32
|
-
_ =>
|
|
29
|
+
_ => Value::String(collected[0].lexeme.clone()),
|
|
33
30
|
}
|
|
34
31
|
} else {
|
|
35
32
|
// Join tokens with spaces to preserve readability for expressions/text
|
|
@@ -39,7 +36,7 @@ pub fn parse_print_token(
|
|
|
39
36
|
.map(|t| t.lexeme.clone())
|
|
40
37
|
.collect::<Vec<_>>()
|
|
41
38
|
.join(" ");
|
|
42
|
-
|
|
39
|
+
Value::String(text.trim().to_string())
|
|
43
40
|
};
|
|
44
41
|
|
|
45
42
|
Statement {
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
use devalang_types::Value;
|
|
2
|
+
|
|
1
3
|
use crate::core::{
|
|
2
4
|
lexer::token::{Token, TokenKind},
|
|
3
5
|
parser::{
|
|
4
6
|
driver::Parser,
|
|
5
7
|
statement::{Statement, StatementKind},
|
|
6
8
|
},
|
|
7
|
-
shared::value::Value,
|
|
8
9
|
store::global::GlobalStore,
|
|
9
10
|
};
|
|
10
11
|
|
|
@@ -20,17 +21,23 @@ pub fn parse_sleep_token(
|
|
|
20
21
|
parser.advance();
|
|
21
22
|
token.lexeme.parse().unwrap_or(0.0)
|
|
22
23
|
} else {
|
|
23
|
-
return
|
|
24
|
+
return crate::core::parser::statement::error_from_token(
|
|
25
|
+
token,
|
|
26
|
+
"Expected number after 'sleep'".to_string(),
|
|
27
|
+
);
|
|
24
28
|
}
|
|
25
29
|
} else {
|
|
26
|
-
return
|
|
30
|
+
return crate::core::parser::statement::error_from_token(
|
|
31
|
+
current_token,
|
|
32
|
+
"Expected number after 'sleep'".to_string(),
|
|
33
|
+
);
|
|
27
34
|
};
|
|
28
35
|
|
|
29
|
-
|
|
36
|
+
Statement {
|
|
30
37
|
kind: StatementKind::Sleep,
|
|
31
38
|
value: Value::Number(duration),
|
|
32
39
|
indent: current_token.indent,
|
|
33
40
|
line: current_token.line,
|
|
34
41
|
column: current_token.column,
|
|
35
|
-
}
|
|
42
|
+
}
|
|
36
43
|
}
|
|
@@ -4,9 +4,9 @@ use crate::core::{
|
|
|
4
4
|
driver::Parser,
|
|
5
5
|
statement::{Statement, StatementKind},
|
|
6
6
|
},
|
|
7
|
-
shared::value::Value,
|
|
8
7
|
store::global::GlobalStore,
|
|
9
8
|
};
|
|
9
|
+
use devalang_types::Value;
|
|
10
10
|
|
|
11
11
|
pub fn parse_spawn_token(
|
|
12
12
|
parser: &mut Parser,
|
|
@@ -19,7 +19,7 @@ pub fn parse_spawn_token(
|
|
|
19
19
|
let name_token = match parser.peek_clone() {
|
|
20
20
|
Some(t) => t,
|
|
21
21
|
None => {
|
|
22
|
-
return
|
|
22
|
+
return crate::core::parser::statement::error_from_token(
|
|
23
23
|
current_token,
|
|
24
24
|
"Expected function name after 'spawn'".to_string(),
|
|
25
25
|
);
|
|
@@ -27,7 +27,7 @@ pub fn parse_spawn_token(
|
|
|
27
27
|
};
|
|
28
28
|
|
|
29
29
|
if name_token.kind != TokenKind::Identifier {
|
|
30
|
-
return
|
|
30
|
+
return crate::core::parser::statement::error_from_token(
|
|
31
31
|
name_token,
|
|
32
32
|
"Expected function name to be an identifier".to_string(),
|
|
33
33
|
);
|
|
@@ -68,7 +68,7 @@ pub fn parse_spawn_token(
|
|
|
68
68
|
parser.advance(); // skip comma
|
|
69
69
|
}
|
|
70
70
|
_ => {
|
|
71
|
-
return
|
|
71
|
+
return crate::core::parser::statement::error_from_token(
|
|
72
72
|
token,
|
|
73
73
|
"Unexpected token in spawn arguments".to_string(),
|
|
74
74
|
);
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
use std::collections::HashMap;
|
|
2
2
|
|
|
3
|
+
use devalang_types::Value;
|
|
4
|
+
|
|
3
5
|
use crate::core::{
|
|
4
6
|
lexer::token::Token,
|
|
5
7
|
parser::{
|
|
6
8
|
driver::Parser,
|
|
9
|
+
handler::dot::parse_dot_token,
|
|
7
10
|
statement::{Statement, StatementKind},
|
|
8
11
|
},
|
|
9
|
-
shared::value::Value,
|
|
10
12
|
store::global::GlobalStore,
|
|
11
13
|
};
|
|
12
14
|
|
|
@@ -21,14 +23,81 @@ pub fn parse_synth_token(
|
|
|
21
23
|
return Statement::unknown();
|
|
22
24
|
};
|
|
23
25
|
|
|
24
|
-
// Expect
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
// Expect a provider/waveform identifier (can be dotted: alias.synth)
|
|
27
|
+
// Also accept a dot-led entity by delegating to the dot parser (e.g. .module.export)
|
|
28
|
+
let synth_waveform = if let Some(first_token) = parser.peek_clone() {
|
|
29
|
+
use crate::core::lexer::token::TokenKind;
|
|
28
30
|
|
|
29
|
-
|
|
31
|
+
if first_token.kind == TokenKind::Dot {
|
|
32
|
+
// Parse dot-entity and extract its entity string
|
|
33
|
+
let dot_stmt = parse_dot_token(parser, _global_store);
|
|
34
|
+
// Extract entity if the parsed statement is a Trigger
|
|
35
|
+
match dot_stmt.kind {
|
|
36
|
+
StatementKind::Trigger { entity, .. } => entity,
|
|
37
|
+
_ => String::new(),
|
|
38
|
+
}
|
|
39
|
+
} else {
|
|
40
|
+
if first_token.kind != crate::core::lexer::token::TokenKind::Identifier
|
|
41
|
+
&& first_token.kind != crate::core::lexer::token::TokenKind::Number
|
|
42
|
+
&& first_token.kind != crate::core::lexer::token::TokenKind::Synth
|
|
43
|
+
{
|
|
44
|
+
return crate::core::parser::statement::error_from_token(
|
|
45
|
+
first_token.clone(),
|
|
46
|
+
"Expected identifier after 'synth'".to_string(),
|
|
47
|
+
);
|
|
48
|
+
}
|
|
30
49
|
|
|
31
|
-
|
|
50
|
+
// Collect dotted parts on the same line
|
|
51
|
+
let mut parts: Vec<String> = Vec::new();
|
|
52
|
+
let current_line = first_token.line;
|
|
53
|
+
loop {
|
|
54
|
+
let Some(tok) = parser.peek_clone() else {
|
|
55
|
+
break;
|
|
56
|
+
};
|
|
57
|
+
if tok.line != current_line {
|
|
58
|
+
break;
|
|
59
|
+
}
|
|
60
|
+
match tok.kind {
|
|
61
|
+
crate::core::lexer::token::TokenKind::Identifier
|
|
62
|
+
| crate::core::lexer::token::TokenKind::Number
|
|
63
|
+
| crate::core::lexer::token::TokenKind::Synth => {
|
|
64
|
+
parts.push(tok.lexeme.clone());
|
|
65
|
+
parser.advance();
|
|
66
|
+
// If next isn't a dot on same line, stop
|
|
67
|
+
if let Some(next) = parser.peek_clone() {
|
|
68
|
+
if !(next.line == current_line
|
|
69
|
+
&& next.kind == crate::core::lexer::token::TokenKind::Dot)
|
|
70
|
+
{
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
} else {
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
crate::core::lexer::token::TokenKind::Dot => {
|
|
78
|
+
parser.advance();
|
|
79
|
+
}
|
|
80
|
+
_ => break,
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
parts.join(".")
|
|
85
|
+
}
|
|
86
|
+
} else {
|
|
87
|
+
return crate::core::parser::statement::error_from_token(
|
|
88
|
+
synth_token,
|
|
89
|
+
"Expected identifier after 'synth'".to_string(),
|
|
90
|
+
);
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
// Skip formatting before optional parameters map
|
|
94
|
+
while parser.check_token(crate::core::lexer::token::TokenKind::Newline)
|
|
95
|
+
|| parser.check_token(crate::core::lexer::token::TokenKind::Indent)
|
|
96
|
+
|| parser.check_token(crate::core::lexer::token::TokenKind::Dedent)
|
|
97
|
+
|| parser.check_token(crate::core::lexer::token::TokenKind::Whitespace)
|
|
98
|
+
{
|
|
99
|
+
parser.advance();
|
|
100
|
+
}
|
|
32
101
|
|
|
33
102
|
// Expect synth optional parameters map
|
|
34
103
|
let parameters = if let Some(params) = parser.parse_map_value() {
|
|
@@ -36,7 +105,7 @@ pub fn parse_synth_token(
|
|
|
36
105
|
if let Value::Map(map) = params {
|
|
37
106
|
map
|
|
38
107
|
} else {
|
|
39
|
-
return
|
|
108
|
+
return crate::core::parser::statement::error_from_token(
|
|
40
109
|
synth_token,
|
|
41
110
|
"Expected a map for synth parameters".to_string(),
|
|
42
111
|
);
|
|
@@ -53,7 +122,8 @@ pub fn parse_synth_token(
|
|
|
53
122
|
(
|
|
54
123
|
"value".to_string(),
|
|
55
124
|
Value::Map(HashMap::from([
|
|
56
|
-
|
|
125
|
+
// Store waveform as identifier to allow resolution from variables/exports
|
|
126
|
+
("waveform".to_string(), Value::Identifier(synth_waveform)),
|
|
57
127
|
("parameters".to_string(), Value::Map(parameters)),
|
|
58
128
|
])),
|
|
59
129
|
),
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
use devalang_types::Value;
|
|
2
|
+
|
|
1
3
|
use crate::core::{
|
|
2
4
|
lexer::token::TokenKind,
|
|
3
5
|
parser::{
|
|
4
6
|
driver::Parser,
|
|
5
7
|
statement::{Statement, StatementKind},
|
|
6
8
|
},
|
|
7
|
-
shared::value::Value,
|
|
8
9
|
store::global::GlobalStore,
|
|
9
10
|
};
|
|
10
11
|
|
|
@@ -20,7 +21,12 @@ pub fn parse_loop_token(parser: &mut Parser, global_store: &mut GlobalStore) ->
|
|
|
20
21
|
|
|
21
22
|
// Peek next to decide
|
|
22
23
|
let Some(next_token) = parser.peek_clone() else {
|
|
23
|
-
return Statement::
|
|
24
|
+
return Statement::error_with_pos(
|
|
25
|
+
loop_token.indent,
|
|
26
|
+
loop_token.line,
|
|
27
|
+
loop_token.column,
|
|
28
|
+
"Expected iterator after loop/for".to_string(),
|
|
29
|
+
);
|
|
24
30
|
};
|
|
25
31
|
|
|
26
32
|
// Try to detect 'for <ident> in [array]:' form
|
|
@@ -66,22 +72,31 @@ pub fn parse_loop_token(parser: &mut Parser, global_store: &mut GlobalStore) ->
|
|
|
66
72
|
Value::Identifier(tok.lexeme.clone())
|
|
67
73
|
}
|
|
68
74
|
_ => {
|
|
69
|
-
return Statement::
|
|
70
|
-
loop_token,
|
|
75
|
+
return Statement::error_with_pos(
|
|
76
|
+
loop_token.indent,
|
|
77
|
+
loop_token.line,
|
|
78
|
+
loop_token.column,
|
|
71
79
|
"Expected array, number, string or identifier after 'in'".to_string(),
|
|
72
80
|
);
|
|
73
81
|
}
|
|
74
82
|
}
|
|
75
83
|
} else {
|
|
76
|
-
return Statement::
|
|
77
|
-
loop_token,
|
|
84
|
+
return Statement::error_with_pos(
|
|
85
|
+
loop_token.indent,
|
|
86
|
+
loop_token.line,
|
|
87
|
+
loop_token.column,
|
|
78
88
|
"Expected array, number, string or identifier after 'in'".to_string(),
|
|
79
89
|
);
|
|
80
90
|
};
|
|
81
91
|
|
|
82
92
|
// Expect ':'
|
|
83
93
|
if !parser.match_token(TokenKind::Colon) {
|
|
84
|
-
return Statement::
|
|
94
|
+
return Statement::error_with_pos(
|
|
95
|
+
loop_token.indent,
|
|
96
|
+
loop_token.line,
|
|
97
|
+
loop_token.column,
|
|
98
|
+
"Expected ':' after foreach header".to_string(),
|
|
99
|
+
);
|
|
85
100
|
}
|
|
86
101
|
|
|
87
102
|
let tokens =
|
|
@@ -109,8 +124,10 @@ pub fn parse_loop_token(parser: &mut Parser, global_store: &mut GlobalStore) ->
|
|
|
109
124
|
|
|
110
125
|
// Fallback to legacy: loop <count>:
|
|
111
126
|
let Some(iterator_token) = parser.peek_clone() else {
|
|
112
|
-
return Statement::
|
|
113
|
-
loop_token,
|
|
127
|
+
return Statement::error_with_pos(
|
|
128
|
+
loop_token.indent,
|
|
129
|
+
loop_token.line,
|
|
130
|
+
loop_token.column,
|
|
114
131
|
"Expected number or identifier after 'loop'".to_string(),
|
|
115
132
|
);
|
|
116
133
|
};
|
|
@@ -133,8 +150,10 @@ pub fn parse_loop_token(parser: &mut Parser, global_store: &mut GlobalStore) ->
|
|
|
133
150
|
Value::String(s)
|
|
134
151
|
}
|
|
135
152
|
_ => {
|
|
136
|
-
return Statement::
|
|
137
|
-
iterator_token.clone(),
|
|
153
|
+
return Statement::error_with_pos(
|
|
154
|
+
iterator_token.clone().indent,
|
|
155
|
+
iterator_token.clone().line,
|
|
156
|
+
iterator_token.clone().column,
|
|
138
157
|
"Expected a number, string or identifier as loop count".to_string(),
|
|
139
158
|
);
|
|
140
159
|
}
|
|
@@ -145,10 +164,16 @@ pub fn parse_loop_token(parser: &mut Parser, global_store: &mut GlobalStore) ->
|
|
|
145
164
|
"Expected ':' after loop count, got {:?}",
|
|
146
165
|
parser.peek_kind()
|
|
147
166
|
);
|
|
148
|
-
return Statement::
|
|
167
|
+
return Statement::error_with_pos(
|
|
168
|
+
loop_token.clone().indent,
|
|
169
|
+
loop_token.clone().line,
|
|
170
|
+
loop_token.clone().column,
|
|
171
|
+
message,
|
|
172
|
+
);
|
|
149
173
|
}
|
|
150
174
|
|
|
151
|
-
let tokens =
|
|
175
|
+
let tokens =
|
|
176
|
+
parser.collect_until(|t| t.kind == TokenKind::Dedent || t.kind == TokenKind::EOF);
|
|
152
177
|
let loop_body = parser.parse_block(tokens.clone(), global_store);
|
|
153
178
|
if let Some(token) = parser.peek() {
|
|
154
179
|
if token.kind == TokenKind::Dedent {
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
use devalang_types::Value;
|
|
2
|
+
|
|
3
|
+
use crate::core::{
|
|
4
|
+
lexer::token::TokenKind,
|
|
5
|
+
parser::{
|
|
6
|
+
driver::Parser,
|
|
7
|
+
statement::{Statement, StatementKind},
|
|
8
|
+
},
|
|
9
|
+
store::global::GlobalStore,
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
pub fn parse_pattern_token(parser: &mut Parser, _global_store: &mut GlobalStore) -> Statement {
|
|
13
|
+
// consume 'pattern'
|
|
14
|
+
parser.advance();
|
|
15
|
+
|
|
16
|
+
let Some(tok) = parser.previous_clone() else {
|
|
17
|
+
return Statement::unknown();
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
// Parse pattern name
|
|
21
|
+
let mut name = String::new();
|
|
22
|
+
if let Some(next) = parser.peek_clone() {
|
|
23
|
+
if next.kind == TokenKind::Identifier {
|
|
24
|
+
parser.advance();
|
|
25
|
+
name = next.lexeme.clone();
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// optional 'with <target>' sequence
|
|
30
|
+
let mut target: Option<String> = None;
|
|
31
|
+
if parser.peek_is("with") {
|
|
32
|
+
parser.advance(); // consume 'with'
|
|
33
|
+
if let Some(tok2) = parser.peek_clone() {
|
|
34
|
+
// target can be identifier or dotted identifier
|
|
35
|
+
if tok2.kind == TokenKind::Identifier {
|
|
36
|
+
parser.advance();
|
|
37
|
+
let mut base = tok2.lexeme.clone();
|
|
38
|
+
if let Some(dot) = parser.peek_clone() {
|
|
39
|
+
if dot.kind == TokenKind::Dot {
|
|
40
|
+
parser.advance();
|
|
41
|
+
if let Some(suf) = parser.peek_clone() {
|
|
42
|
+
if suf.kind == TokenKind::Identifier || suf.kind == TokenKind::Number {
|
|
43
|
+
parser.advance();
|
|
44
|
+
base.push('.');
|
|
45
|
+
base.push_str(&suf.lexeme);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
target = Some(base);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// optional '=' and pattern string
|
|
56
|
+
let mut value: Value = Value::Null;
|
|
57
|
+
if parser.peek_is("=") {
|
|
58
|
+
parser.advance();
|
|
59
|
+
if let Some(tok3) = parser.peek_clone() {
|
|
60
|
+
if tok3.kind == TokenKind::String {
|
|
61
|
+
parser.advance();
|
|
62
|
+
value = Value::String(tok3.lexeme.clone());
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
Statement {
|
|
68
|
+
kind: StatementKind::Pattern { name, target },
|
|
69
|
+
value,
|
|
70
|
+
indent: tok.indent,
|
|
71
|
+
line: tok.line,
|
|
72
|
+
column: tok.column,
|
|
73
|
+
}
|
|
74
|
+
}
|
|
@@ -4,9 +4,9 @@ use crate::core::{
|
|
|
4
4
|
driver::Parser,
|
|
5
5
|
statement::{Statement, StatementKind},
|
|
6
6
|
},
|
|
7
|
-
shared::value::Value,
|
|
8
7
|
store::global::GlobalStore,
|
|
9
8
|
};
|
|
9
|
+
use devalang_types::Value;
|
|
10
10
|
|
|
11
11
|
pub fn parse_tempo_token(parser: &mut Parser, _global_store: &mut GlobalStore) -> Statement {
|
|
12
12
|
parser.advance(); // consume 'bpm'
|
|
@@ -17,8 +17,10 @@ pub fn parse_tempo_token(parser: &mut Parser, _global_store: &mut GlobalStore) -
|
|
|
17
17
|
|
|
18
18
|
// Expect a number or identifier
|
|
19
19
|
let Some(value_token) = parser.peek_clone() else {
|
|
20
|
-
return Statement::
|
|
21
|
-
tempo_token,
|
|
20
|
+
return Statement::error_with_pos(
|
|
21
|
+
tempo_token.indent,
|
|
22
|
+
tempo_token.line,
|
|
23
|
+
tempo_token.column,
|
|
22
24
|
"Expected a number or identifier after 'bpm'".to_string(),
|
|
23
25
|
);
|
|
24
26
|
};
|
|
@@ -33,8 +35,10 @@ pub fn parse_tempo_token(parser: &mut Parser, _global_store: &mut GlobalStore) -
|
|
|
33
35
|
Value::Identifier(value_token.lexeme.clone())
|
|
34
36
|
}
|
|
35
37
|
_ => {
|
|
36
|
-
return Statement::
|
|
37
|
-
value_token.
|
|
38
|
+
return Statement::error_with_pos(
|
|
39
|
+
value_token.indent,
|
|
40
|
+
value_token.line,
|
|
41
|
+
value_token.column,
|
|
38
42
|
format!(
|
|
39
43
|
"Expected a number or identifier after 'bpm', got {:?}",
|
|
40
44
|
value_token.kind
|
package/rust/core/parser/mod.rs
CHANGED