mech_interpreter/
functions.rsuse crate::*;
pub fn function_define(fxn_def: &FunctionDefine, functions: FunctionsRef) -> MResult<FunctionDefinition> {
let fxn_name_id = fxn_def.name.hash();
let mut new_fxn = FunctionDefinition::new(fxn_name_id,fxn_def.name.to_string(), fxn_def.clone());
for input_arg in &fxn_def.input {
let arg_id = input_arg.name.hash();
new_fxn.input.insert(arg_id,input_arg.kind.clone());
let in_arg = Value::F64(new_ref(F64::new(0.0)));
new_fxn.symbols.borrow_mut().insert(arg_id, in_arg, false);
}
let output_arg_ids = fxn_def.output.iter().map(|output_arg| {
let arg_id = output_arg.name.hash();
new_fxn.output.insert(arg_id,output_arg.kind.clone());
arg_id
}).collect::<Vec<u64>>();
for stmnt in &fxn_def.statements {
let result = statement(stmnt, new_fxn.plan.clone(), new_fxn.symbols.clone(), functions.clone());
}
{
let symbol_brrw = new_fxn.symbols.borrow();
for arg_id in output_arg_ids {
match symbol_brrw.get(arg_id) {
Some(cell) => new_fxn.out = cell.clone(),
None => { return Err(MechError{file: file!().to_string(), tokens: fxn_def.output.iter().flat_map(|a| a.tokens()).collect(), msg: "".to_string(), id: line!(), kind: MechErrorKind::OutputUndefinedInFunctionBody(arg_id)});}
}
}
}
Ok(new_fxn)
}
pub fn function_call(fxn_call: &FunctionCall, plan: Plan, symbols: SymbolTableRef, functions: FunctionsRef) -> MResult<Value> {
let fxn_name_id = fxn_call.name.hash();
let fxns_brrw = functions.borrow();
match fxns_brrw.functions.get(&fxn_name_id) {
Some(fxn) => {
let mut new_fxn = function_define(&fxn.code, functions.clone())?; for (ix,(arg_name, arg_expr)) in fxn_call.args.iter().enumerate() {
let value_ref: ValRef = match arg_name {
Some(arg_id) => {
match new_fxn.input.get(&arg_id.hash()) {
Some(kind) => {
let symbols_brrw = new_fxn.symbols.borrow();
symbols_brrw.get(arg_id.hash()).unwrap().clone()
}
None => { return Err(MechError{file: file!().to_string(), tokens: arg_expr.tokens(), msg: "".to_string(), id: line!(), kind: MechErrorKind::UnknownFunctionArgument(arg_id.hash())});}
}
}
None => {
match &new_fxn.input.iter().nth(ix) {
Some((arg_id,kind)) => {
let symbols_brrw = new_fxn.symbols.borrow();
symbols_brrw.get(**arg_id).unwrap().clone()
}
None => { return Err(MechError{file: file!().to_string(), tokens: arg_expr.tokens(), msg: "".to_string(), id: line!(), kind: MechErrorKind::TooManyInputArguments(ix+1,new_fxn.input.len())});}
}
}
};
let result = expression(&arg_expr, plan.clone(), symbols.clone(), functions.clone())?;
let mut ref_brrw = value_ref.borrow_mut();
match (&mut *ref_brrw, &result) {
(Value::I64(arg_ref), Value::I64(i64_ref)) => {
*arg_ref.borrow_mut() = i64_ref.borrow().clone();
}
(Value::F64(arg_ref), Value::F64(f64_ref)) => {
*arg_ref.borrow_mut() = f64_ref.borrow().clone();
}
(x,y) => {return Err(MechError{file: file!().to_string(), tokens: arg_expr.tokens(), msg: "".to_string(), id: line!(), kind: MechErrorKind::KindMismatch(x.kind(),y.kind())});}
}
}
let mut plan_brrw = plan.borrow_mut();
let result = new_fxn.solve();
let result_brrw = result.borrow();
plan_brrw.push(Box::new(UserFunction{fxn: new_fxn.clone()}));
return Ok(result_brrw.clone())
}
None => {
match fxns_brrw.function_compilers.get(&fxn_name_id) {
Some(fxn_compiler) => {
let mut input_arg_values = vec![];
for (arg_name, arg_expr) in fxn_call.args.iter() {
let result = expression(&arg_expr, plan.clone(), symbols.clone(), functions.clone())?;
input_arg_values.push(result);
}
match fxn_compiler.compile(&input_arg_values) {
Ok(new_fxn) => {
let mut plan_brrw = plan.borrow_mut();
new_fxn.solve();
let result = new_fxn.out();
plan_brrw.push(new_fxn);
return Ok(result)
}
Err(x) => {return Err(x);}
}
}
None => {return Err(MechError{file: file!().to_string(), tokens: fxn_call.name.tokens(), msg: "".to_string(), id: line!(), kind: MechErrorKind::MissingFunction(fxn_name_id)});}
}
}
}
unreachable!()
}