mech_interpreter/stdlib/access/
table.rs1#[macro_use]
2use crate::stdlib::*;
3use crate::stdlib::access::*;
4
5macro_rules! impl_col_access_fxn {
8    ($fxn_name:ident, $vector_size:ident, $out_type:ty) => {
9      #[derive(Debug)]
10      struct $fxn_name {
11        source: Matrix<Value>,
12        out: Ref<$vector_size<$out_type>>,
13      }
14      impl MechFunction for $fxn_name {
15        fn solve(&self) {
16          let out_ptr = self.out.as_ptr();
17          unsafe { 
18            for i in 1..=self.source.shape()[0] {
19              paste! {
20                (*out_ptr)[i-1] = self.source.index1d(i).[<as_ $out_type:lower>]().unwrap().borrow().clone();
21              }
22            }
23          }
24        }
25        fn out(&self) -> Value { self.out.to_value() }
26        fn to_string(&self) -> String { format!("{:#?}", self) }
27      }
28    }
29  }
30  
31  macro_rules! impl_col_access_fxn_shapes {
32    ($type:ident) => {
33      paste!{
34        impl_col_access_fxn!([<TableAccessCol $type:camel M1>], Matrix1, [<$type>]);
35        impl_col_access_fxn!([<TableAccessCol $type:camel V2>], Vector2, [<$type>]);
36        impl_col_access_fxn!([<TableAccessCol $type:camel V3>], Vector3, [<$type>]);
37        impl_col_access_fxn!([<TableAccessCol $type:camel V4>], Vector4, [<$type>]);
38        impl_col_access_fxn!([<TableAccessCol $type:camel VD>], DVector, [<$type>]);
39      }
40    }
41  }
42  
43  impl_col_access_fxn_shapes!(bool);
44  impl_col_access_fxn_shapes!(i8);
45  impl_col_access_fxn_shapes!(i16);
46  impl_col_access_fxn_shapes!(i32);
47  impl_col_access_fxn_shapes!(i64);
48  impl_col_access_fxn_shapes!(i128);
49  impl_col_access_fxn_shapes!(u8);
50  impl_col_access_fxn_shapes!(u16);
51  impl_col_access_fxn_shapes!(u32);
52  impl_col_access_fxn_shapes!(u64);
53  impl_col_access_fxn_shapes!(u128);
54  impl_col_access_fxn_shapes!(F32);
55  impl_col_access_fxn_shapes!(F64);
56  
57  macro_rules! impl_access_column_match_arms {
58    ($arg:expr, $($lhs_type:ident, $($default:expr),+);+ $(;)?) => {
59      paste!{
60        match $arg {
61          (Value::Record(rcrd),Value::Id(k)) => {
62            match rcrd.get(&k) {
63              Some(value) => Ok(Box::new(RecordAccess{source: value.clone()})),
64              _ => return Err(MechError{file: file!().to_string(), tokens: vec![], msg: "".to_string(), id: line!(), kind: MechErrorKind::UndefinedField(k)}),
65            }
66          }
67          (Value::Table(tbl),Value::Id(k)) => {
68            let key = Value::Id(k);
69            match (tbl.get(&key),tbl.rows()) {
70              $(
71                $(
72                  (Some((ValueKind::$lhs_type,value)),1) => Ok(Box::new([<TableAccessCol $lhs_type M1>]{source: value.clone(), out: new_ref(Matrix1::from_element($default)) })),
73                  (Some((ValueKind::$lhs_type,value)),2) => Ok(Box::new([<TableAccessCol $lhs_type V2>]{source: value.clone(), out: new_ref(Vector2::from_element($default)) })),
74                  (Some((ValueKind::$lhs_type,value)),3) => Ok(Box::new([<TableAccessCol $lhs_type V3>]{source: value.clone(), out: new_ref(Vector3::from_element($default)) })),
75                  (Some((ValueKind::$lhs_type,value)),4) => Ok(Box::new([<TableAccessCol $lhs_type V4>]{source: value.clone(), out: new_ref(Vector4::from_element($default)) })),
76                  (Some((ValueKind::$lhs_type,value)),n) => Ok(Box::new([<TableAccessCol $lhs_type VD>]{source: value.clone(), out: new_ref(DVector::from_element(n,$default)) })),
77                )+
78              )+
79              _ => return Err(MechError{file: file!().to_string(), tokens: vec![], msg: "".to_string(), id: line!(), kind: MechErrorKind::UndefinedField(k)}),
80            }
81          }
82          x => Err(MechError{file: file!().to_string(),  tokens: vec![], msg: "".to_string(), id: line!(), kind: MechErrorKind::UnhandledFunctionArgumentKind }),
83        }
84      }
85    }
86  }
87  
88  fn impl_access_column_fxn(source: Value, key: Value) -> Result<Box<dyn MechFunction>, MechError> {
89    impl_access_column_match_arms!(
90      (source,key),
91      Bool,false;
92      I8,i8::zero();
93      I16,i16::zero();
94      I32,i32::zero();
95      I64,i64::zero();
96      I128,i128::zero();
97      U8,u8::zero();
98      U16,u16::zero();
99      U32,u32::zero();
100      U64,u64::zero();
101      U128,u128::zero();
102      F32,F32::zero();
103      F64,F64::zero();
104    )
105  }
106  
107  pub struct AccessColumn {}
108  impl NativeFunctionCompiler for AccessColumn {
109    fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>> {
110      if arguments.len() <= 1 {
111        return Err(MechError{file: file!().to_string(), tokens: vec![], msg: "".to_string(), id: line!(), kind: MechErrorKind::IncorrectNumberOfArguments});
112      }
113      let tbl = arguments[0].clone();
114      let key = arguments[1].clone();
115      match impl_access_column_fxn(tbl.clone(), key.clone()) {
116        Ok(fxn) => Ok(fxn),
117        Err(_) => {
118          match (tbl,&key) {
119            (Value::MutableReference(tbl),_) => { impl_access_column_fxn(tbl.borrow().clone(), key.clone()) }
120            x => Err(MechError{file: file!().to_string(),  tokens: vec![], msg: "".to_string(), id: line!(), kind: MechErrorKind::UnhandledFunctionArgumentKind }),
121          }
122        }
123      }
124    }
125  }
126  
127  #[derive(Debug)]
130  struct RecordAccessSwizzle {
131    source: Value,
132  }
133  
134  impl MechFunction for RecordAccessSwizzle {
135    fn solve(&self) {
136      ()
137    }
138    fn out(&self) -> Value { self.source.clone() }
139    fn to_string(&self) -> String { format!("{:#?}", self) }
140  }
141  
142  #[derive(Debug)]
143  struct TableAccessSwizzle {
144    out: Value,
145  }
146  
147  impl MechFunction for TableAccessSwizzle {
148    fn solve(&self) {
149      ()
150    }
151    fn out(&self) -> Value { self.out.clone() }
152    fn to_string(&self) -> String { format!("{:#?}", self) }
153  }
154  
155  pub struct AccessSwizzle {}
156  impl NativeFunctionCompiler for AccessSwizzle {
157    fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>> {
158      if arguments.len() < 3 {
159        return Err(MechError{file: file!().to_string(), tokens: vec![], msg: "".to_string(), id: line!(), kind: MechErrorKind::IncorrectNumberOfArguments});
160      }
161      let keys = &arguments.clone().split_off(1);
162      let src = &arguments[0];
163      match src {
164        Value::Record(rcrd) => {
165          let mut values = vec![];
166          for key in keys {
167            let k = key.as_usize().unwrap() as u64;
168            match rcrd.get(&k) {
169              Some(value) => values.push(value.clone()),
170              None => { return Err(MechError{file: file!().to_string(), tokens: vec![], msg: "".to_string(), id: line!(), kind: MechErrorKind::UndefinedField(k)});}
171            }
172          }
173          Ok(Box::new(RecordAccessSwizzle{source: Value::Tuple(MechTuple::from_vec(values))}))
174        }
175        Value::Table(tbl) => {
176          let mut elements = vec![];
177          for k in keys {
178            match tbl.get(k) {
179              Some((kind, mat_values)) => {
180                elements.push(Box::new(mat_values.to_value()));
181              }
182              None => { return Err(MechError{file: file!().to_string(), tokens: vec![], msg: "".to_string(), id: line!(), kind: MechErrorKind::UndefinedField(*k.as_u64().unwrap().borrow())});}
183            }
184          }
185          let tuple = Value::Tuple(MechTuple{elements});
186          Ok(Box::new(TableAccessSwizzle{out: tuple}))
187        }
188        Value::MutableReference(r) => match &*r.borrow() {
189          Value::Record(rcrd) => {
190            let mut values = vec![];
191            for key in keys {
192              let k = key.as_usize().unwrap() as u64;
193              match rcrd.get(&k) {
194                Some(value) => values.push(value.clone()),
195                None => { return Err(MechError{file: file!().to_string(), tokens: vec![], msg: "".to_string(), id: line!(), kind: MechErrorKind::UndefinedField(k)});}
196              }
197            }
198            Ok(Box::new(RecordAccessSwizzle{source: Value::Tuple(MechTuple::from_vec(values))}))
199          }
200          Value::Table(tbl) => {
201            let mut elements = vec![];
202            for k in keys {
203              match tbl.get(k) {
204                Some((kind, mat_values)) => {
205                  elements.push(Box::new(mat_values.to_value()));
206                }
207                None => { return Err(MechError{file: file!().to_string(), tokens: vec![], msg: "".to_string(), id: line!(), kind: MechErrorKind::UndefinedField(*k.as_u64().unwrap().borrow())});}
208              }
209            }
210            let tuple = Value::Tuple(MechTuple{elements});
211            Ok(Box::new(TableAccessSwizzle{out: tuple}))
212          }
213          _ => todo!(),
214        }
215        _ => todo!(),
216      }
217    }
218  }