mech_interpreter/
statements.rs

1use crate::*;
2use paste::paste;
3
4#[cfg(feature = "variable_define")]
5use crate::stdlib::define::*;
6
7// Statements
8// ----------------------------------------------------------------------------
9
10pub fn statement(stmt: &Statement, p: &Interpreter) -> MResult<Value> {
11  match stmt {
12    #[cfg(feature = "tuple")]
13    Statement::TupleDestructure(tpl_dstrct) => tuple_destructure(&tpl_dstrct, p),
14    #[cfg(feature = "variable_define")]
15    Statement::VariableDefine(var_def) => variable_define(&var_def, p),
16    #[cfg(feature = "variable_assign")]
17    Statement::VariableAssign(var_assgn) => variable_assign(&var_assgn, p),
18    #[cfg(feature = "kind_define")]
19    Statement::KindDefine(knd_def) => kind_define(&knd_def, p),
20    #[cfg(feature = "enum")]
21    Statement::EnumDefine(enm_def) => enum_define(&enm_def, p),
22    #[cfg(feature = "math")]
23    Statement::OpAssign(op_assgn) => op_assign(&op_assgn, p),
24    //Statement::FsmDeclare(_) => todo!(),
25    //Statement::SplitTable => todo!(),
26    //Statement::FlattenTable => todo!(),
27    x => return Err(MechError2::new(
28        FeatureNotEnabledError,
29        None
30      ).with_compiler_loc().with_tokens(x.tokens())
31    ),
32  }
33}
34
35#[cfg(feature = "tuple")]
36pub fn tuple_destructure(tpl_dstrct: &TupleDestructure, p: &Interpreter) -> MResult<Value> {
37  let source = expression(&tpl_dstrct.expression, p)?;
38  let tpl = match &source {
39    Value::Tuple(tpl) => tpl,
40    Value::MutableReference(ref r) => {
41      let r_brrw = r.borrow();
42      &match &*r_brrw {
43        Value::Tuple(tpl) => tpl.clone(),
44        _ => return Err(MechError2::new(
45          DestructureExpectedTupleError{ value: source.kind() },
46          None
47        ).with_compiler_loc().with_tokens(tpl_dstrct.expression.tokens())),
48      }
49    },
50    _ => return Err(MechError2::new(
51      DestructureExpectedTupleError{ value: source.kind() },
52      None
53    ).with_compiler_loc().with_tokens(tpl_dstrct.expression.tokens())),
54  };
55  let symbols = p.symbols();
56  let mut symbols_brrw = symbols.borrow_mut();
57  for (i, var) in tpl_dstrct.vars.iter().enumerate() {
58    let id = var.hash();
59    if symbols_brrw.contains(id) {
60      return Err(MechError2::new(
61        VariableAlreadyDefinedError { id },
62        None
63      ).with_compiler_loc().with_tokens(var.tokens()));
64    }
65    if let Some(element) = tpl.borrow().get(i) {
66      symbols_brrw.insert(id, element.clone(), true);
67      symbols_brrw.dictionary.borrow_mut().insert(id, var.name.to_string());
68    } else {
69      return Err(MechError2::new(
70        TupleDestructureTooManyVarsError{ value: source.kind() },
71        None
72      ).with_compiler_loc().with_tokens(var.tokens()));
73    }
74  }
75  Ok(source)
76}
77
78#[cfg(feature = "math")]
79pub fn op_assign(op_assgn: &OpAssign, p: &Interpreter) -> MResult<Value> {
80  let mut source = expression(&op_assgn.expression, p)?;
81  let slc = &op_assgn.target;
82  let id = slc.name.hash();
83  let sink = { 
84    let mut state_brrw = p.state.borrow_mut();
85    match state_brrw.get_symbol(id) {
86      Some(val) => val.borrow().clone(),
87      None => {return Err(MechError2::new(
88        UndefinedVariableError { id },
89        None,
90      ).with_compiler_loc().with_tokens(slc.name.tokens()));
91      }
92    }
93  };
94  match &slc.subscript {
95    Some(sbscrpt) => {
96      // todo: this only works for the first subscript, it needs to work for multiple subscripts
97      for s in sbscrpt {
98        let fxn = match op_assgn.op {
99          #[cfg(feature = "math_add_assign")]
100          OpAssignOp::Add => add_assign(&s, &sink, &source, p)?,
101          #[cfg(feature = "math_sub_assign")]
102          OpAssignOp::Sub => sub_assign(&s, &sink, &source, p)?,
103          #[cfg(feature = "math_div_assign")]
104          OpAssignOp::Div => div_assign(&s, &sink, &source, p)?,
105          #[cfg(feature = "math_mul_assign")]
106          OpAssignOp::Mul => mul_assign(&s, &sink, &source, p)?,
107          _ => todo!(),
108        };
109        return Ok(fxn);
110      }
111    }
112    None => {
113      let args = vec![sink,source];
114      let fxn: Box<dyn MechFunction> = match op_assgn.op {
115        #[cfg(feature = "math_add_assign")]
116        OpAssignOp::Add => AddAssignValue{}.compile(&args)?,
117        #[cfg(feature = "math_sub_assign")]
118        OpAssignOp::Sub => SubAssignValue{}.compile(&args)?,
119        #[cfg(feature = "math_div_assign")]
120        OpAssignOp::Div => DivAssignValue{}.compile(&args)?,
121        #[cfg(feature = "math_mul_assign")]
122        OpAssignOp::Mul => MulAssignValue{}.compile(&args)?,
123        _ => todo!(),
124      };
125      fxn.solve();
126      let res = fxn.out();
127      p.state.borrow_mut().add_plan_step(fxn);
128      return Ok(res);
129    }
130  }
131  unreachable!(); // subscript should have thrown an error if we can't access an element
132}
133
134#[cfg(feature = "variable_assign")]
135pub fn variable_assign(var_assgn: &VariableAssign, p: &Interpreter) -> MResult<Value> {
136  let mut source = expression(&var_assgn.expression, p)?;
137  let slc = &var_assgn.target;
138  let id = slc.name.hash();
139  let sink = {
140    let symbols = p.symbols();
141    let symbols_brrw = symbols.borrow();
142    match symbols_brrw.get_mutable(id) {
143      Some(val) => val.borrow().clone(),
144      None => {
145        if !symbols_brrw.contains(id) {
146          return Err(MechError2::new(
147            UndefinedVariableError { id },
148            Some("(!)> Variables are defined with the `:=` operator. *e.g.*: {{x := 123}}".to_string()),
149          ).with_compiler_loc().with_tokens(slc.name.tokens()));
150        } else { 
151          return Err(MechError2::new(
152            NotMutableError { id },
153            Some("(!)> Mutable variables are defined with the `~` operator. *e.g.*: {{~x := 123}}".to_string()),
154          ).with_compiler_loc().with_tokens(slc.name.tokens()));
155        }
156      }
157    }
158  };
159  match &slc.subscript {
160    Some(sbscrpt) => {
161      #[cfg(feature = "subscript")]
162      for s in sbscrpt {
163        let s_result = subscript_ref(&s, &sink, &source, p)?;
164        return Ok(s_result);
165      }
166    }
167    #[cfg(feature = "assign")]
168    None => {
169      let args = vec![sink,source];
170      let fxn = AssignValue{}.compile(&args)?;
171      fxn.solve();
172      let res = fxn.out();
173      p.state.borrow_mut().add_plan_step(fxn);
174      return Ok(res);
175    }
176    _ => return Err(MechError2::new(
177      FeatureNotEnabledError,
178      None
179    ).with_compiler_loc().with_tokens(var_assgn.target.tokens())),
180  }
181  unreachable!(); // subscript should have thrown an error if we can't access an element
182}
183
184#[cfg(feature = "enum")]
185pub fn enum_define(enm_def: &EnumDefine, p: &Interpreter) -> MResult<Value> {
186  let id = enm_def.name.hash();
187  let variants = enm_def.variants.iter().map(|v| (v.name.hash(),None)).collect::<Vec<(u64, Option<Value>)>>();
188  let state = &p.state;
189  let mut state_brrw = state.borrow_mut();
190  let enm = MechEnum{id, variants};
191  let val = Value::Enum(Ref::new(enm.clone()));
192  state_brrw.enums.insert(id, enm.clone());
193  state_brrw.kinds.insert(id, val.kind());
194  Ok(val)
195}
196
197#[cfg(feature = "kind_define")]
198pub fn kind_define(knd_def: &KindDefine, p: &Interpreter) -> MResult<Value> {
199  let id = knd_def.name.hash();
200  let kind = kind_annotation(&knd_def.kind.kind, p)?;
201  let value_kind = kind.to_value_kind(&p.state.borrow().kinds)?;
202  let functions = p.functions();
203  let mut kinds = &mut p.state.borrow_mut().kinds;
204  kinds.insert(id, value_kind.clone());
205  Ok(Value::Kind(value_kind))
206}
207
208#[cfg(feature = "variable_define")]
209pub fn variable_define(var_def: &VariableDefine, p: &Interpreter) -> MResult<Value> {
210  let var_id = var_def.var.name.hash();
211  let var_name = var_def.var.name.to_string();
212  {
213    let symbols = p.symbols();
214    if symbols.borrow().contains(var_id) {
215      return Err(MechError2::new(
216        VariableAlreadyDefinedError { id: var_id },
217        None
218      ).with_compiler_loc().with_tokens(var_def.var.name.tokens()));
219    }
220  }
221  let mut result = expression(&var_def.expression, p)?;
222  #[cfg(all(feature = "kind_annotation", feature = "convert"))]
223  if let Some(knd_anntn) =  &var_def.var.kind {
224    let knd = kind_annotation(&knd_anntn.kind,p)?;
225    let mut state_brrw = &mut p.state.borrow_mut();
226    let target_knd = knd.to_value_kind(&mut state_brrw.kinds)?;
227    // Do kind checking
228    match (&result, &target_knd) {
229      // Atom is a variant of an enum
230      #[cfg(all(feature = "atom", feature = "enum"))]
231      (Value::Atom(given_variant_id), ValueKind::Enum(enum_id)) => {
232        let enums = &state_brrw.enums;
233        let my_enum = match enums.get(enum_id) {
234          Some(my_enum) => my_enum,
235          None => todo!(),
236        };
237        // Given atom isn't a variant of the enum
238        if !my_enum.variants.iter().any(|(enum_variant, inner_value)| given_variant_id.borrow().0 == *enum_variant) {
239          return Err(MechError2::new(
240            UnableToConvertAtomToEnumVariantError { atom_id: given_variant_id.borrow().0, target_enum_id: *enum_id },
241            None
242          ).with_compiler_loc().with_tokens(var_def.expression.tokens()));
243        }
244      }
245      // Atoms can't convert into anything else.
246      #[cfg(feature = "atom")]
247      (Value::Atom(given_variant_id), target_kind) => {
248        return Err(MechError2::new(
249          UnableToConvertAtomError { atom_id: given_variant_id.borrow().0},
250          None
251        ).with_compiler_loc().with_tokens(var_def.expression.tokens()));
252      }
253      #[cfg(feature = "matrix")]
254      (Value::MutableReference(v), ValueKind::Matrix(box target_matrix_knd,_)) => {
255        let value = v.borrow().clone();
256        if value.is_matrix() {
257          let convert_fxn = ConvertMatToMat{}.compile(&vec![result.clone(), Value::Kind(target_knd.clone())])?;
258          convert_fxn.solve();
259          let converted_result = convert_fxn.out();
260          state_brrw.add_plan_step(convert_fxn);
261          result = converted_result;
262        } else {
263          let value_kind = value.kind();
264          if value_kind.deref_kind() != target_matrix_knd.clone() && value_kind != *target_matrix_knd {
265            let convert_fxn = ConvertKind{}.compile(&vec![result.clone(), Value::Kind(target_matrix_knd.clone())])?;
266            convert_fxn.solve();
267            let converted_result = convert_fxn.out();
268            state_brrw.add_plan_step(convert_fxn);
269            result = converted_result;
270          };
271          let convert_fxn = ConvertScalarToMat{}.compile(&vec![result.clone(), Value::Kind(target_knd.clone())])?;
272          convert_fxn.solve();
273          let converted_result = convert_fxn.out();
274          state_brrw.add_plan_step(convert_fxn);
275          result = converted_result;          
276        }
277      }
278      #[cfg(feature = "matrix")]
279      (value, ValueKind::Matrix(box target_matrix_knd,_)) => {
280        if value.is_matrix() {
281          let convert_fxn = ConvertMatToMat{}.compile(&vec![result.clone(), Value::Kind(target_knd.clone())])?;
282          convert_fxn.solve();
283          let converted_result = convert_fxn.out();
284          state_brrw.add_plan_step(convert_fxn);
285          result = converted_result;
286        } else {
287          let value_kind = value.kind();
288          if value_kind.deref_kind() != target_matrix_knd.clone() && value_kind != *target_matrix_knd {
289            let convert_fxn = ConvertKind{}.compile(&vec![result.clone(), Value::Kind(target_matrix_knd.clone())])?;
290            convert_fxn.solve();
291            let converted_result = convert_fxn.out();
292            state_brrw.add_plan_step(convert_fxn);
293            result = converted_result;
294          };
295          let convert_fxn = ConvertScalarToMat{}.compile(&vec![result.clone(), Value::Kind(target_knd.clone())])?;
296          convert_fxn.solve();
297          let converted_result = convert_fxn.out();
298          state_brrw.add_plan_step(convert_fxn);
299          result = converted_result;
300        }
301      }
302      // Kind isn't checked
303      x => {
304        let convert_fxn = ConvertKind{}.compile(&vec![result.clone(), Value::Kind(target_knd)])?;
305        convert_fxn.solve();
306        let converted_result = convert_fxn.out();
307        state_brrw.add_plan_step(convert_fxn);
308        result = converted_result;
309      },
310    };
311    // Save symbol to interpreter
312    let val_ref = state_brrw.save_symbol(var_id, var_name.clone(), result.clone(), var_def.mutable);
313    // Add variable define step to plan
314    let var_def_fxn = VarDefine{}.compile(&vec![result.clone(), Value::String(Ref::new(var_name.clone())), Value::Bool(Ref::new(var_def.mutable))])?;
315    state_brrw.add_plan_step(var_def_fxn);
316    return Ok(result);
317  } 
318  let mut state_brrw = p.state.borrow_mut();
319  // Save symbol to interpreter
320  let val_ref = state_brrw.save_symbol(var_id,var_name.clone(),result.clone(),var_def.mutable);
321  // Add variable define step to plan
322  let var_def_fxn = VarDefine{}.compile(&vec![result.clone(), Value::String(Ref::new(var_name.clone())), Value::Bool(Ref::new(var_def.mutable))])?;
323  state_brrw.add_plan_step(var_def_fxn);
324  return Ok(result);
325}
326
327macro_rules! op_assign {
328  ($fxn_name:ident, $op:tt) => {
329    paste!{
330      pub fn $fxn_name(sbscrpt: &Subscript, sink: &Value, source: &Value, p: &Interpreter) -> MResult<Value> {
331        let plan = p.plan();
332        match sbscrpt {
333          Subscript::Dot(x) => {
334            todo!()
335          },
336          Subscript::DotInt(x) => {
337            todo!()
338          },
339          Subscript::Swizzle(x) => {
340            todo!()
341          },
342          Subscript::Bracket(subs) => {
343            let mut fxn_input = vec![sink.clone()];
344            match &subs[..] {
345              [Subscript::Formula(ix)] => {
346                fxn_input.push(source.clone());
347                let ixes = subscript_formula(&subs[0], p)?;
348                let shape = ixes.shape();
349                fxn_input.push(ixes);
350                match shape[..] {
351                  [1,1] => plan.borrow_mut().push(MatrixAssignScalar{}.compile(&fxn_input)?),
352                  [1,n] => plan.borrow_mut().push([<$op AssignRange>]{}.compile(&fxn_input)?),
353                  [n,1] => plan.borrow_mut().push([<$op AssignRange>]{}.compile(&fxn_input)?),
354                  _ => todo!(),
355                }
356              },
357              [Subscript::Formula(ix1),Subscript::All] => {
358                fxn_input.push(source.clone());
359                let ix = subscript_formula(&subs[0], p)?;
360                let shape = ix.shape();
361                fxn_input.push(ix);
362                fxn_input.push(Value::IndexAll);
363                match shape[..] {
364                  [1,1] => plan.borrow_mut().push(MatrixAssignScalarAll{}.compile(&fxn_input)?),
365                  [1,n] => plan.borrow_mut().push([<$op AssignRangeAll>]{}.compile(&fxn_input)?),
366                  [n,1] => plan.borrow_mut().push([<$op AssignRangeAll>]{}.compile(&fxn_input)?),
367                  _ => todo!(),
368                }
369              },
370              [Subscript::Range(ix)] => {
371                fxn_input.push(source.clone());
372                let ixes = subscript_range(&subs[0], p)?;
373                fxn_input.push(ixes);
374                plan.borrow_mut().push([<$op AssignRange>]{}.compile(&fxn_input)?);
375              },
376              [Subscript::Range(ix), Subscript::All] => {
377                fxn_input.push(source.clone());
378                let ixes = subscript_range(&subs[0], p)?;
379                fxn_input.push(ixes);
380                fxn_input.push(Value::IndexAll);
381                plan.borrow_mut().push([<$op AssignRangeAll>]{}.compile(&fxn_input)?);
382              },
383              x => todo!("{:?}", x),
384            };
385            let plan_brrw = plan.borrow();
386            let mut new_fxn = &plan_brrw.last().unwrap();
387            new_fxn.solve();
388            let res = new_fxn.out();
389            return Ok(res);
390          },
391          Subscript::Brace(x) => todo!(),
392          x => todo!("{:?}", x),
393        }
394      }
395    }}}
396
397#[cfg(feature = "math_add_assign")]
398op_assign!(add_assign, Add);
399#[cfg(feature = "math_sub_assign")]
400op_assign!(sub_assign, Sub);
401#[cfg(feature = "math_div_assign")]
402op_assign!(mul_assign, Mul);
403#[cfg(feature = "math_mul_assign")]
404op_assign!(div_assign, Div);
405//#[cfg(feature = "math_exp")]
406//op_assign!(exp_assign, Exp);
407
408#[cfg(all(feature = "subscript", feature = "assign"))]
409pub fn subscript_ref(sbscrpt: &Subscript, sink: &Value, source: &Value, p: &Interpreter) -> MResult<Value> {
410  let plan = p.plan();
411  let symbols = p.symbols();
412  let functions = p.functions();
413  match sbscrpt {
414    Subscript::Dot(x) => {
415      let key = x.hash();
416      let fxn_input: Vec<Value> = vec![sink.clone(), source.clone(), Value::Id(key)];
417      let new_fxn = AssignColumn{}.compile(&fxn_input)?;
418      new_fxn.solve();
419      let res = new_fxn.out();
420      plan.borrow_mut().push(new_fxn);
421      return Ok(res);
422    },
423    Subscript::DotInt(x) => {
424      todo!()
425    },
426    Subscript::Swizzle(x) => {
427      unreachable!()
428    },
429    Subscript::Bracket(subs) => {
430      let mut fxn_input = vec![sink.clone()];
431      match &subs[..] {
432        #[cfg(feature = "subscript_formula")]
433        [Subscript::Formula(ix)] => {
434          fxn_input.push(source.clone());
435          let ixes = subscript_formula(&subs[0], p)?;
436          let shape = ixes.shape();
437          fxn_input.push(ixes);
438          match shape[..] {
439            #[cfg(feature = "matrix")]
440            [1,1] => plan.borrow_mut().push(MatrixAssignScalar{}.compile(&fxn_input)?),
441            #[cfg(all(feature = "matrix", feature = "subscript_range", feature = "assign"))]
442            [1,n] => plan.borrow_mut().push(MatrixAssignRange{}.compile(&fxn_input)?),
443            #[cfg(all(feature = "matrix", feature = "subscript_range", feature = "assign"))]
444            [n,1] => plan.borrow_mut().push(MatrixAssignRange{}.compile(&fxn_input)?),
445            _ => todo!(),
446          }
447        },
448        #[cfg(all(feature = "matrix", feature = "subscript_range"))]
449        [Subscript::Range(ix)] => {
450          fxn_input.push(source.clone());
451          let ixes = subscript_range(&subs[0], p)?;
452          fxn_input.push(ixes);
453          plan.borrow_mut().push(MatrixAssignRange{}.compile(&fxn_input)?);
454        },
455        #[cfg(all(feature = "matrix", feature = "subscript_range"))]
456        [Subscript::All] => {
457          fxn_input.push(source.clone());
458          fxn_input.push(Value::IndexAll);
459          plan.borrow_mut().push(MatrixAssignAll{}.compile(&fxn_input)?);
460        },
461        [Subscript::All,Subscript::All] => todo!(),
462        #[cfg(feature = "subscript_formula")]
463        [Subscript::Formula(ix1),Subscript::Formula(ix2)] => {
464          fxn_input.push(source.clone());
465          let result1 = subscript_formula(&subs[0], p)?;
466          let result2 = subscript_formula(&subs[1], p)?;
467          let shape1 = result1.shape();
468          let shape2 = result2.shape();
469          fxn_input.push(result1);
470          fxn_input.push(result2);
471          match ((shape1[0],shape1[1]),(shape2[0],shape2[1])) {
472            #[cfg(feature = "matrix")]
473            ((1,1),(1,1)) => plan.borrow_mut().push(MatrixAssignScalarScalar{}.compile(&fxn_input)?),
474            #[cfg(all(feature = "matrix", feature = "subscript_range"))]
475            ((1,1),(m,1)) => plan.borrow_mut().push(MatrixAssignScalarRange{}.compile(&fxn_input)?),
476            #[cfg(all(feature = "matrix", feature = "subscript_range"))]
477            ((n,1),(1,1)) => plan.borrow_mut().push(MatrixAssignRangeScalar{}.compile(&fxn_input)?),
478            #[cfg(all(feature = "matrix", feature = "subscript_range"))]
479            ((n,1),(m,1)) => plan.borrow_mut().push(MatrixAssignRangeRange{}.compile(&fxn_input)?),
480            _ => unreachable!(),
481          }          
482        },
483        #[cfg(all(feature = "matrix", feature = "subscript_range"))]
484        [Subscript::Range(ix1),Subscript::Range(ix2)] => {
485          fxn_input.push(source.clone());
486          let result = subscript_range(&subs[0],p)?;
487          fxn_input.push(result);
488          let result = subscript_range(&subs[1],p)?;
489          fxn_input.push(result);
490          plan.borrow_mut().push(MatrixAssignRangeRange{}.compile(&fxn_input)?);
491        },
492        #[cfg(all(feature = "matrix", feature = "subscript_formula"))]
493        [Subscript::All,Subscript::Formula(ix2)] => {
494          fxn_input.push(source.clone());
495          fxn_input.push(Value::IndexAll);
496          let ix = subscript_formula(&subs[1], p)?;
497          let shape = ix.shape();
498          fxn_input.push(ix);
499          match shape[..] {
500            #[cfg(feature = "matrix")]
501            [1,1] => plan.borrow_mut().push(MatrixAssignAllScalar{}.compile(&fxn_input)?),
502            #[cfg(feature = "matrix")]
503            [1,n] => plan.borrow_mut().push(MatrixAssignAllRange{}.compile(&fxn_input)?),
504            #[cfg(feature = "matrix")]
505            [n,1] => plan.borrow_mut().push(MatrixAssignAllRange{}.compile(&fxn_input)?),
506            _ => todo!(),
507          }
508        }
509        #[cfg(feature = "subscript_formula")]
510        [Subscript::Formula(ix1),Subscript::All] => {
511          fxn_input.push(source.clone());
512          let ix = subscript_formula(&subs[0], p)?;
513          let shape = ix.shape();
514          fxn_input.push(ix);
515          fxn_input.push(Value::IndexAll);
516          match shape[..] {
517            #[cfg(feature = "matrix")]
518            [1,1] => plan.borrow_mut().push(MatrixAssignScalarAll{}.compile(&fxn_input)?),
519            #[cfg(all(feature = "matrix", feature = "subscript_range"))]
520            [1,n] => plan.borrow_mut().push(MatrixAssignRangeAll{}.compile(&fxn_input)?),
521            #[cfg(all(feature = "matrix", feature = "subscript_range"))]
522            [n,1] => plan.borrow_mut().push(MatrixAssignRangeAll{}.compile(&fxn_input)?),
523            _ => todo!(),
524          }
525        },
526        #[cfg(all(feature = "subscript_formula", feature = "subscript_range"))]
527        [Subscript::Range(ix1),Subscript::Formula(ix2)] => {
528          fxn_input.push(source.clone());
529          let result = subscript_range(&subs[0],p)?;
530          fxn_input.push(result);
531          let result = subscript_formula(&subs[1], p)?;
532          let shape = result.shape();
533          fxn_input.push(result);
534          match &shape[..] {
535            #[cfg(feature = "matrix")]
536            [1,1] => plan.borrow_mut().push(MatrixAssignRangeScalar{}.compile(&fxn_input)?),
537            #[cfg(feature = "matrix")]
538            [1,n] => plan.borrow_mut().push(MatrixAssignRangeRange{}.compile(&fxn_input)?),
539            #[cfg(feature = "matrix")]
540            [n,1] => plan.borrow_mut().push(MatrixAssignRangeRange{}.compile(&fxn_input)?),
541            _ => todo!(),
542          }
543        },
544        #[cfg(all(feature = "subscript_formula", feature = "subscript_range"))]
545        [Subscript::Formula(ix1),Subscript::Range(ix2)] => {
546          fxn_input.push(source.clone());
547          let result = subscript_formula(&subs[0], p)?;
548          let shape = result.shape();
549          fxn_input.push(result);
550          let result = subscript_range(&subs[1],p)?;
551          fxn_input.push(result);
552          match &shape[..] {
553            #[cfg(feature = "matrix")]
554            [1,1] => plan.borrow_mut().push(MatrixAssignScalarRange{}.compile(&fxn_input)?),
555            #[cfg(feature = "matrix")]
556            [1,n] => plan.borrow_mut().push(MatrixAssignRangeRange{}.compile(&fxn_input)?),
557            #[cfg(feature = "matrix")]
558            [n,1] => plan.borrow_mut().push(MatrixAssignRangeRange{}.compile(&fxn_input)?),
559            _ => todo!(),
560          }
561        },
562        #[cfg(all(feature = "matrix", feature = "subscript_range"))]
563        [Subscript::All,Subscript::Range(ix2)] => {
564          fxn_input.push(source.clone());
565          fxn_input.push(Value::IndexAll);
566          let result = subscript_range(&subs[1],p)?;
567          fxn_input.push(result);
568          plan.borrow_mut().push(MatrixAssignAllRange{}.compile(&fxn_input)?);
569        },
570        #[cfg(all(feature = "matrix", feature = "subscript_range"))]
571        [Subscript::Range(ix1),Subscript::All] => {
572          fxn_input.push(source.clone());
573          let result = subscript_range(&subs[0],p)?;
574          fxn_input.push(result);
575          fxn_input.push(Value::IndexAll);
576          plan.borrow_mut().push(MatrixAssignRangeAll{}.compile(&fxn_input)?);
577        },
578        _ => unreachable!(),
579      };
580      let plan_brrw = plan.borrow();
581      let mut new_fxn = &plan_brrw.last().unwrap();
582      new_fxn.solve();
583      let res = new_fxn.out();
584      return Ok(res);
585    },
586    Subscript::Brace(x) => todo!(),
587    _ => unreachable!(),
588  }
589}
590
591#[derive(Debug, Clone)]
592pub struct UnableToConvertAtomToEnumVariantError {
593  pub atom_id: u64,
594  pub target_enum_id: u64,
595}
596impl MechErrorKind2 for UnableToConvertAtomToEnumVariantError {
597  fn name(&self) -> &str {
598    "UnableToConvertAtomToEnumVariant"
599  }
600  fn message(&self) -> String {
601    format!("Unable to convert atom variant {} to enum {}", self.atom_id, self.target_enum_id)
602  }
603}
604
605#[derive(Debug, Clone)]
606pub struct UnableToConvertAtomError {
607  pub atom_id: u64,
608}
609impl MechErrorKind2 for UnableToConvertAtomError {
610  fn name(&self) -> &str {
611    "UnableToConvertAtom"
612  }
613  fn message(&self) -> String {
614    format!("Unable to atom  {}", self.atom_id)
615  }
616}
617
618#[derive(Debug, Clone)]
619pub struct VariableAlreadyDefinedError {
620  pub id: u64,
621}
622impl MechErrorKind2 for VariableAlreadyDefinedError {
623  fn name(&self) -> &str { "VariableAlreadyDefined" }
624  fn message(&self) -> String {
625    format!("Variable already defined: {}", self.id)
626  }
627}
628
629#[derive(Debug, Clone)]
630pub struct UndefinedVariableError {
631  pub id: u64,
632}
633impl MechErrorKind2 for UndefinedVariableError {
634  fn name(&self) -> &str { "UndefinedVariable" }
635
636  fn message(&self) -> String {
637    format!("Undefined variable: {}", self.id)
638  }
639}
640
641#[derive(Debug, Clone)]
642pub struct NotMutableError {
643  pub id: u64,
644}
645impl MechErrorKind2 for NotMutableError {
646  fn name(&self) -> &str { "NotMutable" }
647  fn message(&self) -> String {
648    format!("Variable is not mutable: {}", self.id)
649  }
650}
651