@devaloop/devalang 0.0.1-alpha.9 → 0.0.1-beta.1

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 (271) hide show
  1. package/.cargo/config.toml +2 -0
  2. package/.devalang +10 -4
  3. package/.github/workflows/ci.yml +103 -0
  4. package/Cargo.toml +80 -48
  5. package/README.md +135 -154
  6. package/docs/CHANGELOG.md +386 -1
  7. package/docs/CONTRIBUTING.md +101 -0
  8. package/docs/ROADMAP.md +10 -7
  9. package/docs/TODO.md +21 -9
  10. package/examples/automation.deva +42 -0
  11. package/examples/bank.deva +7 -0
  12. package/examples/duration.deva +9 -0
  13. package/examples/events.deva +12 -0
  14. package/examples/function.deva +15 -0
  15. package/examples/index.deva +57 -12
  16. package/examples/loop.deva +5 -12
  17. package/examples/pattern.deva +8 -0
  18. package/examples/plugin.deva +16 -0
  19. package/examples/variables.deva +1 -1
  20. package/out-tsc/bin/index.d.ts +2 -0
  21. package/out-tsc/bin/index.js +51 -7
  22. package/out-tsc/core/functions/index.d.ts +37 -0
  23. package/out-tsc/core/functions/index.js +76 -0
  24. package/out-tsc/core/index.d.ts +6 -0
  25. package/out-tsc/core/index.js +22 -0
  26. package/out-tsc/core/types/index.d.ts +4 -0
  27. package/out-tsc/core/types/index.js +20 -0
  28. package/out-tsc/core/types/plugin.d.ts +18 -0
  29. package/out-tsc/core/types/plugin.js +2 -0
  30. package/out-tsc/core/types/result.d.ts +27 -0
  31. package/out-tsc/core/types/result.js +2 -0
  32. package/out-tsc/core/types/statement.d.ts +106 -0
  33. package/out-tsc/core/types/statement.js +2 -0
  34. package/out-tsc/core/types/value.d.ts +43 -0
  35. package/out-tsc/core/types/value.js +2 -0
  36. package/out-tsc/index.d.ts +7 -0
  37. package/out-tsc/index.js +42 -1
  38. package/out-tsc/pkg/devalang_core.d.ts +13 -0
  39. package/out-tsc/pkg/devalang_core.js +50 -0
  40. package/out-tsc/pkg/devalang_core_bg.wasm.d.ts +33 -0
  41. package/out-tsc/scripts/copy-wasm-dts.d.ts +1 -0
  42. package/out-tsc/scripts/copy-wasm-dts.js +73 -0
  43. package/out-tsc/scripts/postinstall.d.ts +1 -0
  44. package/out-tsc/scripts/postinstall.js +83 -0
  45. package/out-tsc/scripts/version/bump.d.ts +1 -0
  46. package/out-tsc/scripts/version/fetch.d.ts +1 -0
  47. package/out-tsc/scripts/version/index.d.ts +1 -0
  48. package/out-tsc/scripts/version/sync.d.ts +1 -0
  49. package/package.json +28 -7
  50. package/project-version.json +4 -4
  51. package/rust/cli/bank/api.rs +122 -0
  52. package/rust/cli/bank/commands.rs +275 -0
  53. package/rust/cli/bank/mod.rs +29 -0
  54. package/rust/cli/build/commands.rs +103 -0
  55. package/rust/cli/build/mod.rs +2 -0
  56. package/rust/cli/build/process.rs +146 -0
  57. package/rust/cli/check/mod.rs +208 -0
  58. package/rust/cli/discover/commands.rs +253 -0
  59. package/rust/cli/discover/config.rs +111 -0
  60. package/rust/cli/discover/fs.rs +19 -0
  61. package/rust/cli/discover/install.rs +103 -0
  62. package/rust/cli/discover/metadata.rs +48 -0
  63. package/rust/cli/discover/mod.rs +5 -0
  64. package/rust/cli/{init.rs → init/commands.rs} +32 -23
  65. package/rust/cli/init/mod.rs +1 -0
  66. package/rust/cli/install/addon.rs +118 -0
  67. package/rust/cli/install/bank.rs +53 -0
  68. package/rust/cli/install/commands.rs +35 -0
  69. package/rust/cli/install/mod.rs +4 -0
  70. package/rust/cli/install/plugin.rs +61 -0
  71. package/rust/cli/login/commands.rs +124 -0
  72. package/rust/cli/login/mod.rs +1 -0
  73. package/rust/cli/mod.rs +12 -205
  74. package/rust/cli/parser.rs +314 -0
  75. package/rust/cli/play/commands.rs +324 -0
  76. package/rust/cli/play/io.rs +17 -0
  77. package/rust/cli/play/mod.rs +5 -0
  78. package/rust/cli/play/process.rs +150 -0
  79. package/rust/cli/play/realtime.rs +91 -0
  80. package/rust/cli/play/utils.rs +23 -0
  81. package/rust/cli/telemetry/commands.rs +22 -0
  82. package/rust/cli/telemetry/event_creator.rs +80 -0
  83. package/rust/cli/telemetry/mod.rs +3 -0
  84. package/rust/cli/telemetry/send.rs +51 -0
  85. package/rust/cli/{template.rs → template/commands.rs} +69 -57
  86. package/rust/cli/template/mod.rs +1 -0
  87. package/rust/cli/update/commands.rs +6 -0
  88. package/rust/cli/update/mod.rs +1 -0
  89. package/rust/config/driver.rs +103 -0
  90. package/rust/config/mod.rs +3 -16
  91. package/rust/config/ops.rs +26 -0
  92. package/rust/config/settings.rs +101 -0
  93. package/rust/core/audio/engine/helpers.rs +170 -0
  94. package/rust/core/audio/engine/mod.rs +7 -0
  95. package/rust/core/audio/engine/sample.rs +366 -0
  96. package/rust/core/audio/engine/synth.rs +325 -0
  97. package/rust/core/audio/evaluator.rs +310 -31
  98. package/rust/core/audio/interpreter/arrow_call.rs +311 -129
  99. package/rust/core/audio/interpreter/automate.rs +18 -0
  100. package/rust/core/audio/interpreter/call.rs +294 -64
  101. package/rust/core/audio/interpreter/condition.rs +71 -69
  102. package/rust/core/audio/interpreter/driver.rs +542 -216
  103. package/rust/core/audio/interpreter/function.rs +26 -0
  104. package/rust/core/audio/interpreter/let_.rs +38 -19
  105. package/rust/core/audio/interpreter/load.rs +19 -18
  106. package/rust/core/audio/interpreter/loop_.rs +114 -67
  107. package/rust/core/audio/interpreter/mod.rs +14 -12
  108. package/rust/core/audio/interpreter/sleep.rs +28 -36
  109. package/rust/core/audio/interpreter/spawn.rs +252 -66
  110. package/rust/core/audio/interpreter/tempo.rs +40 -16
  111. package/rust/core/audio/interpreter/trigger.rs +239 -69
  112. package/rust/core/audio/loader/mod.rs +1 -1
  113. package/rust/core/audio/loader/trigger.rs +97 -52
  114. package/rust/core/audio/mod.rs +7 -6
  115. package/rust/core/audio/player.rs +70 -54
  116. package/rust/core/audio/renderer.rs +54 -54
  117. package/rust/core/audio/special/easing.rs +189 -0
  118. package/rust/core/audio/special/env.rs +45 -0
  119. package/rust/core/audio/special/math.rs +134 -0
  120. package/rust/core/audio/special/mod.rs +9 -0
  121. package/rust/core/audio/special/modulator.rs +143 -0
  122. package/rust/core/builder/mod.rs +86 -80
  123. package/rust/core/debugger/lexer.rs +27 -27
  124. package/rust/core/debugger/mod.rs +30 -21
  125. package/rust/core/debugger/module.rs +55 -0
  126. package/rust/core/debugger/preprocessor.rs +27 -27
  127. package/rust/core/debugger/store.rs +40 -25
  128. package/rust/core/error/mod.rs +269 -60
  129. package/rust/core/lexer/driver.rs +61 -0
  130. package/rust/core/lexer/handler/arrow.rs +82 -31
  131. package/rust/core/lexer/handler/at.rs +21 -21
  132. package/rust/core/lexer/handler/brace.rs +41 -41
  133. package/rust/core/lexer/handler/colon.rs +21 -21
  134. package/rust/core/lexer/handler/comment.rs +30 -30
  135. package/rust/core/lexer/handler/dot.rs +21 -21
  136. package/rust/core/lexer/handler/driver.rs +337 -226
  137. package/rust/core/lexer/handler/identifier.rs +47 -41
  138. package/rust/core/lexer/handler/indent.rs +66 -52
  139. package/rust/core/lexer/handler/mod.rs +15 -14
  140. package/rust/core/lexer/handler/newline.rs +23 -23
  141. package/rust/core/lexer/handler/number.rs +31 -31
  142. package/rust/core/lexer/handler/operator.rs +46 -44
  143. package/rust/core/lexer/handler/parenthesis.rs +41 -0
  144. package/rust/core/lexer/handler/slash.rs +21 -0
  145. package/rust/core/lexer/handler/string.rs +63 -63
  146. package/rust/core/lexer/mod.rs +3 -51
  147. package/rust/core/lexer/token.rs +17 -12
  148. package/rust/core/mod.rs +10 -10
  149. package/rust/core/parser/driver.rs +584 -331
  150. package/rust/core/parser/handler/arrow_call.rs +253 -126
  151. package/rust/core/parser/handler/at.rs +279 -162
  152. package/rust/core/parser/handler/bank.rs +104 -41
  153. package/rust/core/parser/handler/condition.rs +83 -74
  154. package/rust/core/parser/handler/dot.rs +148 -112
  155. package/rust/core/parser/handler/identifier/automate.rs +254 -0
  156. package/rust/core/parser/handler/identifier/call.rs +91 -41
  157. package/rust/core/parser/handler/identifier/emit.rs +70 -0
  158. package/rust/core/parser/handler/identifier/function.rs +113 -0
  159. package/rust/core/parser/handler/identifier/group.rs +89 -75
  160. package/rust/core/parser/handler/identifier/let_.rs +173 -133
  161. package/rust/core/parser/handler/identifier/mod.rs +55 -51
  162. package/rust/core/parser/handler/identifier/on.rs +107 -0
  163. package/rust/core/parser/handler/identifier/print.rs +49 -0
  164. package/rust/core/parser/handler/identifier/sleep.rs +43 -33
  165. package/rust/core/parser/handler/identifier/spawn.rs +91 -41
  166. package/rust/core/parser/handler/identifier/synth.rs +135 -65
  167. package/rust/core/parser/handler/loop_.rs +194 -72
  168. package/rust/core/parser/handler/mod.rs +9 -8
  169. package/rust/core/parser/handler/pattern.rs +74 -0
  170. package/rust/core/parser/handler/tempo.rs +57 -47
  171. package/rust/core/parser/mod.rs +3 -4
  172. package/rust/core/parser/statement.rs +11 -96
  173. package/rust/core/plugin/loader.rs +137 -0
  174. package/rust/core/plugin/mod.rs +2 -0
  175. package/rust/core/plugin/runner.rs +347 -0
  176. package/rust/core/preprocessor/loader.rs +637 -193
  177. package/rust/core/preprocessor/mod.rs +4 -4
  178. package/rust/core/preprocessor/module.rs +60 -50
  179. package/rust/core/preprocessor/processor.rs +114 -76
  180. package/rust/core/preprocessor/resolver/bank.rs +49 -47
  181. package/rust/core/preprocessor/resolver/call.rs +124 -123
  182. package/rust/core/preprocessor/resolver/condition.rs +95 -92
  183. package/rust/core/preprocessor/resolver/driver.rs +324 -227
  184. package/rust/core/preprocessor/resolver/function.rs +69 -0
  185. package/rust/core/preprocessor/resolver/group.rs +94 -61
  186. package/rust/core/preprocessor/resolver/let_.rs +32 -31
  187. package/rust/core/preprocessor/resolver/loop_.rs +318 -91
  188. package/rust/core/preprocessor/resolver/mod.rs +16 -14
  189. package/rust/core/preprocessor/resolver/pattern.rs +83 -0
  190. package/rust/core/preprocessor/resolver/spawn.rs +99 -58
  191. package/rust/core/preprocessor/resolver/synth.rs +54 -50
  192. package/rust/core/preprocessor/resolver/tempo.rs +48 -49
  193. package/rust/core/preprocessor/resolver/trigger.rs +116 -112
  194. package/rust/core/preprocessor/resolver/value.rs +176 -78
  195. package/rust/core/store/export.rs +28 -28
  196. package/rust/core/store/function.rs +40 -0
  197. package/rust/core/store/global.rs +61 -39
  198. package/rust/core/store/import.rs +28 -28
  199. package/rust/core/store/mod.rs +5 -4
  200. package/rust/core/store/variable.rs +51 -28
  201. package/rust/core/utils/mod.rs +1 -2
  202. package/rust/core/utils/path.rs +37 -31
  203. package/rust/lib.rs +308 -117
  204. package/rust/main.rs +364 -65
  205. package/rust/types/Cargo.toml +11 -0
  206. package/rust/types/src/addons.rs +55 -0
  207. package/rust/types/src/ast.rs +202 -0
  208. package/rust/types/src/config.rs +74 -0
  209. package/rust/types/src/lib.rs +12 -0
  210. package/rust/types/src/telemetry.rs +85 -0
  211. package/rust/utils/Cargo.toml +26 -0
  212. package/rust/utils/src/error.rs +186 -0
  213. package/rust/utils/src/file.rs +94 -0
  214. package/rust/utils/src/first_usage.rs +97 -0
  215. package/rust/utils/{mod.rs → src/lib.rs} +9 -6
  216. package/rust/utils/{logger.rs → src/logger.rs} +200 -123
  217. package/rust/utils/src/path.rs +88 -0
  218. package/rust/utils/src/signature.rs +41 -0
  219. package/rust/utils/{spinner.rs → src/spinner.rs} +20 -21
  220. package/rust/utils/src/version.rs +27 -0
  221. package/rust/utils/{watcher.rs → src/watcher.rs} +46 -33
  222. package/rust/web/api.rs +5 -0
  223. package/rust/web/cdn.rs +34 -0
  224. package/rust/web/mod.rs +3 -0
  225. package/rust/web/sso.rs +5 -0
  226. package/templates/minimal/README.md +143 -127
  227. package/templates/welcome/README.md +143 -127
  228. package/templates/welcome/src/index.deva +56 -8
  229. package/templates/welcome/src/variables.deva +2 -4
  230. package/tests/integration.rs +21 -0
  231. package/tests/rust/cli_check_build.rs +21 -0
  232. package/tests/rust/cli_help.rs +12 -0
  233. package/tests/rust/cli_template_list.rs +10 -0
  234. package/tests/rust/cli_version.rs +11 -0
  235. package/tests/typescript/index.spec.ts +136 -0
  236. package/tests/typescript/playhead.spec.ts +36 -0
  237. package/tests/typescript/render_e2e.spec.ts +77 -0
  238. package/tsconfig.json +12 -10
  239. package/typescript/bin/index.ts +19 -5
  240. package/typescript/core/functions/index.ts +83 -0
  241. package/typescript/core/index.ts +6 -0
  242. package/typescript/core/types/index.ts +4 -0
  243. package/typescript/core/types/plugin.ts +19 -0
  244. package/typescript/core/types/result.ts +29 -0
  245. package/typescript/core/types/statement.ts +47 -0
  246. package/typescript/core/types/value.ts +29 -0
  247. package/typescript/index.ts +8 -1
  248. package/typescript/pkg/devalang_core.d.ts +4 -0
  249. package/typescript/pkg/devalang_core.ts +49 -0
  250. package/typescript/scripts/copy-wasm-dts.ts +41 -0
  251. package/typescript/scripts/postinstall.ts +85 -0
  252. package/typescript/scripts/version/bump.ts +0 -1
  253. package/typescript/scripts/version/index.ts +0 -1
  254. package/docs/COMMANDS.md +0 -85
  255. package/docs/CONFIG.md +0 -30
  256. package/docs/SYNTAX.md +0 -210
  257. package/out-tsc/bin/devalang.exe +0 -0
  258. package/out-tsc/scripts/postbuild.js +0 -11
  259. package/rust/cli/build.rs +0 -137
  260. package/rust/cli/check.rs +0 -117
  261. package/rust/cli/play.rs +0 -193
  262. package/rust/config/loader.rs +0 -13
  263. package/rust/core/audio/engine.rs +0 -203
  264. package/rust/core/shared/duration.rs +0 -8
  265. package/rust/core/shared/mod.rs +0 -2
  266. package/rust/core/shared/value.rs +0 -18
  267. package/rust/core/utils/validation.rs +0 -37
  268. package/rust/utils/file.rs +0 -35
  269. package/rust/utils/signature.rs +0 -17
  270. package/rust/utils/version.rs +0 -15
  271. package/typescript/scripts/postbuild.ts +0 -8
