@devaloop/devalang 0.0.1-beta.1 → 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/.devalang +9 -10
- package/Cargo.toml +5 -4
- package/README.md +7 -5
- package/docs/CHANGELOG.md +42 -0
- package/docs/ROADMAP.md +5 -1
- package/docs/TODO.md +3 -14
- package/examples/bus.deva +10 -0
- package/examples/effect.deva +2 -0
- package/examples/filter.deva +11 -0
- package/examples/lfo.deva +9 -0
- package/examples/synth.deva +11 -1
- package/examples/synth_types.deva +17 -0
- package/out-tsc/core/functions/index.d.ts +5 -0
- package/out-tsc/core/functions/index.js +11 -0
- package/out-tsc/pkg/devalang_core.d.ts +2 -0
- package/out-tsc/pkg/devalang_core.js +17 -2
- package/out-tsc/pkg/devalang_core_bg.wasm.d.ts +8 -7
- package/package.json +1 -1
- package/project-version.json +3 -3
- package/rust/cli/bank/api.rs +122 -122
- package/rust/cli/bank/commands.rs +33 -2
- package/rust/cli/bank/mod.rs +29 -29
- package/rust/cli/build/commands.rs +53 -3
- package/rust/cli/build/mod.rs +2 -2
- package/rust/cli/build/process.rs +26 -7
- package/rust/cli/check/mod.rs +2 -2
- package/rust/cli/discover/commands.rs +253 -253
- package/rust/cli/discover/config.rs +111 -111
- package/rust/cli/discover/fs.rs +19 -19
- package/rust/cli/discover/install.rs +103 -103
- package/rust/cli/discover/metadata.rs +48 -48
- package/rust/cli/discover/mod.rs +5 -5
- package/rust/cli/install/addon.rs +118 -118
- package/rust/cli/install/bank.rs +22 -3
- package/rust/cli/install/commands.rs +35 -35
- package/rust/cli/install/mod.rs +4 -4
- package/rust/cli/install/plugin.rs +80 -61
- package/rust/cli/login/commands.rs +124 -124
- package/rust/cli/mod.rs +12 -12
- package/rust/cli/parser.rs +46 -1
- package/rust/cli/play/commands.rs +71 -20
- package/rust/cli/play/mod.rs +5 -5
- package/rust/cli/play/process.rs +14 -5
- package/rust/cli/play/realtime.rs +91 -91
- package/rust/cli/telemetry/commands.rs +22 -22
- package/rust/cli/telemetry/event_creator.rs +80 -80
- package/rust/cli/telemetry/mod.rs +3 -3
- package/rust/cli/telemetry/send.rs +51 -51
- package/rust/cli/template/commands.rs +69 -69
- package/rust/config/driver.rs +112 -103
- package/rust/config/mod.rs +3 -3
- package/rust/config/ops.rs +26 -26
- package/rust/config/settings.rs +101 -101
- 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 -170
- package/rust/core/audio/engine/mod.rs +51 -2
- 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.rs → evaluator/numeric.rs} +1 -159
- 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 +55 -23
- package/rust/core/audio/interpreter/mod.rs +1 -13
- 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/{automate.rs → statements/automate.rs} +16 -18
- package/rust/core/audio/interpreter/{call.rs → statements/call.rs} +5 -4
- package/rust/core/audio/interpreter/{condition.rs → statements/condition.rs} +2 -1
- package/rust/core/audio/interpreter/{function.rs → statements/function.rs} +2 -4
- package/rust/core/audio/interpreter/{let_.rs → statements/let_.rs} +2 -4
- package/rust/core/audio/interpreter/{load.rs → statements/load.rs} +2 -4
- package/rust/core/audio/interpreter/{loop_.rs → statements/loop_.rs} +2 -1
- package/rust/core/audio/interpreter/statements/mod.rs +12 -0
- package/rust/core/audio/interpreter/{sleep.rs → statements/sleep.rs} +28 -28
- package/rust/core/audio/interpreter/{spawn.rs → statements/spawn.rs} +3 -2
- package/rust/core/audio/interpreter/{tempo.rs → statements/tempo.rs} +40 -40
- package/rust/core/audio/interpreter/{trigger.rs → statements/trigger.rs} +1 -1
- package/rust/core/audio/loader/trigger.rs +2 -1
- package/rust/core/audio/mod.rs +6 -7
- package/rust/core/audio/player.rs +70 -70
- package/rust/core/audio/special/easing.rs +189 -189
- package/rust/core/audio/special/env.rs +45 -45
- package/rust/core/audio/special/math.rs +134 -134
- package/rust/core/audio/special/mod.rs +9 -9
- package/rust/core/audio/special/modulator.rs +143 -143
- package/rust/core/builder/mod.rs +45 -2
- package/rust/core/debugger/lexer.rs +27 -27
- package/rust/core/debugger/{module.rs → logs.rs} +3 -6
- package/rust/core/debugger/mod.rs +30 -30
- package/rust/core/debugger/preprocessor.rs +27 -27
- package/rust/core/debugger/store.rs +2 -4
- package/rust/core/error/mod.rs +269 -269
- package/rust/core/lexer/driver.rs +59 -61
- package/rust/core/lexer/handler/arrow.rs +82 -82
- package/rust/core/lexer/handler/at.rs +21 -21
- package/rust/core/lexer/handler/brace.rs +41 -41
- package/rust/core/lexer/handler/colon.rs +21 -21
- package/rust/core/lexer/handler/comment.rs +30 -30
- package/rust/core/lexer/handler/dot.rs +21 -21
- package/rust/core/lexer/handler/driver.rs +337 -337
- package/rust/core/lexer/handler/identifier.rs +47 -47
- package/rust/core/lexer/handler/indent.rs +66 -66
- package/rust/core/lexer/handler/mod.rs +15 -15
- package/rust/core/lexer/handler/newline.rs +23 -23
- package/rust/core/lexer/handler/number.rs +31 -31
- package/rust/core/lexer/handler/operator.rs +46 -46
- package/rust/core/lexer/handler/parenthesis.rs +41 -41
- package/rust/core/lexer/handler/slash.rs +21 -21
- package/rust/core/lexer/handler/string.rs +63 -63
- package/rust/core/lexer/mod.rs +3 -3
- package/rust/core/mod.rs +0 -1
- 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 +28 -4
- package/rust/core/parser/handler/at.rs +279 -279
- package/rust/core/parser/handler/bank.rs +104 -104
- package/rust/core/parser/handler/condition.rs +83 -83
- package/rust/core/parser/handler/dot.rs +148 -148
- package/rust/core/parser/handler/identifier/automate.rs +254 -254
- package/rust/core/parser/handler/identifier/call.rs +91 -91
- package/rust/core/parser/handler/identifier/emit.rs +70 -70
- package/rust/core/parser/handler/identifier/function.rs +113 -113
- package/rust/core/parser/handler/identifier/group.rs +89 -89
- package/rust/core/parser/handler/identifier/let_.rs +173 -173
- package/rust/core/parser/handler/identifier/mod.rs +55 -55
- package/rust/core/parser/handler/identifier/on.rs +107 -107
- package/rust/core/parser/handler/identifier/print.rs +49 -49
- package/rust/core/parser/handler/identifier/sleep.rs +96 -43
- package/rust/core/parser/handler/identifier/spawn.rs +91 -91
- package/rust/core/parser/handler/identifier/synth.rs +135 -135
- package/rust/core/parser/handler/loop_.rs +194 -194
- package/rust/core/parser/handler/mod.rs +9 -9
- package/rust/core/parser/handler/pattern.rs +1 -1
- package/rust/core/parser/handler/tempo.rs +105 -57
- package/rust/core/parser/statement.rs +10 -11
- package/rust/core/plugin/loader.rs +1 -1
- package/rust/core/plugin/mod.rs +2 -2
- package/rust/core/plugin/runner/mod.rs +11 -0
- package/rust/core/plugin/{runner.rs → runner/non_wasm.rs} +297 -347
- 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/module.rs +2 -7
- package/rust/core/preprocessor/{processor.rs → processor/handlers.rs} +6 -13
- package/rust/core/preprocessor/processor/mod.rs +1 -0
- package/rust/core/preprocessor/resolver/bank.rs +49 -49
- package/rust/core/preprocessor/resolver/call.rs +124 -124
- package/rust/core/preprocessor/resolver/condition.rs +95 -95
- package/rust/core/preprocessor/resolver/driver.rs +324 -324
- package/rust/core/preprocessor/resolver/function.rs +2 -2
- package/rust/core/preprocessor/resolver/group.rs +46 -18
- package/rust/core/preprocessor/resolver/let_.rs +32 -32
- package/rust/core/preprocessor/resolver/loop_.rs +318 -318
- package/rust/core/preprocessor/resolver/mod.rs +16 -16
- package/rust/core/preprocessor/resolver/pattern.rs +83 -83
- package/rust/core/preprocessor/resolver/spawn.rs +99 -99
- package/rust/core/preprocessor/resolver/synth.rs +54 -54
- package/rust/core/preprocessor/resolver/tempo.rs +48 -48
- package/rust/core/preprocessor/resolver/trigger.rs +116 -116
- package/rust/core/preprocessor/resolver/value.rs +176 -176
- package/rust/core/store/global.rs +2 -6
- package/rust/core/store/mod.rs +1 -5
- package/rust/lib.rs +18 -3
- package/rust/main.rs +27 -3
- package/rust/types/Cargo.toml +1 -1
- package/rust/types/src/addons.rs +55 -55
- package/rust/types/src/config.rs +84 -74
- package/rust/types/src/lib.rs +15 -12
- package/rust/types/src/plugin.rs +20 -0
- package/rust/types/src/store.rs +139 -0
- package/rust/types/src/telemetry.rs +85 -85
- package/rust/utils/Cargo.toml +2 -2
- package/rust/utils/src/file.rs +94 -94
- package/rust/utils/src/first_usage.rs +97 -97
- package/rust/utils/src/lib.rs +9 -9
- package/rust/utils/src/logger.rs +200 -200
- package/rust/utils/src/path.rs +129 -88
- package/rust/utils/src/signature.rs +41 -41
- package/rust/utils/src/spinner.rs +20 -20
- package/rust/utils/src/version.rs +27 -27
- package/rust/utils/src/watcher.rs +46 -46
- package/rust/web/api.rs +5 -5
- package/rust/web/cdn.rs +34 -34
- package/rust/web/mod.rs +3 -3
- package/tests/integration.rs +21 -21
- package/typescript/core/functions/index.ts +11 -0
- package/typescript/pkg/devalang_core.ts +20 -4
- package/rust/core/audio/engine/sample.rs +0 -366
- package/rust/core/audio/engine/synth.rs +0 -325
- package/rust/core/audio/interpreter/arrow_call.rs +0 -311
- package/rust/core/audio/renderer.rs +0 -54
- package/rust/core/parser/driver.rs +0 -584
- package/rust/core/preprocessor/loader.rs +0 -637
- package/rust/core/store/export.rs +0 -28
- package/rust/core/store/function.rs +0 -40
- package/rust/core/store/import.rs +0 -28
- package/rust/core/store/variable.rs +0 -51
- package/rust/core/utils/mod.rs +0 -1
- package/rust/core/utils/path.rs +0 -37
|
@@ -1,107 +1,107 @@
|
|
|
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_on_token(parser: &mut Parser, _global_store: &mut GlobalStore) -> Statement {
|
|
13
|
-
// consume 'on'
|
|
14
|
-
let on_tok = match parser.peek_clone() {
|
|
15
|
-
Some(tok) => tok,
|
|
16
|
-
None => return Statement::unknown(),
|
|
17
|
-
};
|
|
18
|
-
parser.advance();
|
|
19
|
-
|
|
20
|
-
// Expect event name identifier
|
|
21
|
-
let event_tok = match parser.peek_clone() {
|
|
22
|
-
Some(tok) if tok.kind == TokenKind::Identifier => tok,
|
|
23
|
-
Some(other) => {
|
|
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
|
-
);
|
|
34
|
-
}
|
|
35
|
-
};
|
|
36
|
-
let event_name = event_tok.lexeme.clone();
|
|
37
|
-
parser.advance();
|
|
38
|
-
|
|
39
|
-
// Optional parenthesized args on same line
|
|
40
|
-
let mut args: Option<Vec<Value>> = None;
|
|
41
|
-
if parser.peek_kind() == Some(TokenKind::LParen) {
|
|
42
|
-
parser.advance(); // '('
|
|
43
|
-
let mut collected: Vec<Value> = Vec::new();
|
|
44
|
-
// Collect tokens until ')', supporting numbers and identifiers separated by comma
|
|
45
|
-
while let Some(tok) = parser.peek_clone() {
|
|
46
|
-
match tok.kind {
|
|
47
|
-
TokenKind::RParen => {
|
|
48
|
-
parser.advance();
|
|
49
|
-
break;
|
|
50
|
-
}
|
|
51
|
-
TokenKind::Number => {
|
|
52
|
-
parser.advance();
|
|
53
|
-
collected.push(Value::Number(tok.lexeme.parse().unwrap_or(0.0)));
|
|
54
|
-
}
|
|
55
|
-
TokenKind::Identifier => {
|
|
56
|
-
parser.advance();
|
|
57
|
-
collected.push(Value::Identifier(tok.lexeme));
|
|
58
|
-
}
|
|
59
|
-
TokenKind::Comma => {
|
|
60
|
-
parser.advance();
|
|
61
|
-
}
|
|
62
|
-
TokenKind::Whitespace | TokenKind::Newline => {
|
|
63
|
-
parser.advance();
|
|
64
|
-
}
|
|
65
|
-
_ => {
|
|
66
|
-
break;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
if !collected.is_empty() {
|
|
71
|
-
args = Some(collected);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
// Expect ':' then block
|
|
76
|
-
if parser.peek_kind() != Some(TokenKind::Colon) {
|
|
77
|
-
return crate::core::parser::statement::error_from_token(
|
|
78
|
-
event_tok,
|
|
79
|
-
"Expected ':' after event name".to_string(),
|
|
80
|
-
);
|
|
81
|
-
}
|
|
82
|
-
parser.advance(); // consume ':'
|
|
83
|
-
|
|
84
|
-
let base_indent = on_tok.indent;
|
|
85
|
-
let block_tokens = parser.collect_block_tokens(base_indent);
|
|
86
|
-
// Parse body within current store context
|
|
87
|
-
let body = parser.parse_block(block_tokens, _global_store);
|
|
88
|
-
|
|
89
|
-
let stmt = Statement {
|
|
90
|
-
kind: StatementKind::On {
|
|
91
|
-
event: event_name,
|
|
92
|
-
args,
|
|
93
|
-
body,
|
|
94
|
-
},
|
|
95
|
-
value: Value::Null,
|
|
96
|
-
indent: on_tok.indent,
|
|
97
|
-
line: on_tok.line,
|
|
98
|
-
column: on_tok.column,
|
|
99
|
-
};
|
|
100
|
-
|
|
101
|
-
// Register in global store for later emission
|
|
102
|
-
if let StatementKind::On { event, .. } = &stmt.kind {
|
|
103
|
-
_global_store.register_event_handler(event, stmt.clone());
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
stmt
|
|
107
|
-
}
|
|
1
|
+
use devalang_types::Value;
|
|
2
|
+
|
|
3
|
+
use crate::core::{
|
|
4
|
+
lexer::token::TokenKind,
|
|
5
|
+
parser::{
|
|
6
|
+
driver::parser::Parser,
|
|
7
|
+
statement::{Statement, StatementKind},
|
|
8
|
+
},
|
|
9
|
+
store::global::GlobalStore,
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
pub fn parse_on_token(parser: &mut Parser, _global_store: &mut GlobalStore) -> Statement {
|
|
13
|
+
// consume 'on'
|
|
14
|
+
let on_tok = match parser.peek_clone() {
|
|
15
|
+
Some(tok) => tok,
|
|
16
|
+
None => return Statement::unknown(),
|
|
17
|
+
};
|
|
18
|
+
parser.advance();
|
|
19
|
+
|
|
20
|
+
// Expect event name identifier
|
|
21
|
+
let event_tok = match parser.peek_clone() {
|
|
22
|
+
Some(tok) if tok.kind == TokenKind::Identifier => tok,
|
|
23
|
+
Some(other) => {
|
|
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
|
+
);
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
let event_name = event_tok.lexeme.clone();
|
|
37
|
+
parser.advance();
|
|
38
|
+
|
|
39
|
+
// Optional parenthesized args on same line
|
|
40
|
+
let mut args: Option<Vec<Value>> = None;
|
|
41
|
+
if parser.peek_kind() == Some(TokenKind::LParen) {
|
|
42
|
+
parser.advance(); // '('
|
|
43
|
+
let mut collected: Vec<Value> = Vec::new();
|
|
44
|
+
// Collect tokens until ')', supporting numbers and identifiers separated by comma
|
|
45
|
+
while let Some(tok) = parser.peek_clone() {
|
|
46
|
+
match tok.kind {
|
|
47
|
+
TokenKind::RParen => {
|
|
48
|
+
parser.advance();
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
TokenKind::Number => {
|
|
52
|
+
parser.advance();
|
|
53
|
+
collected.push(Value::Number(tok.lexeme.parse().unwrap_or(0.0)));
|
|
54
|
+
}
|
|
55
|
+
TokenKind::Identifier => {
|
|
56
|
+
parser.advance();
|
|
57
|
+
collected.push(Value::Identifier(tok.lexeme));
|
|
58
|
+
}
|
|
59
|
+
TokenKind::Comma => {
|
|
60
|
+
parser.advance();
|
|
61
|
+
}
|
|
62
|
+
TokenKind::Whitespace | TokenKind::Newline => {
|
|
63
|
+
parser.advance();
|
|
64
|
+
}
|
|
65
|
+
_ => {
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
if !collected.is_empty() {
|
|
71
|
+
args = Some(collected);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Expect ':' then block
|
|
76
|
+
if parser.peek_kind() != Some(TokenKind::Colon) {
|
|
77
|
+
return crate::core::parser::statement::error_from_token(
|
|
78
|
+
event_tok,
|
|
79
|
+
"Expected ':' after event name".to_string(),
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
parser.advance(); // consume ':'
|
|
83
|
+
|
|
84
|
+
let base_indent = on_tok.indent;
|
|
85
|
+
let block_tokens = parser.collect_block_tokens(base_indent);
|
|
86
|
+
// Parse body within current store context
|
|
87
|
+
let body = parser.parse_block(block_tokens, _global_store);
|
|
88
|
+
|
|
89
|
+
let stmt = Statement {
|
|
90
|
+
kind: StatementKind::On {
|
|
91
|
+
event: event_name,
|
|
92
|
+
args,
|
|
93
|
+
body,
|
|
94
|
+
},
|
|
95
|
+
value: Value::Null,
|
|
96
|
+
indent: on_tok.indent,
|
|
97
|
+
line: on_tok.line,
|
|
98
|
+
column: on_tok.column,
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
// Register in global store for later emission
|
|
102
|
+
if let StatementKind::On { event, .. } = &stmt.kind {
|
|
103
|
+
_global_store.register_event_handler(event, stmt.clone());
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
stmt
|
|
107
|
+
}
|
|
@@ -1,49 +1,49 @@
|
|
|
1
|
-
use crate::core::{
|
|
2
|
-
lexer::token::{Token, TokenKind},
|
|
3
|
-
parser::{
|
|
4
|
-
driver::Parser,
|
|
5
|
-
statement::{Statement, StatementKind},
|
|
6
|
-
},
|
|
7
|
-
store::global::GlobalStore,
|
|
8
|
-
};
|
|
9
|
-
use devalang_types::Value;
|
|
10
|
-
|
|
11
|
-
pub fn parse_print_token(
|
|
12
|
-
parser: &mut Parser,
|
|
13
|
-
current_token: Token,
|
|
14
|
-
_global_store: &mut GlobalStore,
|
|
15
|
-
) -> Statement {
|
|
16
|
-
// consume 'print'
|
|
17
|
-
parser.advance();
|
|
18
|
-
|
|
19
|
-
let collected = parser.collect_until(|t| matches!(t.kind, TokenKind::Newline | TokenKind::EOF));
|
|
20
|
-
// Accept: print <identifier|string|number|expression>
|
|
21
|
-
let value = if collected.len() == 1 {
|
|
22
|
-
match collected[0].kind {
|
|
23
|
-
TokenKind::Identifier => Value::Identifier(collected[0].lexeme.clone()),
|
|
24
|
-
TokenKind::String => Value::String(collected[0].lexeme.clone()),
|
|
25
|
-
TokenKind::Number => {
|
|
26
|
-
let n = collected[0].lexeme.parse::<f32>().unwrap_or(0.0);
|
|
27
|
-
Value::Number(n)
|
|
28
|
-
}
|
|
29
|
-
_ => Value::String(collected[0].lexeme.clone()),
|
|
30
|
-
}
|
|
31
|
-
} else {
|
|
32
|
-
// Join tokens with spaces to preserve readability for expressions/text
|
|
33
|
-
let text = collected
|
|
34
|
-
.iter()
|
|
35
|
-
.filter(|t| !matches!(t.kind, TokenKind::Newline | TokenKind::EOF))
|
|
36
|
-
.map(|t| t.lexeme.clone())
|
|
37
|
-
.collect::<Vec<_>>()
|
|
38
|
-
.join(" ");
|
|
39
|
-
Value::String(text.trim().to_string())
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
Statement {
|
|
43
|
-
kind: StatementKind::Print,
|
|
44
|
-
value,
|
|
45
|
-
indent: current_token.indent,
|
|
46
|
-
line: current_token.line,
|
|
47
|
-
column: current_token.column,
|
|
48
|
-
}
|
|
49
|
-
}
|
|
1
|
+
use crate::core::{
|
|
2
|
+
lexer::token::{Token, TokenKind},
|
|
3
|
+
parser::{
|
|
4
|
+
driver::parser::Parser,
|
|
5
|
+
statement::{Statement, StatementKind},
|
|
6
|
+
},
|
|
7
|
+
store::global::GlobalStore,
|
|
8
|
+
};
|
|
9
|
+
use devalang_types::Value;
|
|
10
|
+
|
|
11
|
+
pub fn parse_print_token(
|
|
12
|
+
parser: &mut Parser,
|
|
13
|
+
current_token: Token,
|
|
14
|
+
_global_store: &mut GlobalStore,
|
|
15
|
+
) -> Statement {
|
|
16
|
+
// consume 'print'
|
|
17
|
+
parser.advance();
|
|
18
|
+
|
|
19
|
+
let collected = parser.collect_until(|t| matches!(t.kind, TokenKind::Newline | TokenKind::EOF));
|
|
20
|
+
// Accept: print <identifier|string|number|expression>
|
|
21
|
+
let value = if collected.len() == 1 {
|
|
22
|
+
match collected[0].kind {
|
|
23
|
+
TokenKind::Identifier => Value::Identifier(collected[0].lexeme.clone()),
|
|
24
|
+
TokenKind::String => Value::String(collected[0].lexeme.clone()),
|
|
25
|
+
TokenKind::Number => {
|
|
26
|
+
let n = collected[0].lexeme.parse::<f32>().unwrap_or(0.0);
|
|
27
|
+
Value::Number(n)
|
|
28
|
+
}
|
|
29
|
+
_ => Value::String(collected[0].lexeme.clone()),
|
|
30
|
+
}
|
|
31
|
+
} else {
|
|
32
|
+
// Join tokens with spaces to preserve readability for expressions/text
|
|
33
|
+
let text = collected
|
|
34
|
+
.iter()
|
|
35
|
+
.filter(|t| !matches!(t.kind, TokenKind::Newline | TokenKind::EOF))
|
|
36
|
+
.map(|t| t.lexeme.clone())
|
|
37
|
+
.collect::<Vec<_>>()
|
|
38
|
+
.join(" ");
|
|
39
|
+
Value::String(text.trim().to_string())
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
Statement {
|
|
43
|
+
kind: StatementKind::Print,
|
|
44
|
+
value,
|
|
45
|
+
indent: current_token.indent,
|
|
46
|
+
line: current_token.line,
|
|
47
|
+
column: current_token.column,
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -1,43 +1,96 @@
|
|
|
1
|
-
use devalang_types::Value;
|
|
2
|
-
|
|
3
|
-
use crate::core::{
|
|
4
|
-
lexer::token::{Token, TokenKind},
|
|
5
|
-
parser::{
|
|
6
|
-
driver::Parser,
|
|
7
|
-
statement::{Statement, StatementKind},
|
|
8
|
-
},
|
|
9
|
-
store::global::GlobalStore,
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
pub fn parse_sleep_token(
|
|
13
|
-
parser: &mut Parser,
|
|
14
|
-
current_token: Token,
|
|
15
|
-
_global_store: &mut GlobalStore,
|
|
16
|
-
) -> Statement {
|
|
17
|
-
parser.advance(); // consume "sleep"
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
1
|
+
use devalang_types::Value;
|
|
2
|
+
|
|
3
|
+
use crate::core::{
|
|
4
|
+
lexer::token::{Token, TokenKind},
|
|
5
|
+
parser::{
|
|
6
|
+
driver::parser::Parser,
|
|
7
|
+
statement::{Statement, StatementKind},
|
|
8
|
+
},
|
|
9
|
+
store::global::GlobalStore,
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
pub fn parse_sleep_token(
|
|
13
|
+
parser: &mut Parser,
|
|
14
|
+
current_token: Token,
|
|
15
|
+
_global_store: &mut GlobalStore,
|
|
16
|
+
) -> Statement {
|
|
17
|
+
parser.advance(); // consume "sleep"
|
|
18
|
+
|
|
19
|
+
// Accept number, decimal, fraction like 1/4 (-> Duration::Beat), string, or identifier
|
|
20
|
+
let duration_value = if let Some(token) = parser.peek_clone() {
|
|
21
|
+
match token.kind {
|
|
22
|
+
TokenKind::Number => {
|
|
23
|
+
let mut num = token.lexeme.clone();
|
|
24
|
+
parser.advance();
|
|
25
|
+
// decimal part
|
|
26
|
+
if let Some(dot) = parser.peek_clone() {
|
|
27
|
+
if dot.kind == TokenKind::Dot {
|
|
28
|
+
if let Some(next) = parser.peek_nth(1).cloned() {
|
|
29
|
+
if next.kind == TokenKind::Number {
|
|
30
|
+
parser.advance(); // consume dot
|
|
31
|
+
parser.advance(); // consume next number
|
|
32
|
+
num.push('.');
|
|
33
|
+
num.push_str(&next.lexeme);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// fraction form 1/4 -> Duration::Beat("1/4")
|
|
40
|
+
if let Some(slash) = parser.peek_clone() {
|
|
41
|
+
if slash.kind == TokenKind::Slash {
|
|
42
|
+
parser.advance();
|
|
43
|
+
if let Some(den) = parser.peek_clone() {
|
|
44
|
+
if den.kind == TokenKind::Number || den.kind == TokenKind::Identifier {
|
|
45
|
+
let frac = format!("{}/{}", num, den.lexeme);
|
|
46
|
+
parser.advance();
|
|
47
|
+
Value::Duration(devalang_types::Duration::Beat(frac))
|
|
48
|
+
} else {
|
|
49
|
+
return crate::core::parser::statement::error_from_token(
|
|
50
|
+
slash,
|
|
51
|
+
"Expected denominator after '/' in sleep".to_string(),
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
} else {
|
|
55
|
+
return crate::core::parser::statement::error_from_token(
|
|
56
|
+
slash,
|
|
57
|
+
"Expected denominator after '/' in sleep".to_string(),
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
} else {
|
|
61
|
+
Value::Number(num.parse().unwrap_or(0.0))
|
|
62
|
+
}
|
|
63
|
+
} else {
|
|
64
|
+
Value::Number(num.parse().unwrap_or(0.0))
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
TokenKind::String => {
|
|
68
|
+
parser.advance();
|
|
69
|
+
Value::String(token.lexeme.clone())
|
|
70
|
+
}
|
|
71
|
+
TokenKind::Identifier => {
|
|
72
|
+
parser.advance();
|
|
73
|
+
Value::Identifier(token.lexeme.clone())
|
|
74
|
+
}
|
|
75
|
+
_ => {
|
|
76
|
+
return crate::core::parser::statement::error_from_token(
|
|
77
|
+
token,
|
|
78
|
+
"Expected duration after 'sleep'".to_string(),
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
} else {
|
|
83
|
+
return crate::core::parser::statement::error_from_token(
|
|
84
|
+
current_token,
|
|
85
|
+
"Expected duration after 'sleep'".to_string(),
|
|
86
|
+
);
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
Statement {
|
|
90
|
+
kind: StatementKind::Sleep,
|
|
91
|
+
value: duration_value,
|
|
92
|
+
indent: current_token.indent,
|
|
93
|
+
line: current_token.line,
|
|
94
|
+
column: current_token.column,
|
|
95
|
+
}
|
|
96
|
+
}
|
|
@@ -1,91 +1,91 @@
|
|
|
1
|
-
use crate::core::{
|
|
2
|
-
lexer::token::{Token, TokenKind},
|
|
3
|
-
parser::{
|
|
4
|
-
driver::Parser,
|
|
5
|
-
statement::{Statement, StatementKind},
|
|
6
|
-
},
|
|
7
|
-
store::global::GlobalStore,
|
|
8
|
-
};
|
|
9
|
-
use devalang_types::Value;
|
|
10
|
-
|
|
11
|
-
pub fn parse_spawn_token(
|
|
12
|
-
parser: &mut Parser,
|
|
13
|
-
current_token: Token,
|
|
14
|
-
_global_store: &mut GlobalStore,
|
|
15
|
-
) -> Statement {
|
|
16
|
-
parser.advance(); // consume "spawn"
|
|
17
|
-
|
|
18
|
-
// Expect function name
|
|
19
|
-
let name_token = match parser.peek_clone() {
|
|
20
|
-
Some(t) => t,
|
|
21
|
-
None => {
|
|
22
|
-
return crate::core::parser::statement::error_from_token(
|
|
23
|
-
current_token,
|
|
24
|
-
"Expected function name after 'spawn'".to_string(),
|
|
25
|
-
);
|
|
26
|
-
}
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
if name_token.kind != TokenKind::Identifier {
|
|
30
|
-
return crate::core::parser::statement::error_from_token(
|
|
31
|
-
name_token,
|
|
32
|
-
"Expected function name to be an identifier".to_string(),
|
|
33
|
-
);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
let func_name = name_token.lexeme.clone();
|
|
37
|
-
parser.advance(); // consume function name
|
|
38
|
-
|
|
39
|
-
// Expect '('
|
|
40
|
-
let mut args: Vec<Value> = Vec::new();
|
|
41
|
-
if let Some(open_paren) = parser.peek_clone() {
|
|
42
|
-
if open_paren.kind == TokenKind::LParen {
|
|
43
|
-
parser.advance(); // consume '('
|
|
44
|
-
|
|
45
|
-
// Collect args until ')'
|
|
46
|
-
while let Some(token) = parser.peek_clone() {
|
|
47
|
-
if token.kind == TokenKind::RParen {
|
|
48
|
-
parser.advance(); // consume ')'
|
|
49
|
-
break;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
match token.kind {
|
|
53
|
-
TokenKind::Number => {
|
|
54
|
-
if let Ok(num) = token.lexeme.parse::<f32>() {
|
|
55
|
-
args.push(Value::Number(num));
|
|
56
|
-
}
|
|
57
|
-
parser.advance();
|
|
58
|
-
}
|
|
59
|
-
TokenKind::String => {
|
|
60
|
-
args.push(Value::String(token.lexeme.clone()));
|
|
61
|
-
parser.advance();
|
|
62
|
-
}
|
|
63
|
-
TokenKind::Identifier => {
|
|
64
|
-
args.push(Value::Identifier(token.lexeme.clone()));
|
|
65
|
-
parser.advance();
|
|
66
|
-
}
|
|
67
|
-
TokenKind::Comma => {
|
|
68
|
-
parser.advance(); // skip comma
|
|
69
|
-
}
|
|
70
|
-
_ => {
|
|
71
|
-
return crate::core::parser::statement::error_from_token(
|
|
72
|
-
token,
|
|
73
|
-
"Unexpected token in spawn arguments".to_string(),
|
|
74
|
-
);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
Statement {
|
|
82
|
-
kind: StatementKind::Spawn {
|
|
83
|
-
name: func_name,
|
|
84
|
-
args,
|
|
85
|
-
},
|
|
86
|
-
value: Value::Null,
|
|
87
|
-
indent: current_token.indent,
|
|
88
|
-
line: current_token.line,
|
|
89
|
-
column: current_token.column,
|
|
90
|
-
}
|
|
91
|
-
}
|
|
1
|
+
use crate::core::{
|
|
2
|
+
lexer::token::{Token, TokenKind},
|
|
3
|
+
parser::{
|
|
4
|
+
driver::parser::Parser,
|
|
5
|
+
statement::{Statement, StatementKind},
|
|
6
|
+
},
|
|
7
|
+
store::global::GlobalStore,
|
|
8
|
+
};
|
|
9
|
+
use devalang_types::Value;
|
|
10
|
+
|
|
11
|
+
pub fn parse_spawn_token(
|
|
12
|
+
parser: &mut Parser,
|
|
13
|
+
current_token: Token,
|
|
14
|
+
_global_store: &mut GlobalStore,
|
|
15
|
+
) -> Statement {
|
|
16
|
+
parser.advance(); // consume "spawn"
|
|
17
|
+
|
|
18
|
+
// Expect function name
|
|
19
|
+
let name_token = match parser.peek_clone() {
|
|
20
|
+
Some(t) => t,
|
|
21
|
+
None => {
|
|
22
|
+
return crate::core::parser::statement::error_from_token(
|
|
23
|
+
current_token,
|
|
24
|
+
"Expected function name after 'spawn'".to_string(),
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
if name_token.kind != TokenKind::Identifier {
|
|
30
|
+
return crate::core::parser::statement::error_from_token(
|
|
31
|
+
name_token,
|
|
32
|
+
"Expected function name to be an identifier".to_string(),
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
let func_name = name_token.lexeme.clone();
|
|
37
|
+
parser.advance(); // consume function name
|
|
38
|
+
|
|
39
|
+
// Expect '('
|
|
40
|
+
let mut args: Vec<Value> = Vec::new();
|
|
41
|
+
if let Some(open_paren) = parser.peek_clone() {
|
|
42
|
+
if open_paren.kind == TokenKind::LParen {
|
|
43
|
+
parser.advance(); // consume '('
|
|
44
|
+
|
|
45
|
+
// Collect args until ')'
|
|
46
|
+
while let Some(token) = parser.peek_clone() {
|
|
47
|
+
if token.kind == TokenKind::RParen {
|
|
48
|
+
parser.advance(); // consume ')'
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
match token.kind {
|
|
53
|
+
TokenKind::Number => {
|
|
54
|
+
if let Ok(num) = token.lexeme.parse::<f32>() {
|
|
55
|
+
args.push(Value::Number(num));
|
|
56
|
+
}
|
|
57
|
+
parser.advance();
|
|
58
|
+
}
|
|
59
|
+
TokenKind::String => {
|
|
60
|
+
args.push(Value::String(token.lexeme.clone()));
|
|
61
|
+
parser.advance();
|
|
62
|
+
}
|
|
63
|
+
TokenKind::Identifier => {
|
|
64
|
+
args.push(Value::Identifier(token.lexeme.clone()));
|
|
65
|
+
parser.advance();
|
|
66
|
+
}
|
|
67
|
+
TokenKind::Comma => {
|
|
68
|
+
parser.advance(); // skip comma
|
|
69
|
+
}
|
|
70
|
+
_ => {
|
|
71
|
+
return crate::core::parser::statement::error_from_token(
|
|
72
|
+
token,
|
|
73
|
+
"Unexpected token in spawn arguments".to_string(),
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
Statement {
|
|
82
|
+
kind: StatementKind::Spawn {
|
|
83
|
+
name: func_name,
|
|
84
|
+
args,
|
|
85
|
+
},
|
|
86
|
+
value: Value::Null,
|
|
87
|
+
indent: current_token.indent,
|
|
88
|
+
line: current_token.line,
|
|
89
|
+
column: current_token.column,
|
|
90
|
+
}
|
|
91
|
+
}
|