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