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