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 method_name = method_call[..paren_idx].trim();
27 let args_str = &method_call[paren_idx + 1..];
28
29 let close_paren = args_str
31 .rfind(')')
32 .ok_or_else(|| anyhow!("Missing closing parenthesis in arrow call"))?;
33
34 let args_str = &args_str[..close_paren];
35
36 let args = if args_str.trim().is_empty() {
38 Vec::new()
39 } else {
40 parse_function_args(args_str)?
41 };
42
43 calls.push((method_name.to_string(), args));
44 } else {
45 calls.push((method_call.trim().to_string(), Vec::new()));
47 }
48 }
49
50 if calls.is_empty() {
55 return Err(anyhow!("No method calls found in arrow call"));
56 }
57
58 let (method, args) = calls[0].clone();
59
60 let mut chain_value = HashMap::new();
62 chain_value.insert("target".to_string(), Value::String(target.clone()));
63 chain_value.insert("method".to_string(), Value::String(method.clone()));
64 chain_value.insert("args".to_string(), Value::Array(args.clone()));
65
66 if calls.len() > 1 {
68 let chain_calls: Vec<Value> = calls[1..]
69 .iter()
70 .map(|(m, a)| {
71 let mut call_map = HashMap::new();
72 call_map.insert("method".to_string(), Value::String(m.clone()));
73 call_map.insert("args".to_string(), Value::Array(a.clone()));
74 Value::Map(call_map)
75 })
76 .collect();
77
78 chain_value.insert("chain".to_string(), Value::Array(chain_calls));
79 }
80
81 Ok(Statement::new(
82 StatementKind::ArrowCall {
83 target,
84 method,
85 args,
86 },
87 Value::Map(chain_value),
88 0,
89 line_number,
90 1,
91 ))
92}
93
94pub fn parse_assign(line: &str, line_number: usize) -> Result<Statement> {
96 let assign_parts: Vec<&str> = line.splitn(2, '=').collect();
97 if assign_parts.len() != 2 {
98 return Err(anyhow!("Invalid assignment syntax"));
99 }
100
101 let left = assign_parts[0].trim();
102 let right = assign_parts[1].trim();
103
104 let prop_parts: Vec<&str> = left.splitn(2, '.').collect();
106 if prop_parts.len() != 2 {
107 return Err(anyhow!("Assignment requires target.property syntax"));
108 }
109
110 let target = prop_parts[0].trim().to_string();
111 let property = prop_parts[1].trim().to_string();
112
113 let value = if let Ok(num) = right.parse::<f32>() {
115 Value::Number(num)
116 } else if right.starts_with('"') && right.ends_with('"') {
117 Value::String(right.trim_matches('"').to_string())
118 } else {
119 Value::Identifier(right.to_string())
120 };
121
122 Ok(Statement::new(
123 StatementKind::Assign { target, property },
124 value,
125 0,
126 line_number,
127 1,
128 ))
129}
130
131pub fn parse_bind(line: &str, line_number: usize) -> Result<Statement> {
133 let arrow_parts: Vec<&str> = line.splitn(2, "->").collect();
135 if arrow_parts.len() != 2 {
136 return Err(anyhow!("bind requires source -> target syntax"));
137 }
138
139 let source = arrow_parts[0]
140 .trim()
141 .strip_prefix("bind")
142 .ok_or_else(|| anyhow!("bind parsing error"))?
143 .trim()
144 .to_string();
145
146 let target_part = arrow_parts[1].trim();
147
148 let (target, options) = if let Some(brace_pos) = target_part.find('{') {
150 let target = target_part[..brace_pos].trim().to_string();
151
152 if let Some(close_brace) = target_part.rfind('}') {
154 let options_str = &target_part[brace_pos..close_brace + 1];
155 let options = parse_map_value(options_str)?;
156 (target, Some(options))
157 } else {
158 return Err(anyhow!("unclosed brace in bind options"));
159 }
160 } else {
161 (target_part.to_string(), None)
162 };
163
164 Ok(Statement::new(
165 StatementKind::Bind { source, target },
166 options.unwrap_or(Value::Null),
167 0,
168 line_number,
169 1,
170 ))
171}