@devaloop/devalang 0.0.1-alpha.14 → 0.0.1-alpha.16

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.
Files changed (177) hide show
  1. package/.devalang +10 -8
  2. package/.github/workflows/ci.yml +92 -0
  3. package/Cargo.toml +60 -58
  4. package/README.md +32 -15
  5. package/docs/CHANGELOG.md +93 -1
  6. package/docs/CONTRIBUTING.md +101 -1
  7. package/docs/ROADMAP.md +2 -2
  8. package/docs/TODO.md +1 -1
  9. package/examples/automation.deva +42 -0
  10. package/examples/bank.deva +4 -4
  11. package/examples/events.deva +12 -0
  12. package/examples/function.deva +4 -4
  13. package/examples/index.deva +39 -25
  14. package/examples/loop.deva +5 -11
  15. package/examples/pattern.deva +8 -0
  16. package/examples/plugin.deva +16 -0
  17. package/examples/variables.deva +1 -1
  18. package/out-tsc/bin/index.js +51 -7
  19. package/out-tsc/index.js +3 -1
  20. package/out-tsc/scripts/postbuild.js +9 -10
  21. package/out-tsc/scripts/postinstall.js +49 -0
  22. package/package.json +12 -4
  23. package/project-version.json +3 -3
  24. package/rust/cli/bank.rs +462 -456
  25. package/rust/cli/build.rs +252 -199
  26. package/rust/cli/check.rs +221 -180
  27. package/rust/cli/driver.rs +297 -292
  28. package/rust/cli/generator.rs +1 -0
  29. package/rust/cli/init.rs +87 -79
  30. package/rust/cli/install.rs +35 -32
  31. package/rust/cli/login.rs +127 -134
  32. package/rust/cli/mod.rs +13 -11
  33. package/rust/cli/play.rs +1123 -218
  34. package/rust/cli/telemetry.rs +19 -0
  35. package/rust/cli/template.rs +69 -57
  36. package/rust/cli/update.rs +6 -4
  37. package/rust/common/api.rs +5 -8
  38. package/rust/common/cdn.rs +3 -6
  39. package/rust/common/mod.rs +3 -3
  40. package/rust/common/sso.rs +3 -6
  41. package/rust/config/driver.rs +118 -94
  42. package/rust/config/loader.rs +165 -156
  43. package/rust/config/mod.rs +4 -2
  44. package/rust/config/settings.rs +91 -0
  45. package/rust/config/stats.rs +257 -0
  46. package/rust/core/audio/engine.rs +696 -518
  47. package/rust/core/audio/evaluator.rs +263 -31
  48. package/rust/core/audio/interpreter/arrow_call.rs +198 -161
  49. package/rust/core/audio/interpreter/automate.rs +18 -0
  50. package/rust/core/audio/interpreter/call.rs +98 -95
  51. package/rust/core/audio/interpreter/condition.rs +70 -71
  52. package/rust/core/audio/interpreter/driver.rs +487 -198
  53. package/rust/core/audio/interpreter/function.rs +26 -21
  54. package/rust/core/audio/interpreter/let_.rs +38 -19
  55. package/rust/core/audio/interpreter/load.rs +18 -18
  56. package/rust/core/audio/interpreter/loop_.rs +113 -73
  57. package/rust/core/audio/interpreter/mod.rs +14 -13
  58. package/rust/core/audio/interpreter/sleep.rs +27 -30
  59. package/rust/core/audio/interpreter/spawn.rs +105 -102
  60. package/rust/core/audio/interpreter/tempo.rs +19 -16
  61. package/rust/core/audio/interpreter/trigger.rs +239 -210
  62. package/rust/core/audio/loader/mod.rs +1 -1
  63. package/rust/core/audio/loader/trigger.rs +100 -97
  64. package/rust/core/audio/mod.rs +7 -6
  65. package/rust/core/audio/player.rs +64 -64
  66. package/rust/core/audio/renderer.rs +56 -53
  67. package/rust/core/audio/special/easing.rs +189 -0
  68. package/rust/core/audio/special/env.rs +43 -0
  69. package/rust/core/audio/special/math.rs +102 -0
  70. package/rust/core/audio/special/mod.rs +9 -0
  71. package/rust/core/audio/special/modulator.rs +143 -0
  72. package/rust/core/builder/mod.rs +80 -85
  73. package/rust/core/debugger/lexer.rs +27 -27
  74. package/rust/core/debugger/mod.rs +24 -23
  75. package/rust/core/debugger/module.rs +55 -47
  76. package/rust/core/debugger/preprocessor.rs +27 -27
  77. package/rust/core/debugger/store.rs +40 -39
  78. package/rust/core/error/mod.rs +80 -66
  79. package/rust/core/lexer/handler/arrow.rs +82 -31
  80. package/rust/core/lexer/handler/at.rs +21 -21
  81. package/rust/core/lexer/handler/brace.rs +41 -41
  82. package/rust/core/lexer/handler/colon.rs +21 -21
  83. package/rust/core/lexer/handler/comment.rs +30 -30
  84. package/rust/core/lexer/handler/dot.rs +21 -21
  85. package/rust/core/lexer/handler/driver.rs +337 -263
  86. package/rust/core/lexer/handler/identifier.rs +46 -42
  87. package/rust/core/lexer/handler/indent.rs +66 -66
  88. package/rust/core/lexer/handler/mod.rs +16 -16
  89. package/rust/core/lexer/handler/newline.rs +23 -23
  90. package/rust/core/lexer/handler/number.rs +31 -31
  91. package/rust/core/lexer/handler/operator.rs +46 -44
  92. package/rust/core/lexer/handler/parenthesis.rs +41 -41
  93. package/rust/core/lexer/handler/slash.rs +21 -21
  94. package/rust/core/lexer/handler/string.rs +63 -63
  95. package/rust/core/lexer/mod.rs +54 -51
  96. package/rust/core/lexer/token.rs +97 -91
  97. package/rust/core/mod.rs +11 -11
  98. package/rust/core/parser/driver.rs +513 -408
  99. package/rust/core/parser/handler/arrow_call.rs +233 -211
  100. package/rust/core/parser/handler/at.rs +245 -162
  101. package/rust/core/parser/handler/bank.rs +94 -69
  102. package/rust/core/parser/handler/condition.rs +80 -74
  103. package/rust/core/parser/handler/dot.rs +143 -135
  104. package/rust/core/parser/handler/identifier/automate.rs +257 -0
  105. package/rust/core/parser/handler/identifier/call.rs +91 -88
  106. package/rust/core/parser/handler/identifier/emit.rs +66 -0
  107. package/rust/core/parser/handler/identifier/function.rs +100 -92
  108. package/rust/core/parser/handler/identifier/group.rs +85 -75
  109. package/rust/core/parser/handler/identifier/let_.rs +158 -127
  110. package/rust/core/parser/handler/identifier/mod.rs +54 -52
  111. package/rust/core/parser/handler/identifier/on.rs +98 -0
  112. package/rust/core/parser/handler/identifier/print.rs +52 -0
  113. package/rust/core/parser/handler/identifier/sleep.rs +36 -33
  114. package/rust/core/parser/handler/identifier/spawn.rs +91 -88
  115. package/rust/core/parser/handler/identifier/synth.rs +65 -65
  116. package/rust/core/parser/handler/loop_.rs +170 -72
  117. package/rust/core/parser/handler/mod.rs +8 -8
  118. package/rust/core/parser/handler/tempo.rs +53 -47
  119. package/rust/core/parser/mod.rs +4 -4
  120. package/rust/core/parser/statement.rs +142 -108
  121. package/rust/core/plugin/loader.rs +123 -48
  122. package/rust/core/plugin/mod.rs +2 -1
  123. package/rust/core/plugin/runner.rs +296 -0
  124. package/rust/core/preprocessor/loader.rs +515 -326
  125. package/rust/core/preprocessor/mod.rs +4 -4
  126. package/rust/core/preprocessor/module.rs +60 -58
  127. package/rust/core/preprocessor/processor.rs +99 -101
  128. package/rust/core/preprocessor/resolver/bank.rs +51 -49
  129. package/rust/core/preprocessor/resolver/call.rs +100 -100
  130. package/rust/core/preprocessor/resolver/condition.rs +97 -97
  131. package/rust/core/preprocessor/resolver/driver.rs +310 -278
  132. package/rust/core/preprocessor/resolver/function.rs +69 -78
  133. package/rust/core/preprocessor/resolver/group.rs +96 -91
  134. package/rust/core/preprocessor/resolver/let_.rs +32 -28
  135. package/rust/core/preprocessor/resolver/loop_.rs +320 -91
  136. package/rust/core/preprocessor/resolver/mod.rs +15 -15
  137. package/rust/core/preprocessor/resolver/spawn.rs +76 -92
  138. package/rust/core/preprocessor/resolver/synth.rs +56 -50
  139. package/rust/core/preprocessor/resolver/tempo.rs +50 -49
  140. package/rust/core/preprocessor/resolver/trigger.rs +113 -116
  141. package/rust/core/preprocessor/resolver/value.rs +81 -87
  142. package/rust/core/shared/bank.rs +1 -1
  143. package/rust/core/shared/duration.rs +9 -9
  144. package/rust/core/shared/mod.rs +3 -3
  145. package/rust/core/shared/value.rs +35 -32
  146. package/rust/core/store/function.rs +34 -34
  147. package/rust/core/store/global.rs +55 -38
  148. package/rust/core/store/mod.rs +5 -5
  149. package/rust/core/store/variable.rs +37 -34
  150. package/rust/core/utils/mod.rs +2 -2
  151. package/rust/core/utils/path.rs +37 -31
  152. package/rust/core/utils/validation.rs +35 -37
  153. package/rust/installer/addon.rs +84 -80
  154. package/rust/installer/bank.rs +62 -65
  155. package/rust/installer/mod.rs +5 -5
  156. package/rust/installer/plugin.rs +54 -55
  157. package/rust/installer/utils.rs +56 -56
  158. package/rust/lib.rs +156 -164
  159. package/rust/main.rs +250 -145
  160. package/rust/utils/error.rs +200 -0
  161. package/rust/utils/file.rs +38 -35
  162. package/rust/utils/first_usage.rs +76 -0
  163. package/rust/utils/logger.rs +195 -139
  164. package/rust/utils/mod.rs +9 -50
  165. package/rust/utils/signature.rs +19 -17
  166. package/rust/utils/spinner.rs +22 -19
  167. package/rust/utils/telemetry.rs +292 -0
  168. package/rust/utils/watcher.rs +34 -33
  169. package/templates/minimal/README.md +97 -121
  170. package/templates/welcome/README.md +97 -121
  171. package/typescript/bin/index.ts +19 -5
  172. package/typescript/index.ts +3 -1
  173. package/typescript/scripts/postbuild.ts +10 -6
  174. package/typescript/scripts/postinstall.ts +56 -0
  175. package/typescript/scripts/version/bump.ts +0 -1
  176. package/typescript/scripts/version/index.ts +0 -1
  177. package/out-tsc/bin/devalang.exe +0 -0
