mech_interpreter/
functions.rs

1use crate::*;
2
3// Functions
4// ----------------------------------------------------------------------------
5
6pub fn function_define(fxn_def: &FunctionDefine, p: &Interpreter) -> MResult<FunctionDefinition> {
7  /*let fxn_name_id = fxn_def.name.hash();
8  let mut new_fxn = FunctionDefinition::new(fxn_name_id,fxn_def.name.to_string(), fxn_def.clone());
9  for input_arg in &fxn_def.input {
10    let arg_id = input_arg.name.hash();
11    new_fxn.input.insert(arg_id,input_arg.kind.clone());
12    let in_arg = Value::F64(Ref::new(F64::new(0.0)));
13    new_fxn.symbols.borrow_mut().insert(arg_id, in_arg, false);
14  }
15  let output_arg_ids = fxn_def.output.iter().map(|output_arg| {
16    let arg_id = output_arg.name.hash();
17    new_fxn.output.insert(arg_id,output_arg.kind.clone());
18    arg_id
19  }).collect::<Vec<u64>>();
20  
21  for stmnt in &fxn_def.statements {
22    let result = statement(stmnt, new_fxn.plan.clone(), new_fxn.symbols.clone(), functions.clone());
23  }    
24  // get the output cell
25  {
26    let symbol_brrw = new_fxn.symbols.borrow();
27    for arg_id in output_arg_ids {
28      match symbol_brrw.get(arg_id) {
29        Some(cell) => new_fxn.out = cell.clone(),
30        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)});} 
31      }
32    }
33  }
34  Ok(new_fxn)*/
35  todo!("Function define needs to be redone!");
36}
37
38pub fn function_call(fxn_call: &FunctionCall, p: &Interpreter) -> MResult<Value> {
39  let plan = p.plan();
40  let functions = p.functions();
41  let fxn_name_id = fxn_call.name.hash();
42  let fxns_brrw = functions.borrow();
43  match fxns_brrw.functions.get(&fxn_name_id) {
44    Some(fxn) => {
45      let mut new_fxn = function_define(&fxn.code, p)?; // This just calles function_define again, it should be smarter.
46      for (ix,(arg_name, arg_expr)) in fxn_call.args.iter().enumerate() {
47        // Get the value
48        let value_ref: ValRef = match arg_name {
49          // Arg is called with a name
50          Some(arg_id) => {
51            match new_fxn.input.get(&arg_id.hash()) {
52              // Arg name matches expected name
53              Some(kind) => {
54                let symbols_brrw = new_fxn.symbols.borrow();
55                symbols_brrw.get(arg_id.hash()).unwrap().clone()
56              }
57              // The argument name doesn't match
58              None => { return Err(MechError{file: file!().to_string(), tokens: arg_expr.tokens(), msg: "".to_string(), id: line!(), kind: MechErrorKind::UnknownFunctionArgument(arg_id.hash())});}
59            }
60          }
61          // Arg is called positionally (no arg name supplied)
62          None => {
63            match &new_fxn.input.iter().nth(ix) {
64              Some((arg_id,kind)) => {
65                let symbols_brrw = new_fxn.symbols.borrow();
66                symbols_brrw.get(**arg_id).unwrap().clone()
67              }
68              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())});} 
69            }
70          }
71        };
72        let result = expression(&arg_expr, p)?;
73        let mut ref_brrw = value_ref.borrow_mut();
74        // TODO check types
75        match (&mut *ref_brrw, &result) {
76          #[cfg(feature = "bool")]
77          (Value::Bool(arg_ref), Value::Bool(bool_ref)) => {*arg_ref.borrow_mut() = bool_ref.borrow().clone();}
78          #[cfg(feature = "i8")]
79          (Value::I8(arg_ref), Value::I8(i8_ref)) => {*arg_ref.borrow_mut() = i8_ref.borrow().clone();}
80          #[cfg(feature = "i16")]
81          (Value::I16(arg_ref), Value::I16(i16_ref)) => {*arg_ref.borrow_mut() = i16_ref.borrow().clone();}
82          #[cfg(feature = "i32")]
83          (Value::I32(arg_ref), Value::I32(i32_ref)) => {*arg_ref.borrow_mut() = i32_ref.borrow().clone();}
84          #[cfg(feature = "i64")]
85          (Value::I64(arg_ref), Value::I64(i64_ref)) => {*arg_ref.borrow_mut() = i64_ref.borrow().clone();}
86          #[cfg(feature = "i128")]
87          (Value::I128(arg_ref), Value::I128(i128_ref)) => {*arg_ref.borrow_mut() = i128_ref.borrow().clone();}
88          #[cfg(feature = "u8")]
89          (Value::U8(arg_ref), Value::U8(u8_ref)) => {*arg_ref.borrow_mut() = u8_ref.borrow().clone();}
90          #[cfg(feature = "u16")]
91          (Value::U16(arg_ref), Value::U16(u16_ref)) => {*arg_ref.borrow_mut() = u16_ref.borrow().clone();}
92          #[cfg(feature = "u32")]
93          (Value::U32(arg_ref), Value::U32(u32_ref)) => {*arg_ref.borrow_mut() = u32_ref.borrow().clone();}
94          #[cfg(feature = "u64")]
95          (Value::U64(arg_ref), Value::U64(u64_ref)) => {*arg_ref.borrow_mut() = u64_ref.borrow().clone();}
96          #[cfg(feature = "u128")]
97          (Value::U128(arg_ref), Value::U128(u128_ref)) => {*arg_ref.borrow_mut() = u128_ref.borrow().clone();}
98          #[cfg(feature = "f32")]
99          (Value::F32(arg_ref), Value::F32(f32_ref)) => {*arg_ref.borrow_mut() = f32_ref.borrow().clone();}
100          #[cfg(feature = "f64")]
101          (Value::F64(arg_ref), Value::F64(f64_ref)) => {*arg_ref.borrow_mut() = f64_ref.borrow().clone();}
102          #[cfg(feature = "complex")]
103          (Value::ComplexNumber(arg_ref), Value::ComplexNumber(complex_ref)) => {*arg_ref.borrow_mut() = complex_ref.borrow().clone();}
104          #[cfg(feature = "rational")]
105          (Value::RationalNumber(arg_ref), Value::RationalNumber(rational_ref)) => {*arg_ref.borrow_mut() = rational_ref.borrow().clone();}
106          #[cfg(feature = "string")]
107          (Value::String(arg_ref), Value::String(string_ref)) => {*arg_ref.borrow_mut() = string_ref.borrow().clone();}
108          (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())});}
109        }
110      }
111      // schedule function
112      let mut plan_brrw = plan.borrow_mut();
113      let result = new_fxn.solve();
114      let result_brrw = result.borrow();
115      plan_brrw.push(Box::new(UserFunction{fxn: new_fxn.clone()}));
116      return Ok(result_brrw.clone())
117    }
118    None => { 
119      match fxns_brrw.function_compilers.get(&fxn_name_id) {
120        Some(fxn_compiler) => {
121          let mut input_arg_values = vec![];
122          for (arg_name, arg_expr) in fxn_call.args.iter() {
123            let result = expression(&arg_expr, p)?;
124            input_arg_values.push(result);
125          }
126          match fxn_compiler.compile(&input_arg_values) {
127            Ok(new_fxn) => {
128              let mut plan_brrw = plan.borrow_mut();
129              new_fxn.solve();
130              let result = new_fxn.out();
131              plan_brrw.push(new_fxn);
132              return Ok(result)
133            }
134            Err(x) => {return Err(x);}
135          }
136        }
137        None => {return Err(MechError{file: file!().to_string(), tokens: fxn_call.name.tokens(), msg: "".to_string(), id: line!(), kind: MechErrorKind::MissingFunction(fxn_name_id)});}
138      }
139    }
140  }   
141  unreachable!()
142}