1use crate::*;
2use std::collections::HashMap;
3
4pub type Environment = HashMap<u64, Value>;
8
9pub fn expression(expr: &Expression, env: Option<&Environment>, p: &Interpreter) -> MResult<Value> {
10 match &expr {
11 #[cfg(feature = "variables")]
12 Expression::Var(v) => var(v, env, p),
13 #[cfg(feature = "range")]
14 Expression::Range(rng) => range(&rng, env, p),
15 #[cfg(all(feature = "subscript_slice", feature = "access"))]
16 Expression::Slice(slc) => slice(&slc, env, p),
17 #[cfg(feature = "formulas")]
18 Expression::Formula(fctr) => factor(fctr, env, p),
19 Expression::Structure(strct) => structure(strct, env, p),
20 Expression::Literal(ltrl) => literal(<rl, p),
21 #[cfg(feature = "functions")]
22 Expression::FunctionCall(fxn_call) => function_call(fxn_call, p),
23 #[cfg(feature = "set_comprehensions")]
24 Expression::SetComprehension(set_comp) => set_comprehension(set_comp, p),
25 x => Err(MechError2::new(
27 FeatureNotEnabledError,
28 None
29 ).with_compiler_loc().with_tokens(x.tokens())),
30 }
31}
32
33pub fn pattern_match_value(pattern: &Pattern, value: &Value, env: &mut Environment) -> MResult<()> {
34 match pattern {
35 Pattern::Wildcard => Ok(()),
36 Pattern::Expression(expr) => match expr {
37 Expression::Var(var) => {
38 let id = &var.name.hash();
39 match env.get(id) {
40 Some(existing) if existing == value => Ok(()),
41 Some(existing) => {
42 Err(MechError2::new(
43 PatternMatchError {
44 var: var.name.to_string(),
45 expected: existing.to_string(),
46 found: value.to_string(),
47 },
48 None
49 ).with_compiler_loc())
50 }
51 None => {
52 env.insert(id.clone(), value.clone());
53 Ok(())
54 }
55 }
56 },
57 _ => todo!("Unsupported expression in pattern"),
58 },
59 #[cfg(feature = "tuple")]
60 Pattern::Tuple(pat_tuple) => {
61 match value {
62 Value::Tuple(values) => {
63 let values_brrw = values.borrow();
64 if pat_tuple.0.len() != values_brrw.elements.len() {
65 return Err(MechError2::new(
66 ArityMismatchError{
67 expected: pat_tuple.0.len(),
68 found: values_brrw.elements.len(),
69 },
70 None
71 ).with_compiler_loc());
72 }
73 for (pttrn, val) in pat_tuple.0.iter().zip(values_brrw.elements.iter()) {
74 pattern_match_value(pttrn, val, env)?;
75 }
76 Ok(())
77 }
78 _ => Err(MechError2::new(
79 PatternExpectedTupleError{
80 found: value.kind(),
81 },
82 None
83 ).with_compiler_loc()),
84 }
85 },
86 Pattern::TupleStruct(pat_struct) => {
87 todo!("Implement tuple struct pattern matching")
88 },
89 _ => {
90 Err(MechError2::new(
91 FeatureNotEnabledError,
92 None
93 ).with_compiler_loc())
94 }
95 }
96}
97
98#[cfg(feature = "set_comprehensions")]
99pub fn set_comprehension(set_comp: &SetComprehension,p: &Interpreter) -> MResult<Value> {
100 let mut envs: Vec<Environment> = vec![HashMap::new()];
101 let comprehension_id = hash_str(&format!("{:?}", set_comp));
102 let mut new_p = p.clone();
103 new_p.id = comprehension_id;
104 new_p.clear_plan();
105 for qual in &set_comp.qualifiers {
107 envs = match qual {
108 ComprehensionQualifier::Generator((pttrn, expr)) => {
109 let mut new_envs = Vec::new();
110 for env in &envs {
111 let collection = expression(expr, Some(env), &new_p)?;
113 match collection {
114 Value::Set(mset) => {
115 let set_brrw = mset.borrow();
116
117 for elmnt in set_brrw.set.iter() {
118 let mut new_env = env.clone();
119
120 if pattern_match_value(pttrn, elmnt, &mut new_env).is_ok() {
122 new_envs.push(new_env);
123 }
124 }
126 }
127 Value::MutableReference(ref_set) => {
128 let ref_set_brrw = ref_set.borrow();
129 match &*ref_set_brrw {
130 Value::Set(mset) => {
131 let set_brrw = mset.borrow();
132
133 for elmnt in set_brrw.set.iter() {
134 let mut new_env = env.clone();
135
136 if pattern_match_value(pttrn, elmnt, &mut new_env).is_ok() {
138 new_envs.push(new_env);
139 }
140 }
142 }
143 x => return Err(MechError2::new(
144 SetComprehensionGeneratorError{
145 found: x.kind(),
146 },
147 None
148 ).with_compiler_loc()),
149 }
150 }
151 x => return Err(MechError2::new(
152 SetComprehensionGeneratorError{
153 found: x.kind(),
154 },
155 None
156 ).with_compiler_loc()),
157 }
158 }
159 new_envs
160 }
161 ComprehensionQualifier::Filter(expr) => {
162 envs
164 .into_iter()
165 .filter(|env| {
166 let result = expression(expr, Some(env), &new_p);
167 match result {
168 Ok(Value::Bool(v)) => v.borrow().clone(),
169 Ok(x) => {
170 false
171 }
172 Err(_) => false,
173 }
174 })
175 .collect()
176 }
177 ComprehensionQualifier::Let(var_def) => {
178 envs.into_iter()
179 .map(|mut env| -> MResult<_> {
180 let val = expression(&var_def.expression, Some(&env), &new_p)?;
181 env.insert(var_def.var.name.hash(), val);
182 Ok(env)
183 })
184 .collect::<MResult<Vec<_>>>()?
185 }
186 };
187 }
188 let mut result_set = IndexSet::new();
190 for env in envs {
191 let val = expression(&set_comp.expression, Some(&env), &new_p)?;
192 if !result_set.contains(&val) {
193 result_set.insert(val);
194 }
195 }
196 Ok(Value::Set(Ref::new(MechSet::from_set(result_set))))
197}
198
199
200#[cfg(feature = "range")]
201pub fn range(rng: &RangeExpression, env: Option<&Environment>, p: &Interpreter) -> MResult<Value> {
202 let plan = p.plan();
203 let start = factor(&rng.start, env, p)?;
204 let terminal = factor(&rng.terminal, env, p)?;
205 let new_fxn = match &rng.operator {
206 #[cfg(feature = "range_exclusive")]
207 RangeOp::Exclusive => RangeExclusive{}.compile(&vec![start,terminal])?,
208 #[cfg(feature = "range_inclusive")]
209 RangeOp::Inclusive => RangeInclusive{}.compile(&vec![start,terminal])?,
210 x => unreachable!(),
211 };
212 let mut plan_brrw = plan.borrow_mut();
213 plan_brrw.push(new_fxn);
214 let step = plan_brrw.last().unwrap();
215 step.solve();
216 let res = step.out();
217 Ok(res)
218}
219
220#[cfg(all(feature = "subscript_slice", feature = "access"))]
221pub fn slice(slc: &Slice, env: Option<&Environment>,p: &Interpreter) -> MResult<Value> {
222 let id = slc.name.hash();
223 let val: Value = if let Some(env) = env {
224 if let Some(val) = env.get(&id) {
225 val.clone()
226 } else {
227 match p.symbols().borrow().get(id) {
229 Some(val) => Value::MutableReference(val.clone()),
230 None => {
231 return Err(MechError2::new(
232 UndefinedVariableError { id },
233 None,
234 )
235 .with_compiler_loc()
236 .with_tokens(slc.tokens()))
237 }
238 }
239 }
240 } else {
241 match p.symbols().borrow().get(id) {
242 Some(val) => Value::MutableReference(val.clone()),
243 None => {
244 return Err(MechError2::new(
245 UndefinedVariableError { id },
246 None,
247 )
248 .with_compiler_loc()
249 .with_tokens(slc.tokens()))
250 }
251 }
252 };
253 let mut v = val;
254 for s in &slc.subscript {
255 v = subscript(s, &v, env, p)?;
256 }
257 Ok(v)
258}
259
260#[cfg(feature = "subscript_formula")]
261pub fn subscript_formula(sbscrpt: &Subscript, env: Option<&Environment>, p: &Interpreter) -> MResult<Value> {
262 match sbscrpt {
263 Subscript::Formula(fctr) => {
264 factor(fctr, env, p)
265 }
266 _ => unreachable!()
267 }
268}
269
270#[cfg(feature = "subscript_formula")]
271pub fn subscript_formula_ix(sbscrpt: &Subscript, env: Option<&Environment>, p: &Interpreter) -> MResult<Value> {
272 match sbscrpt {
273 Subscript::Formula(fctr) => {
274 let result = factor(fctr, env, p)?;
275 result.as_index()
276 }
277 _ => unreachable!()
278 }
279}
280
281#[cfg(feature = "subscript_range")]
282pub fn subscript_range(sbscrpt: &Subscript, env: Option<&Environment>, p: &Interpreter) -> MResult<Value> {
283 match sbscrpt {
284 Subscript::Range(rng) => {
285 let result = range(rng, env, p)?;
286 match result.as_vecusize() {
287 Ok(v) => Ok(v.to_value()),
288 Err(_) => Err(MechError2::new(
289 InvalidIndexKindError { kind: result.kind() },
290 None
291 ).with_compiler_loc().with_tokens(rng.tokens())
292 ),
293 }
294 }
295 _ => unreachable!()
296 }
297}
298
299#[cfg(all(feature = "subscript", feature = "access"))]
300pub fn subscript(sbscrpt: &Subscript, val: &Value, env: Option<&Environment>, p: &Interpreter) -> MResult<Value> {
301 let plan = p.plan();
302 match sbscrpt {
303 #[cfg(feature = "table")]
304 Subscript::Dot(x) => {
305 let key = x.hash();
306 let fxn_input: Vec<Value> = vec![val.clone(), Value::Id(key)];
307 let new_fxn = AccessColumn{}.compile(&fxn_input)?;
308 new_fxn.solve();
309 let res = new_fxn.out();
310 plan.borrow_mut().push(new_fxn);
311 return Ok(res);
312 },
313 Subscript::DotInt(x) => {
314 let mut fxn_input = vec![val.clone()];
315 let result = real(&x.clone());
316 fxn_input.push(result.as_index()?);
317 match val.deref_kind() {
318 #[cfg(feature = "matrix")]
319 ValueKind::Matrix(..) => {
320 let new_fxn = MatrixAccessScalar{}.compile(&fxn_input)?;
321 new_fxn.solve();
322 let res = new_fxn.out();
323 plan.borrow_mut().push(new_fxn);
324 return Ok(res);
325 },
326 #[cfg(feature = "tuple")]
327 ValueKind::Tuple(..) => {
328 let new_fxn = TupleAccess{}.compile(&fxn_input)?;
329 new_fxn.solve();
330 let res = new_fxn.out();
331 plan.borrow_mut().push(new_fxn);
332 return Ok(res);
333 },
334 _ => todo!("Implement access for dot int"),
342 }
343 },
344 #[cfg(feature = "swizzle")]
345 Subscript::Swizzle(x) => {
346 let mut keys = x.iter().map(|x| Value::Id(x.hash())).collect::<Vec<Value>>();
347 let mut fxn_input: Vec<Value> = vec![val.clone()];
348 fxn_input.append(&mut keys);
349 let new_fxn = AccessSwizzle{}.compile(&fxn_input)?;
350 new_fxn.solve();
351 let res = new_fxn.out();
352 plan.borrow_mut().push(new_fxn);
353 return Ok(res);
354 },
355 Subscript::Brace(subs) => {
356 let mut fxn_input = vec![val.clone()];
357 match &subs[..] {
358 #[cfg(feature = "subscript_formula")]
359 [Subscript::Formula(ix)] => {
360 let result = subscript_formula(&subs[0], env, p)?;
361 let shape = result.shape();
362 fxn_input.push(result);
363 match shape[..] {
364 [1, 1] => plan.borrow_mut().push(AccessScalar{}.compile(&fxn_input)?),
365 #[cfg(feature = "subscript_range")]
366 [n,1] => plan.borrow_mut().push(AccessRange{}.compile(&fxn_input)?),
367 #[cfg(feature = "subscript_range")]
368 [1,n] => plan.borrow_mut().push(AccessRange{}.compile(&fxn_input)?),
369 _ => todo!(),
370 }
371 },
372 #[cfg(feature = "subscript_range")]
373 [Subscript::Range(ix)] => {
374 let result = subscript_range(&subs[0], env, p)?;
375 fxn_input.push(result);
376 plan.borrow_mut().push(AccessRange{}.compile(&fxn_input)?);
377 },
378 _ => {
384 todo!("Implement brace subscript")
385 }
386 }
387 let plan_brrw = plan.borrow();
388 let mut new_fxn = &plan_brrw.last().unwrap();
389 new_fxn.solve();
390 let res = new_fxn.out();
391 return Ok(res);
392 }
393 #[cfg(feature = "subscript_slice")]
394 Subscript::Bracket(subs) => {
395 let mut fxn_input = vec![val.clone()];
396 match &subs[..] {
397 #[cfg(feature = "subscript_formula")]
398 [Subscript::Formula(ix)] => {
399 let result = subscript_formula_ix(&subs[0], env, p)?;
400 let shape = result.shape();
401 fxn_input.push(result);
402 match shape[..] {
403 [1,1] => plan.borrow_mut().push(AccessScalar{}.compile(&fxn_input)?),
404 #[cfg(feature = "subscript_range")]
405 [1,n] => plan.borrow_mut().push(AccessRange{}.compile(&fxn_input)?),
406 #[cfg(feature = "subscript_range")]
407 [n,1] => plan.borrow_mut().push(AccessRange{}.compile(&fxn_input)?),
408 _ => todo!(),
409 }
410 },
411 #[cfg(feature = "subscript_range")]
412 [Subscript::Range(ix)] => {
413 let result = subscript_range(&subs[0], env, p)?;
414 fxn_input.push(result);
415 plan.borrow_mut().push(AccessRange{}.compile(&fxn_input)?);
416 },
417 [Subscript::All] => {
418 fxn_input.push(Value::IndexAll);
419 #[cfg(feature = "matrix")]
420 plan.borrow_mut().push(MatrixAccessAll{}.compile(&fxn_input)?);
421 },
422 [Subscript::All,Subscript::All] => todo!(),
423 #[cfg(feature = "subscript_formula")]
424 [Subscript::Formula(ix1),Subscript::Formula(ix2)] => {
425 let result = subscript_formula_ix(&subs[0], env, p)?;
426 let shape1 = result.shape();
427 fxn_input.push(result);
428 let result = subscript_formula_ix(&subs[1], env, p)?;
429 let shape2 = result.shape();
430 fxn_input.push(result);
431 match ((shape1[0],shape1[1]),(shape2[0],shape2[1])) {
432 #[cfg(feature = "matrix")]
433 ((1,1),(1,1)) => plan.borrow_mut().push(MatrixAccessScalarScalar{}.compile(&fxn_input)?),
434 #[cfg(feature = "matrix")]
435 ((1,1),(m,1)) => plan.borrow_mut().push(MatrixAccessScalarRange{}.compile(&fxn_input)?),
436 #[cfg(feature = "matrix")]
437 ((n,1),(1,1)) => plan.borrow_mut().push(MatrixAccessRangeScalar{}.compile(&fxn_input)?),
438 #[cfg(feature = "matrix")]
439 ((n,1),(m,1)) => plan.borrow_mut().push(MatrixAccessRangeRange{}.compile(&fxn_input)?),
440 _ => unreachable!(),
441 }
442 },
443 #[cfg(feature = "subscript_range")]
444 [Subscript::Range(ix1),Subscript::Range(ix2)] => {
445 let result = subscript_range(&subs[0], env, p)?;
446 fxn_input.push(result);
447 let result = subscript_range(&subs[1], env, p)?;
448 fxn_input.push(result);
449 #[cfg(feature = "matrix")]
450 plan.borrow_mut().push(MatrixAccessRangeRange{}.compile(&fxn_input)?);
451 },
452 #[cfg(all(feature = "subscript_range", feature = "subscript_formula"))]
453 [Subscript::All,Subscript::Formula(ix2)] => {
454 fxn_input.push(Value::IndexAll);
455 let result = subscript_formula_ix(&subs[1], env, p)?;
456 let shape = result.shape();
457 fxn_input.push(result);
458 match &shape[..] {
459 #[cfg(feature = "matrix")]
460 [1,1] => plan.borrow_mut().push(MatrixAccessAllScalar{}.compile(&fxn_input)?),
461 #[cfg(feature = "matrix")]
462 [1,n] => plan.borrow_mut().push(MatrixAccessAllRange{}.compile(&fxn_input)?),
463 #[cfg(feature = "matrix")]
464 [n,1] => plan.borrow_mut().push(MatrixAccessAllRange{}.compile(&fxn_input)?),
465 _ => todo!(),
466 }
467 },
468 #[cfg(all(feature = "subscript_range", feature = "subscript_formula"))]
469 [Subscript::Formula(ix1),Subscript::All] => {
470 let result = subscript_formula_ix(&subs[0], env, p)?;
471 let shape = result.shape();
472 fxn_input.push(result);
473 fxn_input.push(Value::IndexAll);
474 match &shape[..] {
475 #[cfg(feature = "matrix")]
476 [1,1] => plan.borrow_mut().push(MatrixAccessScalarAll{}.compile(&fxn_input)?),
477 #[cfg(feature = "matrix")]
478 [1,n] => plan.borrow_mut().push(MatrixAccessRangeAll{}.compile(&fxn_input)?),
479 #[cfg(feature = "matrix")]
480 [n,1] => plan.borrow_mut().push(MatrixAccessRangeAll{}.compile(&fxn_input)?),
481 _ => todo!(),
482 }
483 },
484 #[cfg(all(feature = "subscript_range", feature = "subscript_formula"))]
485 [Subscript::Range(ix1),Subscript::Formula(ix2)] => {
486 let result = subscript_range(&subs[0], env, p)?;
487 fxn_input.push(result);
488 let result = subscript_formula_ix(&subs[1], env, p)?;
489 let shape = result.shape();
490 fxn_input.push(result);
491 match &shape[..] {
492 #[cfg(feature = "matrix")]
493 [1,1] => plan.borrow_mut().push(MatrixAccessRangeScalar{}.compile(&fxn_input)?),
494 #[cfg(feature = "matrix")]
495 [1,n] => plan.borrow_mut().push(MatrixAccessRangeRange{}.compile(&fxn_input)?),
496 #[cfg(feature = "matrix")]
497 [n,1] => plan.borrow_mut().push(MatrixAccessRangeRange{}.compile(&fxn_input)?),
498 _ => todo!(),
499 }
500 },
501 #[cfg(all(feature = "subscript_range", feature = "subscript_formula"))]
502 [Subscript::Formula(ix1),Subscript::Range(ix2)] => {
503 let result = subscript_formula_ix(&subs[0], env, p)?;
504 let shape = result.shape();
505 fxn_input.push(result);
506 let result = subscript_range(&subs[1], env, p)?;
507 fxn_input.push(result);
508 match &shape[..] {
509 #[cfg(feature = "matrix")]
510 [1,1] => plan.borrow_mut().push(MatrixAccessScalarRange{}.compile(&fxn_input)?),
511 #[cfg(feature = "matrix")]
512 [1,n] => plan.borrow_mut().push(MatrixAccessRangeRange{}.compile(&fxn_input)?),
513 #[cfg(feature = "matrix")]
514 [n,1] => plan.borrow_mut().push(MatrixAccessRangeRange{}.compile(&fxn_input)?),
515 _ => todo!(),
516 }
517 },
518 #[cfg(feature = "subscript_range")]
519 [Subscript::All,Subscript::Range(ix2)] => {
520 fxn_input.push(Value::IndexAll);
521 let result = subscript_range(&subs[1], env, p)?;
522 fxn_input.push(result);
523 #[cfg(feature = "matrix")]
524 plan.borrow_mut().push(MatrixAccessAllRange{}.compile(&fxn_input)?);
525 },
526 #[cfg(feature = "subscript_range")]
527 [Subscript::Range(ix1),Subscript::All] => {
528 let result = subscript_range(&subs[0], env, p)?;
529 fxn_input.push(result);
530 fxn_input.push(Value::IndexAll);
531 #[cfg(feature = "matrix")]
532 plan.borrow_mut().push(MatrixAccessRangeAll{}.compile(&fxn_input)?);
533 },
534 _ => unreachable!(),
535 };
536 let plan_brrw = plan.borrow();
537 let mut new_fxn = &plan_brrw.last().unwrap();
538 new_fxn.solve();
539 let res = new_fxn.out();
540 return Ok(res);
541 },
542 _ => unreachable!(),
543 }
544}
545
546#[cfg(feature = "symbol_table")]
547pub fn var(v: &Var, env: Option<&Environment>, p: &Interpreter) -> MResult<Value> {
548 let state_brrw = p.state.borrow();
549 let symbols_brrw = state_brrw.symbol_table.borrow();
550 let id = v.name.hash();
551 match env {
552 Some(env) => {
553 match env.get(&id) {
554 Some(value) => {
555 return Ok(value.clone())
556 }
557 None => {
558 match symbols_brrw.get(id) {
559 Some(value) => {
560 return Ok(Value::MutableReference(value.clone()))
561 }
562 None => {
563 return Err(MechError2::new(
564 UndefinedVariableError { id },
565 None
566 ).with_compiler_loc().with_tokens(v.tokens())
567 )
568 }
569 }
570 }
571 }
572 }
573 None => {
574 match symbols_brrw.get(id) {
575 Some(value) => {
576 return Ok(Value::MutableReference(value.clone()))
577 }
578 None => {
579 return Err(MechError2::new(
580 UndefinedVariableError { id },
581 None
582 ).with_compiler_loc().with_tokens(v.tokens())
583 )
584 }
585 }
586 }
587 }
588}
589
590#[cfg(feature = "formulas")]
591pub fn factor(fctr: &Factor, env: Option<&Environment>, p: &Interpreter) -> MResult<Value> {
592 match fctr {
593 Factor::Term(trm) => {
594 let result = term(trm, env, p)?;
595 Ok(result)
596 },
597 Factor::Parenthetical(paren) => factor(&*paren, env, p),
598 Factor::Expression(expr) => expression(expr, env, p),
599 #[cfg(feature = "math_neg")]
600 Factor::Negate(neg) => {
601 let value = factor(neg, env, p)?;
602 let new_fxn = MathNegate{}.compile(&vec![value])?;
603 new_fxn.solve();
604 let out = new_fxn.out();
605 p.state.borrow_mut().add_plan_step(new_fxn);
606 Ok(out)
607 },
608 #[cfg(feature = "logic_not")]
609 Factor::Not(neg) => {
610 let value = factor(neg, env, p)?;
611 let new_fxn = LogicNot{}.compile(&vec![value])?;
612 new_fxn.solve();
613 let out = new_fxn.out();
614 p.state.borrow_mut().add_plan_step(new_fxn);
615 Ok(out)
616 },
617 #[cfg(feature = "matrix_transpose")]
618 Factor::Transpose(fctr) => {
619 use mech_matrix::MatrixTranspose;
620 let value = factor(fctr, env, p)?;
621 let new_fxn = MatrixTranspose{}.compile(&vec![value])?;
622 new_fxn.solve();
623 let out = new_fxn.out();
624 p.state.borrow_mut().add_plan_step(new_fxn);
625 Ok(out)
626 }
627 _ => todo!(),
628 }
629}
630
631#[cfg(feature = "formulas")]
632pub fn term(trm: &Term, env: Option<&Environment>, p: &Interpreter) -> MResult<Value> {
633 let plan = p.plan();
634 let mut lhs = factor(&trm.lhs, env, p)?;
635 let mut term_plan: Vec<Box<dyn MechFunction>> = vec![];
636 for (op,rhs) in &trm.rhs {
637 let rhs = factor(&rhs, env, p)?;
638 let new_fxn: Box<dyn MechFunction> = match op {
639 #[cfg(feature = "math_add")]
641 FormulaOperator::AddSub(AddSubOp::Add) => MathAdd{}.compile(&vec![lhs,rhs])?,
642 #[cfg(feature = "math_sub")]
643 FormulaOperator::AddSub(AddSubOp::Sub) => MathSub{}.compile(&vec![lhs,rhs])?,
644 #[cfg(feature = "math_mul")]
645 FormulaOperator::MulDiv(MulDivOp::Mul) => MathMul{}.compile(&vec![lhs,rhs])?,
646 #[cfg(feature = "math_div")]
647 FormulaOperator::MulDiv(MulDivOp::Div) => MathDiv{}.compile(&vec![lhs,rhs])?,
648 #[cfg(feature = "math_mod")]
649 FormulaOperator::MulDiv(MulDivOp::Mod) => MathMod{}.compile(&vec![lhs,rhs])?,
650 #[cfg(feature = "math_pow")]
651 FormulaOperator::Power(PowerOp::Pow) => MathPow{}.compile(&vec![lhs,rhs])?,
652
653 #[cfg(feature = "matrix_matmul")]
655 FormulaOperator::Vec(VecOp::MatMul) => {
656 use mech_matrix::MatrixMatMul;
657 MatrixMatMul{}.compile(&vec![lhs,rhs])?
658 }
659 #[cfg(feature = "matrix_solve")]
660 FormulaOperator::Vec(VecOp::Solve) => MatrixSolve{}.compile(&vec![lhs,rhs])?,
661 #[cfg(feature = "matrix_cross")]
662 FormulaOperator::Vec(VecOp::Cross) => todo!(),
663 #[cfg(feature = "matrix_dot")]
664 FormulaOperator::Vec(VecOp::Dot) => MatrixDot{}.compile(&vec![lhs,rhs])?,
665
666 #[cfg(feature = "compare_eq")]
668 FormulaOperator::Comparison(ComparisonOp::Equal) => CompareEqual{}.compile(&vec![lhs,rhs])?,
669 #[cfg(feature = "compare_seq")]
670 FormulaOperator::Comparison(ComparisonOp::StrictEqual) => todo!(), #[cfg(feature = "compare_neq")]
672 FormulaOperator::Comparison(ComparisonOp::NotEqual) => CompareNotEqual{}.compile(&vec![lhs,rhs])?,
673 #[cfg(feature = "compare_sneq")]
674 FormulaOperator::Comparison(ComparisonOp::StrictNotEqual) => todo!(), #[cfg(feature = "compare_lte")]
676 FormulaOperator::Comparison(ComparisonOp::LessThanEqual) => CompareLessThanEqual{}.compile(&vec![lhs,rhs])?,
677 #[cfg(feature = "compare_gte")]
678 FormulaOperator::Comparison(ComparisonOp::GreaterThanEqual) => CompareGreaterThanEqual{}.compile(&vec![lhs,rhs])?,
679 #[cfg(feature = "compare_lt")]
680 FormulaOperator::Comparison(ComparisonOp::LessThan) => CompareLessThan{}.compile(&vec![lhs,rhs])?,
681 #[cfg(feature = "compare_gt")]
682 FormulaOperator::Comparison(ComparisonOp::GreaterThan) => CompareGreaterThan{}.compile(&vec![lhs,rhs])?,
683
684 #[cfg(feature = "logic_and")]
686 FormulaOperator::Logic(LogicOp::And) => LogicAnd{}.compile(&vec![lhs,rhs])?,
687 #[cfg(feature = "logic_or")]
688 FormulaOperator::Logic(LogicOp::Or) => LogicOr{}.compile(&vec![lhs,rhs])?,
689 #[cfg(feature = "logic_not")]
690 FormulaOperator::Logic(LogicOp::Not) => LogicNot{}.compile(&vec![lhs,rhs])?,
691 #[cfg(feature = "logic_xor")]
692 FormulaOperator::Logic(LogicOp::Xor) => LogicXor{}.compile(&vec![lhs,rhs])?,
693
694 #[cfg(feature = "table_inner_join")]
696 FormulaOperator::Table(TableOp::InnerJoin) => todo!(),
697 #[cfg(feature = "table_left_outer_join")]
698 FormulaOperator::Table(TableOp::LeftOuterJoin) => todo!(),
699 #[cfg(feature = "table_right_outer_join")]
700 FormulaOperator::Table(TableOp::RightOuterJoin) => todo!(),
701 #[cfg(feature = "table_full_outer_join")]
702 FormulaOperator::Table(TableOp::FullOuterJoin) => todo!(),
703 #[cfg(feature = "table_left_semi_join")]
704 FormulaOperator::Table(TableOp::LeftSemiJoin) => todo!(),
705 #[cfg(feature = "table_left_anti_join")]
706 FormulaOperator::Table(TableOp::LeftAntiJoin) => todo!(),
707
708 #[cfg(feature = "set_union")]
710 FormulaOperator::Set(SetOp::Union) => SetUnion{}.compile(&vec![lhs,rhs])?,
711 #[cfg(feature = "set_intersection")]
712 FormulaOperator::Set(SetOp::Intersection) => SetIntersection{}.compile(&vec![lhs,rhs])?,
713 #[cfg(feature = "set_difference")]
714 FormulaOperator::Set(SetOp::Difference) => SetDifference{}.compile(&vec![lhs,rhs])?,
715 #[cfg(feature = "set_symmetric_difference")]
716 FormulaOperator::Set(SetOp::SymmetricDifference) => SetSymmetricDifference{}.compile(&vec![lhs,rhs])?,
717 #[cfg(feature = "set_complement")]
718 FormulaOperator::Set(SetOp::Complement) => todo!(),
719 #[cfg(feature = "set_subset")]
720 FormulaOperator::Set(SetOp::Subset) => SetSubset{}.compile(&vec![lhs,rhs])?,
721 #[cfg(feature = "set_superset")]
722 FormulaOperator::Set(SetOp::Superset) => SetSuperset{}.compile(&vec![lhs,rhs])?,
723 #[cfg(feature = "set_proper_subset")]
724 FormulaOperator::Set(SetOp::ProperSubset) => SetProperSubset{}.compile(&vec![lhs,rhs])?,
725 #[cfg(feature = "set_proper_superset")]
726 FormulaOperator::Set(SetOp::ProperSuperset) => SetProperSuperset{}.compile(&vec![lhs,rhs])?,
727 #[cfg(feature = "set_element_of")]
728 FormulaOperator::Set(SetOp::ElementOf) => SetElementOf{}.compile(&vec![lhs,rhs])?,
729 #[cfg(feature = "set_not_element_of")]
730 FormulaOperator::Set(SetOp::NotElementOf) => SetNotElementOf{}.compile(&vec![lhs,rhs])?,
731 x => return Err(MechError2::new(
732 UnhandledFormulaOperatorError { operator: x.clone() },
733 None
734 ).with_compiler_loc().with_tokens(trm.tokens())
735 ),
736 };
737 new_fxn.solve();
738 let res = new_fxn.out();
739 term_plan.push(new_fxn);
740 lhs = res;
741 }
742 let mut plan_brrw = plan.borrow_mut();
743 plan_brrw.append(&mut term_plan);
744 return Ok(lhs);
745}
746
747#[derive(Debug, Clone)]
748pub struct UnhandledFormulaOperatorError {
749 pub operator: FormulaOperator,
750}
751impl MechErrorKind2 for UnhandledFormulaOperatorError {
752 fn name(&self) -> &str { "UnhandledFormulaOperator" }
753 fn message(&self) -> String {
754 format!("Unhandled formula operator: {:#?}", self.operator)
755 }
756}
757
758#[derive(Debug, Clone)]
759pub struct UndefinedVariableError {
760 pub id: u64,
761}
762impl MechErrorKind2 for UndefinedVariableError {
763 fn name(&self) -> &str { "UndefinedVariable" }
764
765 fn message(&self) -> String {
766 format!("Undefined variable: {}", self.id)
767 }
768}
769#[derive(Debug, Clone)]
770pub struct InvalidIndexKindError {
771 kind: ValueKind,
772}
773impl MechErrorKind2 for InvalidIndexKindError {
774 fn name(&self) -> &str {
775 "InvalidIndexKind"
776 }
777 fn message(&self) -> String {
778 "Invalid index kind".to_string()
779 }
780}
781
782#[derive(Debug, Clone)]
783pub struct SetComprehensionGeneratorError{
784 found: ValueKind,
785}
786
787impl MechErrorKind2 for SetComprehensionGeneratorError {
788 fn name(&self) -> &str {
789 "SetComprehensionGenerator"
790 }
791 fn message(&self) -> String {
792 format!("Set comprehension generator must produce a set, found kind: {:?}", self.found)
793 }
794}
795
796#[derive(Debug, Clone)]
797pub struct PatternExpectedTupleError{
798 found: ValueKind,
799}
800impl MechErrorKind2 for PatternExpectedTupleError {
801 fn name(&self) -> &str {
802 "PatternExpectedTuple"
803 }
804 fn message(&self) -> String {
805 format!("Pattern expected a tuple, found kind: {:?}", self.found)
806 }
807}
808
809#[derive(Debug, Clone)]
810pub struct ArityMismatchError {
811 expected: usize,
812 found: usize,
813}
814impl MechErrorKind2 for ArityMismatchError {
815 fn name(&self) -> &str {
816 "ArityMismatch"
817 }
818 fn message(&self) -> String {
819 format!("Arity mismatch: expected {}, found {}", self.expected, self.found)
820 }
821}
822
823#[derive(Debug, Clone)]
824pub struct PatternMatchError {
825 pub var: String,
826 pub expected: String,
827 pub found: String,
828}
829
830impl MechErrorKind2 for PatternMatchError {
831 fn name(&self) -> &str {
832 "PatternMatchError"
833 }
834 fn message(&self) -> String {
835 format!(
836 "Pattern match error for variable '{}': expected value {}, found value {}",
837 self.var, self.expected, self.found
838 )
839 }
840}