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
6macro_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#[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}