1use crate::*;
2use paste::paste;
3
4#[cfg(feature = "variable_define")]
5use crate::stdlib::define::*;
6
7pub 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 #[cfg(feature = "state_machines")]
28 Statement::FsmDeclare(fsm_decl) => fsm_declare(fsm_decl, env, p),
29 x => return Err(MechError::new(
32 FeatureNotEnabledError,
33 None
34 ).with_compiler_loc().with_tokens(x.tokens())
35 ),
36 }
37}
38
39#[cfg(feature = "tuple")]
40pub fn tuple_destructure(tpl_dstrct: &TupleDestructure, p: &Interpreter) -> MResult<Value> {
41 let source = expression(&tpl_dstrct.expression, None, p)?;
42 let tpl = match &source {
43 Value::Tuple(tpl) => tpl,
44 Value::MutableReference(r) => {
45 let r_brrw = r.borrow();
46 &match &*r_brrw {
47 Value::Tuple(tpl) => tpl.clone(),
48 _ => return Err(MechError::new(
49 DestructureExpectedTupleError{ value: source.kind() },
50 None
51 ).with_compiler_loc().with_tokens(tpl_dstrct.expression.tokens())),
52 }
53 },
54 _ => return Err(MechError::new(
55 DestructureExpectedTupleError{ value: source.kind() },
56 None
57 ).with_compiler_loc().with_tokens(tpl_dstrct.expression.tokens())),
58 };
59 let symbols = p.symbols();
60 let mut symbols_brrw = symbols.borrow_mut();
61 for (i, var) in tpl_dstrct.vars.iter().enumerate() {
62 let id = var.hash();
63 if symbols_brrw.contains(id) {
64 return Err(MechError::new(
65 VariableAlreadyDefinedError { id },
66 None
67 ).with_compiler_loc().with_tokens(var.tokens()));
68 }
69 if let Some(element) = tpl.borrow().get(i) {
70 symbols_brrw.insert(id, element.clone(), true);
71 symbols_brrw.dictionary.borrow_mut().insert(id, var.name.to_string());
72 } else {
73 return Err(MechError::new(
74 TupleDestructureTooManyVarsError{ value: source.kind() },
75 None
76 ).with_compiler_loc().with_tokens(var.tokens()));
77 }
78 }
79 Ok(source)
80}
81
82#[cfg(feature = "math")]
83pub fn op_assign(op_assgn: &OpAssign, env: Option<&Environment>, p: &Interpreter) -> MResult<Value> {
84 let mut source = expression(&op_assgn.expression, env, p)?;
85 let slc = &op_assgn.target;
86 let id = slc.name.hash();
87 let sink = {
88 let mut state_brrw = p.state.borrow_mut();
89 match state_brrw.get_mutable_symbol(id) {
90 Some(val) => val.borrow().clone(),
91 None => {
92 match state_brrw.contains_symbol(id) {
93 true => return Err(MechError::new(
94 NotMutableError { id },
95 Some("(!)> Mutable variables are defined with the `~` operator. *e.g.*: {{~x := 123}}".to_string()),
96 ).with_compiler_loc().with_tokens(slc.name.tokens())),
97 false => return Err(MechError::new(
98 UndefinedVariableError { id },
99 Some("(!)> Variables are defined with the `:=` operator. *e.g.*: {{x := 123}}".to_string()),
100 ).with_compiler_loc().with_tokens(slc.name.tokens())),
101 }
102 }
103 }
104 };
105 match &slc.subscript {
106 Some(sbscrpt) => {
107 for s in sbscrpt {
109 let fxn = match op_assgn.op {
110 #[cfg(feature = "math_add_assign")]
111 OpAssignOp::Add => add_assign(&s, &sink, &source, env, p)?,
112 #[cfg(feature = "math_sub_assign")]
113 OpAssignOp::Sub => sub_assign(&s, &sink, &source, env, p)?,
114 #[cfg(feature = "math_div_assign")]
115 OpAssignOp::Div => div_assign(&s, &sink, &source, env, p)?,
116 #[cfg(feature = "math_mul_assign")]
117 OpAssignOp::Mul => mul_assign(&s, &sink, &source, env, p)?,
118 _ => todo!(),
119 };
120 return Ok(fxn);
121 }
122 }
123 None => {
124 let args = vec![sink,source];
125 let fxn: Box<dyn MechFunction> = match op_assgn.op {
126 #[cfg(feature = "math_add_assign")]
127 OpAssignOp::Add => AddAssignValue{}.compile(&args)?,
128 #[cfg(feature = "math_sub_assign")]
129 OpAssignOp::Sub => SubAssignValue{}.compile(&args)?,
130 #[cfg(feature = "math_div_assign")]
131 OpAssignOp::Div => DivAssignValue{}.compile(&args)?,
132 #[cfg(feature = "math_mul_assign")]
133 OpAssignOp::Mul => MulAssignValue{}.compile(&args)?,
134 _ => todo!(),
135 };
136 fxn.solve();
137 let res = fxn.out();
138 p.state.borrow_mut().add_plan_step(fxn);
139 return Ok(res);
140 }
141 }
142 unreachable!(); }
144
145#[cfg(feature = "variable_assign")]
146pub fn variable_assign(var_assgn: &VariableAssign, env: Option<&Environment>, p: &Interpreter) -> MResult<Value> {
147 let mut source = expression(&var_assgn.expression, env, p)?;
148 let slc = &var_assgn.target;
149 let id = slc.name.hash();
150 let sink = {
151 let symbols = p.symbols();
152 let symbols_brrw = symbols.borrow();
153 match symbols_brrw.get_mutable(id) {
154 Some(val) => val.borrow().clone(),
155 None => {
156 if !symbols_brrw.contains(id) {
157 return Err(MechError::new(
158 UndefinedVariableError { id },
159 Some("(!)> Variables are defined with the `:=` operator. *e.g.*: {{x := 123}}".to_string()),
160 ).with_compiler_loc().with_tokens(slc.name.tokens()));
161 } else {
162 return Err(MechError::new(
163 NotMutableError { id },
164 Some("(!)> Mutable variables are defined with the `~` operator. *e.g.*: {{~x := 123}}".to_string()),
165 ).with_compiler_loc().with_tokens(slc.name.tokens()));
166 }
167 }
168 }
169 };
170 match &slc.subscript {
171 Some(sbscrpt) => {
172 #[cfg(feature = "subscript")]
173 for s in sbscrpt {
174 let s_result = subscript_ref(&s, &sink, &source, env, p)?;
175 return Ok(s_result);
176 }
177 }
178 #[cfg(feature = "assign")]
179 None => {
180 let args = vec![sink,source];
181 let fxn = AssignValue{}.compile(&args)?;
182 fxn.solve();
183 let res = fxn.out();
184 p.state.borrow_mut().add_plan_step(fxn);
185 return Ok(res);
186 }
187 _ => return Err(MechError::new(
188 FeatureNotEnabledError,
189 None
190 ).with_compiler_loc().with_tokens(var_assgn.target.tokens())),
191 }
192 unreachable!(); }
194
195#[cfg(feature = "enum")]
196pub fn enum_define(enm_def: &EnumDefine, p: &Interpreter) -> MResult<()> {
197 let id = enm_def.name.hash();
198 let mut variants: Vec<(u64, Option<Value>)> = Vec::new();
199 {
200 let mut state_brrw = p.state.borrow_mut();
201 for v in &enm_def.variants {
202 let payload = match &v.value {
203 Some(kind_annotation_node) => {
204 let knd = kind_annotation(&kind_annotation_node.kind, p)?;
205 let vk = knd.to_value_kind(&mut state_brrw.kinds)?;
206 Some(Value::Kind(vk))
207 }
208 None => None,
209 };
210 variants.push((v.name.hash(), payload));
211 }
212 }
213 let state = &p.state;
214 let mut state_brrw = state.borrow_mut();
215 let dictionary = state_brrw.dictionary.clone();
216 {
217 let mut dictionary_brrw = dictionary.borrow_mut();
218 dictionary_brrw.insert(enm_def.name.hash(), enm_def.name.to_string());
219 for variant in &enm_def.variants {
220 dictionary_brrw.insert(variant.name.hash(), variant.name.to_string());
221 }
222 }
223 let enm = MechEnum{id, variants, names: dictionary};
224 let val = Value::Enum(Ref::new(enm.clone()));
225 state_brrw.enums.insert(id, enm.clone());
226 state_brrw.kinds.insert(id, val.kind());
227 Ok(())
228}
229
230#[cfg(feature = "kind_define")]
231pub fn kind_define(knd_def: &KindDefine, p: &Interpreter) -> MResult<Value> {
232 let id = knd_def.name.hash();
233 let kind = kind_annotation(&knd_def.kind.kind, p)?;
234 let value_kind = kind.to_value_kind(&p.state.borrow().kinds)?;
235 let functions = p.functions();
236 let mut kinds = &mut p.state.borrow_mut().kinds;
237 kinds.insert(id, value_kind.clone());
238 Ok(Value::Kind(value_kind))
239}
240
241#[cfg(all(feature = "enum", feature = "atom"))]
242fn value_matches_enum_variant(value: &Value, enum_id: u64, state: &ProgramState) -> bool {
243 let my_enum = match state.enums.get(&enum_id) {
244 Some(enm) => enm,
245 None => return false,
246 };
247 match value {
248 Value::Atom(atom_variant) => {
249 let variant_id = atom_variant.borrow().id();
250 my_enum.variants.iter().any(|(known_variant, payload_kind)| *known_variant == variant_id && payload_kind.is_none())
251 }
252 #[cfg(feature = "tuple")]
253 Value::Tuple(tuple_val) => {
254 let tuple_brrw = tuple_val.borrow();
255 if tuple_brrw.elements.len() != 2 {
256 return false;
257 }
258 let variant_atom = match tuple_brrw.elements[0].as_ref() {
259 Value::Atom(atom) => atom.borrow(),
260 _ => return false,
261 };
262 let variant_id = variant_atom.id();
263 let payload = tuple_brrw.elements[1].as_ref();
264 let (_, declared_payload_kind) = match my_enum.variants.iter().find(|(known_variant, _)| *known_variant == variant_id) {
265 Some(v) => v,
266 None => return false,
267 };
268 match declared_payload_kind {
269 Some(Value::Kind(expected_kind)) => match expected_kind {
270 ValueKind::Enum(inner_enum_id, _) => value_matches_enum_variant(payload, *inner_enum_id, state),
271 _ => {
272 payload.kind() == expected_kind.clone() ||
273 ConvertKind{}.compile(&vec![payload.clone(), Value::Kind(expected_kind.clone())]).is_ok()
274 }
275 },
276 _ => false,
277 }
278 }
279 _ => false,
280 }
281}
282
283#[cfg(feature = "variable_define")]
284pub fn variable_define(var_def: &VariableDefine, p: &Interpreter) -> MResult<Value> {
285 let var_id = var_def.var.name.hash();
286 let var_name = var_def.var.name.to_string();
287 {
288 let symbols = p.symbols();
289 if symbols.borrow().contains(var_id) {
290 return Err(MechError::new(
291 VariableAlreadyDefinedError { id: var_id },
292 None
293 ).with_compiler_loc().with_tokens(var_def.var.name.tokens()));
294 }
295 }
296 let mut result = expression(&var_def.expression, None, p)?;
297 #[cfg(all(feature = "kind_annotation", feature = "convert"))]
298 if let Some(knd_anntn) = &var_def.var.kind {
299 let knd = kind_annotation(&knd_anntn.kind,p)?;
300 let mut state_brrw = &mut p.state.borrow_mut();
301 let target_knd = knd.to_value_kind(&mut state_brrw.kinds)?;
302 match (&result, &target_knd) {
304 #[cfg(all(feature = "atom", feature = "enum"))]
306 (Value::Atom(atom_variant), ValueKind::Enum(enum_id, target_enum_variant_name)) => {
307 let atom_name = atom_variant.borrow().name();
308 if !value_matches_enum_variant(&result, *enum_id, &*state_brrw) {
309 return Err(MechError::new(
310 UnableToConvertAtomToEnumVariantError { atom_name: atom_name.clone(), target_enum_variant_name: target_enum_variant_name.clone() },
311 None
312 ).with_compiler_loc().with_tokens(var_def.expression.tokens()));
313 }
314 }
315 #[cfg(all(feature = "tuple", feature = "atom", feature = "enum"))]
316 (Value::Tuple(tuple_val), ValueKind::Enum(enum_id, target_enum_variant_name)) => {
317 let atom_name = format!("{:?}", tuple_val);
318 if !value_matches_enum_variant(&result, *enum_id, &*state_brrw) {
319 return Err(MechError::new(
320 UnableToConvertAtomToEnumVariantError { atom_name, target_enum_variant_name: target_enum_variant_name.clone() },
321 None
322 ).with_compiler_loc().with_tokens(var_def.expression.tokens()));
323 }
324 }
325 #[cfg(feature = "atom")]
327 (Value::Atom(given_variant_id), target_kind) => {
328 return Err(MechError::new(
329 UnableToConvertAtomError { atom_id: given_variant_id.borrow().0.0},
330 None
331 ).with_compiler_loc().with_tokens(var_def.expression.tokens()));
332 }
333 #[cfg(feature = "record")]
334 (Value::Record(rec), ref target_kind @ ValueKind::Record(target_rec_knd)) => {
335 let rec_brrw = rec.borrow();
336 let rec_knd = rec_brrw.kind();
337 if &rec_knd != *target_kind {
338 return Err(MechError::new(
339 UnableToConvertRecordError { source_record_kind: rec_knd.clone(), target_record_kind: (*target_kind).clone() },
340 None
341 ).with_compiler_loc().with_tokens(var_def.expression.tokens()));
342 }
343 }
344 #[cfg(feature = "matrix")]
345 (Value::MutableReference(v), ValueKind::Matrix(target_matrix_knd,_)) => {
346 let value = v.borrow().clone();
347 if value.is_matrix() {
348 let convert_fxn = ConvertMatToMat{}.compile(&vec![result.clone(), Value::Kind(target_knd.clone())])?;
349 convert_fxn.solve();
350 let converted_result = convert_fxn.out();
351 state_brrw.add_plan_step(convert_fxn);
352 result = converted_result;
353 } else {
354 let value_kind = value.kind();
355 if value_kind.deref_kind() != target_matrix_knd.as_ref().clone() && value_kind != *target_matrix_knd.clone() {
356 let convert_fxn = ConvertKind{}.compile(&vec![result.clone(), Value::Kind(target_matrix_knd.as_ref().clone())])?;
357 convert_fxn.solve();
358 let converted_result = convert_fxn.out();
359 state_brrw.add_plan_step(convert_fxn);
360 result = converted_result;
361 };
362 let convert_fxn = ConvertScalarToMat{}.compile(&vec![result.clone(), Value::Kind(target_knd.clone())])?;
363 convert_fxn.solve();
364 let converted_result = convert_fxn.out();
365 state_brrw.add_plan_step(convert_fxn);
366 result = converted_result;
367 }
368 }
369 #[cfg(feature = "matrix")]
370 (value, ValueKind::Matrix(target_matrix_knd,_)) => {
371 if value.is_matrix() {
372 let convert_fxn = ConvertMatToMat{}.compile(&vec![result.clone(), Value::Kind(target_knd.clone())])?;
373 convert_fxn.solve();
374 let converted_result = convert_fxn.out();
375 state_brrw.add_plan_step(convert_fxn);
376 result = converted_result;
377 } else {
378 let value_kind = value.kind();
379 if value_kind.deref_kind() != target_matrix_knd.as_ref().clone() && value_kind != *target_matrix_knd.clone() {
380 let convert_fxn = ConvertKind{}.compile(&vec![result.clone(), Value::Kind(target_matrix_knd.as_ref().clone())])?;
381 convert_fxn.solve();
382 let converted_result = convert_fxn.out();
383 state_brrw.add_plan_step(convert_fxn);
384 result = converted_result;
385 };
386 let convert_fxn = ConvertScalarToMat{}.compile(&vec![result.clone(), Value::Kind(target_knd.clone())])?;
387 convert_fxn.solve();
388 let converted_result = convert_fxn.out();
389 state_brrw.add_plan_step(convert_fxn);
390 result = converted_result;
391 }
392 }
393 x => {
395 let convert_fxn = ConvertKind{}.compile(&vec![result.clone(), Value::Kind(target_knd)])?;
396 convert_fxn.solve();
397 let converted_result = convert_fxn.out();
398 state_brrw.add_plan_step(convert_fxn);
399 result = converted_result;
400 },
401 };
402 let detached_result = detach_variable_value(&result);
403 let val_ref = state_brrw.save_symbol(var_id, var_name.clone(), detached_result.clone(), var_def.mutable);
405 let var_def_fxn = VarDefine{}.compile(&vec![detached_result.clone(), Value::String(Ref::new(var_name.clone())), Value::Bool(Ref::new(var_def.mutable))])?;
407 state_brrw.add_plan_step(var_def_fxn);
408 return Ok(detached_result);
409 }
410 let mut state_brrw = p.state.borrow_mut();
411 let detached_result = detach_variable_value(&result);
412 let val_ref = state_brrw.save_symbol(var_id,var_name.clone(),detached_result.clone(),var_def.mutable);
414 let var_def_fxn = VarDefine{}.compile(&vec![detached_result.clone(), Value::String(Ref::new(var_name.clone())), Value::Bool(Ref::new(var_def.mutable))])?;
416 state_brrw.add_plan_step(var_def_fxn);
417 return Ok(detached_result);
418}
419
420#[cfg(feature = "state_machines")]
421pub fn fsm_declare(fsm_decl: &FsmDeclare, env: Option<&Environment>, p: &Interpreter) -> MResult<Value> {
422 let result = crate::state_machines::execute_fsm_pipe(&fsm_decl.pipe, env, p)?;
423 let id = fsm_decl.fsm.name.hash();
424 let name = fsm_decl.fsm.name.to_string();
425 #[cfg(feature = "symbol_table")]
426 {
427 let symbols = p.symbols();
428 let mut symbols_brrw = symbols.borrow_mut();
429 symbols_brrw.insert(id, detach_variable_value(&result), false);
430 symbols_brrw.dictionary.borrow_mut().insert(id, name);
431 }
432 Ok(result)
433}
434
435fn detach_variable_value(value: &Value) -> Value {
436 match value {
437 Value::MutableReference(reference) => detach_variable_value(&reference.borrow()),
438 _ => value.clone(),
439 }
440}
441
442macro_rules! op_assign {
443 ($fxn_name:ident, $op:tt) => {
444 paste!{
445 pub fn $fxn_name(sbscrpt: &Subscript, sink: &Value, source: &Value, env: Option<&Environment>, p: &Interpreter) -> MResult<Value> {
446 let plan = p.plan();
447 match sbscrpt {
448 Subscript::Dot(x) => {
449 todo!()
450 },
451 Subscript::DotInt(x) => {
452 todo!()
453 },
454 Subscript::Swizzle(x) => {
455 todo!()
456 },
457 Subscript::Bracket(subs) => {
458 let mut fxn_input = vec![sink.clone()];
459 match &subs[..] {
460 [Subscript::Formula(ix)] => {
461 fxn_input.push(source.clone());
462 let ixes = subscript_formula_ix(&subs[0], env, p)?;
463 let shape = ixes.shape();
464 fxn_input.push(ixes);
465 match shape[..] {
466 [1,1] => plan.borrow_mut().push(MatrixAssignScalar{}.compile(&fxn_input)?),
467 [1,n] => plan.borrow_mut().push([<$op AssignRange>]{}.compile(&fxn_input)?),
468 [n,1] => plan.borrow_mut().push([<$op AssignRange>]{}.compile(&fxn_input)?),
469 _ => todo!(),
470 }
471 },
472 [Subscript::Formula(ix1),Subscript::All] => {
473 fxn_input.push(source.clone());
474 let ix = subscript_formula_ix(&subs[0], env, p)?;
475 let shape = ix.shape();
476 fxn_input.push(ix);
477 fxn_input.push(Value::IndexAll);
478 match shape[..] {
479 [1,1] => plan.borrow_mut().push(MatrixAssignScalarAll{}.compile(&fxn_input)?),
480 [1,n] => plan.borrow_mut().push([<$op AssignRangeAll>]{}.compile(&fxn_input)?),
481 [n,1] => plan.borrow_mut().push([<$op AssignRangeAll>]{}.compile(&fxn_input)?),
482 _ => todo!(),
483 }
484 },
485 [Subscript::Range(ix)] => {
486 fxn_input.push(source.clone());
487 let ixes = subscript_range(&subs[0], env, p)?;
488 fxn_input.push(ixes);
489 plan.borrow_mut().push([<$op AssignRange>]{}.compile(&fxn_input)?);
490 },
491 [Subscript::Range(ix), Subscript::All] => {
492 fxn_input.push(source.clone());
493 let ixes = subscript_range(&subs[0], env, p)?;
494 fxn_input.push(ixes);
495 fxn_input.push(Value::IndexAll);
496 plan.borrow_mut().push([<$op AssignRangeAll>]{}.compile(&fxn_input)?);
497 },
498 x => todo!("{:?}", x),
499 };
500 let plan_brrw = plan.borrow();
501 let mut new_fxn = &plan_brrw.last().unwrap();
502 new_fxn.solve();
503 let res = new_fxn.out();
504 return Ok(res);
505 },
506 Subscript::Brace(x) => todo!(),
507 x => todo!("{:?}", x),
508 }
509 }
510 }}}
511
512#[cfg(feature = "math_add_assign")]
513op_assign!(add_assign, Add);
514#[cfg(feature = "math_sub_assign")]
515op_assign!(sub_assign, Sub);
516#[cfg(feature = "math_div_assign")]
517op_assign!(mul_assign, Mul);
518#[cfg(feature = "math_mul_assign")]
519op_assign!(div_assign, Div);
520#[cfg(all(feature = "subscript", feature = "assign"))]
524pub fn subscript_ref(sbscrpt: &Subscript, sink: &Value, source: &Value, env: Option<&Environment>, p: &Interpreter) -> MResult<Value> {
525 let plan = p.plan();
526 let symbols = p.symbols();
527 let functions = p.functions();
528 match sbscrpt {
529 Subscript::Dot(x) => {
530 let key = x.hash();
531 let fxn_input: Vec<Value> = vec![sink.clone(), source.clone(), Value::Id(key)];
532 let new_fxn = AssignColumn{}.compile(&fxn_input)?;
533 new_fxn.solve();
534 let res = new_fxn.out();
535 plan.borrow_mut().push(new_fxn);
536 return Ok(res);
537 },
538 #[cfg(feature = "tuple")]
539 Subscript::DotInt(x) => {
540 let ix = real(x, p)?.as_index()?;
541 let mut fxn_input: Vec<Value> = vec![sink.clone(), source.clone(), ix.clone()];
542 let new_fxn = TupleAssignScalar{}.compile(&fxn_input)?;
543 new_fxn.solve();
544 let res = new_fxn.out();
545 plan.borrow_mut().push(new_fxn);
546 return Ok(res);
547 },
548 Subscript::Swizzle(x) => {
549 unreachable!()
550 },
551 Subscript::Bracket(subs) => {
552 let mut fxn_input = vec![sink.clone()];
553 match &subs[..] {
554 #[cfg(feature = "subscript_formula")]
555 [Subscript::Formula(ix)] => {
556 fxn_input.push(source.clone());
557 let ixes = subscript_formula_ix(&subs[0], env, p)?;
558 let shape = ixes.shape();
559 fxn_input.push(ixes);
560 match shape[..] {
561 #[cfg(feature = "matrix")]
562 [1,1] => plan.borrow_mut().push(MatrixAssignScalar{}.compile(&fxn_input)?),
563 #[cfg(all(feature = "matrix", feature = "subscript_range", feature = "assign"))]
564 [1,n] => plan.borrow_mut().push(MatrixAssignRange{}.compile(&fxn_input)?),
565 #[cfg(all(feature = "matrix", feature = "subscript_range", feature = "assign"))]
566 [n,1] => plan.borrow_mut().push(MatrixAssignRange{}.compile(&fxn_input)?),
567 _ => todo!(),
568 }
569 },
570 #[cfg(all(feature = "matrix", feature = "subscript_range"))]
571 [Subscript::Range(ix)] => {
572 fxn_input.push(source.clone());
573 let ixes = subscript_range(&subs[0], env, p)?;
574 fxn_input.push(ixes);
575 plan.borrow_mut().push(MatrixAssignRange{}.compile(&fxn_input)?);
576 },
577 #[cfg(all(feature = "matrix", feature = "subscript_range"))]
578 [Subscript::All] => {
579 fxn_input.push(source.clone());
580 fxn_input.push(Value::IndexAll);
581 plan.borrow_mut().push(MatrixAssignAll{}.compile(&fxn_input)?);
582 },
583 [Subscript::All,Subscript::All] => todo!(),
584 #[cfg(feature = "subscript_formula")]
585 [Subscript::Formula(ix1),Subscript::Formula(ix2)] => {
586 fxn_input.push(source.clone());
587 let result1 = subscript_formula_ix(&subs[0], env, p)?;
588 let result2 = subscript_formula_ix(&subs[1], env, p)?;
589 let shape1 = result1.shape();
590 let shape2 = result2.shape();
591 fxn_input.push(result1);
592 fxn_input.push(result2);
593 match ((shape1[0],shape1[1]),(shape2[0],shape2[1])) {
594 #[cfg(feature = "matrix")]
595 ((1,1),(1,1)) => plan.borrow_mut().push(MatrixAssignScalarScalar{}.compile(&fxn_input)?),
596 #[cfg(all(feature = "matrix", feature = "subscript_range"))]
597 ((1,1),(m,1)) => plan.borrow_mut().push(MatrixAssignScalarRange{}.compile(&fxn_input)?),
598 #[cfg(all(feature = "matrix", feature = "subscript_range"))]
599 ((n,1),(1,1)) => plan.borrow_mut().push(MatrixAssignRangeScalar{}.compile(&fxn_input)?),
600 #[cfg(all(feature = "matrix", feature = "subscript_range"))]
601 ((n,1),(m,1)) => plan.borrow_mut().push(MatrixAssignRangeRange{}.compile(&fxn_input)?),
602 _ => unreachable!(),
603 }
604 },
605 #[cfg(all(feature = "matrix", feature = "subscript_range"))]
606 [Subscript::Range(ix1),Subscript::Range(ix2)] => {
607 fxn_input.push(source.clone());
608 let result = subscript_range(&subs[0], env, p)?;
609 fxn_input.push(result);
610 let result = subscript_range(&subs[1], env, p)?;
611 fxn_input.push(result);
612 plan.borrow_mut().push(MatrixAssignRangeRange{}.compile(&fxn_input)?);
613 },
614 #[cfg(all(feature = "matrix", feature = "subscript_formula"))]
615 [Subscript::All,Subscript::Formula(ix2)] => {
616 fxn_input.push(source.clone());
617 fxn_input.push(Value::IndexAll);
618 let ix = subscript_formula_ix(&subs[1], env, p)?;
619 let shape = ix.shape();
620 fxn_input.push(ix);
621 match shape[..] {
622 #[cfg(feature = "matrix")]
623 [1,1] => plan.borrow_mut().push(MatrixAssignAllScalar{}.compile(&fxn_input)?),
624 #[cfg(feature = "matrix")]
625 [1,n] => plan.borrow_mut().push(MatrixAssignAllRange{}.compile(&fxn_input)?),
626 #[cfg(feature = "matrix")]
627 [n,1] => plan.borrow_mut().push(MatrixAssignAllRange{}.compile(&fxn_input)?),
628 _ => todo!(),
629 }
630 }
631 #[cfg(feature = "subscript_formula")]
632 [Subscript::Formula(ix1),Subscript::All] => {
633 fxn_input.push(source.clone());
634 let ix = subscript_formula_ix(&subs[0], env, p)?;
635 let shape = ix.shape();
636 fxn_input.push(ix);
637 fxn_input.push(Value::IndexAll);
638 match shape[..] {
639 #[cfg(feature = "matrix")]
640 [1,1] => plan.borrow_mut().push(MatrixAssignScalarAll{}.compile(&fxn_input)?),
641 #[cfg(all(feature = "matrix", feature = "subscript_range"))]
642 [1,n] => plan.borrow_mut().push(MatrixAssignRangeAll{}.compile(&fxn_input)?),
643 #[cfg(all(feature = "matrix", feature = "subscript_range"))]
644 [n,1] => plan.borrow_mut().push(MatrixAssignRangeAll{}.compile(&fxn_input)?),
645 _ => todo!(),
646 }
647 },
648 #[cfg(all(feature = "subscript_formula", feature = "subscript_range"))]
649 [Subscript::Range(ix1),Subscript::Formula(ix2)] => {
650 fxn_input.push(source.clone());
651 let result = subscript_range(&subs[0], env, p)?;
652 fxn_input.push(result);
653 let result = subscript_formula_ix(&subs[1], env, p)?;
654 let shape = result.shape();
655 fxn_input.push(result);
656 match &shape[..] {
657 #[cfg(feature = "matrix")]
658 [1,1] => plan.borrow_mut().push(MatrixAssignRangeScalar{}.compile(&fxn_input)?),
659 #[cfg(feature = "matrix")]
660 [1,n] => plan.borrow_mut().push(MatrixAssignRangeRange{}.compile(&fxn_input)?),
661 #[cfg(feature = "matrix")]
662 [n,1] => plan.borrow_mut().push(MatrixAssignRangeRange{}.compile(&fxn_input)?),
663 _ => todo!(),
664 }
665 },
666 #[cfg(all(feature = "subscript_formula", feature = "subscript_range"))]
667 [Subscript::Formula(ix1),Subscript::Range(ix2)] => {
668 fxn_input.push(source.clone());
669 let result = subscript_formula_ix(&subs[0], env, p)?;
670 let shape = result.shape();
671 fxn_input.push(result);
672 let result = subscript_range(&subs[1], env, p)?;
673 fxn_input.push(result);
674 match &shape[..] {
675 #[cfg(feature = "matrix")]
676 [1,1] => plan.borrow_mut().push(MatrixAssignScalarRange{}.compile(&fxn_input)?),
677 #[cfg(feature = "matrix")]
678 [1,n] => plan.borrow_mut().push(MatrixAssignRangeRange{}.compile(&fxn_input)?),
679 #[cfg(feature = "matrix")]
680 [n,1] => plan.borrow_mut().push(MatrixAssignRangeRange{}.compile(&fxn_input)?),
681 _ => todo!(),
682 }
683 },
684 #[cfg(all(feature = "matrix", feature = "subscript_range"))]
685 [Subscript::All,Subscript::Range(ix2)] => {
686 fxn_input.push(source.clone());
687 fxn_input.push(Value::IndexAll);
688 let result = subscript_range(&subs[1], env, p)?;
689 fxn_input.push(result);
690 plan.borrow_mut().push(MatrixAssignAllRange{}.compile(&fxn_input)?);
691 },
692 #[cfg(all(feature = "matrix", feature = "subscript_range"))]
693 [Subscript::Range(ix1),Subscript::All] => {
694 fxn_input.push(source.clone());
695 let result = subscript_range(&subs[0], env, p)?;
696 fxn_input.push(result);
697 fxn_input.push(Value::IndexAll);
698 plan.borrow_mut().push(MatrixAssignRangeAll{}.compile(&fxn_input)?);
699 },
700 _ => unreachable!(),
701 };
702 let plan_brrw = plan.borrow();
703 let mut new_fxn = &plan_brrw.last().unwrap();
704 new_fxn.solve();
705 let res = new_fxn.out();
706 return Ok(res);
707 },
708 Subscript::Brace(subs) => {
709 let mut fxn_input = vec![sink.clone()];
710 match &subs[..] {
711 #[cfg(feature = "subscript_formula")]
712 [Subscript::Formula(ix)] => {
713 fxn_input.push(source.clone());
714 let ixes = subscript_formula(&subs[0], env, p)?;
715 let shape = ixes.shape();
716 fxn_input.push(ixes);
717 match shape[..] {
718 #[cfg(feature = "map")]
719 [1,1] => plan.borrow_mut().push(MapAssignScalar{}.compile(&fxn_input)?),
720 _ => todo!(),
725 }
726 },
727 #[cfg(all(feature = "matrix", feature = "subscript_range"))]
728 [Subscript::Range(ix)] => {
729 todo!();
730 },
735 #[cfg(all(feature = "matrix", feature = "subscript_range"))]
736 [Subscript::All] => {
737 todo!();
738 },
742 _ => unreachable!(),
743 };
744 let plan_brrw = plan.borrow();
745 let mut new_fxn = &plan_brrw.last().unwrap();
746 new_fxn.solve();
747 let res = new_fxn.out();
748 return Ok(res);
749 }
750 _ => unreachable!(),
751 }
752}
753
754#[derive(Debug, Clone)]
755pub struct UnableToConvertAtomToEnumVariantError {
756 pub atom_name: String,
757 pub target_enum_variant_name: String,
758}
759impl MechErrorKind for UnableToConvertAtomToEnumVariantError {
760 fn name(&self) -> &str {
761 "UnableToConvertAtomToEnumVariant"
762 }
763 fn message(&self) -> String {
764 format!("Unable to convert atom variant `{} to enum <{}>", self.atom_name, self.target_enum_variant_name)
765 }
766}
767
768#[derive(Debug, Clone)]
769pub struct UnableToConvertAtomError {
770 pub atom_id: u64,
771}
772impl MechErrorKind for UnableToConvertAtomError {
773 fn name(&self) -> &str {
774 "UnableToConvertAtom"
775 }
776 fn message(&self) -> String {
777 format!("Unable to atom {}", self.atom_id)
778 }
779}
780
781#[derive(Debug, Clone)]
782pub struct VariableAlreadyDefinedError {
783 pub id: u64,
784}
785impl MechErrorKind for VariableAlreadyDefinedError {
786 fn name(&self) -> &str { "VariableAlreadyDefined" }
787 fn message(&self) -> String {
788 format!("Variable already defined: {}", self.id)
789 }
790}
791
792#[derive(Debug, Clone)]
793pub struct UndefinedVariableError {
794 pub id: u64,
795}
796impl MechErrorKind for UndefinedVariableError {
797 fn name(&self) -> &str { "UndefinedVariable" }
798
799 fn message(&self) -> String {
800 format!("Undefined variable: {}", self.id)
801 }
802}
803
804#[derive(Debug, Clone)]
805pub struct NotMutableError {
806 pub id: u64,
807}
808impl MechErrorKind for NotMutableError {
809 fn name(&self) -> &str { "NotMutable" }
810 fn message(&self) -> String {
811 format!("Variable is not mutable: {}", self.id)
812 }
813}
814
815#[cfg(feature = "record")]
816#[derive(Debug, Clone)]
817pub struct UnableToConvertRecordError {
818 pub source_record_kind: ValueKind,
819 pub target_record_kind: ValueKind,
820}
821#[cfg(feature = "record")]
822impl MechErrorKind for UnableToConvertRecordError {
823 fn name(&self) -> &str {
824 "UnableToConvertRecord"
825 }
826 fn message(&self) -> String {
827 format!("Unable to convert record of kind `{:?}` to record of kind `{:?}`", self.source_record_kind, self.target_record_kind)
828 }
829}
830