devalang_wasm/language/syntax/parser/driver/statements/
advanced.rs1use super::super::helpers::{parse_function_args, parse_map_value};
2use crate::language::syntax::ast::{Statement, StatementKind, Value};
3use anyhow::{Result, anyhow};
5use std::collections::HashMap;
6
7pub fn parse_arrow_call(line: &str, line_number: usize) -> Result<Statement> {
10 let parts: Vec<&str> = line.split("->").map(|s| s.trim()).collect();
12
13 if parts.len() < 2 {
14 return Err(anyhow!("Arrow call requires at least one '->' operator"));
15 }
16
17 let target = parts[0].to_string();
19
20 let mut calls = Vec::new();
22
23 for method_call in &parts[1..] {
24 if let Some(paren_idx) = method_call.find('(') {
26 let mut method_name = method_call[..paren_idx].trim().to_string();
27 if method_name == "vel" {
29 method_name = "velocity".to_string();
30 }
31 let args_str = &method_call[paren_idx + 1..];
32
33 let close_paren = args_str
35 .rfind(')')
36 .ok_or_else(|| anyhow!("Missing closing parenthesis in arrow call"))?;
37
38 let args_str = &args_str[..close_paren];
39
40 let args = if args_str.trim().is_empty() {
42 Vec::new()
43 } else {
44 parse_function_args(args_str)?
45 };
46
47 calls.push((method_name.to_string(), args));
48 } else {
49 calls.push((method_call.trim().to_string(), Vec::new()));
51 }
52 }
53
54 if calls.is_empty() {
59 return Err(anyhow!("No method calls found in arrow call"));
60 }
61
62 let (method, args) = calls[0].clone();
63
64 let mut chain_value = HashMap::new();
66 chain_value.insert("target".to_string(), Value::String(target.clone()));
67 chain_value.insert("method".to_string(), Value::String(method.clone()));
68 chain_value.insert("args".to_string(), Value::Array(args.clone()));
69
70 if calls.len() > 1 {
72 let chain_calls: Vec<Value> = calls[1..]
73 .iter()
74 .map(|(m, a)| {
75 let mut call_map = HashMap::new();
76 call_map.insert("method".to_string(), Value::String(m.clone()));
77 call_map.insert("args".to_string(), Value::Array(a.clone()));
78 Value::Map(call_map)
79 })
80 .collect();
81
82 chain_value.insert("chain".to_string(), Value::Array(chain_calls));
83 }
84
85 Ok(Statement::new(
86 StatementKind::ArrowCall {
87 target,
88 method,
89 args,
90 },
91 Value::Map(chain_value),
92 0,
93 line_number,
94 1,
95 ))
96}
97
98pub fn parse_assign(line: &str, line_number: usize) -> Result<Statement> {
100 let assign_parts: Vec<&str> = line.splitn(2, '=').collect();
101 if assign_parts.len() != 2 {
102 return Err(anyhow!("Invalid assignment syntax"));
103 }
104
105 let left = assign_parts[0].trim();
106 let right = assign_parts[1].trim();
107
108 let prop_parts: Vec<&str> = left.splitn(2, '.').collect();
110 if prop_parts.len() != 2 {
111 return Err(anyhow!("Assignment requires target.property syntax"));
112 }
113
114 let target = prop_parts[0].trim().to_string();
115 let property = prop_parts[1].trim().to_string();
116
117 let value = if let Ok(num) = right.parse::<f32>() {
119 Value::Number(num)
120 } else if right.starts_with('"') && right.ends_with('"') {
121 Value::String(right.trim_matches('"').to_string())
122 } else {
123 Value::Identifier(right.to_string())
124 };
125
126 Ok(Statement::new(
127 StatementKind::Assign { target, property },
128 value,
129 0,
130 line_number,
131 1,
132 ))
133}
134
135pub fn parse_bind(line: &str, line_number: usize) -> Result<Statement> {
137 let after_bind = line
145 .trim()
146 .strip_prefix("bind")
147 .ok_or_else(|| anyhow!("bind parsing error"))?
148 .trim();
149
150 let arrow_parts: Vec<&str> = after_bind.splitn(2, "->").collect();
151 if arrow_parts.len() != 2 {
152 return Err(anyhow!("bind requires source -> target syntax"));
153 }
154
155 let left_raw = arrow_parts[0].trim();
157 let right_raw = arrow_parts[1].trim();
158
159 fn extract_with(side: &str) -> Result<(String, Option<Value>)> {
161 let s = side.trim();
162 if let Some(with_pos) = s.find("with") {
164 let before = s[..with_pos].trim().to_string();
165 let after = s[with_pos + "with".len()..].trim();
166 if after.starts_with('{') {
167 if let Some(close_brace) = after.rfind('}') {
168 let options_str = &after[..close_brace + 1];
169 let options = parse_map_value(options_str)?;
170 return Ok((before, Some(options)));
171 } else {
172 return Err(anyhow!("unclosed brace in bind options"));
173 }
174 }
175 }
176 Ok((s.to_string(), None))
178 }
179
180 let (source_candidate, left_opts) = extract_with(left_raw)?;
181 let (target_candidate, right_opts) = extract_with(right_raw)?;
182
183 let merged_options = match (left_opts, right_opts) {
185 (Some(mut l), Some(r)) => {
186 if let (Value::Map(lm), Value::Map(rm)) = (&mut l, &r) {
188 for (k, v) in rm.iter() {
189 lm.insert(k.clone(), v.clone());
190 }
191 Some(l)
192 } else {
193 Some(r)
194 }
195 }
196 (Some(l), None) => Some(l),
197 (None, Some(r)) => Some(r),
198 (None, None) => None,
199 };
200
201 let source = source_candidate;
202 let target = target_candidate;
203
204 Ok(Statement::new(
205 StatementKind::Bind { source, target },
206 merged_options.unwrap_or(Value::Null),
207 0,
208 line_number,
209 1,
210 ))
211}