1use crate::CapId;
2use serde::{Deserialize, Deserializer, Serialize, Serializer};
3use serde_json::Value;
4
5#[derive(Debug, Clone, PartialEq)]
8pub enum ILExpression {
9 Literal(Value),
11
12 Variable { var_ref: u32 },
14
15 Plan { plan: ILPlan },
17
18 Bind { bind: BindExpression },
20
21 If { if_expr: Box<IfExpression> },
23
24 Get { get: GetExpression },
26
27 Call { call: CallExpression },
29
30 MapOp { map: MapExpression },
32
33 FilterOp { filter: FilterExpression },
35
36 ReduceOp { reduce: ReduceExpression },
38}
39
40impl Serialize for ILExpression {
42 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
43 where
44 S: Serializer,
45 {
46 use serde_json::json;
47
48 let value = match self {
49 ILExpression::Literal(v) => v.clone(),
50 ILExpression::Variable { var_ref } => json!(["var", var_ref]),
51 ILExpression::Plan { plan } => {
52 let mut arr = vec![json!("plan")];
53 arr.push(json!(plan.captures));
55 arr.push(json!(plan.operations));
56 arr.push(serde_json::to_value(&*plan.result).unwrap());
57 Value::Array(arr)
58 }
59 ILExpression::Bind { bind } => {
60 json!(["bind", bind.value, bind.body])
61 }
62 ILExpression::If { if_expr } => {
63 json!([
64 "if",
65 if_expr.condition,
66 if_expr.then_branch,
67 if_expr.else_branch
68 ])
69 }
70 ILExpression::Get { get } => {
71 json!(["get", get.object, get.property])
72 }
73 ILExpression::Call { call } => {
74 let mut arr = vec![
75 json!("call"),
76 serde_json::to_value(&*call.target).unwrap(),
77 json!(call.method),
78 ];
79 for arg in &call.args {
80 arr.push(serde_json::to_value(arg).unwrap());
81 }
82 Value::Array(arr)
83 }
84 ILExpression::MapOp { map } => {
85 json!(["map", map.array, map.function])
86 }
87 ILExpression::FilterOp { filter } => {
88 json!(["filter", filter.array, filter.predicate])
89 }
90 ILExpression::ReduceOp { reduce } => {
91 json!(["reduce", reduce.array, reduce.function, reduce.initial])
92 }
93 };
94
95 value.serialize(serializer)
96 }
97}
98
99impl<'de> Deserialize<'de> for ILExpression {
101 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
102 where
103 D: Deserializer<'de>,
104 {
105 let value = Value::deserialize(deserializer)?;
106
107 if let Value::Array(arr) = &value {
109 if !arr.is_empty() {
110 if let Some(Value::String(type_str)) = arr.first() {
111 return match type_str.as_str() {
112 "var" => {
113 if arr.len() != 2 {
114 return Err(serde::de::Error::custom(
115 "var requires exactly 2 elements",
116 ));
117 }
118 let index = arr[1].as_u64().ok_or_else(|| {
119 serde::de::Error::custom("var index must be a number")
120 })? as u32;
121 Ok(ILExpression::Variable { var_ref: index })
122 }
123 "bind" => {
124 if arr.len() != 3 {
125 return Err(serde::de::Error::custom(
126 "bind requires exactly 3 elements",
127 ));
128 }
129 let value = Box::new(
130 serde_json::from_value(arr[1].clone())
131 .map_err(serde::de::Error::custom)?,
132 );
133 let body = Box::new(
134 serde_json::from_value(arr[2].clone())
135 .map_err(serde::de::Error::custom)?,
136 );
137 Ok(ILExpression::Bind {
138 bind: BindExpression { value, body },
139 })
140 }
141 "if" => {
142 if arr.len() != 4 {
143 return Err(serde::de::Error::custom(
144 "if requires exactly 4 elements",
145 ));
146 }
147 let condition = Box::new(
148 serde_json::from_value(arr[1].clone())
149 .map_err(serde::de::Error::custom)?,
150 );
151 let then_branch = Box::new(
152 serde_json::from_value(arr[2].clone())
153 .map_err(serde::de::Error::custom)?,
154 );
155 let else_branch = Box::new(
156 serde_json::from_value(arr[3].clone())
157 .map_err(serde::de::Error::custom)?,
158 );
159 Ok(ILExpression::If {
160 if_expr: Box::new(IfExpression {
161 condition,
162 then_branch,
163 else_branch,
164 }),
165 })
166 }
167 "get" => {
168 if arr.len() != 3 {
169 return Err(serde::de::Error::custom(
170 "get requires exactly 3 elements",
171 ));
172 }
173 let object = Box::new(
174 serde_json::from_value(arr[1].clone())
175 .map_err(serde::de::Error::custom)?,
176 );
177 let property = arr[2]
178 .as_str()
179 .ok_or_else(|| {
180 serde::de::Error::custom("get property must be a string")
181 })?
182 .to_string();
183 Ok(ILExpression::Get {
184 get: GetExpression { object, property },
185 })
186 }
187 "call" => {
188 if arr.len() < 3 {
189 return Err(serde::de::Error::custom(
190 "call requires at least 3 elements",
191 ));
192 }
193 let target = Box::new(
194 serde_json::from_value(arr[1].clone())
195 .map_err(serde::de::Error::custom)?,
196 );
197 let method = arr[2]
198 .as_str()
199 .ok_or_else(|| {
200 serde::de::Error::custom("call method must be a string")
201 })?
202 .to_string();
203 let args = arr[3..]
204 .iter()
205 .map(|v| serde_json::from_value(v.clone()))
206 .collect::<Result<Vec<_>, _>>()
207 .map_err(serde::de::Error::custom)?;
208 Ok(ILExpression::Call {
209 call: CallExpression {
210 target,
211 method,
212 args,
213 },
214 })
215 }
216 "map" => {
217 if arr.len() != 3 {
218 return Err(serde::de::Error::custom(
219 "map requires exactly 3 elements",
220 ));
221 }
222 let array = Box::new(
223 serde_json::from_value(arr[1].clone())
224 .map_err(serde::de::Error::custom)?,
225 );
226 let function = Box::new(
227 serde_json::from_value(arr[2].clone())
228 .map_err(serde::de::Error::custom)?,
229 );
230 Ok(ILExpression::MapOp {
231 map: MapExpression { array, function },
232 })
233 }
234 "filter" => {
235 if arr.len() != 3 {
236 return Err(serde::de::Error::custom(
237 "filter requires exactly 3 elements",
238 ));
239 }
240 let array = Box::new(
241 serde_json::from_value(arr[1].clone())
242 .map_err(serde::de::Error::custom)?,
243 );
244 let predicate = Box::new(
245 serde_json::from_value(arr[2].clone())
246 .map_err(serde::de::Error::custom)?,
247 );
248 Ok(ILExpression::FilterOp {
249 filter: FilterExpression { array, predicate },
250 })
251 }
252 "reduce" => {
253 if arr.len() != 4 {
254 return Err(serde::de::Error::custom(
255 "reduce requires exactly 4 elements",
256 ));
257 }
258 let array = Box::new(
259 serde_json::from_value(arr[1].clone())
260 .map_err(serde::de::Error::custom)?,
261 );
262 let function = Box::new(
263 serde_json::from_value(arr[2].clone())
264 .map_err(serde::de::Error::custom)?,
265 );
266 let initial = Box::new(
267 serde_json::from_value(arr[3].clone())
268 .map_err(serde::de::Error::custom)?,
269 );
270 Ok(ILExpression::ReduceOp {
271 reduce: ReduceExpression {
272 array,
273 function,
274 initial,
275 },
276 })
277 }
278 "plan" => {
279 if arr.len() != 4 {
280 return Err(serde::de::Error::custom(
281 "plan requires exactly 4 elements",
282 ));
283 }
284 let captures = serde_json::from_value(arr[1].clone())
285 .map_err(serde::de::Error::custom)?;
286 let operations = serde_json::from_value(arr[2].clone())
287 .map_err(serde::de::Error::custom)?;
288 let result = Box::new(
289 serde_json::from_value(arr[3].clone())
290 .map_err(serde::de::Error::custom)?,
291 );
292 Ok(ILExpression::Plan {
293 plan: ILPlan {
294 captures,
295 operations,
296 result,
297 },
298 })
299 }
300 _ => Ok(ILExpression::Literal(value)),
301 };
302 }
303 }
304 }
305
306 Ok(ILExpression::Literal(value))
308 }
309}
310
311#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
312pub struct ILPlan {
313 pub captures: Vec<CapId>,
314 pub operations: Vec<ILOperation>,
315 pub result: Box<ILExpression>,
316}
317
318#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
319pub struct BindExpression {
320 pub value: Box<ILExpression>,
321 pub body: Box<ILExpression>,
322}
323
324#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
325pub struct IfExpression {
326 pub condition: Box<ILExpression>,
327 pub then_branch: Box<ILExpression>,
328 pub else_branch: Box<ILExpression>,
329}
330
331#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
332pub struct GetExpression {
333 pub object: Box<ILExpression>,
334 pub property: String,
335}
336
337#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
338pub struct CallExpression {
339 pub target: Box<ILExpression>,
340 pub method: String,
341 pub args: Vec<ILExpression>,
342}
343
344#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
345pub struct MapExpression {
346 pub array: Box<ILExpression>,
347 pub function: Box<ILExpression>,
348}
349
350#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
351pub struct FilterExpression {
352 pub array: Box<ILExpression>,
353 pub predicate: Box<ILExpression>,
354}
355
356#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
357pub struct ReduceExpression {
358 pub array: Box<ILExpression>,
359 pub function: Box<ILExpression>,
360 pub initial: Box<ILExpression>,
361}
362
363#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
365#[serde(untagged)]
366pub enum ILOperation {
367 Store { store: StoreOperation },
369
370 Execute { execute: Box<ILExpression> },
372}
373
374#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
375pub struct StoreOperation {
376 pub slot: u32,
377 pub value: Box<ILExpression>,
378}
379
380pub struct ILContext {
382 pub variables: Vec<Value>,
383 pub captures: Vec<CapId>,
384}
385
386impl ILContext {
387 pub fn new(captures: Vec<CapId>) -> Self {
388 Self {
389 variables: Vec::new(),
390 captures,
391 }
392 }
393
394 pub fn with_capacity(capacity: usize, captures: Vec<CapId>) -> Self {
395 Self {
396 variables: Vec::with_capacity(capacity),
397 captures,
398 }
399 }
400
401 pub fn get_variable(&self, index: u32) -> Option<&Value> {
402 self.variables.get(index as usize)
403 }
404
405 pub fn set_variable(&mut self, index: u32, value: Value) -> Result<(), ILError> {
406 let idx = index as usize;
407 if idx >= self.variables.len() {
408 self.variables.resize_with(idx + 1, || Value::Null);
409 }
410 self.variables[idx] = value;
411 Ok(())
412 }
413
414 pub fn push_variable(&mut self, value: Value) -> u32 {
415 let index = self.variables.len() as u32;
416 self.variables.push(value);
417 index
418 }
419
420 pub fn get_capture(&self, index: u32) -> Option<&CapId> {
421 self.captures.get(index as usize)
422 }
423}
424
425#[derive(Debug, thiserror::Error)]
426pub enum ILError {
427 #[error("Variable not found: {0}")]
428 VariableNotFound(u32),
429
430 #[error("Capture not found: {0}")]
431 CaptureNotFound(u32),
432
433 #[error("Type error: expected {expected}, got {actual}")]
434 TypeError { expected: String, actual: String },
435
436 #[error("Execution failed: {0}")]
437 ExecutionFailed(String),
438
439 #[error("Invalid operation: {0}")]
440 InvalidOperation(String),
441}
442
443impl ILExpression {
444 pub fn var(index: u32) -> Self {
446 ILExpression::Variable { var_ref: index }
447 }
448
449 pub fn literal(value: Value) -> Self {
451 ILExpression::Literal(value)
452 }
453
454 pub fn bind(value: ILExpression, body: ILExpression) -> Self {
456 ILExpression::Bind {
457 bind: BindExpression {
458 value: Box::new(value),
459 body: Box::new(body),
460 },
461 }
462 }
463
464 pub fn if_expr(
466 condition: ILExpression,
467 then_branch: ILExpression,
468 else_branch: ILExpression,
469 ) -> Self {
470 ILExpression::If {
471 if_expr: Box::new(IfExpression {
472 condition: Box::new(condition),
473 then_branch: Box::new(then_branch),
474 else_branch: Box::new(else_branch),
475 }),
476 }
477 }
478
479 pub fn get(object: ILExpression, property: String) -> Self {
481 ILExpression::Get {
482 get: GetExpression {
483 object: Box::new(object),
484 property,
485 },
486 }
487 }
488
489 pub fn call(target: ILExpression, method: String, args: Vec<ILExpression>) -> Self {
491 ILExpression::Call {
492 call: CallExpression {
493 target: Box::new(target),
494 method,
495 args,
496 },
497 }
498 }
499
500 pub fn map(array: ILExpression, function: ILExpression) -> Self {
502 ILExpression::MapOp {
503 map: MapExpression {
504 array: Box::new(array),
505 function: Box::new(function),
506 },
507 }
508 }
509}
510
511#[cfg(test)]
512mod tests {
513 use super::*;
514 use serde_json::json;
515
516 #[test]
517 fn test_variable_expression() {
518 let expr = ILExpression::var(0);
519 let json = serde_json::to_value(&expr).unwrap();
520 assert_eq!(json, json!(["var", 0]));
521
522 let deserialized: ILExpression = serde_json::from_value(json).unwrap();
523 assert_eq!(expr, deserialized);
524 }
525
526 #[test]
527 fn test_bind_expression() {
528 let expr = ILExpression::bind(ILExpression::literal(json!(42)), ILExpression::var(0));
529
530 let json = serde_json::to_value(&expr).unwrap();
531 let deserialized: ILExpression = serde_json::from_value(json).unwrap();
532 assert_eq!(expr, deserialized);
533 }
534
535 #[test]
536 fn test_if_expression() {
537 let expr = ILExpression::if_expr(
538 ILExpression::var(0),
539 ILExpression::literal(json!("true branch")),
540 ILExpression::literal(json!("false branch")),
541 );
542
543 let json = serde_json::to_value(&expr).unwrap();
544 let deserialized: ILExpression = serde_json::from_value(json).unwrap();
545 assert_eq!(expr, deserialized);
546 }
547
548 #[test]
549 fn test_map_expression() {
550 let expr = ILExpression::map(
551 ILExpression::var(0),
552 ILExpression::bind(
553 ILExpression::var(1),
554 ILExpression::call(ILExpression::var(1), "toString".to_string(), vec![]),
555 ),
556 );
557
558 let json = serde_json::to_value(&expr).unwrap();
559 let deserialized: ILExpression = serde_json::from_value(json).unwrap();
560 assert_eq!(expr, deserialized);
561 }
562
563 #[test]
564 fn test_il_context() {
565 let mut context = ILContext::new(vec![CapId::new(1)]);
566
567 context.set_variable(0, json!("first")).unwrap();
568 context.set_variable(2, json!("third")).unwrap();
569
570 assert_eq!(context.get_variable(0), Some(&json!("first")));
571 assert_eq!(context.get_variable(1), Some(&Value::Null));
572 assert_eq!(context.get_variable(2), Some(&json!("third")));
573
574 let index = context.push_variable(json!("pushed"));
575 assert_eq!(index, 3);
576 assert_eq!(context.get_variable(3), Some(&json!("pushed")));
577 }
578}