@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,162 +1,245 @@
1
- use crate::core::{
2
- lexer::token::TokenKind,
3
- parser::{ driver::Parser, statement::{ Statement, StatementKind } },
4
- shared::value::Value,
5
- store::global::GlobalStore,
6
- };
7
- pub fn parse_at_token(parser: &mut Parser, global_store: &mut GlobalStore) -> Statement {
8
- parser.advance(); // consume '@'
9
-
10
- let Some(token) = parser.peek_clone() else {
11
- return Statement::unknown();
12
- };
13
-
14
- let keyword = token.lexeme.as_str();
15
-
16
- match keyword {
17
- "import" => {
18
- parser.advance(); // consume 'import'
19
-
20
- if !parser.match_token(TokenKind::LBrace) {
21
- return Statement::error(token, "Expected '{{' after 'import'".to_string());
22
- }
23
-
24
- let mut names = Vec::new();
25
- while let Some(token) = parser.peek() {
26
- match &token.kind {
27
- TokenKind::Identifier => {
28
- names.push(token.lexeme.clone());
29
- parser.advance();
30
- }
31
- TokenKind::Comma => {
32
- parser.advance();
33
- }
34
- TokenKind::RBrace => {
35
- parser.advance();
36
- break;
37
- }
38
- _ => {
39
- let message = format!(
40
- "Unexpected token in import list: {:?}",
41
- token.kind.clone()
42
- );
43
- return Statement::error(token.clone(), message);
44
- }
45
- }
46
- }
47
-
48
- let Some(from_token) = parser.peek_clone() else {
49
- return Statement::error(token, "Expected 'from' after import list".to_string());
50
- };
51
-
52
- if from_token.lexeme != "from" {
53
- return Statement::error(token, "Expected keyword 'from'".to_string());
54
- }
55
-
56
- parser.advance(); // consume 'from'
57
-
58
- let Some(source_token) = parser.peek() else {
59
- return Statement::error(token, "Expected string after 'from'".to_string());
60
- };
61
-
62
- if source_token.kind != TokenKind::String {
63
- return Statement::error(token, "Expected string after 'from'".to_string());
64
- }
65
-
66
- let source = source_token.lexeme.clone();
67
- parser.advance(); // consume string
68
-
69
- Statement {
70
- kind: StatementKind::Import { names, source },
71
- value: Value::Null,
72
- indent: token.indent,
73
- line: token.line,
74
- column: token.column,
75
- }
76
- }
77
-
78
- "export" => {
79
- parser.advance(); // consume 'export'
80
-
81
- parser.advance(); // consume '{'
82
-
83
- let names_tokens = parser.collect_until(|t| TokenKind::RBrace == t.kind);
84
- let mut names: Vec<String> = Vec::new();
85
-
86
- for token in names_tokens {
87
- if token.kind == TokenKind::Identifier {
88
- names.push(token.lexeme.clone());
89
- } else if token.kind == TokenKind::Comma {
90
- continue; // Ignore commas
91
- } else if token.kind == TokenKind::RBrace {
92
- break; // Stop at the closing brace
93
- } else {
94
- return Statement::error(token, "Unexpected token in export list".to_string());
95
- }
96
- }
97
-
98
- Statement {
99
- kind: StatementKind::Export {
100
- names: names.clone(),
101
- source: parser.current_module.clone(),
102
- },
103
- value: Value::Null,
104
- indent: token.indent,
105
- line: token.line,
106
- column: token.column,
107
- }
108
- }
109
-
110
- "load" => {
111
- parser.advance(); // consume 'load'
112
-
113
- // Exemple : @load "preset.mydeva"
114
- let Some(path_token) = parser.peek() else {
115
- return Statement::error(token, "Expected string after 'load'".to_string());
116
- };
117
-
118
- if path_token.kind != TokenKind::String {
119
- return Statement::error(token, "Expected string after 'load'".to_string());
120
- }
121
-
122
- let path = path_token.lexeme.clone();
123
-
124
- parser.advance(); // consume string
125
- parser.advance(); // consume 'as'
126
-
127
- let Some(as_token) = parser.peek_clone() else {
128
- return Statement::error(
129
- token,
130
- "Expected 'as' after path in load statement".to_string()
131
- );
132
- };
133
-
134
- if as_token.kind != TokenKind::Identifier {
135
- return Statement::error(
136
- token,
137
- "Expected identifier after 'as' in load statement".to_string()
138
- );
139
- }
140
-
141
- let alias = as_token.lexeme.clone();
142
-
143
- parser.advance(); // consume identifier
144
-
145
- Statement {
146
- kind: StatementKind::Load {
147
- source: path,
148
- alias,
149
- },
150
- value: Value::Null,
151
- indent: token.indent,
152
- line: token.line,
153
- column: token.column,
154
- }
155
- }
156
-
157
- _ => {
158
- let message = format!("Unknown keyword after '@' : {}", keyword);
159
- Statement::error(token, message)
160
- }
161
- }
162
- }
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
+ pub fn parse_at_token(parser: &mut Parser, _global_store: &mut GlobalStore) -> Statement {
11
+ parser.advance(); // consume '@'
12
+
13
+ let Some(token) = parser.peek_clone() else {
14
+ return Statement::unknown();
15
+ };
16
+
17
+ let keyword = token.lexeme.as_str();
18
+
19
+ match keyword {
20
+ "use" => {
21
+ parser.advance(); // consume 'use'
22
+ let Some(use_token) = parser.previous_clone() else {
23
+ return Statement::unknown();
24
+ };
25
+
26
+ // Expect plugin author
27
+ let Some(author_token) = parser.peek_clone() else {
28
+ return Statement::error(use_token, "Expected plugin author".to_string());
29
+ };
30
+ if author_token.kind != TokenKind::Identifier {
31
+ return Statement::error(
32
+ author_token,
33
+ "Expected identifier for plugin author".to_string(),
34
+ );
35
+ }
36
+ parser.advance(); // consume author
37
+
38
+ // Expect '.'
39
+ if !parser.match_token(TokenKind::Dot) {
40
+ return Statement::error(
41
+ author_token,
42
+ "Expected '.' after plugin author".to_string(),
43
+ );
44
+ }
45
+
46
+ // Expect plugin name
47
+ let Some(plugin_token) = parser.peek_clone() else {
48
+ return Statement::error(author_token, "Expected plugin name".to_string());
49
+ };
50
+
51
+ let name = match plugin_token.kind {
52
+ TokenKind::Identifier | TokenKind::Number => {
53
+ parser.advance();
54
+ format!("{}.{}", author_token.lexeme, plugin_token.lexeme)
55
+ }
56
+ _ => {
57
+ return Statement::error(
58
+ plugin_token,
59
+ "Expected identifier or number for plugin name".to_string(),
60
+ );
61
+ }
62
+ };
63
+
64
+ // Optional alias
65
+ let alias = if parser.match_token(TokenKind::As) {
66
+ let Some(alias_token) = parser.peek_clone() else {
67
+ return Statement::error(
68
+ use_token,
69
+ "Expected identifier after 'as'".to_string(),
70
+ );
71
+ };
72
+ if alias_token.kind != TokenKind::Identifier {
73
+ return Statement::error(
74
+ alias_token,
75
+ "Expected identifier after 'as'".to_string(),
76
+ );
77
+ }
78
+ parser.advance();
79
+ Some(alias_token.lexeme.clone())
80
+ } else {
81
+ None
82
+ };
83
+
84
+ Statement {
85
+ kind: StatementKind::Use {
86
+ name: name.clone(),
87
+ alias,
88
+ },
89
+ value: Value::Null,
90
+ indent: use_token.indent,
91
+ line: use_token.line,
92
+ column: use_token.column,
93
+ }
94
+ }
95
+
96
+ "import" => {
97
+ parser.advance(); // consume 'import'
98
+
99
+ if !parser.match_token(TokenKind::LBrace) {
100
+ return Statement::error(token, "Expected '{{' after 'import'".to_string());
101
+ }
102
+
103
+ let mut names = Vec::new();
104
+ while let Some(token) = parser.peek() {
105
+ match &token.kind {
106
+ TokenKind::Identifier => {
107
+ names.push(token.lexeme.clone());
108
+ parser.advance();
109
+ }
110
+ TokenKind::Comma => {
111
+ parser.advance();
112
+ }
113
+ TokenKind::RBrace => {
114
+ parser.advance();
115
+ break;
116
+ }
117
+ _ => {
118
+ let message =
119
+ format!("Unexpected token in import list: {:?}", token.kind.clone());
120
+ return Statement::error(token.clone(), message);
121
+ }
122
+ }
123
+ }
124
+
125
+ let Some(from_token) = parser.peek_clone() else {
126
+ return Statement::error(token, "Expected 'from' after import list".to_string());
127
+ };
128
+
129
+ if from_token.lexeme != "from" {
130
+ return Statement::error(token, "Expected keyword 'from'".to_string());
131
+ }
132
+
133
+ parser.advance(); // consume 'from'
134
+
135
+ let Some(source_token) = parser.peek() else {
136
+ return Statement::error(token, "Expected string after 'from'".to_string());
137
+ };
138
+
139
+ if source_token.kind != TokenKind::String {
140
+ return Statement::error(token, "Expected string after 'from'".to_string());
141
+ }
142
+
143
+ let source = source_token.lexeme.clone();
144
+ parser.advance(); // consume string
145
+
146
+ Statement {
147
+ kind: StatementKind::Import { names, source },
148
+ value: Value::Null,
149
+ indent: token.indent,
150
+ line: token.line,
151
+ column: token.column,
152
+ }
153
+ }
154
+
155
+ "export" => {
156
+ parser.advance(); // consume 'export'
157
+
158
+ parser.advance(); // consume '{'
159
+
160
+ let names_tokens = parser.collect_until(|t| TokenKind::RBrace == t.kind);
161
+ let mut names: Vec<String> = Vec::new();
162
+
163
+ for token in names_tokens {
164
+ if token.kind == TokenKind::Identifier {
165
+ names.push(token.lexeme.clone());
166
+ } else if token.kind == TokenKind::Comma {
167
+ continue; // Ignore commas
168
+ } else if token.kind == TokenKind::RBrace {
169
+ break; // Stop at the closing brace
170
+ } else {
171
+ return Statement::error(token, "Unexpected token in export list".to_string());
172
+ }
173
+ }
174
+
175
+ Statement {
176
+ kind: StatementKind::Export {
177
+ names: names.clone(),
178
+ source: parser.current_module.clone(),
179
+ },
180
+ value: Value::Null,
181
+ indent: token.indent,
182
+ line: token.line,
183
+ column: token.column,
184
+ }
185
+ }
186
+
187
+ "load" => {
188
+ parser.advance(); // consume 'load'
189
+
190
+ // Example: @load "preset.mydeva"
191
+ let Some(path_token) = parser.peek() else {
192
+ return Statement::error(token, "Expected string after 'load'".to_string());
193
+ };
194
+
195
+ if path_token.kind != TokenKind::String {
196
+ return Statement::error(token, "Expected string after 'load'".to_string());
197
+ }
198
+
199
+ let path = path_token.lexeme.clone();
200
+
201
+ parser.advance(); // consume string
202
+
203
+ if !parser.match_token(TokenKind::As) {
204
+ return Statement::error(
205
+ token,
206
+ "Expected 'as' after path in load statement".to_string(),
207
+ );
208
+ }
209
+
210
+ let Some(alias_token) = parser.peek_clone() else {
211
+ return Statement::error(
212
+ token,
213
+ "Expected identifier after 'as' in load statement".to_string(),
214
+ );
215
+ };
216
+
217
+ if alias_token.kind != TokenKind::Identifier {
218
+ return Statement::error(
219
+ token,
220
+ "Expected identifier after 'as' in load statement".to_string(),
221
+ );
222
+ }
223
+
224
+ let alias = alias_token.lexeme.clone();
225
+
226
+ parser.advance(); // consume identifier
227
+
228
+ Statement {
229
+ kind: StatementKind::Load {
230
+ source: path,
231
+ alias,
232
+ },
233
+ value: Value::Null,
234
+ indent: token.indent,
235
+ line: token.line,
236
+ column: token.column,
237
+ }
238
+ }
239
+
240
+ _ => {
241
+ let message = format!("Unknown keyword after '@' : {}", keyword);
242
+ Statement::error(token, message)
243
+ }
244
+ }
245
+ }
@@ -1,69 +1,94 @@
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_bank_token(parser: &mut Parser, _global_store: &mut GlobalStore) -> Statement {
9
- parser.advance(); // consume 'bank'
10
-
11
- let Some(bank_token) = parser.previous_clone() else {
12
- return Statement::unknown();
13
- };
14
-
15
- let bank_value = if let Some(token) = parser.peek_clone() {
16
- match token.kind {
17
- TokenKind::Identifier | TokenKind::Number => {
18
- parser.advance(); // consume identifier or number
19
-
20
- let mut value = token.lexeme.clone();
21
-
22
- // Support namespaced banks: <author>.<bank_name>
23
- if let Some(next) = parser.peek_clone() {
24
- if next.kind == TokenKind::Dot {
25
- parser.advance(); // consume '.'
26
- if let Some(last) = parser.peek_clone() {
27
- match last.kind {
28
- TokenKind::Identifier | TokenKind::Number => {
29
- parser.advance();
30
- value = format!("{}.{}", value, last.lexeme);
31
- Value::String(value)
32
- }
33
- _ => Value::Unknown,
34
- }
35
- } else {
36
- Value::Unknown
37
- }
38
- } else {
39
- match token.kind {
40
- TokenKind::Identifier => Value::Identifier(value),
41
- TokenKind::Number => Value::Number(value.parse::<f32>().unwrap_or(0.0)),
42
- _ => Value::Unknown,
43
- }
44
- }
45
- } else {
46
- match token.kind {
47
- TokenKind::Identifier => Value::Identifier(value),
48
- TokenKind::Number => Value::Number(value.parse::<f32>().unwrap_or(0.0)),
49
- _ => Value::Unknown,
50
- }
51
- }
52
- }
53
- _ => Value::Unknown,
54
- }
55
- } else {
56
- return Statement::error(
57
- bank_token,
58
- "Expected identifier or number after 'bank'".to_string()
59
- );
60
- };
61
-
62
- Statement {
63
- kind: StatementKind::Bank,
64
- value: bank_value,
65
- indent: bank_token.indent,
66
- line: bank_token.line,
67
- column: bank_token.column,
68
- }
69
- }
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_bank_token(parser: &mut Parser, _global_store: &mut GlobalStore) -> Statement {
12
+ // consume 'bank'
13
+ parser.advance();
14
+
15
+ let Some(bank_tok) = parser.previous_clone() else {
16
+ return Statement::unknown();
17
+ };
18
+
19
+ // Parse bank name
20
+ let bank_value: Value = match parser.peek_clone() {
21
+ Some(tok) => match tok.kind {
22
+ TokenKind::Identifier | TokenKind::Number => {
23
+ // base name
24
+ parser.advance();
25
+ let mut base = tok.lexeme.clone();
26
+ // optional .suffix (identifier or number)
27
+ if let Some(dot) = parser.peek_clone() {
28
+ if dot.kind == TokenKind::Dot {
29
+ // consume '.' and the following ident/number
30
+ parser.advance();
31
+ if let Some(suffix) = parser.peek_clone() {
32
+ match suffix.kind {
33
+ TokenKind::Identifier | TokenKind::Number => {
34
+ parser.advance();
35
+ base.push('.');
36
+ base.push_str(&suffix.lexeme);
37
+ Value::String(base)
38
+ }
39
+ _ => Value::Identifier(base),
40
+ }
41
+ } else {
42
+ Value::Identifier(base)
43
+ }
44
+ } else {
45
+ match tok.kind {
46
+ TokenKind::Identifier => Value::String(base),
47
+ TokenKind::Number => Value::Number(base.parse::<f32>().unwrap_or(0.0)),
48
+ _ => Value::Unknown,
49
+ }
50
+ }
51
+ } else {
52
+ match tok.kind {
53
+ TokenKind::Identifier => Value::String(base),
54
+ TokenKind::Number => Value::Number(base.parse::<f32>().unwrap_or(0.0)),
55
+ _ => Value::Unknown,
56
+ }
57
+ }
58
+ }
59
+ TokenKind::String => {
60
+ parser.advance();
61
+ Value::String(tok.lexeme.clone())
62
+ }
63
+ _ => Value::Unknown,
64
+ },
65
+ None => Value::Unknown,
66
+ };
67
+
68
+ if matches!(bank_value, Value::Unknown | Value::Null) {
69
+ return Statement::error(bank_tok, "Expected a bank name".to_string());
70
+ }
71
+
72
+ // Optional alias: as <identifier>
73
+ let mut alias: Option<String> = None;
74
+ if parser.peek_is("as") {
75
+ // consume 'as'
76
+ parser.advance();
77
+ let Some(next) = parser.peek_clone() else {
78
+ return Statement::error(bank_tok, "Expected identifier after 'as'".to_string());
79
+ };
80
+ if next.kind != TokenKind::Identifier {
81
+ return Statement::error(next, "Expected identifier after 'as'".to_string());
82
+ }
83
+ parser.advance();
84
+ alias = Some(next.lexeme.clone());
85
+ }
86
+
87
+ Statement {
88
+ kind: StatementKind::Bank { alias },
89
+ value: bank_value,
90
+ indent: bank_tok.indent,
91
+ line: bank_tok.line,
92
+ column: bank_tok.column,
93
+ }
94
+ }