@devaloop/devalang 0.0.1-beta.1 → 0.0.1-beta.3

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 (207) hide show
  1. package/.devalang +9 -10
  2. package/Cargo.toml +84 -80
  3. package/README.md +10 -7
  4. package/docs/CHANGELOG.md +83 -0
  5. package/docs/ROADMAP.md +6 -2
  6. package/docs/TODO.md +3 -14
  7. package/examples/bus.deva +10 -0
  8. package/examples/chain.deva +19 -0
  9. package/examples/effect.deva +2 -0
  10. package/examples/filter.deva +11 -0
  11. package/examples/lfo.deva +9 -0
  12. package/examples/plugin.deva +10 -10
  13. package/examples/routing.deva +23 -0
  14. package/examples/synth.deva +11 -1
  15. package/examples/synth_types.deva +17 -0
  16. package/out-tsc/bin/project-version.json +6 -0
  17. package/out-tsc/core/functions/index.d.ts +5 -0
  18. package/out-tsc/core/functions/index.js +11 -0
  19. package/out-tsc/pkg/devalang_core.d.ts +2 -0
  20. package/out-tsc/pkg/devalang_core.js +17 -2
  21. package/out-tsc/pkg/devalang_core_bg.wasm.d.ts +1 -0
  22. package/out-tsc/scripts/version/copy-to-binary.d.ts +1 -0
  23. package/out-tsc/scripts/version/copy-to-binary.js +79 -0
  24. package/package.json +23 -10
  25. package/project-version.json +3 -3
  26. package/rust/bindings/Cargo.toml +9 -0
  27. package/rust/bindings/src/lib.rs +86 -0
  28. package/rust/cli/addon/commands.rs +35 -0
  29. package/rust/cli/addon/download.rs +234 -0
  30. package/rust/cli/addon/install.rs +33 -0
  31. package/rust/cli/addon/list.rs +224 -0
  32. package/rust/cli/addon/metadata.rs +124 -0
  33. package/rust/cli/addon/mod.rs +8 -0
  34. package/rust/cli/addon/remove.rs +271 -0
  35. package/rust/cli/addon/update.rs +305 -0
  36. package/rust/cli/{install/addon.rs → addon/utils.rs} +34 -43
  37. package/rust/cli/build/commands.rs +153 -103
  38. package/rust/cli/build/mod.rs +2 -2
  39. package/rust/cli/build/process.rs +165 -146
  40. package/rust/cli/check/mod.rs +208 -208
  41. package/rust/cli/discover/commands.rs +53 -31
  42. package/rust/cli/discover/config.rs +2 -4
  43. package/rust/cli/discover/install.rs +139 -28
  44. package/rust/cli/discover/metadata.rs +3 -3
  45. package/rust/cli/login/commands.rs +124 -124
  46. package/rust/cli/me/commands.rs +52 -0
  47. package/rust/cli/me/mod.rs +1 -0
  48. package/rust/cli/mod.rs +2 -2
  49. package/rust/cli/parser.rs +76 -70
  50. package/rust/cli/play/commands.rs +375 -324
  51. package/rust/cli/play/mod.rs +5 -5
  52. package/rust/cli/play/process.rs +159 -150
  53. package/rust/cli/play/realtime.rs +91 -91
  54. package/rust/cli/telemetry/commands.rs +22 -22
  55. package/rust/cli/telemetry/event_creator.rs +80 -80
  56. package/rust/cli/telemetry/mod.rs +3 -3
  57. package/rust/cli/telemetry/send.rs +51 -51
  58. package/rust/cli/template/commands.rs +69 -69
  59. package/rust/config/driver.rs +112 -103
  60. package/rust/config/mod.rs +3 -3
  61. package/rust/config/ops.rs +26 -26
  62. package/rust/config/settings.rs +101 -101
  63. package/rust/core/audio/engine/driver.rs +237 -0
  64. package/rust/core/audio/engine/export.rs +169 -0
  65. package/rust/core/audio/engine/helpers.rs +178 -170
  66. package/rust/core/audio/engine/mod.rs +56 -7
  67. package/rust/core/audio/engine/notes/dsp.rs +88 -0
  68. package/rust/core/audio/engine/notes/mod.rs +53 -0
  69. package/rust/core/audio/engine/notes/params.rs +294 -0
  70. package/rust/core/audio/engine/sample/insert.rs +300 -0
  71. package/rust/core/audio/engine/sample/mod.rs +40 -0
  72. package/rust/core/audio/engine/sample/padding.rs +170 -0
  73. package/rust/core/audio/evaluator/condition.rs +61 -0
  74. package/rust/core/audio/evaluator/mod.rs +9 -0
  75. package/rust/core/audio/{evaluator.rs → evaluator/numeric.rs} +152 -310
  76. package/rust/core/audio/evaluator/rhs.rs +16 -0
  77. package/rust/core/audio/evaluator/string_expr.rs +94 -0
  78. package/rust/core/audio/interpreter/driver.rs +574 -542
  79. package/rust/core/audio/interpreter/mod.rs +2 -14
  80. package/rust/core/audio/interpreter/statements/arrow_call/interprete.rs +179 -0
  81. package/rust/core/audio/interpreter/statements/arrow_call/methods/chord.rs +398 -0
  82. package/rust/core/audio/interpreter/statements/arrow_call/methods/effects.rs +323 -0
  83. package/rust/core/audio/interpreter/statements/arrow_call/methods/mod.rs +3 -0
  84. package/rust/core/audio/interpreter/statements/arrow_call/methods/note.rs +371 -0
  85. package/rust/core/audio/interpreter/statements/arrow_call/mod.rs +3 -0
  86. package/rust/core/audio/interpreter/statements/arrow_call/types/arp.rs +192 -0
  87. package/rust/core/audio/interpreter/statements/arrow_call/types/mod.rs +24 -0
  88. package/rust/core/audio/interpreter/statements/arrow_call/types/pad.rs +116 -0
  89. package/rust/core/audio/interpreter/statements/arrow_call/types/pluck.rs +97 -0
  90. package/rust/core/audio/interpreter/statements/arrow_call/types/sub.rs +100 -0
  91. package/rust/core/audio/interpreter/{automate.rs → statements/automate.rs} +2 -4
  92. package/rust/core/audio/interpreter/{call.rs → statements/call.rs} +36 -5
  93. package/rust/core/audio/interpreter/{condition.rs → statements/condition.rs} +72 -71
  94. package/rust/core/audio/interpreter/{function.rs → statements/function.rs} +24 -26
  95. package/rust/core/audio/interpreter/{let_.rs → statements/let_.rs} +36 -38
  96. package/rust/core/audio/interpreter/{load.rs → statements/load.rs} +17 -19
  97. package/rust/core/audio/interpreter/{loop_.rs → statements/loop_.rs} +115 -114
  98. package/rust/core/audio/interpreter/statements/mod.rs +12 -0
  99. package/rust/core/audio/interpreter/{sleep.rs → statements/sleep.rs} +28 -28
  100. package/rust/core/audio/interpreter/{spawn.rs → statements/spawn.rs} +54 -4
  101. package/rust/core/audio/interpreter/{tempo.rs → statements/tempo.rs} +40 -40
  102. package/rust/core/audio/interpreter/{trigger.rs → statements/trigger.rs} +242 -239
  103. package/rust/core/audio/loader/trigger.rs +98 -97
  104. package/rust/core/audio/mod.rs +6 -7
  105. package/rust/core/audio/special/easing.rs +189 -189
  106. package/rust/core/audio/special/env.rs +45 -45
  107. package/rust/core/audio/special/math.rs +134 -134
  108. package/rust/core/audio/special/modulator.rs +143 -143
  109. package/rust/core/builder/mod.rs +129 -86
  110. package/rust/core/debugger/{module.rs → logs.rs} +52 -55
  111. package/rust/core/debugger/mod.rs +30 -30
  112. package/rust/core/debugger/store.rs +38 -40
  113. package/rust/core/error/mod.rs +269 -269
  114. package/rust/core/lexer/driver.rs +2 -4
  115. package/rust/core/mod.rs +9 -10
  116. package/rust/core/parser/driver/block.rs +111 -0
  117. package/rust/core/parser/driver/cursor.rs +82 -0
  118. package/rust/core/parser/driver/driver_impl.rs +159 -0
  119. package/rust/core/parser/driver/mod.rs +6 -0
  120. package/rust/core/parser/driver/parse_array.rs +120 -0
  121. package/rust/core/parser/driver/parse_map.rs +247 -0
  122. package/rust/core/parser/driver/parser.rs +160 -0
  123. package/rust/core/parser/handler/arrow_call.rs +90 -15
  124. package/rust/core/parser/handler/at.rs +279 -279
  125. package/rust/core/parser/handler/bank.rs +104 -104
  126. package/rust/core/parser/handler/condition.rs +83 -83
  127. package/rust/core/parser/handler/dot.rs +148 -148
  128. package/rust/core/parser/handler/identifier/automate.rs +254 -254
  129. package/rust/core/parser/handler/identifier/call.rs +91 -91
  130. package/rust/core/parser/handler/identifier/emit.rs +70 -70
  131. package/rust/core/parser/handler/identifier/function.rs +113 -113
  132. package/rust/core/parser/handler/identifier/group.rs +89 -89
  133. package/rust/core/parser/handler/identifier/let_.rs +173 -173
  134. package/rust/core/parser/handler/identifier/mod.rs +55 -55
  135. package/rust/core/parser/handler/identifier/on.rs +107 -107
  136. package/rust/core/parser/handler/identifier/print.rs +49 -49
  137. package/rust/core/parser/handler/identifier/sleep.rs +96 -43
  138. package/rust/core/parser/handler/identifier/spawn.rs +91 -91
  139. package/rust/core/parser/handler/identifier/synth.rs +39 -3
  140. package/rust/core/parser/handler/loop_.rs +194 -194
  141. package/rust/core/parser/handler/pattern.rs +25 -2
  142. package/rust/core/parser/handler/tempo.rs +105 -57
  143. package/rust/core/parser/statement.rs +10 -11
  144. package/rust/core/plugin/loader.rs +137 -137
  145. package/rust/core/plugin/runner/mod.rs +11 -0
  146. package/rust/core/plugin/{runner.rs → runner/non_wasm.rs} +206 -72
  147. package/rust/core/plugin/runner/wasm32.rs +44 -0
  148. package/rust/core/preprocessor/loader/inject.rs +313 -0
  149. package/rust/core/preprocessor/loader/loader_helpers.rs +110 -0
  150. package/rust/core/preprocessor/loader/mod.rs +235 -0
  151. package/rust/core/preprocessor/module.rs +55 -60
  152. package/rust/core/preprocessor/{processor.rs → processor/handlers.rs} +107 -114
  153. package/rust/core/preprocessor/processor/mod.rs +1 -0
  154. package/rust/core/preprocessor/resolver/function.rs +69 -69
  155. package/rust/core/preprocessor/resolver/group.rs +122 -94
  156. package/rust/core/preprocessor/resolver/pattern.rs +14 -2
  157. package/rust/core/store/global.rs +57 -61
  158. package/rust/core/store/mod.rs +1 -5
  159. package/rust/lib.rs +323 -308
  160. package/rust/macros/Cargo.toml +14 -0
  161. package/rust/macros/src/lib.rs +52 -0
  162. package/rust/main.rs +336 -143
  163. package/rust/types/Cargo.toml +1 -1
  164. package/rust/types/src/addons.rs +57 -55
  165. package/rust/types/src/config.rs +82 -74
  166. package/rust/types/src/lib.rs +15 -12
  167. package/rust/types/src/plugin.rs +20 -0
  168. package/rust/types/src/store.rs +139 -0
  169. package/rust/types/src/telemetry.rs +85 -85
  170. package/rust/utils/Cargo.toml +5 -2
  171. package/rust/utils/src/file.rs +477 -94
  172. package/rust/utils/src/first_usage.rs +97 -97
  173. package/rust/utils/src/lib.rs +9 -9
  174. package/rust/utils/src/logger.rs +200 -200
  175. package/rust/utils/src/path.rs +158 -88
  176. package/rust/utils/src/signature.rs +41 -41
  177. package/rust/utils/src/spinner.rs +20 -20
  178. package/rust/utils/src/version.rs +58 -27
  179. package/rust/utils/src/watcher.rs +46 -46
  180. package/rust/web/api.rs +5 -5
  181. package/rust/web/auth.rs +5 -0
  182. package/rust/web/cdn.rs +34 -34
  183. package/rust/web/forge.rs +5 -0
  184. package/rust/web/mod.rs +2 -0
  185. package/tests/integration.rs +21 -21
  186. package/typescript/core/functions/index.ts +11 -0
  187. package/typescript/pkg/devalang_core.ts +20 -4
  188. package/typescript/scripts/version/copy-to-binary.ts +82 -0
  189. package/rust/cli/bank/api.rs +0 -122
  190. package/rust/cli/bank/commands.rs +0 -275
  191. package/rust/cli/bank/mod.rs +0 -29
  192. package/rust/cli/install/bank.rs +0 -53
  193. package/rust/cli/install/commands.rs +0 -35
  194. package/rust/cli/install/mod.rs +0 -4
  195. package/rust/cli/install/plugin.rs +0 -61
  196. package/rust/core/audio/engine/sample.rs +0 -366
  197. package/rust/core/audio/engine/synth.rs +0 -325
  198. package/rust/core/audio/interpreter/arrow_call.rs +0 -311
  199. package/rust/core/audio/renderer.rs +0 -54
  200. package/rust/core/parser/driver.rs +0 -584
  201. package/rust/core/preprocessor/loader.rs +0 -637
  202. package/rust/core/store/export.rs +0 -28
  203. package/rust/core/store/function.rs +0 -40
  204. package/rust/core/store/import.rs +0 -28
  205. package/rust/core/store/variable.rs +0 -51
  206. package/rust/core/utils/mod.rs +0 -1
  207. package/rust/core/utils/path.rs +0 -37
