mech_interpreter/stdlib/
convert.rs

1#[macro_use]
2use crate::stdlib::*;
3
4// ----------------------------------------------------------------------------
5// Type Conversion Library
6// ----------------------------------------------------------------------------
7
8// Convert --------------------------------------------------------------------
9
10#[macro_export]  
11macro_rules! impl_convert_op {
12  ($struct_name:ident, $arg_type:ty, $out_type:ty, $out_type2:ty, $op:ident) => {
13    #[derive(Debug)]
14    
15    struct $struct_name {
16      arg: Ref<$arg_type>,
17      out: Ref<$out_type>,
18    }
19    impl MechFunction for $struct_name
20    where
21      Ref<$out_type>: ToValue
22    {
23      fn solve(&self) {
24        let arg_ptr = self.arg.as_ptr();
25        let out_ptr = self.out.as_ptr();
26        $op!(arg_ptr,out_ptr,$out_type2)
27      }
28      fn out(&self) -> Value { self.out.to_value() }
29      fn to_string(&self) -> String { format!("{:#?}", self) }
30    }
31  }
32}
33
34macro_rules! convert_op1 {
35  ($arg:expr, $out:expr, $out_type:ty) => {
36    unsafe{ *$out = *$arg as $out_type }
37  };}
38
39macro_rules! convert_op2 {
40  ($arg:expr, $out:expr, $out_type:ty) => {
41    unsafe{ *$out = (*$arg).0 as $out_type }
42  };}
43
44macro_rules! convert_op3 {
45  ($arg:expr, $out:expr, $out_type:ty) => {
46    unsafe{ (*$out).0 = (*$arg) as $out_type }
47  };}
48
49macro_rules! convert_op4 {
50  ($arg:expr, $out:expr, $out_type:ty) => {
51    unsafe{ (*$out).0 = (*$arg).0 as $out_type }
52  };}
53
54macro_rules! impl_convert_op_group {
55  ($from:ty, [$($to:ty),*], $func:ident) => {
56    paste!{
57      $(
58        impl_convert_op!([<ConvertS $from:upper $to:upper>], $from, $to, [<$to:lower>], $func);
59      )*
60    }
61  };
62}
63
64// From Type -> To Types
65impl_convert_op_group!(i8,   [i8, i16, i32, i64, i128, u8, u16, u32, u64, u128], convert_op1);
66impl_convert_op_group!(i16,  [i8, i16, i32, i64, i128, u8, u16, u32, u64, u128], convert_op1);
67impl_convert_op_group!(i32,  [i8, i16, i32, i64, i128, u8, u16, u32, u64, u128], convert_op1);
68impl_convert_op_group!(i64,  [i8, i16, i32, i64, i128, u8, u16, u32, u64, u128], convert_op1);
69impl_convert_op_group!(i128, [i8, i16, i32, i64, i128, u8, u16, u32, u64, u128], convert_op1);
70
71impl_convert_op_group!(u8,   [i8, i16, i32, i64, i128, u8, u16, u32, u64, u128], convert_op1);
72impl_convert_op_group!(u16,  [i8, i16, i32, i64, i128, u8, u16, u32, u64, u128], convert_op1);
73impl_convert_op_group!(u32,  [i8, i16, i32, i64, i128, u8, u16, u32, u64, u128], convert_op1);
74impl_convert_op_group!(u64,  [i8, i16, i32, i64, i128, u8, u16, u32, u64, u128], convert_op1);
75impl_convert_op_group!(u128, [i8, i16, i32, i64, i128, u8, u16, u32, u64, u128], convert_op1);
76
77impl_convert_op_group!(F32,  [i8, i16, i32, i64, i128, u8, u16, u32, u64, u128], convert_op2);
78impl_convert_op_group!(F64,  [i8, i16, i32, i64, i128, u8, u16, u32, u64, u128], convert_op2);
79
80impl_convert_op_group!(i8,   [F32, F64], convert_op3);
81impl_convert_op_group!(i16,  [F32, F64], convert_op3);
82impl_convert_op_group!(i32,  [F32, F64], convert_op3);
83impl_convert_op_group!(i64,  [F32, F64], convert_op3);
84impl_convert_op_group!(i128, [F32, F64], convert_op3);
85impl_convert_op_group!(u8,   [F32, F64], convert_op3);
86impl_convert_op_group!(u16,  [F32, F64], convert_op3);
87impl_convert_op_group!(u32,  [F32, F64], convert_op3);
88impl_convert_op_group!(u64,  [F32, F64], convert_op3);
89impl_convert_op_group!(u128, [F32, F64], convert_op3);
90
91impl_convert_op_group!(F32,  [F32, F64], convert_op4);
92impl_convert_op_group!(F64,  [F32, F64], convert_op4);
93
94#[derive(Debug)]
95struct ConvertSEnum {
96  out: Value,
97}
98impl MechFunction for ConvertSEnum
99{
100  fn solve(&self) { }
101  fn out(&self) -> Value { self.out.clone() }
102  fn to_string(&self) -> String { format!("{:#?}", self) }
103}
104
105macro_rules! convertm2m {
106  ($from:tt, $to:expr) => {
107    paste!{
108      #[derive(Debug)]
109      struct [<ConvertM $from:upper M $to:upper>] {
110        arg: Matrix<$from>,
111        out: Matrix<$to>,
112      }
113      impl MechFunction for [<ConvertM $from:upper M $to:upper>]
114      {
115        fn solve(&self) { 
116          let arg_vec = self.arg.as_vec();
117          self.out.set(arg_vec.iter().map(|x| *x as $to).collect::<Vec<$to>>());
118        }
119        fn out(&self) -> Value { Value::[<Matrix $to:upper>](self.out.clone()) }
120        fn to_string(&self) -> String { format!("{:#?}", self) }
121      }
122    }
123  }
124}
125
126macro_rules! convertm2f {
127  ($from:tt, $to:expr) => {
128    paste!{
129      #[derive(Debug)]
130      struct [<ConvertM $from:upper M $to:upper>] {
131        arg: Matrix<$from>,
132        out: Matrix<$to>,
133      }
134      impl MechFunction for [<ConvertM $from:upper M $to:upper>]
135      {
136        fn solve(&self) { 
137          let arg_vec = self.arg.as_vec();
138          self.out.set(arg_vec.iter().map(|x| $from::into(*x)).collect::<Vec<$to>>());
139        }
140        fn out(&self) -> Value { Value::[<Matrix $to:upper>](self.out.clone()) }
141        fn to_string(&self) -> String { format!("{:#?}", self) }
142      }
143    }
144  }
145}
146
147macro_rules! convertf2m {
148  ($from:tt, $to:expr) => {
149    paste!{
150      #[derive(Debug)]
151      struct [<ConvertM $from:upper M $to:upper>] {
152        arg: Matrix<$from>,
153        out: Matrix<$to>,
154      }
155      impl MechFunction for [<ConvertM $from:upper M $to:upper>]
156      {
157        fn solve(&self) { 
158          let arg_vec = self.arg.as_vec();
159          self.out.set(arg_vec.iter().map(|x| x.0 as $to).collect::<Vec<$to>>());
160        }
161        fn out(&self) -> Value { Value::[<Matrix $to:upper>](self.out.clone()) }
162        fn to_string(&self) -> String { format!("{:#?}", self) }
163      }
164    }
165  }
166}
167
168macro_rules! convertf2f {
169  ($from:tt, $to:expr) => {
170    paste!{
171      #[derive(Debug)]
172      struct [<ConvertM $from:upper M $to:upper>] {
173        arg: Matrix<$from>,
174        out: Matrix<$to>,
175      }
176      impl MechFunction for [<ConvertM $from:upper M $to:upper>]
177      {
178        fn solve(&self) { 
179          let arg_vec = self.arg.as_vec();
180          self.out.set(arg_vec.iter().map(|x| $to::new(x.0 as [<$to:lower>])).collect::<Vec<$to>>());
181        }
182        fn out(&self) -> Value { Value::[<Matrix $to:upper>](self.out.clone()) }
183        fn to_string(&self) -> String { format!("{:#?}", self) }
184      }
185    }
186  }
187}
188
189convertm2m!(u8, u8);
190convertm2m!(u8, u16);
191convertm2m!(u8, u32);
192convertm2m!(u8, u64);
193convertm2m!(u8, u128);
194convertm2m!(u8, i8);
195convertm2m!(u8, i16);
196convertm2m!(u8, i32);
197convertm2m!(u8, i64);
198convertm2m!(u8, i128);
199convertm2f!(u8, F32);
200convertm2f!(u8, F64);
201
202convertm2m!(u16, u8);
203convertm2m!(u16, u16);
204convertm2m!(u16, u32);
205convertm2m!(u16, u64);
206convertm2m!(u16, u128);
207convertm2m!(u16, i8);
208convertm2m!(u16, i16);
209convertm2m!(u16, i32);
210convertm2m!(u16, i64);
211convertm2m!(u16, i128);
212convertm2f!(u16, F32);
213convertm2f!(u16, F64);
214
215convertm2m!(u32, u8);
216convertm2m!(u32, u16);
217convertm2m!(u32, u32);
218convertm2m!(u32, u64);
219convertm2m!(u32, u128);
220convertm2m!(u32, i8);
221convertm2m!(u32, i16);
222convertm2m!(u32, i32);
223convertm2m!(u32, i64);
224convertm2m!(u32, i128);
225convertm2f!(u32, F32);
226convertm2f!(u32, F64);
227
228convertm2m!(u64, u8);
229convertm2m!(u64, u16);
230convertm2m!(u64, u32);
231convertm2m!(u64, u64);
232convertm2m!(u64, u128);
233convertm2m!(u64, i8);
234convertm2m!(u64, i16);
235convertm2m!(u64, i32);
236convertm2m!(u64, i64);
237convertm2m!(u64, i128);
238convertm2f!(u64, F32);
239convertm2f!(u64, F64);
240
241convertm2m!(u128, u8);
242convertm2m!(u128, u16);
243convertm2m!(u128, u32);
244convertm2m!(u128, u64);
245convertm2m!(u128, u128);
246convertm2m!(u128, i8);
247convertm2m!(u128, i16);
248convertm2m!(u128, i32);
249convertm2m!(u128, i64);
250convertm2m!(u128, i128);
251convertm2f!(u128, F32);
252convertm2f!(u128, F64);
253
254convertm2m!(i8, u8);
255convertm2m!(i8, u16);
256convertm2m!(i8, u32);
257convertm2m!(i8, u64);
258convertm2m!(i8, u128);
259convertm2m!(i8, i8);
260convertm2m!(i8, i16);
261convertm2m!(i8, i32);
262convertm2m!(i8, i64);
263convertm2m!(i8, i128);
264convertm2f!(i8, F32);
265convertm2f!(i8, F64);
266
267convertm2m!(i16, u8);
268convertm2m!(i16, u16);
269convertm2m!(i16, u32);
270convertm2m!(i16, u64);
271convertm2m!(i16, u128);
272convertm2m!(i16, i8);
273convertm2m!(i16, i16);
274convertm2m!(i16, i32);
275convertm2m!(i16, i64);
276convertm2m!(i16, i128);
277convertm2f!(i16, F32);
278convertm2f!(i16, F64);
279
280convertm2m!(i32, u8);
281convertm2m!(i32, u16);
282convertm2m!(i32, u32);
283convertm2m!(i32, u64);
284convertm2m!(i32, u128);
285convertm2m!(i32, i8);
286convertm2m!(i32, i16);
287convertm2m!(i32, i32);
288convertm2m!(i32, i64);
289convertm2m!(i32, i128);
290convertm2f!(i32, F32);
291convertm2f!(i32, F64);
292
293convertm2m!(i64, u8);
294convertm2m!(i64, u16);
295convertm2m!(i64, u32);
296convertm2m!(i64, u64);
297convertm2m!(i64, u128);
298convertm2m!(i64, i8);
299convertm2m!(i64, i16);
300convertm2m!(i64, i32);
301convertm2m!(i64, i64);
302convertm2m!(i64, i128);
303convertm2f!(i64, F32);
304convertm2f!(i64, F64);
305
306convertm2m!(i128, u8);
307convertm2m!(i128, u16);
308convertm2m!(i128, u32);
309convertm2m!(i128, u64);
310convertm2m!(i128, u128);
311convertm2m!(i128, i8);
312convertm2m!(i128, i16);
313convertm2m!(i128, i32);
314convertm2m!(i128, i64);
315convertm2m!(i128, i128);
316convertm2f!(i128, F32);
317convertm2f!(i128, F64);
318
319convertf2m!(F64, u8);
320convertf2m!(F64, u16);
321convertf2m!(F64, u32);
322convertf2m!(F64, u64);
323convertf2m!(F64, u128);
324convertf2m!(F64, i8);
325convertf2m!(F64, i16);
326convertf2m!(F64, i32);
327convertf2m!(F64, i64);
328convertf2m!(F64, i128);
329convertf2f!(F64, F32);
330convertf2f!(F64, F64);
331
332convertf2m!(F32, u8);
333convertf2m!(F32, u16);
334convertf2m!(F32, u32);
335convertf2m!(F32, u64);
336convertf2m!(F32, u128);
337convertf2m!(F32, i8);
338convertf2m!(F32, i16);
339convertf2m!(F32, i32);
340convertf2m!(F32, i64);
341convertf2m!(F32, i128);
342convertf2f!(F32, F32);
343convertf2f!(F32, F64);
344
345macro_rules! impl_conversion_match_arms {
346  ($arg:expr, $($input_type:ident => $($target_type:ident),+);+ $(;)?) => {
347    paste!{
348      match $arg {
349        $(
350          $(
351            (Value::[<$input_type:upper>](arg), ValueKind::[<$target_type:upper>]) => {Ok(Box::new([<ConvertS $input_type:upper $target_type:upper>]{arg: arg.clone(), out: new_ref($target_type::zero())}))},
352            (Value::[<Matrix $input_type:upper>](arg), ValueKind::Matrix(kind,size)) => {
353              match *kind {
354                ValueKind::U8 => {let in_shape = arg.shape();let out = u8::to_matrix(vec![0; in_shape[0]*in_shape[1]], in_shape[0], in_shape[1]);Ok(Box::new([<ConvertM $input_type:upper MU8>]{arg: arg.clone(), out}))}
355                ValueKind::U16 => {let in_shape = arg.shape();let out = u16::to_matrix(vec![0; in_shape[0]*in_shape[1]], in_shape[0], in_shape[1]);Ok(Box::new([<ConvertM $input_type:upper MU16>]{arg: arg.clone(), out}))}
356                ValueKind::U32 => {let in_shape = arg.shape();let out = u32::to_matrix(vec![0; in_shape[0]*in_shape[1]], in_shape[0], in_shape[1]);Ok(Box::new([<ConvertM $input_type:upper MU32>]{arg: arg.clone(), out}))}
357                ValueKind::U64 => {let in_shape = arg.shape();let out = u64::to_matrix(vec![0; in_shape[0]*in_shape[1]], in_shape[0], in_shape[1]);Ok(Box::new([<ConvertM $input_type:upper MU64>]{arg: arg.clone(), out}))}
358                //ValueKind::U128 => {let in_shape = arg.shape();let out = u128::to_matrix(vec![0; in_shape[0]*in_shape[1]], in_shape[0], in_shape[1]);Ok(Box::new([<ConvertM $input_type:upper MU128>]{arg: arg.clone(), out}))}
359                ValueKind::I8 => {let in_shape = arg.shape();let out = i8::to_matrix(vec![0; in_shape[0]*in_shape[1]], in_shape[0], in_shape[1]);Ok(Box::new([<ConvertM $input_type:upper MI8>]{arg: arg.clone(), out}))}
360                ValueKind::I16 => {let in_shape = arg.shape();let out = i16::to_matrix(vec![0; in_shape[0]*in_shape[1]], in_shape[0], in_shape[1]);Ok(Box::new([<ConvertM $input_type:upper MI16>]{arg: arg.clone(), out}))}
361                ValueKind::I32 => {let in_shape = arg.shape();let out = i32::to_matrix(vec![0; in_shape[0]*in_shape[1]], in_shape[0], in_shape[1]);Ok(Box::new([<ConvertM $input_type:upper MI32>]{arg: arg.clone(), out}))}
362                ValueKind::I64 => {let in_shape = arg.shape();let out = i64::to_matrix(vec![0; in_shape[0]*in_shape[1]], in_shape[0], in_shape[1]);Ok(Box::new([<ConvertM $input_type:upper MI64>]{arg: arg.clone(), out}))}
363                //ValueKind::I128 => {let in_shape = arg.shape();let out = i128::to_matrix(vec![0; in_shape[0]*in_shape[1]], in_shape[0], in_shape[1]);Ok(Box::new([<ConvertM $input_type:upper MI128>]{arg: arg.clone(), out}))}
364                ValueKind::F32 => {let in_shape = arg.shape();let out = F32::to_matrix(vec![F32::zero(); in_shape[0]*in_shape[1]], in_shape[0], in_shape[1]);Ok(Box::new([<ConvertM $input_type:upper MF32>]{arg: arg.clone(), out}))}
365                ValueKind::F64 => {let in_shape = arg.shape();let out = F64::to_matrix(vec![F64::zero(); in_shape[0]*in_shape[1]], in_shape[0], in_shape[1]);Ok(Box::new([<ConvertM $input_type:upper MF64>]{arg: arg.clone(), out}))}
366                _ => todo!(),
367              }
368            },
369          )+
370        )+
371        (Value::Atom(varian_id), ValueKind::Enum(enum_id)) => {
372          let variants = vec![(varian_id,None)];
373          let enm = MechEnum{id: enum_id, variants};
374          let val = Value::Enum(Box::new(enm.clone()));
375          Ok(Box::new(ConvertSEnum{out: val}))
376        }
377        x => Err(MechError{file: file!().to_string(), tokens: vec![], msg: "".to_string(), id: line!(), kind: MechErrorKind::UnhandledFunctionArgumentKind}),
378      }
379    }
380  }
381}
382
383fn impl_conversion_fxn(source_value: Value, target_kind: ValueKind) -> MResult<Box<dyn MechFunction>>  {
384  impl_conversion_match_arms!(
385    (source_value, target_kind),
386    i8   => i8, i16, i32, i64, i128, u8, u16, u32, u64, u128, F32, F64;
387    i16  => i8, i16, i32, i64, i128, u8, u16, u32, u64, u128, F32, F64;
388    i32  => i8, i16, i32, i64, i128, u8, u16, u32, u64, u128, F32, F64;
389    i64  => i8, i16, i32, i64, i128, u8, u16, u32, u64, u128, F32, F64;
390    i128 => i8, i16, i32, i64, i128, u8, u16, u32, u64, u128, F32, F64;
391    u8   => i8, i16, i32, i64, i128, u8, u16, u32, u64, u128, F32, F64;
392    u16  => i8, i16, i32, i64, i128, u8, u16, u32, u64, u128, F32, F64;
393    u32  => i8, i16, i32, i64, i128, u8, u16, u32, u64, u128, F32, F64;
394    u64  => i8, i16, i32, i64, i128, u8, u16, u32, u64, u128, F32, F64;
395    u128 => i8, i16, i32, i64, i128, u8, u16, u32, u64, u128, F32, F64;
396    F32  => i8, i16, i32, i64, i128, u8, u16, u32, u64, u128, F32, F64;
397    F64  => i8, i16, i32, i64, i128, u8, u16, u32, u64, u128, F32, F64;
398  )
399}
400
401pub struct ConvertKind {}
402
403impl NativeFunctionCompiler for ConvertKind {
404  fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>> {
405    if arguments.len() != 2 {
406      return Err(MechError{file: file!().to_string(), tokens: vec![], msg: "".to_string(), id: line!(), kind: MechErrorKind::IncorrectNumberOfArguments});
407    }
408    let source_value = arguments[0].clone();
409    let target_kind = arguments[1].kind();
410    match impl_conversion_fxn(source_value.clone(), target_kind.clone()) {
411      Ok(fxn) => Ok(fxn),
412      Err(_) => {
413        match source_value {
414          Value::MutableReference(rhs) => impl_conversion_fxn(rhs.borrow().clone(), target_kind.clone()),
415          Value::Atom(atom_id) => impl_conversion_fxn(source_value, target_kind.clone()),
416          Value::MatrixU32(ref mat) => impl_conversion_fxn(source_value, target_kind.clone()),
417          x => {
418            println!("{:?}",x);
419            todo!();
420          }
421        }
422      }
423    }
424  }
425}