mech_interpreter/
expressions.rs

1use crate::*;
2
3// Expressions
4// ----------------------------------------------------------------------------
5
6pub fn expression(expr: &Expression, p: &Interpreter) -> MResult<Value> {
7  match &expr {
8    #[cfg(feature = "variables")]
9    Expression::Var(v) => var(&v, p),
10    #[cfg(feature = "range")]
11    Expression::Range(rng) => range(&rng, p),
12    #[cfg(feature = "subscript_slice")]
13    Expression::Slice(slc) => slice(&slc, p),
14    #[cfg(feature = "formulas")]
15    Expression::Formula(fctr) => factor(fctr, p),
16    Expression::Structure(strct) => structure(strct, p),
17    Expression::Literal(ltrl) => literal(&ltrl, p),
18    #[cfg(feature = "functions")]
19    Expression::FunctionCall(fxn_call) => function_call(fxn_call, p),
20    //Expression::FsmPipe(_) => todo!(),
21    x => Err(MechError{file: file!().to_string(), tokens: x.tokens(), msg: format!("Feature not enabled {:?}", x), id: line!(), kind: MechErrorKind::None}),
22  }
23}
24
25#[cfg(feature = "range")]
26pub fn range(rng: &RangeExpression, p: &Interpreter) -> MResult<Value> {
27  let plan = p.plan();
28  let start = factor(&rng.start, p)?;
29  let terminal = factor(&rng.terminal, p)?;
30  let new_fxn = match &rng.operator {
31    #[cfg(feature = "range_exclusive")]
32    RangeOp::Exclusive => RangeExclusive{}.compile(&vec![start,terminal])?,
33    #[cfg(feature = "range_inclusive")]
34    RangeOp::Inclusive => RangeInclusive{}.compile(&vec![start,terminal])?,
35    x => unreachable!(),
36  };
37  let mut plan_brrw = plan.borrow_mut();
38  plan_brrw.push(new_fxn);
39  let step = plan_brrw.last().unwrap();
40  step.solve();
41  let res = step.out();
42  Ok(res)
43}
44
45#[cfg(feature = "subscript")]
46pub fn slice(slc: &Slice, p: &Interpreter) -> MResult<Value> {
47  let symbols = p.symbols();
48  let plan = p.plan();
49  let functions = p.functions();
50  let name = slc.name.hash();
51  let symbols_brrw = symbols.borrow();
52  let val: Value = match symbols_brrw.get(name) {
53    Some(val) => Value::MutableReference(val.clone()),
54    None => {return Err(MechError{file: file!().to_string(), tokens: slc.name.tokens(), msg: "".to_string(), id: line!(), kind: MechErrorKind::UndefinedVariable(name)});}
55  };
56  let mut v = val;
57  for s in &slc.subscript {
58    let s_result = subscript(&s, &v, p)?;
59    v = s_result;
60  }
61  return Ok(v);
62}
63
64#[cfg(feature = "subscript_formula")]
65pub fn subscript_formula(sbscrpt: &Subscript, p: &Interpreter) -> MResult<Value> {
66  match sbscrpt {
67    Subscript::Formula(fctr) => {
68      let result = factor(fctr,p)?;
69      result.as_index()
70    }
71    _ => unreachable!()
72  }
73}
74
75#[cfg(feature = "subscript_range")]
76pub fn subscript_range(sbscrpt: &Subscript, p: &Interpreter) -> MResult<Value> {
77  match sbscrpt {
78    Subscript::Range(rng) => {
79      let result = range(rng,p)?;
80      match result.as_vecusize() {
81        Some(v) => Ok(v.to_value()),
82        None => Err(MechError{file: file!().to_string(), tokens: rng.tokens(), msg: "".to_string(), id: line!(), kind: MechErrorKind::UnhandledIndexKind}),
83      }
84    }
85    _ => unreachable!()
86  }
87}
88
89#[cfg(feature = "subscript")]
90pub fn subscript(sbscrpt: &Subscript, val: &Value, p: &Interpreter) -> MResult<Value> {
91  let plan = p.plan();
92  match sbscrpt {
93    #[cfg(feature = "table")]
94    Subscript::Dot(x) => {
95      let key = x.hash();
96      let fxn_input: Vec<Value> = vec![val.clone(), Value::Id(key)];
97      let new_fxn = AccessColumn{}.compile(&fxn_input)?;
98      new_fxn.solve();
99      let res = new_fxn.out();
100      plan.borrow_mut().push(new_fxn);
101      return Ok(res);
102    },
103    Subscript::DotInt(x) => {
104      let mut fxn_input = vec![val.clone()];
105      let result = real(&x.clone());
106      fxn_input.push(result.as_index()?);
107      match val.deref_kind() {
108        #[cfg(feature = "matrix")]
109        ValueKind::Matrix(..) => {
110          let new_fxn = MatrixAccessScalar{}.compile(&fxn_input)?;
111          new_fxn.solve();
112          let res = new_fxn.out();
113          plan.borrow_mut().push(new_fxn);
114          return Ok(res);
115        },
116        #[cfg(feature = "tuple")]
117        ValueKind::Tuple(..) => {
118          let new_fxn = TupleAccess{}.compile(&fxn_input)?;
119          new_fxn.solve();
120          let res = new_fxn.out();
121          plan.borrow_mut().push(new_fxn);
122          return Ok(res);
123        },
124        /*ValueKind::Record(_) => {
125          let new_fxn = RecordAccessScalar{}.compile(&fxn_input)?;
126          new_fxn.solve();
127          let res = new_fxn.out();
128          plan.borrow_mut().push(new_fxn);
129          return Ok(res);
130        },*/
131        _ => todo!("Implement access for dot int"),
132      }
133    },
134    #[cfg(feature = "swizzle")]
135    Subscript::Swizzle(x) => {
136      let mut keys = x.iter().map(|x| Value::Id(x.hash())).collect::<Vec<Value>>();
137      let mut fxn_input: Vec<Value> = vec![val.clone()];
138      fxn_input.append(&mut keys);
139      let new_fxn = AccessSwizzle{}.compile(&fxn_input)?;
140      new_fxn.solve();
141      let res = new_fxn.out();
142      plan.borrow_mut().push(new_fxn);
143      return Ok(res);
144    },
145    #[cfg(feature = "subscript_slice")]
146    Subscript::Brace(subs) |
147    Subscript::Bracket(subs) => {
148      let mut fxn_input = vec![val.clone()];
149      match &subs[..] {
150        [Subscript::Formula(ix)] => {
151          let result = subscript_formula(&subs[0], p)?;
152          let shape = result.shape();
153          fxn_input.push(result);
154          match shape[..] {
155            [1,1] => plan.borrow_mut().push(AccessScalar{}.compile(&fxn_input)?),
156            #[cfg(feature = "subscript_range")]
157            [1,n] => plan.borrow_mut().push(AccessRange{}.compile(&fxn_input)?),
158            #[cfg(feature = "subscript_range")]
159            [n,1] => plan.borrow_mut().push(AccessRange{}.compile(&fxn_input)?),
160            _ => todo!(),
161          }
162        },
163        #[cfg(feature = "subscript_range")]
164        [Subscript::Range(ix)] => {
165          let result = subscript_range(&subs[0],p)?;
166          fxn_input.push(result);
167          plan.borrow_mut().push(AccessRange{}.compile(&fxn_input)?);
168        },
169        #[cfg(feature = "subscript_range")]
170        [Subscript::All] => {
171          fxn_input.push(Value::IndexAll);
172          #[cfg(feature = "matrix")]
173          plan.borrow_mut().push(MatrixAccessAll{}.compile(&fxn_input)?);
174        },
175        [Subscript::All,Subscript::All] => todo!(),
176        #[cfg(feature = "subscript_range")]
177        [Subscript::Formula(ix1),Subscript::Formula(ix2)] => {
178          let result = subscript_formula(&subs[0], p)?;
179          let shape1 = result.shape();
180          fxn_input.push(result);
181          let result = subscript_formula(&subs[1], p)?;
182          let shape2 = result.shape();
183          fxn_input.push(result);
184          match ((shape1[0],shape1[1]),(shape2[0],shape2[1])) {
185            #[cfg(feature = "matrix")]
186            ((1,1),(1,1)) => plan.borrow_mut().push(MatrixAccessScalarScalar{}.compile(&fxn_input)?),
187            #[cfg(feature = "matrix")]
188            ((1,1),(m,1)) => plan.borrow_mut().push(MatrixAccessScalarRange{}.compile(&fxn_input)?),
189            #[cfg(feature = "matrix")]
190            ((n,1),(1,1)) => plan.borrow_mut().push(MatrixAccessRangeScalar{}.compile(&fxn_input)?),
191            #[cfg(feature = "matrix")]
192            ((n,1),(m,1)) => plan.borrow_mut().push(MatrixAccessRangeRange{}.compile(&fxn_input)?),
193            _ => unreachable!(),
194          }
195        },
196        #[cfg(feature = "subscript_range")]
197        [Subscript::Range(ix1),Subscript::Range(ix2)] => {
198          let result = subscript_range(&subs[0],p)?;
199          fxn_input.push(result);
200          let result = subscript_range(&subs[1],p)?;
201          fxn_input.push(result);
202          #[cfg(feature = "matrix")]
203          plan.borrow_mut().push(MatrixAccessRangeRange{}.compile(&fxn_input)?);
204        },
205        #[cfg(all(feature = "subscript_range", feature = "subscript_formula"))]
206        [Subscript::All,Subscript::Formula(ix2)] => {
207          fxn_input.push(Value::IndexAll);
208          let result = subscript_formula(&subs[1], p)?;
209          let shape = result.shape();
210          fxn_input.push(result);
211          match &shape[..] {
212            #[cfg(feature = "matrix")]
213            [1,1] => plan.borrow_mut().push(MatrixAccessAllScalar{}.compile(&fxn_input)?),
214            #[cfg(feature = "matrix")]
215            [1,n] => plan.borrow_mut().push(MatrixAccessAllRange{}.compile(&fxn_input)?),
216            #[cfg(feature = "matrix")]
217            [n,1] => plan.borrow_mut().push(MatrixAccessAllRange{}.compile(&fxn_input)?),
218            _ => todo!(),
219          }
220        },
221        #[cfg(all(feature = "subscript_range", feature = "subscript_formula"))]
222        [Subscript::Formula(ix1),Subscript::All] => {
223          let result = subscript_formula(&subs[0], p)?;
224          let shape = result.shape();
225          fxn_input.push(result);
226          fxn_input.push(Value::IndexAll);
227          match &shape[..] {
228            #[cfg(feature = "matrix")]
229            [1,1] => plan.borrow_mut().push(MatrixAccessScalarAll{}.compile(&fxn_input)?),
230            #[cfg(feature = "matrix")]
231            [1,n] => plan.borrow_mut().push(MatrixAccessRangeAll{}.compile(&fxn_input)?),
232            #[cfg(feature = "matrix")]
233            [n,1] => plan.borrow_mut().push(MatrixAccessRangeAll{}.compile(&fxn_input)?),
234            _ => todo!(),
235          }
236        },
237        #[cfg(all(feature = "subscript_range", feature = "subscript_formula"))]
238        [Subscript::Range(ix1),Subscript::Formula(ix2)] => {
239          let result = subscript_range(&subs[0],p)?;
240          fxn_input.push(result);
241          let result = subscript_formula(&subs[1], p)?;
242          let shape = result.shape();
243          fxn_input.push(result);
244          match &shape[..] {
245            #[cfg(feature = "matrix")]
246            [1,1] => plan.borrow_mut().push(MatrixAccessRangeScalar{}.compile(&fxn_input)?),
247            #[cfg(feature = "matrix")]
248            [1,n] => plan.borrow_mut().push(MatrixAccessRangeRange{}.compile(&fxn_input)?),
249            #[cfg(feature = "matrix")]
250            [n,1] => plan.borrow_mut().push(MatrixAccessRangeRange{}.compile(&fxn_input)?),
251            _ => todo!(),
252          }
253        },
254        #[cfg(all(feature = "subscript_range", feature = "subscript_formula"))]
255        [Subscript::Formula(ix1),Subscript::Range(ix2)] => {
256          let result = subscript_formula(&subs[0], p)?;
257          let shape = result.shape();
258          fxn_input.push(result);
259          let result = subscript_range(&subs[1],p)?;
260          fxn_input.push(result);
261          match &shape[..] {
262            #[cfg(feature = "matrix")]
263            [1,1] => plan.borrow_mut().push(MatrixAccessScalarRange{}.compile(&fxn_input)?),
264            #[cfg(feature = "matrix")]
265            [1,n] => plan.borrow_mut().push(MatrixAccessRangeRange{}.compile(&fxn_input)?),
266            #[cfg(feature = "matrix")]
267            [n,1] => plan.borrow_mut().push(MatrixAccessRangeRange{}.compile(&fxn_input)?),
268            _ => todo!(),
269          }
270        },
271        #[cfg(feature = "subscript_range")]
272        [Subscript::All,Subscript::Range(ix2)] => {
273          fxn_input.push(Value::IndexAll);
274          let result = subscript_range(&subs[1],p)?;
275          fxn_input.push(result);
276          #[cfg(feature = "matrix")]
277          plan.borrow_mut().push(MatrixAccessAllRange{}.compile(&fxn_input)?);
278        },
279        #[cfg(feature = "subscript_range")]
280        [Subscript::Range(ix1),Subscript::All] => {
281          let result = subscript_range(&subs[0],p)?;
282          fxn_input.push(result);
283          fxn_input.push(Value::IndexAll);
284          #[cfg(feature = "matrix")]
285          plan.borrow_mut().push(MatrixAccessRangeAll{}.compile(&fxn_input)?);
286        },
287        _ => unreachable!(),
288      };
289      let plan_brrw = plan.borrow();
290      let mut new_fxn = &plan_brrw.last().unwrap();
291      new_fxn.solve();
292      let res = new_fxn.out();
293      return Ok(res);
294    },
295    _ => unreachable!(),
296  }
297}
298
299#[cfg(feature = "symbol_table")]
300pub fn var(v: &Var, p: &Interpreter) -> MResult<Value> {
301  let state_brrw = p.state.borrow();
302  let symbols_brrw = state_brrw.symbol_table.borrow();
303  let id = v.name.hash();
304  match symbols_brrw.get(id) {
305    Some(value) => {
306      return Ok(Value::MutableReference(value.clone()))
307    }
308    None => {
309      return Err(MechError{file: file!().to_string(), tokens: v.tokens(), msg: "".to_string(), id: line!(), kind: MechErrorKind::UndefinedVariable(id)});
310    }
311  }
312}
313
314#[cfg(feature = "formulas")]
315pub fn factor(fctr: &Factor, p: &Interpreter) -> MResult<Value> {
316  match fctr {
317    Factor::Term(trm) => {
318      let result = term(trm, p)?;
319      Ok(result)
320    },
321    Factor::Parenthetical(paren) => factor(&*paren, p),
322    Factor::Expression(expr) => expression(expr, p),
323    #[cfg(feature = "math_neg")]
324    Factor::Negate(neg) => {
325      let value = factor(neg, p)?;
326      let new_fxn = MathNegate{}.compile(&vec![value])?;
327      new_fxn.solve();
328      let out = new_fxn.out();
329      p.state.borrow_mut().add_plan_step(new_fxn);
330      Ok(out)
331    },
332    #[cfg(feature = "logic_not")]
333    Factor::Not(neg) => {
334      let value = factor(neg, p)?;
335      let new_fxn = LogicNot{}.compile(&vec![value])?;
336      new_fxn.solve();
337      let out = new_fxn.out();
338      p.state.borrow_mut().add_plan_step(new_fxn);
339      Ok(out)
340    },
341    #[cfg(feature = "matrix_transpose")]
342    Factor::Transpose(fctr) => {
343      use mech_matrix::MatrixTranspose;
344      let value = factor(fctr, p)?;
345      let new_fxn = MatrixTranspose{}.compile(&vec![value])?;
346      new_fxn.solve();
347      let out = new_fxn.out();
348      p.state.borrow_mut().add_plan_step(new_fxn);
349      Ok(out)
350    }
351    _ => todo!(),
352  }
353}
354
355#[cfg(feature = "formulas")]
356pub fn term(trm: &Term, p: &Interpreter) -> MResult<Value> {
357  let plan = p.plan();
358  let mut lhs = factor(&trm.lhs, p)?;
359  let mut term_plan: Vec<Box<dyn MechFunction>> = vec![];
360  for (op,rhs) in &trm.rhs {
361    let rhs = factor(&rhs, p)?;
362    let new_fxn: Box<dyn MechFunction> = match op {
363      // Math
364      #[cfg(feature = "math_add")]
365      FormulaOperator::AddSub(AddSubOp::Add) => MathAdd{}.compile(&vec![lhs,rhs])?,
366      #[cfg(feature = "math_sub")]
367      FormulaOperator::AddSub(AddSubOp::Sub) => MathSub{}.compile(&vec![lhs,rhs])?,
368      #[cfg(feature = "math_mul")]
369      FormulaOperator::MulDiv(MulDivOp::Mul) => MathMul{}.compile(&vec![lhs,rhs])?,
370      #[cfg(feature = "math_div")]
371      FormulaOperator::MulDiv(MulDivOp::Div) => MathDiv{}.compile(&vec![lhs,rhs])?,
372      #[cfg(feature = "math_mod")]
373      FormulaOperator::MulDiv(MulDivOp::Mod) => MathMod{}.compile(&vec![lhs,rhs])?,
374      #[cfg(feature = "math_exp")]
375      FormulaOperator::Exponent(ExponentOp::Exp) => MathExp{}.compile(&vec![lhs,rhs])?,
376
377      // Matrix
378      #[cfg(feature = "matrix_matmul")]
379      FormulaOperator::Vec(VecOp::MatMul) => {
380        use mech_matrix::MatrixMatMul;
381        MatrixMatMul{}.compile(&vec![lhs,rhs])?
382      }
383      #[cfg(feature = "matrix_solve")]
384      FormulaOperator::Vec(VecOp::Solve) => todo!(),
385      #[cfg(feature = "matrix_cross")]
386      FormulaOperator::Vec(VecOp::Cross) => todo!(),
387      #[cfg(feature = "matrix_dot")]
388      FormulaOperator::Vec(VecOp::Dot) => MatrixDot{}.compile(&vec![lhs,rhs])?,
389
390      // Compare
391      #[cfg(feature = "compare_eq")]
392      FormulaOperator::Comparison(ComparisonOp::Equal) => CompareEqual{}.compile(&vec![lhs,rhs])?,
393      #[cfg(feature = "compare_seq")]
394      FormulaOperator::Comparison(ComparisonOp::StrictEqual) => todo!(), //CompareStrictEqual{}.compile(&vec![lhs,rhs])?,
395      #[cfg(feature = "compare_neq")]
396      FormulaOperator::Comparison(ComparisonOp::NotEqual) => CompareNotEqual{}.compile(&vec![lhs,rhs])?,
397      #[cfg(feature = "compare_sneq")]
398      FormulaOperator::Comparison(ComparisonOp::StrictNotEqual) => todo!(), //CompareStrictNotEqual{}.compile(&vec![lhs,rhs])?,
399      #[cfg(feature = "compare_lte")]
400      FormulaOperator::Comparison(ComparisonOp::LessThanEqual) => CompareLessThanEqual{}.compile(&vec![lhs,rhs])?,
401      #[cfg(feature = "compare_gte")]
402      FormulaOperator::Comparison(ComparisonOp::GreaterThanEqual) => CompareGreaterThanEqual{}.compile(&vec![lhs,rhs])?,
403      #[cfg(feature = "compare_lt")]
404      FormulaOperator::Comparison(ComparisonOp::LessThan) => CompareLessThan{}.compile(&vec![lhs,rhs])?,
405      #[cfg(feature = "compare_gt")]
406      FormulaOperator::Comparison(ComparisonOp::GreaterThan) => CompareGreaterThan{}.compile(&vec![lhs,rhs])?,
407
408      // Logic
409      #[cfg(feature = "logic_and")]
410      FormulaOperator::Logic(LogicOp::And) => LogicAnd{}.compile(&vec![lhs,rhs])?,
411      #[cfg(feature = "logic_or")]
412      FormulaOperator::Logic(LogicOp::Or)  => LogicOr{}.compile(&vec![lhs,rhs])?,
413      #[cfg(feature = "logic_not")]
414      FormulaOperator::Logic(LogicOp::Not) => LogicNot{}.compile(&vec![lhs,rhs])?,
415      #[cfg(feature = "logic_xor")]
416      FormulaOperator::Logic(LogicOp::Xor) => LogicXor{}.compile(&vec![lhs,rhs])?,
417      
418      // Table
419      #[cfg(feature = "table_inner_join")]
420      FormulaOperator::Table(TableOp::InnerJoin) => todo!(),
421      #[cfg(feature = "table_left_outer_join")]
422      FormulaOperator::Table(TableOp::LeftOuterJoin) => todo!(),
423      #[cfg(feature = "table_right_outer_join")]
424      FormulaOperator::Table(TableOp::RightOuterJoin) => todo!(),
425      #[cfg(feature = "table_full_outer_join")]
426      FormulaOperator::Table(TableOp::FullOuterJoin) => todo!(),
427      #[cfg(feature = "table_left_semi_join")]
428      FormulaOperator::Table(TableOp::LeftSemiJoin) => todo!(),
429      #[cfg(feature = "table_left_anti_join")]
430      FormulaOperator::Table(TableOp::LeftAntiJoin) => todo!(),
431
432      // Set
433      #[cfg(feature = "set_union")]
434      FormulaOperator::Set(SetOp::Union) => todo!(),
435      #[cfg(feature = "set_intersection")]
436      FormulaOperator::Set(SetOp::Intersection) => todo!(),
437      #[cfg(feature = "set_difference")]
438      FormulaOperator::Set(SetOp::Difference) => todo!(),
439      #[cfg(feature = "set_complement")]
440      FormulaOperator::Set(SetOp::Complement) => todo!(),
441      #[cfg(feature = "set_subset")]
442      FormulaOperator::Set(SetOp::Subset) => todo!(),
443      #[cfg(feature = "set_superset")]
444      FormulaOperator::Set(SetOp::Superset) => todo!(),
445      #[cfg(feature = "set_proper_subset")]
446      FormulaOperator::Set(SetOp::ProperSubset) => todo!(),
447      #[cfg(feature = "set_proper_superset")]
448      FormulaOperator::Set(SetOp::ProperSuperset) => todo!(),
449      #[cfg(feature = "set_element_of")]
450      FormulaOperator::Set(SetOp::ElementOf) => todo!(),
451      #[cfg(feature = "set_not_element_of")]
452      FormulaOperator::Set(SetOp::NotElementOf) => todo!(),
453      x => return Err(MechError{file: file!().to_string(), tokens: vec![], msg: format!("{x:#?}"), id: line!(), kind: MechErrorKind::UnhandledFormulaOperator(x.clone())}),
454    };
455    new_fxn.solve();
456    let res = new_fxn.out();
457    term_plan.push(new_fxn);
458    lhs = res;
459  }
460  let mut plan_brrw = plan.borrow_mut();
461  plan_brrw.append(&mut term_plan);
462  return Ok(lhs);
463}