@@ -1,162 +1,279 @@
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 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
+ pub fn parse_at_token(parser: &mut Parser, _global_store: &mut GlobalStore) -> Statement {
12
+ parser.advance(); // consume '@'
13
+
14
+ let Some(token) = parser.peek_clone() else {
15
+ return Statement::unknown();
16
+ };
17
+
18
+ let keyword = token.lexeme.as_str();
19
+
20
+ match keyword {
21
+ "use" => {
22
+ parser.advance(); // consume 'use'
23
+ let Some(use_token) = parser.previous_clone() else {
24
+ return Statement::unknown();
25
+ };
26
+
27
+ // Expect plugin author
28
+ let Some(author_token) = parser.peek_clone() else {
29
+ return crate::core::parser::statement::error_from_token(
30
+ use_token,
31
+ "Expected plugin author".to_string(),
32
+ );
33
+ };
34
+ if author_token.kind != TokenKind::Identifier {
35
+ return crate::core::parser::statement::error_from_token(
36
+ author_token,
37
+ "Expected identifier for plugin author".to_string(),
38
+ );
39
+ }
40
+ parser.advance(); // consume author
41
+
42
+ // Expect '.'
43
+ if !parser.match_token(TokenKind::Dot) {
44
+ return crate::core::parser::statement::error_from_token(
45
+ author_token,
46
+ "Expected '.' after plugin author".to_string(),
47
+ );
48
+ }
49
+
50
+ // Expect plugin name
51
+ let Some(plugin_token) = parser.peek_clone() else {
52
+ return crate::core::parser::statement::error_from_token(
53
+ author_token,
54
+ "Expected plugin name".to_string(),
55
+ );
56
+ };
57
+
58
+ let name = match plugin_token.kind {
59
+ TokenKind::Identifier | TokenKind::Number => {
60
+ parser.advance();
61
+ format!("{}.{}", author_token.lexeme, plugin_token.lexeme)
62
+ }
63
+ _ => {
64
+ return crate::core::parser::statement::error_from_token(
65
+ plugin_token,
66
+ "Expected identifier or number for plugin name".to_string(),
67
+ );
68
+ }
69
+ };
70
+
71
+ // Optional alias
72
+ let alias = if parser.match_token(TokenKind::As) {
73
+ let Some(alias_token) = parser.peek_clone() else {
74
+ return crate::core::parser::statement::error_from_token(
75
+ use_token,
76
+ "Expected identifier after 'as'".to_string(),
77
+ );
78
+ };
79
+ if alias_token.kind != TokenKind::Identifier {
80
+ return crate::core::parser::statement::error_from_token(
81
+ alias_token,
82
+ "Expected identifier after 'as'".to_string(),
83
+ );
84
+ }
85
+ parser.advance();
86
+ Some(alias_token.lexeme.clone())
87
+ } else {
88
+ None
89
+ };
90
+
91
+ Statement {
92
+ kind: StatementKind::Use {
93
+ name: name.clone(),
94
+ alias,
95
+ },
96
+ value: Value::Null,
97
+ indent: use_token.indent,
98
+ line: use_token.line,
99
+ column: use_token.column,
100
+ }
101
+ }
102
+
103
+ "import" => {
104
+ parser.advance(); // consume 'import'
105
+
106
+ if !parser.match_token(TokenKind::LBrace) {
107
+ return crate::core::parser::statement::error_from_token(
108
+ token,
109
+ "Expected '{{' after 'import'".to_string(),
110
+ );
111
+ }
112
+
113
+ let mut names = Vec::new();
114
+ while let Some(token) = parser.peek() {
115
+ match &token.kind {
116
+ TokenKind::Identifier => {
117
+ names.push(token.lexeme.clone());
118
+ parser.advance();
119
+ }
120
+ TokenKind::Comma => {
121
+ parser.advance();
122
+ }
123
+ TokenKind::RBrace => {
124
+ parser.advance();
125
+ break;
126
+ }
127
+ _ => {
128
+ let message =
129
+ format!("Unexpected token in import list: {:?}", token.kind.clone());
130
+ return crate::core::parser::statement::error_from_token(
131
+ token.clone(),
132
+ message,
133
+ );
134
+ }
135
+ }
136
+ }
137
+
138
+ let Some(from_token) = parser.peek_clone() else {
139
+ return crate::core::parser::statement::error_from_token(
140
+ token,
141
+ "Expected 'from' after import list".to_string(),
142
+ );
143
+ };
144
+
145
+ if from_token.lexeme != "from" {
146
+ return crate::core::parser::statement::error_from_token(
147
+ token,
148
+ "Expected keyword 'from'".to_string(),
149
+ );
150
+ }
151
+
152
+ parser.advance(); // consume 'from'
153
+
154
+ let Some(source_token) = parser.peek() else {
155
+ return crate::core::parser::statement::error_from_token(
156
+ token,
157
+ "Expected string after 'from'".to_string(),
158
+ );
159
+ };
160
+
161
+ if source_token.kind != TokenKind::String {
162
+ return crate::core::parser::statement::error_from_token(
163
+ token,
164
+ "Expected string after 'from'".to_string(),
165
+ );
166
+ }
167
+
168
+ let source = source_token.lexeme.clone();
169
+ parser.advance(); // consume string
170
+
171
+ Statement {
172
+ kind: StatementKind::Import { names, source },
173
+ value: Value::Null,
174
+ indent: token.indent,
175
+ line: token.line,
176
+ column: token.column,
177
+ }
178
+ }
179
+
180
+ "export" => {
181
+ parser.advance(); // consume 'export'
182
+
183
+ parser.advance(); // consume '{'
184
+
185
+ let names_tokens = parser.collect_until(|t| TokenKind::RBrace == t.kind);
186
+ let mut names: Vec<String> = Vec::new();
187
+
188
+ for token in names_tokens {
189
+ if token.kind == TokenKind::Identifier {
190
+ names.push(token.lexeme.clone());
191
+ } else if token.kind == TokenKind::Comma {
192
+ continue; // Ignore commas
193
+ } else if token.kind == TokenKind::RBrace {
194
+ break; // Stop at the closing brace
195
+ } else {
196
+ return crate::core::parser::statement::error_from_token(
197
+ token,
198
+ "Unexpected token in export list".to_string(),
199
+ );
200
+ }
201
+ }
202
+
203
+ Statement {
204
+ kind: StatementKind::Export {
205
+ names: names.clone(),
206
+ source: parser.current_module.clone(),
207
+ },
208
+ value: Value::Null,
209
+ indent: token.indent,
210
+ line: token.line,
211
+ column: token.column,
212
+ }
213
+ }
214
+
215
+ "load" => {
216
+ parser.advance(); // consume 'load'
217
+
218
+ // Example: @load "preset.mydeva"
219
+ let Some(path_token) = parser.peek() else {
220
+ return crate::core::parser::statement::error_from_token(
221
+ token,
222
+ "Expected string after 'load'".to_string(),
223
+ );
224
+ };
225
+
226
+ if path_token.kind != TokenKind::String {
227
+ return crate::core::parser::statement::error_from_token(
228
+ token,
229
+ "Expected string after 'load'".to_string(),
230
+ );
231
+ }
232
+
233
+ let path = path_token.lexeme.clone();
234
+
235
+ parser.advance(); // consume string
236
+
237
+ if !parser.match_token(TokenKind::As) {
238
+ return crate::core::parser::statement::error_from_token(
239
+ token,
240
+ "Expected 'as' after path in load statement".to_string(),
241
+ );
242
+ }
243
+
244
+ let Some(alias_token) = parser.peek_clone() else {
245
+ return crate::core::parser::statement::error_from_token(
246
+ token,
247
+ "Expected identifier after 'as' in load statement".to_string(),
248
+ );
249
+ };
250
+
251
+ if alias_token.kind != TokenKind::Identifier {
252
+ return crate::core::parser::statement::error_from_token(
253
+ token,
254
+ "Expected identifier after 'as' in load statement".to_string(),
255
+ );
256
+ }
257
+
258
+ let alias = alias_token.lexeme.clone();
259
+
260
+ parser.advance(); // consume identifier
261
+
262
+ Statement {
263
+ kind: StatementKind::Load {
264
+ source: path,
265
+ alias,
266
+ },
267
+ value: Value::Null,
268
+ indent: token.indent,
269
+ line: token.line,
270
+ column: token.column,
271
+ }
272
+ }
273
+
274
+ _ => {
275
+ let message = format!("Unknown keyword after '@' : {}", keyword);
276
+ crate::core::parser::statement::error_from_token(token, message)
277
+ }
278
+ }
279
+ }
@@ -1,41 +1,104 @@
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 => {
18
- parser.advance();
19
- Value::Identifier(token.lexeme.clone())
20
- }
21
- TokenKind::Number => {
22
- parser.advance();
23
- Value::Number(token.lexeme.parse::<f32>().unwrap_or(0.0))
24
- }
25
- _ => Value::Unknown,
26
- }
27
- } else {
28
- return Statement::error(
29
- bank_token,
30
- "Expected identifier or number after 'bank'".to_string()
31
- );
32
- };
33
-
34
- Statement {
35
- kind: StatementKind::Bank,
36
- value: bank_value,
37
- indent: bank_token.indent,
38
- line: bank_token.line,
39
- column: bank_token.column,
40
- }
41
- }
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_bank_token(parser: &mut Parser, _global_store: &mut GlobalStore) -> Statement {
13
+ // consume 'bank'
14
+ parser.advance();
15
+
16
+ let Some(bank_tok) = parser.previous_clone() else {
17
+ return Statement::unknown();
18
+ };
19
+
20
+ // Parse bank name
21
+ let bank_value: Value = match parser.peek_clone() {
22
+ Some(tok) => match tok.kind {
23
+ TokenKind::Identifier | TokenKind::Number => {
24
+ // base name
25
+ parser.advance();
26
+ let mut base = tok.lexeme.clone();
27
+ // optional .suffix (identifier or number)
28
+ if let Some(dot) = parser.peek_clone() {
29
+ if dot.kind == TokenKind::Dot {
30
+ // consume '.' and the following ident/number
31
+ parser.advance();
32
+ if let Some(suffix) = parser.peek_clone() {
33
+ match suffix.kind {
34
+ TokenKind::Identifier | TokenKind::Number => {
35
+ parser.advance();
36
+ base.push('.');
37
+ base.push_str(&suffix.lexeme);
38
+ Value::String(base)
39
+ }
40
+ _ => Value::Identifier(base),
41
+ }
42
+ } else {
43
+ Value::Identifier(base)
44
+ }
45
+ } else {
46
+ match tok.kind {
47
+ TokenKind::Identifier => Value::String(base),
48
+ TokenKind::Number => Value::Number(base.parse::<f32>().unwrap_or(0.0)),
49
+ _ => Value::Unknown,
50
+ }
51
+ }
52
+ } else {
53
+ match tok.kind {
54
+ TokenKind::Identifier => Value::String(base),
55
+ TokenKind::Number => Value::Number(base.parse::<f32>().unwrap_or(0.0)),
56
+ _ => Value::Unknown,
57
+ }
58
+ }
59
+ }
60
+ TokenKind::String => {
61
+ parser.advance();
62
+ Value::String(tok.lexeme.clone())
63
+ }
64
+ _ => Value::Unknown,
65
+ },
66
+ None => Value::Unknown,
67
+ };
68
+
69
+ if matches!(bank_value, Value::Unknown | Value::Null) {
70
+ return crate::core::parser::statement::error_from_token(
71
+ bank_tok,
72
+ "Expected a bank name".to_string(),
73
+ );
74
+ }
75
+
76
+ // Optional alias: as <identifier>
77
+ let mut alias: Option<String> = None;
78
+ if parser.peek_is("as") {
79
+ // consume 'as'
80
+ parser.advance();
81
+ let Some(next) = parser.peek_clone() else {
82
+ return crate::core::parser::statement::error_from_token(
83
+ bank_tok,
84
+ "Expected identifier after 'as'".to_string(),
85
+ );
86
+ };
87
+ if next.kind != TokenKind::Identifier {
88
+ return crate::core::parser::statement::error_from_token(
89
+ next,
90
+ "Expected identifier after 'as'".to_string(),
91
+ );
92
+ }
93
+ parser.advance();
94
+ alias = Some(next.lexeme.clone());
95
+ }
96
+
97
+ Statement {
98
+ kind: StatementKind::Bank { alias },
99
+ value: bank_value,
100
+ indent: bank_tok.indent,
101
+ line: bank_tok.line,
102
+ column: bank_tok.column,
103
+ }
104
+ }