@@ -1,92 +1,100 @@
1
- use crate::core::{
2
- lexer::{ token::TokenKind },
3
- parser::{ statement::{ Statement, StatementKind }, driver::Parser },
4
- shared::value::Value,
5
- store::global::GlobalStore,
6
- };
7
-
8
- pub fn parse_function_token(parser: &mut Parser, global_store: &mut GlobalStore) -> Statement {
9
- parser.advance(); // consume 'fn'
10
-
11
- let fn_token = match parser.previous_clone() {
12
- Some(tok) => tok,
13
- None => return Statement::unknown(),
14
- };
15
-
16
- let name_token = match parser.peek_clone() {
17
- Some(tok) => tok,
18
- None => return Statement::error(fn_token, "Expected function name after 'fn'".to_string()),
19
- };
20
-
21
- if name_token.kind != TokenKind::Identifier {
22
- return Statement::error(
23
- name_token.clone(),
24
- "Expected function name to be an identifier".to_string()
25
- );
26
- }
27
-
28
- let function_name = name_token.lexeme.clone();
29
- parser.advance(); // consume function name
30
-
31
- let mut parameters = Vec::new();
32
- let mut body = Vec::new();
33
-
34
- // Expect '('
35
- if parser.peek_kind() != Some(TokenKind::LParen) {
36
- return Statement::error(name_token.clone(), "Expected '(' after function name".to_string());
37
- }
38
- parser.advance(); // consume '('
39
-
40
- // Parse parameters until ')'
41
- let tokens = parser.collect_until(|t| t.kind == TokenKind::RParen || t.kind == TokenKind::EOF);
42
- for token in tokens {
43
- if token.kind == TokenKind::Identifier {
44
- parameters.push(token.lexeme.clone());
45
- }
46
- }
47
-
48
- if parser.peek_kind() == Some(TokenKind::RParen) {
49
- parser.advance(); // consume ')'
50
- } else {
51
- return Statement::error(name_token.clone(), "Expected ')' after parameters".to_string());
52
- }
53
-
54
- // Expect colon
55
- if parser.peek_kind() != Some(TokenKind::Colon) {
56
- return Statement::error(name_token.clone(), "Expected ':' after ')'".to_string());
57
- }
58
- parser.advance(); // consume ':'
59
-
60
- // Collect ALL tokens indented after this line until Dedent
61
- let base_indent = fn_token.indent;
62
- let mut body_tokens = Vec::new();
63
-
64
- while let Some(tok) = parser.peek() {
65
- if tok.kind == TokenKind::Dedent && tok.indent <= base_indent {
66
- break;
67
- }
68
- body_tokens.push(parser.advance().unwrap().clone());
69
- }
70
-
71
- // arse those tokens into block statements
72
- body = parser.parse_block(body_tokens.clone(), global_store);
73
-
74
- // Skip Dedent if present
75
- if let Some(tok) = parser.peek() {
76
- if tok.kind == TokenKind::Dedent {
77
- parser.advance();
78
- }
79
- }
80
-
81
- Statement {
82
- kind: StatementKind::Function {
83
- name: function_name.clone(),
84
- parameters: parameters.clone(),
85
- body: body.clone(),
86
- },
87
- value: Value::Null,
88
- indent: fn_token.indent,
89
- line: fn_token.line,
90
- column: fn_token.column,
91
- }
92
- }
1
+ use crate::core::{
2
+ lexer::token::TokenKind,
3
+ parser::{
4
+ driver::Parser,
5
+ statement::{Statement, StatementKind},
6
+ },
7
+ shared::value::Value,
8
+ store::global::GlobalStore,
9
+ };
10
+
11
+ pub fn parse_function_token(parser: &mut Parser, global_store: &mut GlobalStore) -> Statement {
12
+ parser.advance(); // consume 'fn'
13
+
14
+ let fn_token = match parser.previous_clone() {
15
+ Some(tok) => tok,
16
+ None => return Statement::unknown(),
17
+ };
18
+
19
+ let name_token = match parser.peek_clone() {
20
+ Some(tok) => tok,
21
+ None => return Statement::error(fn_token, "Expected function name after 'fn'".to_string()),
22
+ };
23
+
24
+ if name_token.kind != TokenKind::Identifier {
25
+ return Statement::error(
26
+ name_token.clone(),
27
+ "Expected function name to be an identifier".to_string(),
28
+ );
29
+ }
30
+
31
+ let function_name = name_token.lexeme.clone();
32
+ parser.advance(); // consume function name
33
+
34
+ let mut parameters = Vec::new();
35
+
36
+ // Expect '('
37
+ if parser.peek_kind() != Some(TokenKind::LParen) {
38
+ return Statement::error(
39
+ name_token.clone(),
40
+ "Expected '(' after function name".to_string(),
41
+ );
42
+ }
43
+ parser.advance(); // consume '('
44
+
45
+ // Parse parameters until ')'
46
+ let tokens = parser.collect_until(|t| t.kind == TokenKind::RParen || t.kind == TokenKind::EOF);
47
+ for token in tokens {
48
+ if token.kind == TokenKind::Identifier {
49
+ parameters.push(token.lexeme.clone());
50
+ }
51
+ }
52
+
53
+ if parser.peek_kind() == Some(TokenKind::RParen) {
54
+ parser.advance(); // consume ')'
55
+ } else {
56
+ return Statement::error(
57
+ name_token.clone(),
58
+ "Expected ')' after parameters".to_string(),
59
+ );
60
+ }
61
+
62
+ // Expect colon
63
+ if parser.peek_kind() != Some(TokenKind::Colon) {
64
+ return Statement::error(name_token.clone(), "Expected ':' after ')'".to_string());
65
+ }
66
+ parser.advance(); // consume ':'
67
+
68
+ // Collect ALL tokens indented after this line until Dedent
69
+ let base_indent = fn_token.indent;
70
+ let mut body_tokens = Vec::new();
71
+
72
+ while let Some(tok) = parser.peek() {
73
+ if tok.kind == TokenKind::Dedent && tok.indent <= base_indent {
74
+ break;
75
+ }
76
+ body_tokens.push(parser.advance().unwrap().clone());
77
+ }
78
+
79
+ // Parse those tokens into block statements
80
+ let body = parser.parse_block(body_tokens.clone(), global_store);
81
+
82
+ // Skip Dedent if present
83
+ if let Some(tok) = parser.peek() {
84
+ if tok.kind == TokenKind::Dedent {
85
+ parser.advance();
86
+ }
87
+ }
88
+
89
+ Statement {
90
+ kind: StatementKind::Function {
91
+ name: function_name.clone(),
92
+ parameters: parameters.clone(),
93
+ body: body.clone(),
94
+ },
95
+ value: Value::Null,
96
+ indent: fn_token.indent,
97
+ line: fn_token.line,
98
+ column: fn_token.column,
99
+ }
100
+ }
@@ -1,75 +1,85 @@
1
- use crate::core::{
2
- lexer::token::{ Token, TokenKind },
3
- parser::{ statement::{ Statement, StatementKind }, driver::Parser },
4
- shared::value::Value,
5
- store::global::GlobalStore,
6
- };
7
- use std::collections::HashMap;
8
-
9
- pub fn parse_group_token(
10
- parser: &mut Parser,
11
- current_token: Token,
12
- global_store: &mut GlobalStore
13
- ) -> Statement {
14
- parser.advance(); // consume "group"
15
-
16
- let Some(identifier_token) = parser.peek_clone() else {
17
- return Statement::error(current_token, "Expected identifier after 'group'".to_string());
18
- };
19
-
20
- if identifier_token.kind != TokenKind::Identifier && identifier_token.kind != TokenKind::String {
21
- return Statement::error(identifier_token, "Expected valid identifier".to_string());
22
- }
23
-
24
- parser.advance(); // consume identifier
25
-
26
- let Some(colon_token) = parser.peek_clone() else {
27
- return Statement::error(
28
- identifier_token,
29
- "Expected ':' after group identifier".to_string()
30
- );
31
- };
32
-
33
- if colon_token.kind != TokenKind::Colon {
34
- return Statement::error(
35
- colon_token.clone(),
36
- "Expected ':' after group identifier".to_string()
37
- );
38
- }
39
-
40
- parser.advance(); // consume ':'
41
-
42
- let base_indent = current_token.indent;
43
-
44
- // Clone without consuming tokens
45
- let mut index = parser.token_index;
46
- let mut tokens_inside_group = Vec::new();
47
-
48
- while index < parser.tokens.len() {
49
- let token = parser.tokens[index].clone();
50
-
51
- if token.indent <= base_indent && token.kind != TokenKind::Newline {
52
- break;
53
- }
54
-
55
- tokens_inside_group.push(token);
56
- index += 1;
57
- }
58
-
59
- // Advance index once to skip the processed tokens
60
- parser.token_index = index;
61
-
62
- let body = parser.parse_block(tokens_inside_group, global_store);
63
-
64
- let mut value_map = HashMap::new();
65
- value_map.insert("identifier".to_string(), Value::String(identifier_token.lexeme.clone()));
66
- value_map.insert("body".to_string(), Value::Block(body));
67
-
68
- return Statement {
69
- kind: StatementKind::Group,
70
- value: Value::Map(value_map),
71
- indent: current_token.indent,
72
- line: current_token.line,
73
- column: current_token.column,
74
- };
75
- }
1
+ use crate::core::{
2
+ lexer::token::{Token, TokenKind},
3
+ parser::{
4
+ driver::Parser,
5
+ statement::{Statement, StatementKind},
6
+ },
7
+ shared::value::Value,
8
+ store::global::GlobalStore,
9
+ };
10
+ use std::collections::HashMap;
11
+
12
+ pub fn parse_group_token(
13
+ parser: &mut Parser,
14
+ current_token: Token,
15
+ global_store: &mut GlobalStore,
16
+ ) -> Statement {
17
+ parser.advance(); // consume "group"
18
+
19
+ let Some(identifier_token) = parser.peek_clone() else {
20
+ return Statement::error(
21
+ current_token,
22
+ "Expected identifier after 'group'".to_string(),
23
+ );
24
+ };
25
+
26
+ if identifier_token.kind != TokenKind::Identifier && identifier_token.kind != TokenKind::String
27
+ {
28
+ return Statement::error(identifier_token, "Expected valid identifier".to_string());
29
+ }
30
+
31
+ parser.advance(); // consume identifier
32
+
33
+ let Some(colon_token) = parser.peek_clone() else {
34
+ return Statement::error(
35
+ identifier_token,
36
+ "Expected ':' after group identifier".to_string(),
37
+ );
38
+ };
39
+
40
+ if colon_token.kind != TokenKind::Colon {
41
+ return Statement::error(
42
+ colon_token.clone(),
43
+ "Expected ':' after group identifier".to_string(),
44
+ );
45
+ }
46
+
47
+ parser.advance(); // consume ':'
48
+
49
+ let base_indent = current_token.indent;
50
+
51
+ // Clone without consuming tokens
52
+ let mut index = parser.token_index;
53
+ let mut tokens_inside_group = Vec::new();
54
+
55
+ while index < parser.tokens.len() {
56
+ let token = parser.tokens[index].clone();
57
+
58
+ if token.indent <= base_indent && token.kind != TokenKind::Newline {
59
+ break;
60
+ }
61
+
62
+ tokens_inside_group.push(token);
63
+ index += 1;
64
+ }
65
+
66
+ // Advance index once to skip the processed tokens
67
+ parser.token_index = index;
68
+
69
+ let body = parser.parse_block(tokens_inside_group, global_store);
70
+
71
+ let mut value_map = HashMap::new();
72
+ value_map.insert(
73
+ "identifier".to_string(),
74
+ Value::String(identifier_token.lexeme.clone()),
75
+ );
76
+ value_map.insert("body".to_string(), Value::Block(body));
77
+
78
+ return Statement {
79
+ kind: StatementKind::Group,
80
+ value: Value::Map(value_map),
81
+ indent: current_token.indent,
82
+ line: current_token.line,
83
+ column: current_token.column,
84
+ };
85
+ }
@@ -1,127 +1,158 @@
1
- use std::collections::HashMap;
2
-
3
- use crate::core::{
4
- lexer::token::{ Token, TokenKind },
5
- parser::{
6
- driver::Parser,
7
- handler::{ dot::parse_dot_token, identifier::synth::parse_synth_token },
8
- statement::{ Statement, StatementKind },
9
- },
10
- shared::value::Value,
11
- store::global::GlobalStore,
12
- };
13
-
14
- pub fn parse_let_token(
15
- parser: &mut Parser,
16
- current_token: Token,
17
- global_store: &mut GlobalStore
18
- ) -> Statement {
19
- parser.advance(); // consume "let"
20
-
21
- let identifier = if let Some(token) = parser.peek_clone() {
22
- if token.kind == TokenKind::Identifier {
23
- parser.advance();
24
- token.lexeme.clone()
25
- } else {
26
- return Statement::error(token, "Expected identifier after 'let'".to_string());
27
- }
28
- } else {
29
- return Statement::error(current_token, "Expected identifier after 'let'".to_string());
30
- };
31
-
32
- if !parser.match_token(TokenKind::Equals) {
33
- return Statement::error(current_token, "Expected '=' after identifier".to_string());
34
- }
35
-
36
- let value = match parser.peek_clone() {
37
- Some(token) if token.kind == TokenKind::Dot => {
38
- let dot_stmt = parse_dot_token(parser, global_store);
39
- Value::Statement(Box::new(dot_stmt))
40
- }
41
- Some(token) if token.kind == TokenKind::Synth => {
42
- let synth_stmt = parse_synth_token(parser, token.clone(), global_store);
43
- Value::Statement(Box::new(synth_stmt))
44
- }
45
- Some(token) if token.kind == TokenKind::Identifier => {
46
- parser.advance();
47
- Value::Identifier(token.lexeme.clone())
48
- }
49
- Some(token) if token.kind == TokenKind::String => {
50
- parser.advance();
51
- Value::String(token.lexeme.clone())
52
- }
53
- Some(token) if token.kind == TokenKind::Number => {
54
- parser.advance();
55
- Value::Number(token.lexeme.parse().unwrap_or(0.0))
56
- }
57
- Some(token) if token.kind == TokenKind::Boolean => {
58
- parser.advance();
59
- Value::Boolean(token.lexeme.parse().unwrap_or(false))
60
- }
61
- Some(token) if token.kind == TokenKind::LBrace => {
62
- parser.advance();
63
-
64
- let mut map = HashMap::new();
65
-
66
- while let Some(key_token) = parser.peek_clone() {
67
- if key_token.kind == TokenKind::RBrace {
68
- parser.advance(); // consume '}'
69
- break;
70
- }
71
-
72
- if key_token.kind != TokenKind::Identifier {
73
- return Statement::error(token, "Expected key identifier in map".to_string());
74
- }
75
- parser.advance();
76
- let key = key_token.lexeme.clone();
77
-
78
- if !parser.match_token(TokenKind::Colon) {
79
- let message = format!("Expected ':' after key '{}'", key);
80
- return Statement::error(token, message);
81
- }
82
-
83
- let val = match parser.peek_clone() {
84
- Some(t) if t.kind == TokenKind::Number => {
85
- parser.advance();
86
- Value::Number(t.lexeme.parse().unwrap_or(0.0))
87
- }
88
- Some(t) if t.kind == TokenKind::String => {
89
- parser.advance();
90
- Value::String(t.lexeme.clone())
91
- }
92
- Some(t) if t.kind == TokenKind::Identifier => {
93
- parser.advance();
94
- Value::Identifier(t.lexeme.clone())
95
- }
96
- _ => Value::Null,
97
- };
98
-
99
- if val == Value::Null {
100
- let message = format!("Invalid value for key '{}'", key);
101
- return Statement::error(token, message);
102
- }
103
-
104
- map.insert(key, val);
105
-
106
- if let Some(t) = parser.peek() {
107
- if t.kind == TokenKind::Comma {
108
- parser.advance(); // skip comma
109
- }
110
- }
111
- }
112
-
113
- Value::Map(map)
114
- }
115
- _ => {
116
- return Statement::error(current_token, "Unhandled value type after '='".to_string());
117
- }
118
- };
119
-
120
- Statement {
121
- kind: StatementKind::Let { name: identifier },
122
- value: value,
123
- indent: current_token.indent,
124
- line: current_token.line,
125
- column: current_token.column,
126
- }
127
- }
1
+ use std::collections::HashMap;
2
+
3
+ use crate::core::{
4
+ lexer::token::{Token, TokenKind},
5
+ parser::{
6
+ driver::Parser,
7
+ handler::{dot::parse_dot_token, identifier::synth::parse_synth_token},
8
+ statement::{Statement, StatementKind},
9
+ },
10
+ shared::value::Value,
11
+ store::global::GlobalStore,
12
+ };
13
+
14
+ pub fn parse_let_token(
15
+ parser: &mut Parser,
16
+ current_token: Token,
17
+ global_store: &mut GlobalStore,
18
+ ) -> Statement {
19
+ parser.advance(); // consume "let"
20
+
21
+ let identifier = if let Some(token) = parser.peek_clone() {
22
+ if token.kind == TokenKind::Identifier {
23
+ parser.advance();
24
+ token.lexeme.clone()
25
+ } else {
26
+ return Statement::error(token, "Expected identifier after 'let'".to_string());
27
+ }
28
+ } else {
29
+ return Statement::error(current_token, "Expected identifier after 'let'".to_string());
30
+ };
31
+
32
+ if !parser.match_token(TokenKind::Equals) {
33
+ return Statement::error(current_token, "Expected '=' after identifier".to_string());
34
+ }
35
+
36
+ // If RHS begins with '$' or contains expression tokens ('+', '-', '*', '/', '(', '['),
37
+ // collect the rest of the line as a raw expression string.
38
+ if let Some(tok) = parser.peek_clone() {
39
+ let line = tok.line;
40
+ if tok.lexeme.starts_with('$')
41
+ || matches!(
42
+ tok.kind,
43
+ TokenKind::Identifier | TokenKind::Number | TokenKind::LParen | TokenKind::LBracket
44
+ )
45
+ {
46
+ // Collect tokens until end of the current line
47
+ let collected = parser.collect_until(|t| {
48
+ t.line != line || matches!(t.kind, TokenKind::Newline | TokenKind::EOF)
49
+ });
50
+ let mut text = String::new();
51
+ for t in collected.iter() {
52
+ if matches!(t.kind, TokenKind::Newline | TokenKind::EOF) {
53
+ break;
54
+ }
55
+ text.push_str(&t.lexeme);
56
+ }
57
+ return Statement {
58
+ kind: StatementKind::Let { name: identifier },
59
+ value: Value::String(text.trim().to_string()),
60
+ indent: current_token.indent,
61
+ line: current_token.line,
62
+ column: current_token.column,
63
+ };
64
+ }
65
+ }
66
+
67
+ let value = match parser.peek_clone() {
68
+ Some(token) if token.kind == TokenKind::Dot => {
69
+ let dot_stmt = parse_dot_token(parser, global_store);
70
+ Value::Statement(Box::new(dot_stmt))
71
+ }
72
+ Some(token) if token.kind == TokenKind::Synth => {
73
+ let synth_stmt = parse_synth_token(parser, token.clone(), global_store);
74
+ Value::Statement(Box::new(synth_stmt))
75
+ }
76
+ Some(token) if token.kind == TokenKind::Identifier => {
77
+ parser.advance();
78
+ Value::Identifier(token.lexeme.clone())
79
+ }
80
+ Some(token) if token.kind == TokenKind::String => {
81
+ parser.advance();
82
+ Value::String(token.lexeme.clone())
83
+ }
84
+ Some(token) if token.kind == TokenKind::Number => {
85
+ parser.advance();
86
+ Value::Number(token.lexeme.parse().unwrap_or(0.0))
87
+ }
88
+ Some(token) if token.kind == TokenKind::Boolean => {
89
+ parser.advance();
90
+ Value::Boolean(token.lexeme.parse().unwrap_or(false))
91
+ }
92
+ Some(token) if token.kind == TokenKind::LBrace => {
93
+ parser.advance();
94
+
95
+ let mut map = HashMap::new();
96
+
97
+ while let Some(key_token) = parser.peek_clone() {
98
+ if key_token.kind == TokenKind::RBrace {
99
+ parser.advance(); // consume '}'
100
+ break;
101
+ }
102
+
103
+ if key_token.kind != TokenKind::Identifier {
104
+ return Statement::error(token, "Expected key identifier in map".to_string());
105
+ }
106
+ parser.advance();
107
+ let key = key_token.lexeme.clone();
108
+
109
+ if !parser.match_token(TokenKind::Colon) {
110
+ let message = format!("Expected ':' after key '{}'", key);
111
+ return Statement::error(token, message);
112
+ }
113
+
114
+ let val = match parser.peek_clone() {
115
+ Some(t) if t.kind == TokenKind::Number => {
116
+ parser.advance();
117
+ Value::Number(t.lexeme.parse().unwrap_or(0.0))
118
+ }
119
+ Some(t) if t.kind == TokenKind::String => {
120
+ parser.advance();
121
+ Value::String(t.lexeme.clone())
122
+ }
123
+ Some(t) if t.kind == TokenKind::Identifier => {
124
+ parser.advance();
125
+ Value::Identifier(t.lexeme.clone())
126
+ }
127
+ _ => Value::Null,
128
+ };
129
+
130
+ if val == Value::Null {
131
+ let message = format!("Invalid value for key '{}'", key);
132
+ return Statement::error(token, message);
133
+ }
134
+
135
+ map.insert(key, val);
136
+
137
+ if let Some(t) = parser.peek() {
138
+ if t.kind == TokenKind::Comma {
139
+ parser.advance(); // skip comma
140
+ }
141
+ }
142
+ }
143
+
144
+ Value::Map(map)
145
+ }
146
+ _ => {
147
+ return Statement::error(current_token, "Unhandled value type after '='".to_string());
148
+ }
149
+ };
150
+
151
+ Statement {
152
+ kind: StatementKind::Let { name: identifier },
153
+ value: value,
154
+ indent: current_token.indent,
155
+ line: current_token.line,
156
+ column: current_token.column,
157
+ }
158
+ }