@devaloop/devalang 0.0.1-alpha.9 → 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.
Files changed (322) hide show
  1. package/.cargo/config.toml +2 -0
  2. package/.devalang +6 -1
  3. package/.github/workflows/ci.yml +103 -0
  4. package/Cargo.toml +81 -48
  5. package/README.md +137 -154
  6. package/docs/CHANGELOG.md +428 -1
  7. package/docs/CONTRIBUTING.md +101 -0
  8. package/docs/ROADMAP.md +14 -7
  9. package/docs/TODO.md +16 -15
  10. package/examples/automation.deva +42 -0
  11. package/examples/bank.deva +7 -0
  12. package/examples/bus.deva +10 -0
  13. package/examples/duration.deva +9 -0
  14. package/examples/effect.deva +2 -0
  15. package/examples/events.deva +12 -0
  16. package/examples/filter.deva +11 -0
  17. package/examples/function.deva +15 -0
  18. package/examples/index.deva +57 -12
  19. package/examples/lfo.deva +9 -0
  20. package/examples/loop.deva +5 -12
  21. package/examples/pattern.deva +8 -0
  22. package/examples/plugin.deva +16 -0
  23. package/examples/synth.deva +11 -1
  24. package/examples/synth_types.deva +17 -0
  25. package/examples/variables.deva +1 -1
  26. package/out-tsc/bin/index.d.ts +2 -0
  27. package/out-tsc/bin/index.js +51 -7
  28. package/out-tsc/core/functions/index.d.ts +42 -0
  29. package/out-tsc/core/functions/index.js +87 -0
  30. package/out-tsc/core/index.d.ts +6 -0
  31. package/out-tsc/core/index.js +22 -0
  32. package/out-tsc/core/types/index.d.ts +4 -0
  33. package/out-tsc/core/types/index.js +20 -0
  34. package/out-tsc/core/types/plugin.d.ts +18 -0
  35. package/out-tsc/core/types/plugin.js +2 -0
  36. package/out-tsc/core/types/result.d.ts +27 -0
  37. package/out-tsc/core/types/result.js +2 -0
  38. package/out-tsc/core/types/statement.d.ts +106 -0
  39. package/out-tsc/core/types/statement.js +2 -0
  40. package/out-tsc/core/types/value.d.ts +43 -0
  41. package/out-tsc/core/types/value.js +2 -0
  42. package/out-tsc/index.d.ts +7 -0
  43. package/out-tsc/index.js +42 -1
  44. package/out-tsc/pkg/devalang_core.d.ts +15 -0
  45. package/out-tsc/pkg/devalang_core.js +65 -0
  46. package/out-tsc/pkg/devalang_core_bg.wasm.d.ts +34 -0
  47. package/out-tsc/scripts/copy-wasm-dts.d.ts +1 -0
  48. package/out-tsc/scripts/copy-wasm-dts.js +73 -0
  49. package/out-tsc/scripts/postinstall.d.ts +1 -0
  50. package/out-tsc/scripts/postinstall.js +83 -0
  51. package/out-tsc/scripts/version/bump.d.ts +1 -0
  52. package/out-tsc/scripts/version/fetch.d.ts +1 -0
  53. package/out-tsc/scripts/version/index.d.ts +1 -0
  54. package/out-tsc/scripts/version/sync.d.ts +1 -0
  55. package/package.json +28 -7
  56. package/project-version.json +4 -4
  57. package/rust/cli/bank/api.rs +122 -0
  58. package/rust/cli/bank/commands.rs +306 -0
  59. package/rust/cli/bank/mod.rs +29 -0
  60. package/rust/cli/build/commands.rs +153 -0
  61. package/rust/cli/build/mod.rs +2 -0
  62. package/rust/cli/build/process.rs +165 -0
  63. package/rust/cli/check/mod.rs +208 -0
  64. package/rust/cli/discover/commands.rs +253 -0
  65. package/rust/cli/discover/config.rs +111 -0
  66. package/rust/cli/discover/fs.rs +19 -0
  67. package/rust/cli/discover/install.rs +103 -0
  68. package/rust/cli/discover/metadata.rs +48 -0
  69. package/rust/cli/discover/mod.rs +5 -0
  70. package/rust/cli/{init.rs → init/commands.rs} +32 -23
  71. package/rust/cli/init/mod.rs +1 -0
  72. package/rust/cli/install/addon.rs +118 -0
  73. package/rust/cli/install/bank.rs +72 -0
  74. package/rust/cli/install/commands.rs +35 -0
  75. package/rust/cli/install/mod.rs +4 -0
  76. package/rust/cli/install/plugin.rs +80 -0
  77. package/rust/cli/login/commands.rs +124 -0
  78. package/rust/cli/login/mod.rs +1 -0
  79. package/rust/cli/mod.rs +9 -202
  80. package/rust/cli/parser.rs +359 -0
  81. package/rust/cli/play/commands.rs +375 -0
  82. package/rust/cli/play/io.rs +17 -0
  83. package/rust/cli/play/mod.rs +5 -0
  84. package/rust/cli/play/process.rs +159 -0
  85. package/rust/cli/play/realtime.rs +91 -0
  86. package/rust/cli/play/utils.rs +23 -0
  87. package/rust/cli/telemetry/commands.rs +22 -0
  88. package/rust/cli/telemetry/event_creator.rs +80 -0
  89. package/rust/cli/telemetry/mod.rs +3 -0
  90. package/rust/cli/telemetry/send.rs +51 -0
  91. package/rust/cli/{template.rs → template/commands.rs} +17 -5
  92. package/rust/cli/template/mod.rs +1 -0
  93. package/rust/cli/update/commands.rs +6 -0
  94. package/rust/cli/update/mod.rs +1 -0
  95. package/rust/config/driver.rs +112 -0
  96. package/rust/config/mod.rs +3 -16
  97. package/rust/config/ops.rs +26 -0
  98. package/rust/config/settings.rs +101 -0
  99. package/rust/core/audio/engine/driver.rs +220 -0
  100. package/rust/core/audio/engine/export.rs +169 -0
  101. package/rust/core/audio/engine/helpers.rs +178 -0
  102. package/rust/core/audio/engine/mod.rs +56 -0
  103. package/rust/core/audio/engine/notes/dsp.rs +85 -0
  104. package/rust/core/audio/engine/notes/mod.rs +44 -0
  105. package/rust/core/audio/engine/notes/params.rs +294 -0
  106. package/rust/core/audio/engine/sample/insert.rs +199 -0
  107. package/rust/core/audio/engine/sample/mod.rs +40 -0
  108. package/rust/core/audio/engine/sample/padding.rs +170 -0
  109. package/rust/core/audio/evaluator/condition.rs +61 -0
  110. package/rust/core/audio/evaluator/mod.rs +9 -0
  111. package/rust/core/audio/evaluator/numeric.rs +152 -0
  112. package/rust/core/audio/evaluator/rhs.rs +16 -0
  113. package/rust/core/audio/evaluator/string_expr.rs +94 -0
  114. package/rust/core/audio/interpreter/driver.rs +574 -216
  115. package/rust/core/audio/interpreter/mod.rs +2 -12
  116. package/rust/core/audio/interpreter/statements/arrow_call/interprete.rs +175 -0
  117. package/rust/core/audio/interpreter/statements/arrow_call/methods/chord.rs +384 -0
  118. package/rust/core/audio/interpreter/statements/arrow_call/methods/mod.rs +2 -0
  119. package/rust/core/audio/interpreter/statements/arrow_call/methods/note.rs +316 -0
  120. package/rust/core/audio/interpreter/statements/arrow_call/mod.rs +3 -0
  121. package/rust/core/audio/interpreter/statements/arrow_call/types/arp.rs +192 -0
  122. package/rust/core/audio/interpreter/statements/arrow_call/types/mod.rs +24 -0
  123. package/rust/core/audio/interpreter/statements/arrow_call/types/pad.rs +116 -0
  124. package/rust/core/audio/interpreter/statements/arrow_call/types/pluck.rs +97 -0
  125. package/rust/core/audio/interpreter/statements/arrow_call/types/sub.rs +100 -0
  126. package/rust/core/audio/interpreter/statements/automate.rs +16 -0
  127. package/rust/core/audio/interpreter/statements/call.rs +295 -0
  128. package/rust/core/audio/interpreter/{condition.rs → statements/condition.rs} +72 -69
  129. package/rust/core/audio/interpreter/statements/function.rs +24 -0
  130. package/rust/core/audio/interpreter/statements/let_.rs +36 -0
  131. package/rust/core/audio/interpreter/statements/load.rs +17 -0
  132. package/rust/core/audio/interpreter/statements/loop_.rs +115 -0
  133. package/rust/core/audio/interpreter/statements/mod.rs +12 -0
  134. package/rust/core/audio/interpreter/statements/sleep.rs +28 -0
  135. package/rust/core/audio/interpreter/statements/spawn.rs +253 -0
  136. package/rust/core/audio/interpreter/statements/tempo.rs +40 -0
  137. package/rust/core/audio/interpreter/statements/trigger.rs +239 -0
  138. package/rust/core/audio/loader/mod.rs +1 -1
  139. package/rust/core/audio/loader/trigger.rs +98 -52
  140. package/rust/core/audio/mod.rs +2 -2
  141. package/rust/core/audio/player.rs +28 -12
  142. package/rust/core/audio/special/easing.rs +189 -0
  143. package/rust/core/audio/special/env.rs +45 -0
  144. package/rust/core/audio/special/math.rs +134 -0
  145. package/rust/core/audio/special/mod.rs +9 -0
  146. package/rust/core/audio/special/modulator.rs +143 -0
  147. package/rust/core/builder/mod.rs +129 -80
  148. package/rust/core/debugger/lexer.rs +4 -4
  149. package/rust/core/debugger/logs.rs +52 -0
  150. package/rust/core/debugger/mod.rs +11 -2
  151. package/rust/core/debugger/preprocessor.rs +4 -4
  152. package/rust/core/debugger/store.rs +38 -25
  153. package/rust/core/error/mod.rs +221 -12
  154. package/rust/core/lexer/driver.rs +59 -0
  155. package/rust/core/lexer/handler/arrow.rs +62 -11
  156. package/rust/core/lexer/handler/at.rs +5 -5
  157. package/rust/core/lexer/handler/brace.rs +11 -11
  158. package/rust/core/lexer/handler/colon.rs +5 -5
  159. package/rust/core/lexer/handler/comment.rs +3 -3
  160. package/rust/core/lexer/handler/dot.rs +6 -6
  161. package/rust/core/lexer/handler/driver.rs +143 -32
  162. package/rust/core/lexer/handler/identifier.rs +11 -5
  163. package/rust/core/lexer/handler/indent.rs +18 -4
  164. package/rust/core/lexer/handler/mod.rs +6 -5
  165. package/rust/core/lexer/handler/newline.rs +3 -3
  166. package/rust/core/lexer/handler/number.rs +5 -5
  167. package/rust/core/lexer/handler/operator.rs +5 -3
  168. package/rust/core/lexer/handler/parenthesis.rs +41 -0
  169. package/rust/core/lexer/handler/slash.rs +21 -0
  170. package/rust/core/lexer/handler/string.rs +3 -3
  171. package/rust/core/lexer/mod.rs +1 -49
  172. package/rust/core/lexer/token.rs +17 -12
  173. package/rust/core/mod.rs +9 -10
  174. package/rust/core/parser/driver/block.rs +111 -0
  175. package/rust/core/parser/driver/cursor.rs +82 -0
  176. package/rust/core/parser/driver/driver_impl.rs +139 -0
  177. package/rust/core/parser/driver/mod.rs +6 -0
  178. package/rust/core/parser/driver/parse_array.rs +120 -0
  179. package/rust/core/parser/driver/parse_map.rs +223 -0
  180. package/rust/core/parser/driver/parser.rs +160 -0
  181. package/rust/core/parser/handler/arrow_call.rs +277 -126
  182. package/rust/core/parser/handler/at.rs +142 -25
  183. package/rust/core/parser/handler/bank.rs +83 -20
  184. package/rust/core/parser/handler/condition.rs +14 -5
  185. package/rust/core/parser/handler/dot.rs +111 -75
  186. package/rust/core/parser/handler/identifier/automate.rs +254 -0
  187. package/rust/core/parser/handler/identifier/call.rs +74 -24
  188. package/rust/core/parser/handler/identifier/emit.rs +70 -0
  189. package/rust/core/parser/handler/identifier/function.rs +113 -0
  190. package/rust/core/parser/handler/identifier/group.rs +28 -14
  191. package/rust/core/parser/handler/identifier/let_.rs +61 -21
  192. package/rust/core/parser/handler/identifier/mod.rs +24 -20
  193. package/rust/core/parser/handler/identifier/on.rs +107 -0
  194. package/rust/core/parser/handler/identifier/print.rs +49 -0
  195. package/rust/core/parser/handler/identifier/sleep.rs +77 -14
  196. package/rust/core/parser/handler/identifier/spawn.rs +81 -31
  197. package/rust/core/parser/handler/identifier/synth.rs +102 -32
  198. package/rust/core/parser/handler/loop_.rs +144 -22
  199. package/rust/core/parser/handler/mod.rs +6 -5
  200. package/rust/core/parser/handler/pattern.rs +74 -0
  201. package/rust/core/parser/handler/tempo.rs +67 -9
  202. package/rust/core/parser/mod.rs +3 -4
  203. package/rust/core/parser/statement.rs +6 -92
  204. package/rust/core/plugin/loader.rs +137 -0
  205. package/rust/core/plugin/mod.rs +2 -0
  206. package/rust/core/plugin/runner/mod.rs +11 -0
  207. package/rust/core/plugin/runner/non_wasm.rs +297 -0
  208. package/rust/core/plugin/runner/wasm32.rs +43 -0
  209. package/rust/core/preprocessor/loader/inject.rs +278 -0
  210. package/rust/core/preprocessor/loader/loader_helpers.rs +110 -0
  211. package/rust/core/preprocessor/loader/mod.rs +235 -0
  212. package/rust/core/preprocessor/mod.rs +4 -4
  213. package/rust/core/preprocessor/module.rs +55 -50
  214. package/rust/core/preprocessor/processor/handlers.rs +107 -0
  215. package/rust/core/preprocessor/processor/mod.rs +1 -0
  216. package/rust/core/preprocessor/resolver/bank.rs +14 -12
  217. package/rust/core/preprocessor/resolver/call.rs +106 -105
  218. package/rust/core/preprocessor/resolver/condition.rs +13 -10
  219. package/rust/core/preprocessor/resolver/driver.rs +145 -48
  220. package/rust/core/preprocessor/resolver/function.rs +69 -0
  221. package/rust/core/preprocessor/resolver/group.rs +122 -61
  222. package/rust/core/preprocessor/resolver/let_.rs +13 -12
  223. package/rust/core/preprocessor/resolver/loop_.rs +240 -13
  224. package/rust/core/preprocessor/resolver/mod.rs +8 -6
  225. package/rust/core/preprocessor/resolver/pattern.rs +83 -0
  226. package/rust/core/preprocessor/resolver/spawn.rs +83 -42
  227. package/rust/core/preprocessor/resolver/synth.rs +15 -11
  228. package/rust/core/preprocessor/resolver/tempo.rs +13 -14
  229. package/rust/core/preprocessor/resolver/trigger.rs +32 -28
  230. package/rust/core/preprocessor/resolver/value.rs +111 -13
  231. package/rust/core/store/global.rs +57 -39
  232. package/rust/core/store/mod.rs +0 -3
  233. package/rust/lib.rs +323 -117
  234. package/rust/main.rs +388 -65
  235. package/rust/types/Cargo.toml +11 -0
  236. package/rust/types/src/addons.rs +55 -0
  237. package/rust/types/src/ast.rs +202 -0
  238. package/rust/types/src/config.rs +84 -0
  239. package/rust/types/src/lib.rs +15 -0
  240. package/rust/types/src/plugin.rs +20 -0
  241. package/rust/types/src/store.rs +139 -0
  242. package/rust/types/src/telemetry.rs +85 -0
  243. package/rust/utils/Cargo.toml +26 -0
  244. package/rust/utils/src/error.rs +186 -0
  245. package/rust/utils/src/file.rs +94 -0
  246. package/rust/utils/src/first_usage.rs +97 -0
  247. package/rust/utils/{mod.rs → src/lib.rs} +6 -3
  248. package/rust/utils/{logger.rs → src/logger.rs} +94 -17
  249. package/rust/utils/src/path.rs +129 -0
  250. package/rust/utils/src/signature.rs +41 -0
  251. package/rust/utils/{spinner.rs → src/spinner.rs} +7 -8
  252. package/rust/utils/src/version.rs +27 -0
  253. package/rust/utils/{watcher.rs → src/watcher.rs} +17 -4
  254. package/rust/web/api.rs +5 -0
  255. package/rust/web/cdn.rs +34 -0
  256. package/rust/web/mod.rs +3 -0
  257. package/rust/web/sso.rs +5 -0
  258. package/templates/minimal/README.md +143 -127
  259. package/templates/welcome/README.md +143 -127
  260. package/templates/welcome/src/index.deva +56 -8
  261. package/templates/welcome/src/variables.deva +2 -4
  262. package/tests/integration.rs +21 -0
  263. package/tests/rust/cli_check_build.rs +21 -0
  264. package/tests/rust/cli_help.rs +12 -0
  265. package/tests/rust/cli_template_list.rs +10 -0
  266. package/tests/rust/cli_version.rs +11 -0
  267. package/tests/typescript/index.spec.ts +136 -0
  268. package/tests/typescript/playhead.spec.ts +36 -0
  269. package/tests/typescript/render_e2e.spec.ts +77 -0
  270. package/tsconfig.json +12 -10
  271. package/typescript/bin/index.ts +19 -5
  272. package/typescript/core/functions/index.ts +94 -0
  273. package/typescript/core/index.ts +6 -0
  274. package/typescript/core/types/index.ts +4 -0
  275. package/typescript/core/types/plugin.ts +19 -0
  276. package/typescript/core/types/result.ts +29 -0
  277. package/typescript/core/types/statement.ts +47 -0
  278. package/typescript/core/types/value.ts +29 -0
  279. package/typescript/index.ts +8 -1
  280. package/typescript/pkg/devalang_core.d.ts +4 -0
  281. package/typescript/pkg/devalang_core.ts +65 -0
  282. package/typescript/scripts/copy-wasm-dts.ts +41 -0
  283. package/typescript/scripts/postinstall.ts +85 -0
  284. package/typescript/scripts/version/bump.ts +0 -1
  285. package/typescript/scripts/version/index.ts +0 -1
  286. package/docs/COMMANDS.md +0 -85
  287. package/docs/CONFIG.md +0 -30
  288. package/docs/SYNTAX.md +0 -210
  289. package/out-tsc/bin/devalang.exe +0 -0
  290. package/out-tsc/scripts/postbuild.js +0 -11
  291. package/rust/cli/build.rs +0 -137
  292. package/rust/cli/check.rs +0 -117
  293. package/rust/cli/play.rs +0 -193
  294. package/rust/config/loader.rs +0 -13
  295. package/rust/core/audio/engine.rs +0 -203
  296. package/rust/core/audio/evaluator.rs +0 -31
  297. package/rust/core/audio/interpreter/arrow_call.rs +0 -129
  298. package/rust/core/audio/interpreter/call.rs +0 -64
  299. package/rust/core/audio/interpreter/let_.rs +0 -19
  300. package/rust/core/audio/interpreter/load.rs +0 -18
  301. package/rust/core/audio/interpreter/loop_.rs +0 -67
  302. package/rust/core/audio/interpreter/sleep.rs +0 -36
  303. package/rust/core/audio/interpreter/spawn.rs +0 -66
  304. package/rust/core/audio/interpreter/tempo.rs +0 -16
  305. package/rust/core/audio/interpreter/trigger.rs +0 -69
  306. package/rust/core/audio/renderer.rs +0 -54
  307. package/rust/core/parser/driver.rs +0 -331
  308. package/rust/core/preprocessor/loader.rs +0 -193
  309. package/rust/core/preprocessor/processor.rs +0 -76
  310. package/rust/core/shared/duration.rs +0 -8
  311. package/rust/core/shared/mod.rs +0 -2
  312. package/rust/core/shared/value.rs +0 -18
  313. package/rust/core/store/export.rs +0 -28
  314. package/rust/core/store/import.rs +0 -28
  315. package/rust/core/store/variable.rs +0 -28
  316. package/rust/core/utils/mod.rs +0 -2
  317. package/rust/core/utils/path.rs +0 -31
  318. package/rust/core/utils/validation.rs +0 -37
  319. package/rust/utils/file.rs +0 -35
  320. package/rust/utils/signature.rs +0 -17
  321. package/rust/utils/version.rs +0 -15
  322. package/typescript/scripts/postbuild.ts +0 -8
