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