@@ -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,7 +1,7 @@
1
1
  use crate::core::{
2
2
  lexer::token::TokenKind,
3
3
  parser::{
4
- driver::Parser,
4
+ driver::parser::Parser,
5
5
  statement::{Statement, StatementKind},
6
6
  },
7
7
  store::global::GlobalStore,
@@ -66,10 +66,15 @@ fn parse_map_literal(parser: &mut Parser) -> Value {
66
66
  if let Some(TokenKind::Slash) = parser.peek_kind() {
67
67
  parser.advance(); // '/'
68
68
  if let Some(den) = parser.peek_clone() {
69
- if den.kind == TokenKind::Number {
69
+ if den.kind == TokenKind::Number
70
+ || den.kind == TokenKind::Identifier
71
+ {
70
72
  parser.advance();
71
73
  let beat = format!("{}/{}", value_token.lexeme, den.lexeme);
72
- map.insert(key, Value::Beat(beat));
74
+ map.insert(
75
+ key,
76
+ Value::Duration(devalang_types::Duration::Beat(beat)),
77
+ );
73
78
  continue;
74
79
  }
75
80
  }
@@ -175,6 +180,22 @@ pub fn parse_arrow_call(parser: &mut Parser, _global_store: &mut GlobalStore) ->
175
180
  parser.advance(); // ->
176
181
  parser.advance(); // method
177
182
 
183
+ let args = parse_arrow_args(parser);
184
+ Statement {
185
+ kind: StatementKind::ArrowCall {
186
+ target: target_token.lexeme.clone(),
187
+ method: method_token.lexeme.clone(),
188
+ args,
189
+ },
190
+ value: Value::Null,
191
+ indent: target_token.indent,
192
+ line: target_token.line,
193
+ column: target_token.column,
194
+ }
195
+ }
196
+
197
+ // Parse args after the method token. Reused by continuation parser.
198
+ fn parse_arrow_args(parser: &mut Parser) -> Vec<Value> {
178
199
  let mut args = Vec::new();
179
200
  let mut paren_depth = 0;
180
201
  let mut map_depth = 0;
@@ -219,35 +240,89 @@ pub fn parse_arrow_call(parser: &mut Parser, _global_store: &mut GlobalStore) ->
219
240
  let value = match token.kind {
220
241
  TokenKind::Identifier => Value::Identifier(token.lexeme.clone()),
221
242
  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)
243
+ TokenKind::Number => {
244
+ if let Some(TokenKind::Slash) = parser.peek_kind() {
245
+ parser.advance(); // consume '/'
246
+ if let Some(den) = parser.peek_clone() {
247
+ if den.kind == TokenKind::Number || den.kind == TokenKind::Identifier {
248
+ parser.advance();
249
+ let beat = format!("{}/{}", token.lexeme, den.lexeme);
250
+ Value::Duration(devalang_types::Duration::Beat(beat))
251
+ } else {
252
+ Value::Number(token.lexeme.parse::<f32>().unwrap_or(0.0))
253
+ }
254
+ } else {
255
+ Value::Number(token.lexeme.parse::<f32>().unwrap_or(0.0))
256
+ }
257
+ } else {
258
+ Value::Number(token.lexeme.parse::<f32>().unwrap_or(0.0))
259
+ }
229
260
  }
261
+ TokenKind::LBrace => parse_map_literal(parser),
230
262
  _ => Value::Unknown,
231
263
  };
232
264
 
233
265
  args.push(value);
234
266
 
235
- // Stop if we reach the end of the statement
236
267
  if paren_depth == 0 && (token.kind == TokenKind::RParen || token.kind == TokenKind::RBrace)
237
268
  {
238
269
  break;
239
270
  }
240
271
  }
241
272
 
273
+ args
274
+ }
275
+
276
+ // Parse an arrow continuation that begins with an Arrow token. If prev_target is Some,
277
+ // use it as the call target; otherwise produce an Unknown statement.
278
+ pub fn parse_arrow_continuation(
279
+ parser: &mut Parser,
280
+ _global_store: &mut GlobalStore,
281
+ prev_target: Option<String>,
282
+ ) -> Statement {
283
+ // We expect current token to be Arrow
284
+ let arrow_tok = parser.peek_clone();
285
+ if arrow_tok.is_none() {
286
+ return Statement::unknown();
287
+ }
288
+
289
+ // If there is no previous target, consume arrow and return unknown
290
+ let Some(target) = prev_target else {
291
+ parser.advance(); // consume Arrow
292
+ return Statement::unknown();
293
+ };
294
+
295
+ // consume '->'
296
+ parser.advance();
297
+
298
+ // next token should be method identifier
299
+ let Some(method_token) = parser.peek_nth(0).cloned() else {
300
+ return Statement::unknown();
301
+ };
302
+
303
+ if method_token.kind != TokenKind::Identifier {
304
+ parser.advance();
305
+ return Statement::unknown_with_pos(
306
+ method_token.indent,
307
+ method_token.line,
308
+ method_token.column,
309
+ );
310
+ }
311
+
312
+ // consume method
313
+ parser.advance();
314
+
315
+ let args = parse_arrow_args(parser);
316
+
242
317
  Statement {
243
318
  kind: StatementKind::ArrowCall {
244
- target: target_token.lexeme.clone(),
319
+ target,
245
320
  method: method_token.lexeme.clone(),
246
321
  args,
247
322
  },
248
323
  value: Value::Null,
249
- indent: target_token.indent,
250
- line: target_token.line,
251
- column: target_token.column,
324
+ indent: method_token.indent,
325
+ line: method_token.line,
326
+ column: method_token.column,
252
327
  }
253
328
  }