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