1use crate::*;
2
3pub 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(<rl, p),
18 #[cfg(feature = "functions")]
19 Expression::FunctionCall(fxn_call) => function_call(fxn_call, p),
20 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 _ => 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 #[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 #[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 #[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!(), #[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!(), #[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 #[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 #[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 #[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}