devalang_core/core/parser/handler/
arrow_call.rs

1use crate::core::{
2    lexer::token::TokenKind,
3    parser::{ driver::Parser, statement::{ Statement, StatementKind } },
4    shared::value::Value,
5    store::global::GlobalStore,
6};
7
8fn parse_map_literal(parser: &mut Parser) -> Value {
9    // Assumes '{' has already been consumed by caller
10    let mut map = std::collections::HashMap::new();
11    loop {
12        let Some(inner_token) = parser.peek_clone() else { break; };
13
14        match inner_token.kind {
15            TokenKind::RBrace => {
16                parser.advance(); // consume '}'
17                break;
18            }
19            TokenKind::Newline | TokenKind::Comma => {
20                parser.advance();
21                continue;
22            }
23            _ => {}
24        }
25
26        // Key
27        parser.advance();
28        let key = inner_token.lexeme.clone();
29
30        // Expect ':'
31        if let Some(colon_token) = parser.peek_clone() {
32            if colon_token.kind == TokenKind::Colon {
33                parser.advance(); // consume ':'
34
35                // Value
36                if let Some(value_token) = parser.peek_clone() {
37                    match value_token.kind {
38                        TokenKind::LBrace => {
39                            parser.advance(); // consume '{'
40                            let nested = parse_map_literal(parser);
41                            map.insert(key, nested);
42                        }
43                        TokenKind::Identifier => {
44                            parser.advance();
45                            let v = if value_token.lexeme == "true" {
46                                Value::Boolean(true)
47                            } else if value_token.lexeme == "false" {
48                                Value::Boolean(false)
49                            } else {
50                                Value::Identifier(value_token.lexeme.clone())
51                            };
52                            map.insert(key, v);
53                        }
54                        TokenKind::String => {
55                            parser.advance();
56                            map.insert(key, Value::String(value_token.lexeme.clone()));
57                        }
58                        TokenKind::Number => {
59                            parser.advance();
60                            // Beat fraction support: NUMBER '/' NUMBER
61                            if let Some(TokenKind::Slash) = parser.peek_kind() {
62                                parser.advance(); // '/'
63                                if let Some(den) = parser.peek_clone() {
64                                    if den.kind == TokenKind::Number {
65                                        parser.advance();
66                                        let beat = format!("{}/{}", value_token.lexeme, den.lexeme);
67                                        map.insert(key, Value::Beat(beat));
68                                        continue;
69                                    }
70                                }
71                            }
72                            // Decimal support NUMBER '.' NUMBER
73                            if let Some(next) = parser.peek_clone() {
74                                if next.kind == TokenKind::Dot {
75                                    parser.advance(); // '.'
76                                    if let Some(after) = parser.peek_clone() {
77                                        if after.kind == TokenKind::Number {
78                                            parser.advance();
79                                            let combined = format!("{}.{}", value_token.lexeme, after.lexeme);
80                                            map.insert(key, Value::Number(combined.parse::<f32>().unwrap_or(0.0)));
81                                            continue;
82                                        }
83                                    }
84                                }
85                            }
86                            map.insert(key, Value::Number(value_token.lexeme.parse::<f32>().unwrap_or(0.0)));
87                        }
88                        TokenKind::Boolean => {
89                            parser.advance();
90                            map.insert(key, Value::Boolean(value_token.lexeme.parse::<bool>().unwrap_or(false)));
91                        }
92                        _ => {
93                            // Unknown value type, consume and store Unknown
94                            parser.advance();
95                            map.insert(key, Value::Unknown);
96                        }
97                    }
98                }
99            }
100        }
101    }
102    Value::Map(map)
103}
104
105pub fn parse_arrow_call(parser: &mut Parser, _global_store: &mut GlobalStore) -> Statement {
106    let Some(target_token) = parser.peek_clone() else {
107        return Statement::unknown();
108    };
109
110    if target_token.kind != TokenKind::Identifier {
111        parser.advance(); // consume target token
112        return Statement::unknown();
113    }
114
115    let Some(arrow_token) = parser.peek_nth(1).cloned() else {
116        parser.advance(); // consume arrow token
117        return Statement {
118            kind: StatementKind::Unknown,
119            value: Value::String(target_token.lexeme.clone()),
120            indent: target_token.indent,
121            line: target_token.line,
122            column: target_token.column,
123        };
124    };
125
126    if arrow_token.kind != TokenKind::Arrow {
127        parser.advance(); // consume method token
128        return Statement {
129            kind: StatementKind::Unknown,
130            value: Value::String(target_token.lexeme.clone()),
131            indent: target_token.indent,
132            line: target_token.line,
133            column: target_token.column,
134        };
135    }
136
137    // We have a valid arrow call, so we consume the arrow token
138    let Some(method_token) = parser.peek_nth(2).cloned() else {
139        parser.advance();
140        return Statement::unknown();
141    };
142
143    if method_token.kind != TokenKind::Identifier {
144        parser.advance();
145        return Statement::unknown();
146    }
147
148    // Consume the tokens for target, arrow, and method
149    parser.advance(); // target
150    parser.advance(); // ->
151    parser.advance(); // method
152
153    let mut args = Vec::new();
154    let mut paren_depth = 0;
155    let mut map_depth = 0;
156
157    while let Some(token) = parser.peek_clone() {
158        if token.kind == TokenKind::Newline || token.kind == TokenKind::EOF {
159            break;
160        }
161        if token.kind == TokenKind::LParen {
162            paren_depth += 1;
163        }
164        if token.kind == TokenKind::RParen {
165            if paren_depth > 0 {
166                paren_depth -= 1;
167                parser.advance();
168                if paren_depth == 0 {
169                    break;
170                }
171                continue;
172            } else {
173                break;
174            }
175        }
176        if token.kind == TokenKind::LBrace {
177            map_depth += 1;
178        }
179        if token.kind == TokenKind::RBrace {
180            if map_depth > 0 {
181                map_depth -= 1;
182                parser.advance();
183                if map_depth == 0 {
184                    continue;
185                }
186                continue;
187            } else {
188                break;
189            }
190        }
191
192        parser.advance();
193
194    let value = match token.kind {
195            TokenKind::Identifier => Value::Identifier(token.lexeme.clone()),
196            TokenKind::String => Value::String(token.lexeme.clone()),
197            TokenKind::Number => Value::Number(token.lexeme.parse::<f32>().unwrap_or(0.0)),
198            TokenKind::LBrace => {
199        // Handle map literal (supports nested maps)
200        let map_val = parse_map_literal(parser);
201        // We consumed the matching '}', so outer map_depth should be decremented
202        // if the caller tracks it.
203        map_val
204            }
205            _ => Value::Unknown,
206        };
207
208        args.push(value);
209
210        // Stop if we reach the end of the statement
211    if paren_depth == 0 && (token.kind == TokenKind::RParen || token.kind == TokenKind::RBrace) {
212            break;
213        }
214    }
215
216    Statement {
217        kind: StatementKind::ArrowCall {
218            target: target_token.lexeme.clone(),
219            method: method_token.lexeme.clone(),
220            args,
221        },
222        value: Value::Null,
223        indent: target_token.indent,
224        line: target_token.line,
225        column: target_token.column,
226    }
227}