use crate::*;
use paste::paste;
#[cfg(feature = "variable_define")]
use crate::stdlib::define::*;
pub fn statement(stmt: &Statement, env: Option<&Environment>, p: &Interpreter) -> MResult<Value> {
match stmt {
#[cfg(feature = "tuple")]
Statement::TupleDestructure(tpl_dstrct) => tuple_destructure(&tpl_dstrct, p),
#[cfg(feature = "variable_define")]
Statement::VariableDefine(var_def) => variable_define(&var_def, p),
#[cfg(feature = "variable_assign")]
Statement::VariableAssign(var_assgn) => variable_assign(&var_assgn, env, p),
#[cfg(feature = "kind_define")]
Statement::KindDefine(knd_def) => kind_define(&knd_def, p),
#[cfg(feature = "enum")]
Statement::EnumDefine(enm_def) => {
enum_define(&enm_def, p)?;
Ok(Value::Empty)
}
#[cfg(feature = "math")]
Statement::OpAssign(op_assgn) => op_assign(&op_assgn, env, p),
x => return Err(MechError::new(
FeatureNotEnabledError,
None
).with_compiler_loc().with_tokens(x.tokens())
),
}
}
#[cfg(feature = "tuple")]
pub fn tuple_destructure(tpl_dstrct: &TupleDestructure, p: &Interpreter) -> MResult<Value> {
let source = expression(&tpl_dstrct.expression, None, p)?;
let tpl = match &source {
Value::Tuple(tpl) => tpl,
Value::MutableReference(r) => {
let r_brrw = r.borrow();
&match &*r_brrw {
Value::Tuple(tpl) => tpl.clone(),
_ => return Err(MechError::new(
DestructureExpectedTupleError{ value: source.kind() },
None
).with_compiler_loc().with_tokens(tpl_dstrct.expression.tokens())),
}
},
_ => return Err(MechError::new(
DestructureExpectedTupleError{ value: source.kind() },
None
).with_compiler_loc().with_tokens(tpl_dstrct.expression.tokens())),
};
let symbols = p.symbols();
let mut symbols_brrw = symbols.borrow_mut();
for (i, var) in tpl_dstrct.vars.iter().enumerate() {
let id = var.hash();
if symbols_brrw.contains(id) {
return Err(MechError::new(
VariableAlreadyDefinedError { id },
None
).with_compiler_loc().with_tokens(var.tokens()));
}
if let Some(element) = tpl.borrow().get(i) {
symbols_brrw.insert(id, element.clone(), true);
symbols_brrw.dictionary.borrow_mut().insert(id, var.name.to_string());
} else {
return Err(MechError::new(
TupleDestructureTooManyVarsError{ value: source.kind() },
None
).with_compiler_loc().with_tokens(var.tokens()));
}
}
Ok(source)
}
#[cfg(feature = "math")]
pub fn op_assign(op_assgn: &OpAssign, env: Option<&Environment>, p: &Interpreter) -> MResult<Value> {
let mut source = expression(&op_assgn.expression, env, p)?;
let slc = &op_assgn.target;
let id = slc.name.hash();
let sink = {
let mut state_brrw = p.state.borrow_mut();
match state_brrw.get_mutable_symbol(id) {
Some(val) => val.borrow().clone(),
None => {
match state_brrw.contains_symbol(id) {
true => return Err(MechError::new(
NotMutableError { id },
Some("(!)> Mutable variables are defined with the `~` operator. *e.g.*: {{~x := 123}}".to_string()),
).with_compiler_loc().with_tokens(slc.name.tokens())),
false => return Err(MechError::new(
UndefinedVariableError { id },
Some("(!)> Variables are defined with the `:=` operator. *e.g.*: {{x := 123}}".to_string()),
).with_compiler_loc().with_tokens(slc.name.tokens())),
}
}
}
};
match &slc.subscript {
Some(sbscrpt) => {
for s in sbscrpt {
let fxn = match op_assgn.op {
#[cfg(feature = "math_add_assign")]
OpAssignOp::Add => add_assign(&s, &sink, &source, env, p)?,
#[cfg(feature = "math_sub_assign")]
OpAssignOp::Sub => sub_assign(&s, &sink, &source, env, p)?,
#[cfg(feature = "math_div_assign")]
OpAssignOp::Div => div_assign(&s, &sink, &source, env, p)?,
#[cfg(feature = "math_mul_assign")]
OpAssignOp::Mul => mul_assign(&s, &sink, &source, env, p)?,
_ => todo!(),
};
return Ok(fxn);
}
}
None => {
let args = vec![sink,source];
let fxn: Box<dyn MechFunction> = match op_assgn.op {
#[cfg(feature = "math_add_assign")]
OpAssignOp::Add => AddAssignValue{}.compile(&args)?,
#[cfg(feature = "math_sub_assign")]
OpAssignOp::Sub => SubAssignValue{}.compile(&args)?,
#[cfg(feature = "math_div_assign")]
OpAssignOp::Div => DivAssignValue{}.compile(&args)?,
#[cfg(feature = "math_mul_assign")]
OpAssignOp::Mul => MulAssignValue{}.compile(&args)?,
_ => todo!(),
};
fxn.solve();
let res = fxn.out();
p.state.borrow_mut().add_plan_step(fxn);
return Ok(res);
}
}
unreachable!(); }
#[cfg(feature = "variable_assign")]
pub fn variable_assign(var_assgn: &VariableAssign, env: Option<&Environment>, p: &Interpreter) -> MResult<Value> {
let mut source = expression(&var_assgn.expression, env, p)?;
let slc = &var_assgn.target;
let id = slc.name.hash();
let sink = {
let symbols = p.symbols();
let symbols_brrw = symbols.borrow();
match symbols_brrw.get_mutable(id) {
Some(val) => val.borrow().clone(),
None => {
if !symbols_brrw.contains(id) {
return Err(MechError::new(
UndefinedVariableError { id },
Some("(!)> Variables are defined with the `:=` operator. *e.g.*: {{x := 123}}".to_string()),
).with_compiler_loc().with_tokens(slc.name.tokens()));
} else {
return Err(MechError::new(
NotMutableError { id },
Some("(!)> Mutable variables are defined with the `~` operator. *e.g.*: {{~x := 123}}".to_string()),
).with_compiler_loc().with_tokens(slc.name.tokens()));
}
}
}
};
match &slc.subscript {
Some(sbscrpt) => {
#[cfg(feature = "subscript")]
for s in sbscrpt {
let s_result = subscript_ref(&s, &sink, &source, env, p)?;
return Ok(s_result);
}
}
#[cfg(feature = "assign")]
None => {
let args = vec![sink,source];
let fxn = AssignValue{}.compile(&args)?;
fxn.solve();
let res = fxn.out();
p.state.borrow_mut().add_plan_step(fxn);
return Ok(res);
}
_ => return Err(MechError::new(
FeatureNotEnabledError,
None
).with_compiler_loc().with_tokens(var_assgn.target.tokens())),
}
unreachable!(); }
#[cfg(feature = "enum")]
pub fn enum_define(enm_def: &EnumDefine, p: &Interpreter) -> MResult<()> {
let id = enm_def.name.hash();
let variants = enm_def.variants.iter().map(|v| (v.name.hash(),None)).collect::<Vec<(u64, Option<Value>)>>();
let state = &p.state;
let mut state_brrw = state.borrow_mut();
let dictionary = state_brrw.dictionary.clone();
{
let mut dictionary_brrw = dictionary.borrow_mut();
dictionary_brrw.insert(enm_def.name.hash(), enm_def.name.to_string());
for variant in &enm_def.variants {
dictionary_brrw.insert(variant.name.hash(), variant.name.to_string());
}
}
let enm = MechEnum{id, variants, names: dictionary};
let val = Value::Enum(Ref::new(enm.clone()));
state_brrw.enums.insert(id, enm.clone());
state_brrw.kinds.insert(id, val.kind());
Ok(())
}
#[cfg(feature = "kind_define")]
pub fn kind_define(knd_def: &KindDefine, p: &Interpreter) -> MResult<Value> {
let id = knd_def.name.hash();
let kind = kind_annotation(&knd_def.kind.kind, p)?;
let value_kind = kind.to_value_kind(&p.state.borrow().kinds)?;
let functions = p.functions();
let mut kinds = &mut p.state.borrow_mut().kinds;
kinds.insert(id, value_kind.clone());
Ok(Value::Kind(value_kind))
}
#[cfg(feature = "variable_define")]
pub fn variable_define(var_def: &VariableDefine, p: &Interpreter) -> MResult<Value> {
let var_id = var_def.var.name.hash();
let var_name = var_def.var.name.to_string();
{
let symbols = p.symbols();
if symbols.borrow().contains(var_id) {
return Err(MechError::new(
VariableAlreadyDefinedError { id: var_id },
None
).with_compiler_loc().with_tokens(var_def.var.name.tokens()));
}
}
let mut result = expression(&var_def.expression, None, p)?;
#[cfg(all(feature = "kind_annotation", feature = "convert"))]
if let Some(knd_anntn) = &var_def.var.kind {
let knd = kind_annotation(&knd_anntn.kind,p)?;
let mut state_brrw = &mut p.state.borrow_mut();
let target_knd = knd.to_value_kind(&mut state_brrw.kinds)?;
match (&result, &target_knd) {
#[cfg(all(feature = "atom", feature = "enum"))]
(Value::Atom(atom_variant), ValueKind::Enum(enum_id, target_enum_variant_name)) => {
let atom_variant_brrw = atom_variant.borrow();
let enums = &state_brrw.enums;
let my_enum = match enums.get(enum_id) {
Some(my_enum) => my_enum,
None => todo!(),
};
let dictionary = state_brrw.dictionary.clone();
let atom_id = atom_variant_brrw.id();
let atom_name = atom_variant_brrw.name();
let enum_variant_name = if let Some((enum_name, variant_name)) = atom_name.split_once('/') {
if enum_name != target_enum_variant_name {
return Err(MechError::new(
UnableToConvertAtomToEnumVariantError { atom_name: atom_name.clone(), target_enum_variant_name: target_enum_variant_name.to_string() },
None
).with_compiler_loc().with_tokens(var_def.expression.tokens()));
}
variant_name.to_string()
} else {
return Err(MechError::new(
UnableToConvertAtomToEnumVariantError { atom_name: atom_name.clone(), target_enum_variant_name: target_enum_variant_name.clone() },
None
).with_compiler_loc().with_tokens(var_def.expression.tokens()));
};
let variant_id = hash_str(&enum_variant_name);
if !my_enum.variants.iter().any(|(known_enum_variant, inner_value)| variant_id == *known_enum_variant) {
return Err(MechError::new(
UnableToConvertAtomToEnumVariantError { atom_name: atom_name.clone(), target_enum_variant_name: target_enum_variant_name.clone() },
None
).with_compiler_loc().with_tokens(var_def.expression.tokens()));
}
}
#[cfg(feature = "atom")]
(Value::Atom(given_variant_id), target_kind) => {
return Err(MechError::new(
UnableToConvertAtomError { atom_id: given_variant_id.borrow().0.0},
None
).with_compiler_loc().with_tokens(var_def.expression.tokens()));
}
#[cfg(feature = "record")]
(Value::Record(rec), ref target_kind @ ValueKind::Record(target_rec_knd)) => {
let rec_brrw = rec.borrow();
let rec_knd = rec_brrw.kind();
if &rec_knd != *target_kind {
return Err(MechError::new(
UnableToConvertRecordError { source_record_kind: rec_knd.clone(), target_record_kind: (*target_kind).clone() },
None
).with_compiler_loc().with_tokens(var_def.expression.tokens()));
}
}
#[cfg(feature = "matrix")]
(Value::MutableReference(v), ValueKind::Matrix(target_matrix_knd,_)) => {
let value = v.borrow().clone();
if value.is_matrix() {
let convert_fxn = ConvertMatToMat{}.compile(&vec![result.clone(), Value::Kind(target_knd.clone())])?;
convert_fxn.solve();
let converted_result = convert_fxn.out();
state_brrw.add_plan_step(convert_fxn);
result = converted_result;
} else {
let value_kind = value.kind();
if value_kind.deref_kind() != target_matrix_knd.as_ref().clone() && value_kind != *target_matrix_knd.clone() {
let convert_fxn = ConvertKind{}.compile(&vec![result.clone(), Value::Kind(target_matrix_knd.as_ref().clone())])?;
convert_fxn.solve();
let converted_result = convert_fxn.out();
state_brrw.add_plan_step(convert_fxn);
result = converted_result;
};
let convert_fxn = ConvertScalarToMat{}.compile(&vec![result.clone(), Value::Kind(target_knd.clone())])?;
convert_fxn.solve();
let converted_result = convert_fxn.out();
state_brrw.add_plan_step(convert_fxn);
result = converted_result;
}
}
#[cfg(feature = "matrix")]
(value, ValueKind::Matrix(target_matrix_knd,_)) => {
if value.is_matrix() {
let convert_fxn = ConvertMatToMat{}.compile(&vec![result.clone(), Value::Kind(target_knd.clone())])?;
convert_fxn.solve();
let converted_result = convert_fxn.out();
state_brrw.add_plan_step(convert_fxn);
result = converted_result;
} else {
let value_kind = value.kind();
if value_kind.deref_kind() != target_matrix_knd.as_ref().clone() && value_kind != *target_matrix_knd.clone() {
let convert_fxn = ConvertKind{}.compile(&vec![result.clone(), Value::Kind(target_matrix_knd.as_ref().clone())])?;
convert_fxn.solve();
let converted_result = convert_fxn.out();
state_brrw.add_plan_step(convert_fxn);
result = converted_result;
};
let convert_fxn = ConvertScalarToMat{}.compile(&vec![result.clone(), Value::Kind(target_knd.clone())])?;
convert_fxn.solve();
let converted_result = convert_fxn.out();
state_brrw.add_plan_step(convert_fxn);
result = converted_result;
}
}
x => {
let convert_fxn = ConvertKind{}.compile(&vec![result.clone(), Value::Kind(target_knd)])?;
convert_fxn.solve();
let converted_result = convert_fxn.out();
state_brrw.add_plan_step(convert_fxn);
result = converted_result;
},
};
let detached_result = detach_variable_value(&result);
let val_ref = state_brrw.save_symbol(var_id, var_name.clone(), detached_result.clone(), var_def.mutable);
let var_def_fxn = VarDefine{}.compile(&vec![detached_result.clone(), Value::String(Ref::new(var_name.clone())), Value::Bool(Ref::new(var_def.mutable))])?;
state_brrw.add_plan_step(var_def_fxn);
return Ok(detached_result);
}
let mut state_brrw = p.state.borrow_mut();
let detached_result = detach_variable_value(&result);
let val_ref = state_brrw.save_symbol(var_id,var_name.clone(),detached_result.clone(),var_def.mutable);
let var_def_fxn = VarDefine{}.compile(&vec![detached_result.clone(), Value::String(Ref::new(var_name.clone())), Value::Bool(Ref::new(var_def.mutable))])?;
state_brrw.add_plan_step(var_def_fxn);
return Ok(detached_result);
}
fn detach_variable_value(value: &Value) -> Value {
match value {
Value::MutableReference(reference) => detach_variable_value(&reference.borrow()),
_ => value.clone(),
}
}
macro_rules! op_assign {
($fxn_name:ident, $op:tt) => {
paste!{
pub fn $fxn_name(sbscrpt: &Subscript, sink: &Value, source: &Value, env: Option<&Environment>, p: &Interpreter) -> MResult<Value> {
let plan = p.plan();
match sbscrpt {
Subscript::Dot(x) => {
todo!()
},
Subscript::DotInt(x) => {
todo!()
},
Subscript::Swizzle(x) => {
todo!()
},
Subscript::Bracket(subs) => {
let mut fxn_input = vec![sink.clone()];
match &subs[..] {
[Subscript::Formula(ix)] => {
fxn_input.push(source.clone());
let ixes = subscript_formula_ix(&subs[0], env, p)?;
let shape = ixes.shape();
fxn_input.push(ixes);
match shape[..] {
[1,1] => plan.borrow_mut().push(MatrixAssignScalar{}.compile(&fxn_input)?),
[1,n] => plan.borrow_mut().push([<$op AssignRange>]{}.compile(&fxn_input)?),
[n,1] => plan.borrow_mut().push([<$op AssignRange>]{}.compile(&fxn_input)?),
_ => todo!(),
}
},
[Subscript::Formula(ix1),Subscript::All] => {
fxn_input.push(source.clone());
let ix = subscript_formula_ix(&subs[0], env, p)?;
let shape = ix.shape();
fxn_input.push(ix);
fxn_input.push(Value::IndexAll);
match shape[..] {
[1,1] => plan.borrow_mut().push(MatrixAssignScalarAll{}.compile(&fxn_input)?),
[1,n] => plan.borrow_mut().push([<$op AssignRangeAll>]{}.compile(&fxn_input)?),
[n,1] => plan.borrow_mut().push([<$op AssignRangeAll>]{}.compile(&fxn_input)?),
_ => todo!(),
}
},
[Subscript::Range(ix)] => {
fxn_input.push(source.clone());
let ixes = subscript_range(&subs[0], env, p)?;
fxn_input.push(ixes);
plan.borrow_mut().push([<$op AssignRange>]{}.compile(&fxn_input)?);
},
[Subscript::Range(ix), Subscript::All] => {
fxn_input.push(source.clone());
let ixes = subscript_range(&subs[0], env, p)?;
fxn_input.push(ixes);
fxn_input.push(Value::IndexAll);
plan.borrow_mut().push([<$op AssignRangeAll>]{}.compile(&fxn_input)?);
},
x => todo!("{:?}", x),
};
let plan_brrw = plan.borrow();
let mut new_fxn = &plan_brrw.last().unwrap();
new_fxn.solve();
let res = new_fxn.out();
return Ok(res);
},
Subscript::Brace(x) => todo!(),
x => todo!("{:?}", x),
}
}
}}}
#[cfg(feature = "math_add_assign")]
op_assign!(add_assign, Add);
#[cfg(feature = "math_sub_assign")]
op_assign!(sub_assign, Sub);
#[cfg(feature = "math_div_assign")]
op_assign!(mul_assign, Mul);
#[cfg(feature = "math_mul_assign")]
op_assign!(div_assign, Div);
#[cfg(all(feature = "subscript", feature = "assign"))]
pub fn subscript_ref(sbscrpt: &Subscript, sink: &Value, source: &Value, env: Option<&Environment>, p: &Interpreter) -> MResult<Value> {
let plan = p.plan();
let symbols = p.symbols();
let functions = p.functions();
match sbscrpt {
Subscript::Dot(x) => {
let key = x.hash();
let fxn_input: Vec<Value> = vec![sink.clone(), source.clone(), Value::Id(key)];
let new_fxn = AssignColumn{}.compile(&fxn_input)?;
new_fxn.solve();
let res = new_fxn.out();
plan.borrow_mut().push(new_fxn);
return Ok(res);
},
#[cfg(feature = "tuple")]
Subscript::DotInt(x) => {
let ix = real(x, p)?.as_index()?;
let mut fxn_input: Vec<Value> = vec![sink.clone(), source.clone(), ix.clone()];
let new_fxn = TupleAssignScalar{}.compile(&fxn_input)?;
new_fxn.solve();
let res = new_fxn.out();
plan.borrow_mut().push(new_fxn);
return Ok(res);
},
Subscript::Swizzle(x) => {
unreachable!()
},
Subscript::Bracket(subs) => {
let mut fxn_input = vec![sink.clone()];
match &subs[..] {
#[cfg(feature = "subscript_formula")]
[Subscript::Formula(ix)] => {
fxn_input.push(source.clone());
let ixes = subscript_formula_ix(&subs[0], env, p)?;
let shape = ixes.shape();
fxn_input.push(ixes);
match shape[..] {
#[cfg(feature = "matrix")]
[1,1] => plan.borrow_mut().push(MatrixAssignScalar{}.compile(&fxn_input)?),
#[cfg(all(feature = "matrix", feature = "subscript_range", feature = "assign"))]
[1,n] => plan.borrow_mut().push(MatrixAssignRange{}.compile(&fxn_input)?),
#[cfg(all(feature = "matrix", feature = "subscript_range", feature = "assign"))]
[n,1] => plan.borrow_mut().push(MatrixAssignRange{}.compile(&fxn_input)?),
_ => todo!(),
}
},
#[cfg(all(feature = "matrix", feature = "subscript_range"))]
[Subscript::Range(ix)] => {
fxn_input.push(source.clone());
let ixes = subscript_range(&subs[0], env, p)?;
fxn_input.push(ixes);
plan.borrow_mut().push(MatrixAssignRange{}.compile(&fxn_input)?);
},
#[cfg(all(feature = "matrix", feature = "subscript_range"))]
[Subscript::All] => {
fxn_input.push(source.clone());
fxn_input.push(Value::IndexAll);
plan.borrow_mut().push(MatrixAssignAll{}.compile(&fxn_input)?);
},
[Subscript::All,Subscript::All] => todo!(),
#[cfg(feature = "subscript_formula")]
[Subscript::Formula(ix1),Subscript::Formula(ix2)] => {
fxn_input.push(source.clone());
let result1 = subscript_formula_ix(&subs[0], env, p)?;
let result2 = subscript_formula_ix(&subs[1], env, p)?;
let shape1 = result1.shape();
let shape2 = result2.shape();
fxn_input.push(result1);
fxn_input.push(result2);
match ((shape1[0],shape1[1]),(shape2[0],shape2[1])) {
#[cfg(feature = "matrix")]
((1,1),(1,1)) => plan.borrow_mut().push(MatrixAssignScalarScalar{}.compile(&fxn_input)?),
#[cfg(all(feature = "matrix", feature = "subscript_range"))]
((1,1),(m,1)) => plan.borrow_mut().push(MatrixAssignScalarRange{}.compile(&fxn_input)?),
#[cfg(all(feature = "matrix", feature = "subscript_range"))]
((n,1),(1,1)) => plan.borrow_mut().push(MatrixAssignRangeScalar{}.compile(&fxn_input)?),
#[cfg(all(feature = "matrix", feature = "subscript_range"))]
((n,1),(m,1)) => plan.borrow_mut().push(MatrixAssignRangeRange{}.compile(&fxn_input)?),
_ => unreachable!(),
}
},
#[cfg(all(feature = "matrix", feature = "subscript_range"))]
[Subscript::Range(ix1),Subscript::Range(ix2)] => {
fxn_input.push(source.clone());
let result = subscript_range(&subs[0], env, p)?;
fxn_input.push(result);
let result = subscript_range(&subs[1], env, p)?;
fxn_input.push(result);
plan.borrow_mut().push(MatrixAssignRangeRange{}.compile(&fxn_input)?);
},
#[cfg(all(feature = "matrix", feature = "subscript_formula"))]
[Subscript::All,Subscript::Formula(ix2)] => {
fxn_input.push(source.clone());
fxn_input.push(Value::IndexAll);
let ix = subscript_formula_ix(&subs[1], env, p)?;
let shape = ix.shape();
fxn_input.push(ix);
match shape[..] {
#[cfg(feature = "matrix")]
[1,1] => plan.borrow_mut().push(MatrixAssignAllScalar{}.compile(&fxn_input)?),
#[cfg(feature = "matrix")]
[1,n] => plan.borrow_mut().push(MatrixAssignAllRange{}.compile(&fxn_input)?),
#[cfg(feature = "matrix")]
[n,1] => plan.borrow_mut().push(MatrixAssignAllRange{}.compile(&fxn_input)?),
_ => todo!(),
}
}
#[cfg(feature = "subscript_formula")]
[Subscript::Formula(ix1),Subscript::All] => {
fxn_input.push(source.clone());
let ix = subscript_formula_ix(&subs[0], env, p)?;
let shape = ix.shape();
fxn_input.push(ix);
fxn_input.push(Value::IndexAll);
match shape[..] {
#[cfg(feature = "matrix")]
[1,1] => plan.borrow_mut().push(MatrixAssignScalarAll{}.compile(&fxn_input)?),
#[cfg(all(feature = "matrix", feature = "subscript_range"))]
[1,n] => plan.borrow_mut().push(MatrixAssignRangeAll{}.compile(&fxn_input)?),
#[cfg(all(feature = "matrix", feature = "subscript_range"))]
[n,1] => plan.borrow_mut().push(MatrixAssignRangeAll{}.compile(&fxn_input)?),
_ => todo!(),
}
},
#[cfg(all(feature = "subscript_formula", feature = "subscript_range"))]
[Subscript::Range(ix1),Subscript::Formula(ix2)] => {
fxn_input.push(source.clone());
let result = subscript_range(&subs[0], env, p)?;
fxn_input.push(result);
let result = subscript_formula_ix(&subs[1], env, p)?;
let shape = result.shape();
fxn_input.push(result);
match &shape[..] {
#[cfg(feature = "matrix")]
[1,1] => plan.borrow_mut().push(MatrixAssignRangeScalar{}.compile(&fxn_input)?),
#[cfg(feature = "matrix")]
[1,n] => plan.borrow_mut().push(MatrixAssignRangeRange{}.compile(&fxn_input)?),
#[cfg(feature = "matrix")]
[n,1] => plan.borrow_mut().push(MatrixAssignRangeRange{}.compile(&fxn_input)?),
_ => todo!(),
}
},
#[cfg(all(feature = "subscript_formula", feature = "subscript_range"))]
[Subscript::Formula(ix1),Subscript::Range(ix2)] => {
fxn_input.push(source.clone());
let result = subscript_formula_ix(&subs[0], env, p)?;
let shape = result.shape();
fxn_input.push(result);
let result = subscript_range(&subs[1], env, p)?;
fxn_input.push(result);
match &shape[..] {
#[cfg(feature = "matrix")]
[1,1] => plan.borrow_mut().push(MatrixAssignScalarRange{}.compile(&fxn_input)?),
#[cfg(feature = "matrix")]
[1,n] => plan.borrow_mut().push(MatrixAssignRangeRange{}.compile(&fxn_input)?),
#[cfg(feature = "matrix")]
[n,1] => plan.borrow_mut().push(MatrixAssignRangeRange{}.compile(&fxn_input)?),
_ => todo!(),
}
},
#[cfg(all(feature = "matrix", feature = "subscript_range"))]
[Subscript::All,Subscript::Range(ix2)] => {
fxn_input.push(source.clone());
fxn_input.push(Value::IndexAll);
let result = subscript_range(&subs[1], env, p)?;
fxn_input.push(result);
plan.borrow_mut().push(MatrixAssignAllRange{}.compile(&fxn_input)?);
},
#[cfg(all(feature = "matrix", feature = "subscript_range"))]
[Subscript::Range(ix1),Subscript::All] => {
fxn_input.push(source.clone());
let result = subscript_range(&subs[0], env, p)?;
fxn_input.push(result);
fxn_input.push(Value::IndexAll);
plan.borrow_mut().push(MatrixAssignRangeAll{}.compile(&fxn_input)?);
},
_ => unreachable!(),
};
let plan_brrw = plan.borrow();
let mut new_fxn = &plan_brrw.last().unwrap();
new_fxn.solve();
let res = new_fxn.out();
return Ok(res);
},
Subscript::Brace(subs) => {
let mut fxn_input = vec![sink.clone()];
match &subs[..] {
#[cfg(feature = "subscript_formula")]
[Subscript::Formula(ix)] => {
fxn_input.push(source.clone());
let ixes = subscript_formula(&subs[0], env, p)?;
let shape = ixes.shape();
fxn_input.push(ixes);
match shape[..] {
#[cfg(feature = "map")]
[1,1] => plan.borrow_mut().push(MapAssignScalar{}.compile(&fxn_input)?),
_ => todo!(),
}
},
#[cfg(all(feature = "matrix", feature = "subscript_range"))]
[Subscript::Range(ix)] => {
todo!();
},
#[cfg(all(feature = "matrix", feature = "subscript_range"))]
[Subscript::All] => {
todo!();
},
_ => unreachable!(),
};
let plan_brrw = plan.borrow();
let mut new_fxn = &plan_brrw.last().unwrap();
new_fxn.solve();
let res = new_fxn.out();
return Ok(res);
}
_ => unreachable!(),
}
}
#[derive(Debug, Clone)]
pub struct UnableToConvertAtomToEnumVariantError {
pub atom_name: String,
pub target_enum_variant_name: String,
}
impl MechErrorKind for UnableToConvertAtomToEnumVariantError {
fn name(&self) -> &str {
"UnableToConvertAtomToEnumVariant"
}
fn message(&self) -> String {
format!("Unable to convert atom variant `{} to enum <{}>", self.atom_name, self.target_enum_variant_name)
}
}
#[derive(Debug, Clone)]
pub struct UnableToConvertAtomError {
pub atom_id: u64,
}
impl MechErrorKind for UnableToConvertAtomError {
fn name(&self) -> &str {
"UnableToConvertAtom"
}
fn message(&self) -> String {
format!("Unable to atom {}", self.atom_id)
}
}
#[derive(Debug, Clone)]
pub struct VariableAlreadyDefinedError {
pub id: u64,
}
impl MechErrorKind for VariableAlreadyDefinedError {
fn name(&self) -> &str { "VariableAlreadyDefined" }
fn message(&self) -> String {
format!("Variable already defined: {}", self.id)
}
}
#[derive(Debug, Clone)]
pub struct UndefinedVariableError {
pub id: u64,
}
impl MechErrorKind for UndefinedVariableError {
fn name(&self) -> &str { "UndefinedVariable" }
fn message(&self) -> String {
format!("Undefined variable: {}", self.id)
}
}
#[derive(Debug, Clone)]
pub struct NotMutableError {
pub id: u64,
}
impl MechErrorKind for NotMutableError {
fn name(&self) -> &str { "NotMutable" }
fn message(&self) -> String {
format!("Variable is not mutable: {}", self.id)
}
}
#[cfg(feature = "record")]
#[derive(Debug, Clone)]
pub struct UnableToConvertRecordError {
pub source_record_kind: ValueKind,
pub target_record_kind: ValueKind,
}
#[cfg(feature = "record")]
impl MechErrorKind for UnableToConvertRecordError {
fn name(&self) -> &str {
"UnableToConvertRecord"
}
fn message(&self) -> String {
format!("Unable to convert record of kind `{:?}` to record of kind `{:?}`", self.source_record_kind, self.target_record_kind)
}
}