@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,126 +1,253 @@
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,
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
+ parser.advance();
71
+ let beat = format!("{}/{}", value_token.lexeme, den.lexeme);
72
+ map.insert(key, Value::Beat(beat));
73
+ continue;
74
+ }
75
+ }
76
+ }
77
+ // Decimal support NUMBER '.' NUMBER
78
+ if let Some(next) = parser.peek_clone() {
79
+ if next.kind == TokenKind::Dot {
80
+ parser.advance(); // '.'
81
+ if let Some(after) = parser.peek_clone() {
82
+ if after.kind == TokenKind::Number {
83
+ parser.advance();
84
+ let combined =
85
+ format!("{}.{}", value_token.lexeme, after.lexeme);
86
+ map.insert(
87
+ key,
88
+ Value::Number(
89
+ combined.parse::<f32>().unwrap_or(0.0),
90
+ ),
91
+ );
92
+ continue;
93
+ }
94
+ }
95
+ }
96
+ }
97
+ map.insert(
98
+ key,
99
+ Value::Number(value_token.lexeme.parse::<f32>().unwrap_or(0.0)),
100
+ );
101
+ }
102
+ TokenKind::Boolean => {
103
+ parser.advance();
104
+ map.insert(
105
+ key,
106
+ Value::Boolean(value_token.lexeme.parse::<bool>().unwrap_or(false)),
107
+ );
108
+ }
109
+ _ => {
110
+ // Unknown value type, consume and store Unknown
111
+ parser.advance();
112
+ map.insert(key, Value::Unknown);
113
+ }
114
+ }
115
+ }
116
+ }
117
+ }
118
+ }
119
+ Value::Map(map)
120
+ }
121
+
122
+ pub fn parse_arrow_call(parser: &mut Parser, _global_store: &mut GlobalStore) -> Statement {
123
+ let Some(target_token) = parser.peek_clone() else {
124
+ return Statement::unknown();
125
+ };
126
+
127
+ if target_token.kind != TokenKind::Identifier {
128
+ parser.advance(); // consume target token
129
+ return Statement::unknown_with_pos(
130
+ target_token.indent,
131
+ target_token.line,
132
+ target_token.column,
133
+ );
134
+ }
135
+
136
+ let Some(arrow_token) = parser.peek_nth(1).cloned() else {
137
+ parser.advance(); // consume arrow token
138
+ return Statement::unknown_with_pos(
139
+ target_token.indent,
140
+ target_token.line,
141
+ target_token.column,
142
+ );
143
+ };
144
+
145
+ if arrow_token.kind != TokenKind::Arrow {
146
+ parser.advance(); // consume method token
147
+ return Statement::unknown_with_pos(
148
+ target_token.indent,
149
+ target_token.line,
150
+ target_token.column,
151
+ );
152
+ }
153
+
154
+ // We have a valid arrow call, so we consume the arrow token
155
+ let Some(method_token) = parser.peek_nth(2).cloned() else {
156
+ parser.advance();
157
+ return Statement::unknown_with_pos(
158
+ target_token.indent,
159
+ target_token.line,
160
+ target_token.column,
161
+ );
162
+ };
163
+
164
+ if method_token.kind != TokenKind::Identifier {
165
+ parser.advance();
166
+ return Statement::unknown_with_pos(
167
+ method_token.indent,
168
+ method_token.line,
169
+ method_token.column,
170
+ );
171
+ }
172
+
173
+ // Consume the tokens for target, arrow, and method
174
+ parser.advance(); // target
175
+ parser.advance(); // ->
176
+ parser.advance(); // method
177
+
178
+ let mut args = Vec::new();
179
+ let mut paren_depth = 0;
180
+ let mut map_depth = 0;
181
+
182
+ while let Some(token) = parser.peek_clone() {
183
+ if token.kind == TokenKind::Newline || token.kind == TokenKind::EOF {
184
+ break;
185
+ }
186
+ if token.kind == TokenKind::LParen {
187
+ paren_depth += 1;
188
+ }
189
+ if token.kind == TokenKind::RParen {
190
+ if paren_depth > 0 {
191
+ paren_depth -= 1;
192
+ parser.advance();
193
+ if paren_depth == 0 {
194
+ break;
195
+ }
196
+ continue;
197
+ } else {
198
+ break;
199
+ }
200
+ }
201
+ if token.kind == TokenKind::LBrace {
202
+ map_depth += 1;
203
+ }
204
+ if token.kind == TokenKind::RBrace {
205
+ if map_depth > 0 {
206
+ map_depth -= 1;
207
+ parser.advance();
208
+ if map_depth == 0 {
209
+ continue;
210
+ }
211
+ continue;
212
+ } else {
213
+ break;
214
+ }
215
+ }
216
+
217
+ parser.advance();
218
+
219
+ let value = match token.kind {
220
+ TokenKind::Identifier => Value::Identifier(token.lexeme.clone()),
221
+ TokenKind::String => Value::String(token.lexeme.clone()),
222
+ TokenKind::Number => Value::Number(token.lexeme.parse::<f32>().unwrap_or(0.0)),
223
+ TokenKind::LBrace => {
224
+ // Handle map literal (supports nested maps)
225
+
226
+ // We consumed the matching '}', so outer map_depth should be decremented
227
+ // if the caller tracks it.
228
+ parse_map_literal(parser)
229
+ }
230
+ _ => Value::Unknown,
231
+ };
232
+
233
+ args.push(value);
234
+
235
+ // Stop if we reach the end of the statement
236
+ if paren_depth == 0 && (token.kind == TokenKind::RParen || token.kind == TokenKind::RBrace)
237
+ {
238
+ break;
239
+ }
240
+ }
241
+
242
+ Statement {
243
+ kind: StatementKind::ArrowCall {
244
+ target: target_token.lexeme.clone(),
245
+ method: method_token.lexeme.clone(),
246
+ args,
247
+ },
248
+ value: Value::Null,
249
+ indent: target_token.indent,
250
+ line: target_token.line,
251
+ column: target_token.column,
252
+ }
253
+ }