@@ -0,0 +1,160 @@
1
+ use crate::core::{
2
+ lexer::token::{Token, TokenKind},
3
+ parser::statement::Statement,
4
+ store::global::GlobalStore,
5
+ };
6
+ use devalang_types::Value;
7
+
8
+ #[derive(Debug, Clone, PartialEq)]
9
+ pub struct Parser {
10
+ pub resolve_modules: bool,
11
+ pub tokens: Vec<Token>,
12
+ pub token_index: usize,
13
+ pub current_module: String,
14
+ pub previous: Option<Token>,
15
+ }
16
+
17
+ impl Default for Parser {
18
+ fn default() -> Self {
19
+ Self::new()
20
+ }
21
+ }
22
+
23
+ impl Parser {
24
+ pub fn new() -> Self {
25
+ Parser {
26
+ resolve_modules: false,
27
+ tokens: Vec::new(),
28
+ token_index: 0,
29
+ current_module: String::new(),
30
+ previous: None,
31
+ }
32
+ }
33
+
34
+ pub fn set_current_module(&mut self, module_path: String) {
35
+ self.current_module = module_path;
36
+ }
37
+
38
+ pub fn advance(&mut self) -> Option<&Token> {
39
+ crate::core::parser::driver::cursor::advance_impl(self)
40
+ }
41
+
42
+ pub fn peek_is(&self, expected: &str) -> bool {
43
+ crate::core::parser::driver::cursor::peek_is_impl(self, expected)
44
+ }
45
+
46
+ pub fn peek_nth(&self, n: usize) -> Option<&Token> {
47
+ crate::core::parser::driver::cursor::peek_nth_impl(self, n)
48
+ }
49
+
50
+ pub fn peek_nth_kind(&self, n: usize) -> Option<TokenKind> {
51
+ crate::core::parser::driver::cursor::peek_nth_kind_impl(self, n)
52
+ }
53
+
54
+ pub fn advance_if(&mut self, kind: TokenKind) -> bool {
55
+ crate::core::parser::driver::cursor::advance_if_impl(self, kind)
56
+ }
57
+
58
+ pub fn match_token(&mut self, kind: TokenKind) -> bool {
59
+ crate::core::parser::driver::cursor::match_token_impl(self, kind)
60
+ }
61
+
62
+ pub fn previous_clone(&self) -> Option<Token> {
63
+ crate::core::parser::driver::cursor::previous_clone_impl(self)
64
+ }
65
+
66
+ pub fn parse_block(
67
+ &self,
68
+ tokens: Vec<Token>,
69
+ global_store: &mut GlobalStore,
70
+ ) -> Vec<Statement> {
71
+ crate::core::parser::driver::block::parse_block(self, tokens, global_store)
72
+ }
73
+
74
+ pub fn parse_tokens(
75
+ &mut self,
76
+ tokens: Vec<Token>,
77
+ global_store: &mut GlobalStore,
78
+ ) -> Vec<Statement> {
79
+ crate::core::parser::driver::driver_impl::parse_tokens_impl(self, tokens, global_store)
80
+ }
81
+
82
+ pub fn check_token(&self, kind: TokenKind) -> bool {
83
+ crate::core::parser::driver::cursor::peek_impl(self).is_some_and(|t| t.kind == kind)
84
+ }
85
+
86
+ pub fn peek_kind(&self) -> Option<TokenKind> {
87
+ crate::core::parser::driver::cursor::peek_impl(self).map(|t| t.kind.clone())
88
+ }
89
+
90
+ pub fn parse_map_value(&mut self) -> Option<Value> {
91
+ // Delegated to parse_map.rs
92
+ crate::core::parser::driver::parse_map::parse_map_value(self)
93
+ }
94
+
95
+ // Parse an array value like [1, 2, 3] or ["a", b]
96
+ pub fn parse_array_value(&mut self) -> Option<Value> {
97
+ // delegated to parse_array.rs
98
+ crate::core::parser::driver::parse_array::parse_array_value(self)
99
+ }
100
+
101
+ pub fn peek(&self) -> Option<&Token> {
102
+ self.tokens.get(self.token_index)
103
+ }
104
+
105
+ pub fn peek_clone(&self) -> Option<Token> {
106
+ self.tokens.get(self.token_index).cloned()
107
+ }
108
+
109
+ pub fn expect(&mut self, kind: TokenKind) -> Result<&Token, String> {
110
+ let tok = self.advance().ok_or("Unexpected end of input")?;
111
+ if tok.kind == kind {
112
+ Ok(tok)
113
+ } else {
114
+ Err(format!("Expected {:?}, got {:?}", kind, tok.kind))
115
+ }
116
+ }
117
+
118
+ pub fn collect_block_tokens(&mut self, base_indent: usize) -> Vec<Token> {
119
+ crate::core::parser::driver::block::collect_block_tokens(self, base_indent)
120
+ }
121
+
122
+ pub fn collect_until<F>(&mut self, condition: F) -> Vec<Token>
123
+ where
124
+ F: Fn(&Token) -> bool,
125
+ {
126
+ crate::core::parser::driver::block::collect_until(self, condition)
127
+ }
128
+
129
+ pub fn is_eof(&self) -> bool {
130
+ self.token_index >= self.tokens.len()
131
+ }
132
+
133
+ pub fn parse_block_until_next_else(
134
+ &mut self,
135
+ base_indent: usize,
136
+ global_store: &mut GlobalStore,
137
+ ) -> Vec<Statement> {
138
+ crate::core::parser::driver::block::parse_block_until_next_else(
139
+ self,
140
+ base_indent,
141
+ global_store,
142
+ )
143
+ }
144
+
145
+ pub fn parse_condition_until_colon(&mut self) -> Option<Value> {
146
+ crate::core::parser::driver::driver_impl::parse_condition_until_colon_impl(self)
147
+ }
148
+
149
+ pub fn parse_block_until_else_or_dedent(
150
+ &mut self,
151
+ base_indent: usize,
152
+ global_store: &mut GlobalStore,
153
+ ) -> Vec<Statement> {
154
+ crate::core::parser::driver::block::parse_block_until_else_or_dedent(
155
+ self,
156
+ base_indent,
157
+ global_store,
158
+ )
159
+ }
160
+ }
@@ -1,126 +1,277 @@
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
-
8
- pub fn parse_arrow_call(parser: &mut Parser, global_store: &mut GlobalStore) -> Statement {
9
- let Some(target_token) = parser.peek_clone() else {
10
- return Statement::unknown();
11
- };
12
-
13
- if target_token.kind != TokenKind::Identifier {
14
- parser.advance(); // consume target token
15
- return Statement::unknown();
16
- }
17
-
18
- let Some(arrow_token) = parser.peek_nth(1).cloned() else {
19
- parser.advance(); // consume arrow token
20
- return Statement {
21
- kind: StatementKind::Unknown,
22
- value: Value::String(target_token.lexeme.clone()),
23
- indent: target_token.indent,
24
- line: target_token.line,
25
- column: target_token.column,
26
- };
27
- };
28
-
29
- if arrow_token.kind != TokenKind::Arrow {
30
- parser.advance(); // consume method token
31
- return Statement {
32
- kind: StatementKind::Unknown,
33
- value: Value::String(target_token.lexeme.clone()),
34
- indent: target_token.indent,
35
- line: target_token.line,
36
- column: target_token.column,
37
- };
38
- }
39
-
40
- // We have a valid arrow call, so we consume the arrow token
41
- let Some(method_token) = parser.peek_nth(2).cloned() else {
42
- parser.advance();
43
- return Statement::unknown();
44
- };
45
-
46
- if method_token.kind != TokenKind::Identifier {
47
- parser.advance();
48
- return Statement::unknown();
49
- }
50
-
51
- // Consume the tokens for target, arrow, and method
52
- parser.advance(); // target
53
- parser.advance(); // ->
54
- parser.advance(); // method
55
-
56
- let mut args = Vec::new();
57
-
58
- while let Some(token) = parser.peek_clone() {
59
- if token.kind == TokenKind::Newline || token.kind == TokenKind::EOF {
60
- break;
61
- }
62
-
63
- parser.advance();
64
-
65
- let value = match token.kind {
66
- TokenKind::Identifier => Value::Identifier(token.lexeme.clone()),
67
- TokenKind::String => Value::String(token.lexeme.clone()),
68
- TokenKind::Number => Value::Number(token.lexeme.parse::<f32>().unwrap_or(0.0)),
69
- TokenKind::LBrace => {
70
- // Handle map literal
71
- let mut map = std::collections::HashMap::new();
72
- while let Some(inner_token) = parser.peek_clone() {
73
- if inner_token.kind == TokenKind::RBrace {
74
- parser.advance(); // consume RBrace
75
- break;
76
- }
77
- if inner_token.kind == TokenKind::Newline || inner_token.kind == TokenKind::EOF {
78
- break;
79
- }
80
- parser.advance(); // consume key token
81
- let key = inner_token.lexeme.clone();
82
-
83
- if let Some(colon_token) = parser.peek_clone() {
84
- if colon_token.kind == TokenKind::Colon {
85
- parser.advance(); // consume colon
86
- if let Some(value_token) = parser.peek_clone() {
87
- parser.advance(); // consume value token
88
- let value = match value_token.kind {
89
- TokenKind::Identifier =>
90
- Value::Identifier(value_token.lexeme.clone()),
91
- TokenKind::String => Value::String(value_token.lexeme.clone()),
92
- TokenKind::Number =>
93
- Value::Number(
94
- value_token.lexeme.parse::<f32>().unwrap_or(0.0)
95
- ),
96
- TokenKind::Boolean =>
97
- Value::Boolean(
98
- value_token.lexeme.parse::<bool>().unwrap_or(false)
99
- ),
100
- _ => Value::Unknown,
101
- };
102
- map.insert(key, value);
103
- }
104
- }
105
- }
106
- }
107
- Value::Map(map)
108
- }
109
- _ => Value::Unknown,
110
- };
111
-
112
- args.push(value);
113
- }
114
-
115
- Statement {
116
- kind: StatementKind::ArrowCall {
117
- target: target_token.lexeme.clone(),
118
- method: method_token.lexeme.clone(),
119
- args,
120
- },
121
- value: Value::Null,
122
- indent: target_token.indent,
123
- line: target_token.line,
124
- column: target_token.column,
125
- }
126
- }
1
+ use crate::core::{
2
+ lexer::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
+ fn parse_map_literal(parser: &mut Parser) -> Value {
12
+ // Assumes '{' has already been consumed by caller
13
+ let mut map = std::collections::HashMap::new();
14
+ loop {
15
+ let Some(inner_token) = parser.peek_clone() else {
16
+ break;
17
+ };
18
+
19
+ match inner_token.kind {
20
+ TokenKind::RBrace => {
21
+ parser.advance(); // consume '}'
22
+ break;
23
+ }
24
+ TokenKind::Newline | TokenKind::Comma => {
25
+ parser.advance();
26
+ continue;
27
+ }
28
+ _ => {}
29
+ }
30
+
31
+ // Key
32
+ parser.advance();
33
+ let key = inner_token.lexeme.clone();
34
+
35
+ // Expect ':'
36
+ if let Some(colon_token) = parser.peek_clone() {
37
+ if colon_token.kind == TokenKind::Colon {
38
+ parser.advance(); // consume ':'
39
+
40
+ // Value
41
+ if let Some(value_token) = parser.peek_clone() {
42
+ match value_token.kind {
43
+ TokenKind::LBrace => {
44
+ parser.advance(); // consume '{'
45
+ let nested = parse_map_literal(parser);
46
+ map.insert(key, nested);
47
+ }
48
+ TokenKind::Identifier => {
49
+ parser.advance();
50
+ let v = if value_token.lexeme == "true" {
51
+ Value::Boolean(true)
52
+ } else if value_token.lexeme == "false" {
53
+ Value::Boolean(false)
54
+ } else {
55
+ Value::Identifier(value_token.lexeme.clone())
56
+ };
57
+ map.insert(key, v);
58
+ }
59
+ TokenKind::String => {
60
+ parser.advance();
61
+ map.insert(key, Value::String(value_token.lexeme.clone()));
62
+ }
63
+ TokenKind::Number => {
64
+ parser.advance();
65
+ // Beat fraction support: NUMBER '/' NUMBER
66
+ if let Some(TokenKind::Slash) = parser.peek_kind() {
67
+ parser.advance(); // '/'
68
+ if let Some(den) = parser.peek_clone() {
69
+ if den.kind == TokenKind::Number
70
+ || den.kind == TokenKind::Identifier
71
+ {
72
+ parser.advance();
73
+ let beat = format!("{}/{}", value_token.lexeme, den.lexeme);
74
+ map.insert(
75
+ key,
76
+ Value::Duration(devalang_types::Duration::Beat(beat)),
77
+ );
78
+ continue;
79
+ }
80
+ }
81
+ }
82
+ // Decimal support NUMBER '.' NUMBER
83
+ if let Some(next) = parser.peek_clone() {
84
+ if next.kind == TokenKind::Dot {
85
+ parser.advance(); // '.'
86
+ if let Some(after) = parser.peek_clone() {
87
+ if after.kind == TokenKind::Number {
88
+ parser.advance();
89
+ let combined =
90
+ format!("{}.{}", value_token.lexeme, after.lexeme);
91
+ map.insert(
92
+ key,
93
+ Value::Number(
94
+ combined.parse::<f32>().unwrap_or(0.0),
95
+ ),
96
+ );
97
+ continue;
98
+ }
99
+ }
100
+ }
101
+ }
102
+ map.insert(
103
+ key,
104
+ Value::Number(value_token.lexeme.parse::<f32>().unwrap_or(0.0)),
105
+ );
106
+ }
107
+ TokenKind::Boolean => {
108
+ parser.advance();
109
+ map.insert(
110
+ key,
111
+ Value::Boolean(value_token.lexeme.parse::<bool>().unwrap_or(false)),
112
+ );
113
+ }
114
+ _ => {
115
+ // Unknown value type, consume and store Unknown
116
+ parser.advance();
117
+ map.insert(key, Value::Unknown);
118
+ }
119
+ }
120
+ }
121
+ }
122
+ }
123
+ }
124
+ Value::Map(map)
125
+ }
126
+
127
+ pub fn parse_arrow_call(parser: &mut Parser, _global_store: &mut GlobalStore) -> Statement {
128
+ let Some(target_token) = parser.peek_clone() else {
129
+ return Statement::unknown();
130
+ };
131
+
132
+ if target_token.kind != TokenKind::Identifier {
133
+ parser.advance(); // consume target token
134
+ return Statement::unknown_with_pos(
135
+ target_token.indent,
136
+ target_token.line,
137
+ target_token.column,
138
+ );
139
+ }
140
+
141
+ let Some(arrow_token) = parser.peek_nth(1).cloned() else {
142
+ parser.advance(); // consume arrow token
143
+ return Statement::unknown_with_pos(
144
+ target_token.indent,
145
+ target_token.line,
146
+ target_token.column,
147
+ );
148
+ };
149
+
150
+ if arrow_token.kind != TokenKind::Arrow {
151
+ parser.advance(); // consume method token
152
+ return Statement::unknown_with_pos(
153
+ target_token.indent,
154
+ target_token.line,
155
+ target_token.column,
156
+ );
157
+ }
158
+
159
+ // We have a valid arrow call, so we consume the arrow token
160
+ let Some(method_token) = parser.peek_nth(2).cloned() else {
161
+ parser.advance();
162
+ return Statement::unknown_with_pos(
163
+ target_token.indent,
164
+ target_token.line,
165
+ target_token.column,
166
+ );
167
+ };
168
+
169
+ if method_token.kind != TokenKind::Identifier {
170
+ parser.advance();
171
+ return Statement::unknown_with_pos(
172
+ method_token.indent,
173
+ method_token.line,
174
+ method_token.column,
175
+ );
176
+ }
177
+
178
+ // Consume the tokens for target, arrow, and method
179
+ parser.advance(); // target
180
+ parser.advance(); // ->
181
+ parser.advance(); // method
182
+
183
+ let mut args = Vec::new();
184
+ let mut paren_depth = 0;
185
+ let mut map_depth = 0;
186
+
187
+ while let Some(token) = parser.peek_clone() {
188
+ if token.kind == TokenKind::Newline || token.kind == TokenKind::EOF {
189
+ break;
190
+ }
191
+ if token.kind == TokenKind::LParen {
192
+ paren_depth += 1;
193
+ }
194
+ if token.kind == TokenKind::RParen {
195
+ if paren_depth > 0 {
196
+ paren_depth -= 1;
197
+ parser.advance();
198
+ if paren_depth == 0 {
199
+ break;
200
+ }
201
+ continue;
202
+ } else {
203
+ break;
204
+ }
205
+ }
206
+ if token.kind == TokenKind::LBrace {
207
+ map_depth += 1;
208
+ }
209
+ if token.kind == TokenKind::RBrace {
210
+ if map_depth > 0 {
211
+ map_depth -= 1;
212
+ parser.advance();
213
+ if map_depth == 0 {
214
+ continue;
215
+ }
216
+ continue;
217
+ } else {
218
+ break;
219
+ }
220
+ }
221
+
222
+ parser.advance();
223
+
224
+ let value = match token.kind {
225
+ TokenKind::Identifier => Value::Identifier(token.lexeme.clone()),
226
+ TokenKind::String => Value::String(token.lexeme.clone()),
227
+ TokenKind::Number => {
228
+ // support fraction literal as bare arg: 1/4
229
+ // note: token has already been advanced earlier in the loop
230
+ if let Some(TokenKind::Slash) = parser.peek_kind() {
231
+ parser.advance(); // consume '/'
232
+ if let Some(den) = parser.peek_clone() {
233
+ if den.kind == TokenKind::Number || den.kind == TokenKind::Identifier {
234
+ parser.advance();
235
+ let beat = format!("{}/{}", token.lexeme, den.lexeme);
236
+ Value::Duration(devalang_types::Duration::Beat(beat))
237
+ } else {
238
+ Value::Number(token.lexeme.parse::<f32>().unwrap_or(0.0))
239
+ }
240
+ } else {
241
+ Value::Number(token.lexeme.parse::<f32>().unwrap_or(0.0))
242
+ }
243
+ } else {
244
+ Value::Number(token.lexeme.parse::<f32>().unwrap_or(0.0))
245
+ }
246
+ }
247
+ TokenKind::LBrace => {
248
+ // Handle map literal (supports nested maps)
249
+
250
+ // We consumed the matching '}', so outer map_depth should be decremented
251
+ // if the caller tracks it.
252
+ parse_map_literal(parser)
253
+ }
254
+ _ => Value::Unknown,
255
+ };
256
+
257
+ args.push(value);
258
+
259
+ // Stop if we reach the end of the statement
260
+ if paren_depth == 0 && (token.kind == TokenKind::RParen || token.kind == TokenKind::RBrace)
261
+ {
262
+ break;
263
+ }
264
+ }
265
+
266
+ Statement {
267
+ kind: StatementKind::ArrowCall {
268
+ target: target_token.lexeme.clone(),
269
+ method: method_token.lexeme.clone(),
270
+ args,
271
+ },
272
+ value: Value::Null,
273
+ indent: target_token.indent,
274
+ line: target_token.line,
275
+ column: target_token.column,
276
+ }
277
+ }