mech_interpreter/stdlib/assign/
table.rs

1#[macro_use]
2use crate::stdlib::*;
3use self::assign::*;
4use na::{Vector3, DVector, Vector2, Vector4, RowDVector, Matrix1, Matrix3, Matrix4, RowVector3, RowVector4, RowVector2, DMatrix, Rotation3, Matrix2x3, Matrix3x2, Matrix6, Matrix2};
5
6// x.a = 1 --------------------------------------------------------------------
7
8// Table Set ------------------------------------------------------------------
9
10macro_rules! impl_col_set_fxn {
11  ($fxn_name:ident, $vector_size_in:ident, $vector_size_out:ident, $out_type:ty) => {
12    #[derive(Debug)]
13    struct $fxn_name {
14      source: Ref<$vector_size_in<$out_type>>,
15      sink: Ref<$vector_size_out<Value>>,
16    }
17    impl MechFunctionImpl for $fxn_name {
18      fn solve(&self) {
19        let source_ptr = self.source.as_ptr();
20        let sink_ptr = self.sink.as_mut_ptr();
21        unsafe { 
22          for i in 0..(*source_ptr).len() {
23            paste! {
24              (&mut (*sink_ptr))[i] = Value::[<$out_type:camel>](Ref::new((*source_ptr).index(i).clone()));
25            }
26          }
27        }
28      }
29      fn out(&self) -> Value { Value::MatrixValue(Matrix::$vector_size_out(self.sink.clone())) }
30      fn to_string(&self) -> String { format!("{:#?}", self) }
31    }
32    #[cfg(feature = "compiler")]
33    impl MechFunctionCompiler for $fxn_name 
34    where
35      $vector_size_in<$out_type>: CompileConst + ConstElem + AsValueKind,
36      $vector_size_out<Value>: CompileConst + ConstElem + AsValueKind,
37      $out_type: CompileConst + ConstElem + AsValueKind,
38    {
39      fn compile(&self, ctx: &mut CompileCtx) -> MResult<Register> {
40        let name = format!("{}<{},{}>", stringify!($fxn_name), $vector_size_in::<$out_type>::as_value_kind(), $vector_size_out::<Value>::as_value_kind());
41        compile_unop!(name, self.sink, self.source, ctx, FeatureFlag::Builtin(FeatureKind::Assign) );
42      }
43    }
44  }
45}
46
47macro_rules! impl_col_set_fxn_shapes {
48  ($type:ident) => {
49    paste!{
50      #[cfg(feature = "matrix1")]
51      impl_col_set_fxn!([<TableSetCol $type:camel M1>], Matrix1, Matrix1, $type);
52      #[cfg(feature = "vector2")]
53      impl_col_set_fxn!([<TableSetCol $type:camel V2>], Vector2, Vector2, $type);
54      #[cfg(feature = "vector3")]
55      impl_col_set_fxn!([<TableSetCol $type:camel V3>], Vector3, Vector3, $type);
56      #[cfg(feature = "vector4")]
57      impl_col_set_fxn!([<TableSetCol $type:camel V4>], Vector4, Vector4, $type);
58      #[cfg(feature = "vectord")]
59      impl_col_set_fxn!([<TableSetCol $type:camel VD>], DVector, DVector, $type);
60      #[cfg(all(feature = "vectord", feature = "vector4"))]
61      impl_col_set_fxn!([<TableSetCol $type:camel VDV4>], Vector4, DVector, $type);
62      #[cfg(all(feature = "vectord", feature = "vector3"))]
63      impl_col_set_fxn!([<TableSetCol $type:camel VDV3>], Vector3, DVector, $type);
64      #[cfg(all(feature = "vectord", feature = "vector2"))]
65      impl_col_set_fxn!([<TableSetCol $type:camel VDV2>], Vector2, DVector, $type);
66      #[cfg(all(feature = "vectord", feature = "matrix1"))]
67      impl_col_set_fxn!([<TableSetCol $type:camel VDM1>], Matrix1, DVector, $type);
68    }
69  }
70}
71
72#[cfg(feature = "bool")]
73impl_col_set_fxn_shapes!(bool);
74#[cfg(feature = "i8")]
75impl_col_set_fxn_shapes!(i8);
76#[cfg(feature = "i16")]
77impl_col_set_fxn_shapes!(i16);
78#[cfg(feature = "i32")]
79impl_col_set_fxn_shapes!(i32);
80#[cfg(feature = "i64")]
81impl_col_set_fxn_shapes!(i64);
82#[cfg(feature = "i128")]
83impl_col_set_fxn_shapes!(i128);
84#[cfg(feature = "u8")]
85impl_col_set_fxn_shapes!(u8);
86#[cfg(feature = "u16")]
87impl_col_set_fxn_shapes!(u16);
88#[cfg(feature = "u32")]
89impl_col_set_fxn_shapes!(u32);
90#[cfg(feature = "u64")]
91impl_col_set_fxn_shapes!(u64);
92#[cfg(feature = "u128")]
93impl_col_set_fxn_shapes!(u128);
94#[cfg(feature = "f32")]
95impl_col_set_fxn_shapes!(f32);
96#[cfg(feature = "f64")]
97impl_col_set_fxn_shapes!(f64);
98#[cfg(feature = "string")]
99impl_col_set_fxn_shapes!(String);
100#[cfg(feature = "complex")]
101impl_col_set_fxn_shapes!(C64);
102#[cfg(feature = "rational")]
103impl_col_set_fxn_shapes!(R64);
104
105macro_rules! impl_set_column_match_arms {
106  ($arg:expr, $($lhs_type:ident, $type_ident:ident, $type_feature:literal);+ $(;)?) => {
107    paste::paste! {
108      match $arg {
109        (Value::Table(tbl), source, Value::Id(k)) => {
110          let tbl_brrw = tbl.borrow();
111          match (tbl_brrw.get(&k), tbl_brrw.rows(), source) {
112            $(
113              #[cfg(all(feature = $type_feature, feature = "matrix1"))]
114              (Some((ValueKind::$lhs_type, Matrix::Matrix1(sink))), 1, Value::[<Matrix $lhs_type>](Matrix::Matrix1(source))) =>Ok(Box::new([<TableSetCol $lhs_type M1>]{ source: source.clone(), sink: sink.clone() })),
115              #[cfg(all(feature = $type_feature, feature = "vector2"))]
116              (Some((ValueKind::$lhs_type, Matrix::Vector2(sink))), 2, Value::[<Matrix $lhs_type>](Matrix::Vector2(source))) =>Ok(Box::new([<TableSetCol $lhs_type V2>]{ source: source.clone(), sink: sink.clone() })),
117              #[cfg(all(feature = $type_feature, feature = "vector3"))]
118              (Some((ValueKind::$lhs_type, Matrix::Vector3(sink))), 3, Value::[<Matrix $lhs_type>](Matrix::Vector3(source))) =>Ok(Box::new([<TableSetCol $lhs_type V3>]{ source: source.clone(), sink: sink.clone() })),
119              #[cfg(all(feature = $type_feature, feature = "vector4"))]
120              (Some((ValueKind::$lhs_type, Matrix::Vector4(sink))), 4, Value::[<Matrix $lhs_type>](Matrix::Vector4(source))) =>Ok(Box::new([<TableSetCol $lhs_type V4>]{ source: source.clone(), sink: sink.clone() })),
121              #[cfg(all(feature = $type_feature, feature = "vectord"))]
122              (Some((ValueKind::$lhs_type, Matrix::DVector(sink))), n, Value::[<Matrix $lhs_type>](Matrix::DVector(source))) =>Ok(Box::new([<TableSetCol $lhs_type VD>]{ source: source.clone(), sink: sink.clone() })),
123              #[cfg(all(feature = $type_feature, feature = "vectord", feature = "vector4"))]
124              (Some((ValueKind::$lhs_type, Matrix::DVector(sink))), n, Value::[<Matrix $lhs_type>](Matrix::Vector4(source))) =>Ok(Box::new([<TableSetCol $lhs_type VDV4>]{ source: source.clone(), sink: sink.clone() })),
125              #[cfg(all(feature = $type_feature, feature = "vectord", feature = "vector3"))]
126              (Some((ValueKind::$lhs_type, Matrix::DVector(sink))), n, Value::[<Matrix $lhs_type>](Matrix::Vector3(source))) =>Ok(Box::new([<TableSetCol $lhs_type VDV3>]{ source: source.clone(), sink: sink.clone() })),
127              #[cfg(all(feature = $type_feature, feature = "vectord", feature = "vector2"))]
128              (Some((ValueKind::$lhs_type, Matrix::DVector(sink))), n, Value::[<Matrix $lhs_type>](Matrix::Vector2(source))) =>Ok(Box::new([<TableSetCol $lhs_type VDV2>]{ source: source.clone(), sink: sink.clone() })),
129              #[cfg(all(feature = $type_feature, feature = "vectord", feature = "matrix1"))]
130              (Some((ValueKind::$lhs_type, Matrix::DVector(sink))), n, Value::[<Matrix $lhs_type>](Matrix::Matrix1(source))) =>Ok(Box::new([<TableSetCol $lhs_type VDM1>]{ source: source.clone(), sink: sink.clone() })),
131            )+
132            x => return Err(MechError2::new(
133              UndefinedTableColumnError { id: k.clone() }, None).with_compiler_loc()
134            )
135          }
136        }
137        (sink, source, key) => Err(MechError2::new(
138            UnhandledFunctionArgumentKind3 { arg: (sink.kind(), source.kind(), key.kind()), fxn_name: stringify!($fxn_name).to_string() },
139            None
140          ).with_compiler_loc()
141        ),
142      }
143    }
144  }
145}
146
147fn impl_set_column_fxn(sink: Value, source: Value, key: Value) -> MResult<Box<dyn MechFunction>> {
148  impl_set_column_match_arms!(
149    (sink,source,key),
150    Bool, bool, "bool";
151    I8,   i8,   "i8";
152    I16,  i16,  "i16";
153    I32,  i32,  "i32";
154    I64,  i64,  "i64";
155    I128, i128, "i128";
156    U8,   u8,   "u8";
157    U16,  u16,  "u16";
158    U32,  u32,  "u32";
159    U64,  u64,  "u64";
160    U128, u128, "u128";
161    F32,  f32,  "f32";
162    F64,  f64,  "f64";
163    String, String, "string";
164    C64, C64,"complex";
165    R64, R64,"rational";
166  )
167}
168
169pub struct AssignTableColumn {}
170impl NativeFunctionCompiler for AssignTableColumn {
171  fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>> {
172    if arguments.len() < 3 {
173      return Err(MechError2::new(IncorrectNumberOfArguments { expected: 1, found: arguments.len() }, None).with_compiler_loc());
174    }
175    let sink = arguments[0].clone();
176    let source = arguments[1].clone();
177    let key = arguments[2].clone();
178    match impl_set_column_fxn(sink.clone(), source.clone(), key.clone()) {
179      Ok(fxn) => Ok(fxn),
180      Err(_) => {
181        match (&sink,&source,&key) {
182          (Value::MutableReference(sink),_,_) => { impl_set_column_fxn(sink.borrow().clone(), source.clone(), key.clone()) }
183          (sink, source, key) => Err(MechError2::new(
184              UnhandledFunctionArgumentKind3 { arg: (sink.kind(), source.kind(), key.kind()), fxn_name: "table/assign-column".to_string() },
185              None
186            ).with_compiler_loc()
187          ),
188        }
189      }
190    }
191  }
192}
193
194// table1 += table2 ------------------------------------------------------------
195
196#[derive(Debug)]
197struct TableAppendRecord {
198  sink: Ref<MechTable>,
199  source: Ref<MechRecord>,
200}
201impl MechFunctionImpl for TableAppendRecord {
202  fn solve(&self) {
203    unsafe {
204      let mut sink_ptr = (&mut *(self.sink.as_mut_ptr()));
205      let source_ptr = &(*(self.source.as_ptr()));
206      sink_ptr.append_record(source_ptr.clone());
207    }
208  }
209  fn out(&self) -> Value { Value::Table(self.sink.clone()) }
210  fn to_string(&self) -> String { format!("{:#?}", self) }
211}
212#[cfg(feature = "compiler")]
213impl MechFunctionCompiler for TableAppendRecord {
214  fn compile(&self, ctx: &mut CompileCtx) -> MResult<Register> {
215    let name = format!("TableAppendRecord");
216    compile_unop!(name, self.sink, self.source, ctx, FeatureFlag::Builtin(FeatureKind::Assign) );
217  }
218}
219
220#[derive(Debug)]
221struct TableAppendTable {
222  sink: Ref<MechTable>,
223  source: Ref<MechTable>,
224}
225impl MechFunctionImpl for TableAppendTable {
226  fn solve(&self) {
227    unsafe {
228      let mut sink_ptr = (&mut *(self.sink.as_mut_ptr()));
229      let source_ptr = &(*(self.source.as_ptr()));
230      sink_ptr.append_table(&source_ptr);
231    }
232  }
233  fn out(&self) -> Value { Value::Table(self.sink.clone()) }
234  fn to_string(&self) -> String { format!("{:#?}", self) }
235}
236#[cfg(feature = "compiler")]
237impl MechFunctionCompiler for TableAppendTable {
238  fn compile(&self, ctx: &mut CompileCtx) -> MResult<Register> {
239    let name = format!("TableAppendTable");
240    compile_unop!(name, self.sink, self.source, ctx, FeatureFlag::Builtin(FeatureKind::Table) );
241  }
242}
243
244pub fn add_assign_table_fxn(sink: Value, source: Value) -> MResult<Box<dyn MechFunction>> {
245  match (sink.clone(),source.clone()) {
246    (Value::Table(tbl), Value::Record(rcrd)) => {
247      tbl.borrow().check_record_schema(&rcrd.borrow())?;
248      return Ok(Box::new(TableAppendRecord{ sink: tbl, source: rcrd }))
249    }
250    (Value::Table(tbl_sink), Value::Table(tbl_src)) => {
251      tbl_sink.borrow().check_table_schema(&tbl_src.borrow())?;
252      return Ok(Box::new(TableAppendTable{ sink: tbl_sink, source: tbl_src }))
253    }
254    (sink,source) => return Err(MechError2::new(
255        UnhandledFunctionArgumentKind2 { arg: (sink.kind(),source.kind()), fxn_name: "table/add-assign".to_string() },
256        None
257      ).with_compiler_loc()
258    ),
259  }
260}
261
262pub struct AddAssignTable {}
263impl NativeFunctionCompiler for AddAssignTable {
264  fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>> {
265    if arguments.len() <= 1 {
266      return Err(MechError2::new(IncorrectNumberOfArguments { expected: 1, found: arguments.len() }, None).with_compiler_loc());
267    }
268    let sink = arguments[0].clone();
269    let source = arguments[1].clone();
270    match add_assign_table_fxn(sink.clone(),source.clone()) {
271      Ok(fxn) => Ok(fxn),
272      Err(x) => {
273        match (sink,source) {
274          (Value::MutableReference(sink),Value::MutableReference(source)) => { add_assign_table_fxn(sink.borrow().clone(),source.borrow().clone()) },
275          (sink,Value::MutableReference(source)) => { add_assign_table_fxn(sink.clone(),source.borrow().clone()) },
276          (Value::MutableReference(sink),source) => { add_assign_table_fxn(sink.borrow().clone(),source.clone()) },
277          (sink,source) => Err(MechError2::new(
278              UnhandledFunctionArgumentKind2 { arg: (sink.kind(),source.kind()), fxn_name: "table/add-assign".to_string() },
279              None
280            ).with_compiler_loc()
281          ),
282        }
283      }
284    }
285  }
286}
287
288#[derive(Debug, Clone)]
289pub struct UndefinedTableColumnError {
290  pub id: u64,
291}
292impl MechErrorKind2 for UndefinedTableColumnError {
293  fn name(&self) -> &str { "UndefinedTableColumn" }
294  fn message(&self) -> String {
295      format!("Column {:?} is not defined in this table.", self.id)
296  }
297}