1use crate::il_extended::{ILContext, ILError, ILExpression, ILOperation, ILPlan};
2use crate::RpcTarget;
3use serde_json::Value;
4use std::future::Future;
5use std::pin::Pin;
6use std::sync::Arc;
7
8pub struct ILExecutor {
10 #[allow(dead_code)] capabilities: Vec<Arc<dyn RpcTarget>>,
12}
13
14impl ILExecutor {
15 pub fn new() -> Self {
16 Self {
17 capabilities: Vec::new(),
18 }
19 }
20
21 pub fn with_capabilities(capabilities: Vec<Arc<dyn RpcTarget>>) -> Self {
22 Self { capabilities }
23 }
24
25 pub fn execute<'a>(
27 &'a self,
28 expr: &'a ILExpression,
29 context: &'a mut ILContext,
30 ) -> Pin<Box<dyn Future<Output = Result<Value, ILError>> + 'a>> {
31 Box::pin(self.execute_impl(expr, context))
32 }
33
34 async fn execute_impl(
36 &self,
37 expr: &ILExpression,
38 context: &mut ILContext,
39 ) -> Result<Value, ILError> {
40 match expr {
41 ILExpression::Literal(value) => Ok(value.clone()),
42
43 ILExpression::Variable { var_ref } => context
44 .get_variable(*var_ref)
45 .cloned()
46 .ok_or(ILError::VariableNotFound(*var_ref)),
47
48 ILExpression::Plan { plan } => self.execute_plan(plan, context).await,
49
50 ILExpression::Bind { bind } => {
51 let value = self.execute(&bind.value, context).await?;
52 let _var_index = context.push_variable(value);
53 let result = self.execute(&bind.body, context).await?;
54 Ok(result)
56 }
57
58 ILExpression::If { if_expr } => {
59 let condition = self.execute(&if_expr.condition, context).await?;
60 if self.is_truthy(&condition) {
61 self.execute(&if_expr.then_branch, context).await
62 } else {
63 self.execute(&if_expr.else_branch, context).await
64 }
65 }
66
67 ILExpression::Get { get } => {
68 let object = self.execute(&get.object, context).await?;
69 self.get_property(&object, &get.property)
70 }
71
72 ILExpression::Call { call } => {
73 let target = self.execute(&call.target, context).await?;
74 let mut args = Vec::new();
75 for arg_expr in &call.args {
76 args.push(self.execute(arg_expr, context).await?);
77 }
78 self.call_method(target, &call.method, args).await
79 }
80
81 ILExpression::MapOp { map } => {
82 let array = self.execute(&map.array, context).await?;
83 self.execute_map(array, &map.function, context).await
84 }
85
86 ILExpression::FilterOp { filter } => {
87 let array = self.execute(&filter.array, context).await?;
88 self.execute_filter(array, &filter.predicate, context).await
89 }
90
91 ILExpression::ReduceOp { reduce } => {
92 let array = self.execute(&reduce.array, context).await?;
93 let initial = self.execute(&reduce.initial, context).await?;
94 self.execute_reduce(array, &reduce.function, initial, context)
95 .await
96 }
97 }
98 }
99
100 async fn execute_plan(&self, plan: &ILPlan, context: &mut ILContext) -> Result<Value, ILError> {
102 for operation in &plan.operations {
104 match operation {
105 ILOperation::Store { store } => {
106 let value = self.execute(&store.value, context).await?;
107 context.set_variable(store.slot, value)?;
108 }
109 ILOperation::Execute { execute } => {
110 self.execute(execute, context).await?;
112 }
113 }
114 }
115
116 self.execute(&plan.result, context).await
118 }
119
120 async fn execute_map(
122 &self,
123 array: Value,
124 function: &ILExpression,
125 context: &mut ILContext,
126 ) -> Result<Value, ILError> {
127 match array {
128 Value::Array(items) => {
129 let mut results = Vec::new();
130 for item in items {
131 let var_index = context.push_variable(item);
133
134 let result = if let ILExpression::Bind { .. } = function {
136 self.execute(function, context).await?
138 } else {
139 let bind_expr =
141 ILExpression::bind(ILExpression::var(var_index), function.clone());
142 self.execute(&bind_expr, context).await?
143 };
144
145 results.push(result);
146 }
147 Ok(Value::Array(results))
148 }
149 _ => Err(ILError::TypeError {
150 expected: "array".to_string(),
151 actual: self.value_type_name(&array),
152 }),
153 }
154 }
155
156 async fn execute_filter(
158 &self,
159 array: Value,
160 predicate: &ILExpression,
161 context: &mut ILContext,
162 ) -> Result<Value, ILError> {
163 match array {
164 Value::Array(items) => {
165 let mut results = Vec::new();
166 for item in items {
167 let mut predicate_context = ILContext::new(context.captures.clone());
170 predicate_context.set_variable(0, item.clone()).unwrap();
171
172 let condition = self.execute(predicate, &mut predicate_context).await?;
174
175 if self.is_truthy(&condition) {
176 results.push(item);
177 }
178 }
179 Ok(Value::Array(results))
180 }
181 _ => Err(ILError::TypeError {
182 expected: "array".to_string(),
183 actual: self.value_type_name(&array),
184 }),
185 }
186 }
187
188 async fn execute_reduce(
190 &self,
191 array: Value,
192 function: &ILExpression,
193 mut accumulator: Value,
194 context: &mut ILContext,
195 ) -> Result<Value, ILError> {
196 match array {
197 Value::Array(items) => {
198 for item in items {
199 let acc_index = context.push_variable(accumulator.clone());
201 let item_index = context.push_variable(item);
202
203 let bind_expr = ILExpression::bind(
205 ILExpression::var(acc_index),
206 ILExpression::bind(ILExpression::var(item_index), function.clone()),
207 );
208
209 accumulator = self.execute(&bind_expr, context).await?;
210 }
211 Ok(accumulator)
212 }
213 _ => Err(ILError::TypeError {
214 expected: "array".to_string(),
215 actual: self.value_type_name(&array),
216 }),
217 }
218 }
219
220 fn get_property(&self, object: &Value, property: &str) -> Result<Value, ILError> {
222 match object {
223 Value::Object(map) => map.get(property).cloned().ok_or_else(|| {
224 ILError::ExecutionFailed(format!("Property '{}' not found", property))
225 }),
226 _ => Err(ILError::TypeError {
227 expected: "object".to_string(),
228 actual: self.value_type_name(object),
229 }),
230 }
231 }
232
233 async fn call_method(
235 &self,
236 _target: Value,
237 _method: &str,
238 _args: Vec<Value>,
239 ) -> Result<Value, ILError> {
240 Err(ILError::ExecutionFailed(
243 "Method calls require capability resolution (not yet implemented)".to_string(),
244 ))
245 }
246
247 fn is_truthy(&self, value: &Value) -> bool {
249 match value {
250 Value::Null => false,
251 Value::Bool(b) => *b,
252 Value::Number(n) => n.as_f64().map(|f| f != 0.0).unwrap_or(false),
253 Value::String(s) => !s.is_empty(),
254 Value::Array(a) => !a.is_empty(),
255 Value::Object(_) => true,
256 }
257 }
258
259 fn value_type_name(&self, value: &Value) -> String {
261 match value {
262 Value::Null => "null".to_string(),
263 Value::Bool(_) => "boolean".to_string(),
264 Value::Number(_) => "number".to_string(),
265 Value::String(_) => "string".to_string(),
266 Value::Array(_) => "array".to_string(),
267 Value::Object(_) => "object".to_string(),
268 }
269 }
270}
271
272impl Default for ILExecutor {
273 fn default() -> Self {
274 Self::new()
275 }
276}
277
278#[cfg(test)]
279mod tests {
280 use super::*;
281 use crate::il_extended::FilterExpression;
282 use serde_json::json;
283
284 #[tokio::test]
285 async fn test_execute_literal() {
286 let executor = ILExecutor::new();
287 let mut context = ILContext::new(vec![]);
288
289 let expr = ILExpression::literal(json!(42));
290 let result = executor.execute_impl(&expr, &mut context).await.unwrap();
291 assert_eq!(result, json!(42));
292 }
293
294 #[tokio::test]
295 async fn test_execute_variable() {
296 let executor = ILExecutor::new();
297 let mut context = ILContext::new(vec![]);
298 context.set_variable(0, json!("hello")).unwrap();
299
300 let expr = ILExpression::var(0);
301 let result = executor.execute_impl(&expr, &mut context).await.unwrap();
302 assert_eq!(result, json!("hello"));
303 }
304
305 #[tokio::test]
306 async fn test_execute_bind() {
307 let executor = ILExecutor::new();
308 let mut context = ILContext::new(vec![]);
309
310 let expr = ILExpression::bind(
311 ILExpression::literal(json!(100)),
312 ILExpression::var(0), );
314
315 let result = executor.execute_impl(&expr, &mut context).await.unwrap();
316 assert_eq!(result, json!(100));
317 }
318
319 #[tokio::test]
320 async fn test_execute_if() {
321 let executor = ILExecutor::new();
322 let mut context = ILContext::new(vec![]);
323
324 let expr = ILExpression::if_expr(
326 ILExpression::literal(json!(true)),
327 ILExpression::literal(json!("then")),
328 ILExpression::literal(json!("else")),
329 );
330 let result = executor.execute_impl(&expr, &mut context).await.unwrap();
331 assert_eq!(result, json!("then"));
332
333 let expr = ILExpression::if_expr(
335 ILExpression::literal(json!(false)),
336 ILExpression::literal(json!("then")),
337 ILExpression::literal(json!("else")),
338 );
339 let result = executor.execute_impl(&expr, &mut context).await.unwrap();
340 assert_eq!(result, json!("else"));
341 }
342
343 #[tokio::test]
344 async fn test_execute_get() {
345 let executor = ILExecutor::new();
346 let mut context = ILContext::new(vec![]);
347
348 let expr = ILExpression::get(
349 ILExpression::literal(json!({
350 "name": "John",
351 "age": 30
352 })),
353 "name".to_string(),
354 );
355
356 let result = executor.execute_impl(&expr, &mut context).await.unwrap();
357 assert_eq!(result, json!("John"));
358 }
359
360 #[tokio::test]
361 async fn test_execute_map() {
362 let executor = ILExecutor::new();
363 let mut context = ILContext::new(vec![]);
364
365 let expr = ILExpression::map(
367 ILExpression::literal(json!([1, 2, 3])),
368 ILExpression::var(0),
371 );
372
373 let result = executor.execute_impl(&expr, &mut context).await.unwrap();
376 assert!(matches!(result, Value::Array(_)));
377 }
378
379 #[tokio::test]
380 async fn test_execute_filter() {
381 let executor = ILExecutor::new();
382 let mut context = ILContext::new(vec![]);
383
384 let expr = ILExpression::FilterOp {
386 filter: FilterExpression {
387 array: Box::new(ILExpression::literal(json!([true, false, true]))),
388 predicate: Box::new(ILExpression::var(0)), },
390 };
391
392 let result = executor.execute_impl(&expr, &mut context).await.unwrap();
393 match result {
394 Value::Array(items) => {
395 assert_eq!(items.len(), 2);
396 assert_eq!(items[0], json!(true));
397 assert_eq!(items[1], json!(true));
398 }
399 _ => panic!("Expected array result"),
400 }
401 }
402}