1#[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 MechFunctionImpl for $fxn_name {
15 fn solve(&self) {
16 let out_ptr = self.out.as_mut_ptr();
17 unsafe {
18 for i in 1..=self.source.shape()[0] {
19 paste! {
20 (&mut (*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 #[cfg(feature = "compiler")]
29 impl MechFunctionCompiler for $fxn_name {
30 fn compile(&self, ctx: &mut CompileCtx) -> MResult<Register> {
31 let mut registers = [0, 0];
32 registers[0] = compile_register_brrw!(self.out, ctx);
33 registers[1] = compile_register!(self.source, ctx);
34 ctx.features.insert(FeatureFlag::Builtin(FeatureKind::Access));
35 ctx.emit_unop(
36 hash_str(stringify!($fxn_name)),
37 registers[0],
38 registers[1],
39 );
40 Ok(registers[0])
41 }
42 }
43 }
44}
45
46macro_rules! impl_col_access_fxn_shapes {
47 ($type:ident) => {
48 paste!{
49 #[cfg(feature = "matrix1")]
50 impl_col_access_fxn!([<TableAccessCol $type:camel M1>], Matrix1, [<$type>]);
51 #[cfg(feature = "vector2")]
52 impl_col_access_fxn!([<TableAccessCol $type:camel V2>], Vector2, [<$type>]);
53 #[cfg(feature = "vector3")]
54 impl_col_access_fxn!([<TableAccessCol $type:camel V3>], Vector3, [<$type>]);
55 #[cfg(feature = "vector4")]
56 impl_col_access_fxn!([<TableAccessCol $type:camel V4>], Vector4, [<$type>]);
57 #[cfg(feature = "vectord")]
58 impl_col_access_fxn!([<TableAccessCol $type:camel VD>], DVector, [<$type>]);
59 }
60 }
61}
62
63#[cfg(all(feature = "bool", feature = "matrix"))]
64impl_col_access_fxn_shapes!(bool);
65#[cfg(all(feature = "i8", feature = "matrix"))]
66impl_col_access_fxn_shapes!(i8);
67#[cfg(all(feature = "i16", feature = "matrix"))]
68impl_col_access_fxn_shapes!(i16);
69#[cfg(all(feature = "i32", feature = "matrix"))]
70impl_col_access_fxn_shapes!(i32);
71#[cfg(all(feature = "i64", feature = "matrix"))]
72impl_col_access_fxn_shapes!(i64);
73#[cfg(all(feature = "i128", feature = "matrix"))]
74impl_col_access_fxn_shapes!(i128);
75#[cfg(all(feature = "u8", feature = "matrix"))]
76impl_col_access_fxn_shapes!(u8);
77#[cfg(all(feature = "u16", feature = "matrix"))]
78impl_col_access_fxn_shapes!(u16);
79#[cfg(all(feature = "u32", feature = "matrix"))]
80impl_col_access_fxn_shapes!(u32);
81#[cfg(all(feature = "u64", feature = "matrix"))]
82impl_col_access_fxn_shapes!(u64);
83#[cfg(all(feature = "u128", feature = "matrix"))]
84impl_col_access_fxn_shapes!(u128);
85#[cfg(all(feature = "f32", feature = "matrix"))]
86impl_col_access_fxn_shapes!(f32);
87#[cfg(all(feature = "f64", feature = "matrix"))]
88impl_col_access_fxn_shapes!(f64);
89#[cfg(all(feature = "string", feature = "matrix"))]
90impl_col_access_fxn_shapes!(String);
91#[cfg(all(feature = "complex", feature = "matrix"))]
92impl_col_access_fxn_shapes!(C64);
93#[cfg(all(feature = "rational", feature = "matrix"))]
94impl_col_access_fxn_shapes!(R64);
95
96macro_rules! impl_access_column_table_match_arms {
97 ($arg:expr, $($lhs_type:ident, $($default:expr, $type_string:tt),+);+ $(;)?) => {
98 paste!{
99 match $arg {
100 (Value::Table(tbl),Value::Id(k)) => {
101 let tbl_brrw = tbl.borrow();
102 match (tbl_brrw.get(&k),tbl_brrw.rows()) {
103 $(
104 $(
105 #[cfg(all(feature = $type_string, feature = "matrix1"))]
106 (Some((ValueKind::$lhs_type,value)),1) => Ok(Box::new([<TableAccessCol $lhs_type M1>]{source: value.clone(), out: Ref::new(Matrix1::from_element($default)) })),
107 #[cfg(all(feature = $type_string, feature = "vector2"))]
108 (Some((ValueKind::$lhs_type,value)),2) => Ok(Box::new([<TableAccessCol $lhs_type V2>]{source: value.clone(), out: Ref::new(Vector2::from_element($default)) })),
109 #[cfg(all(feature = $type_string, feature = "vector3"))]
110 (Some((ValueKind::$lhs_type,value)),3) => Ok(Box::new([<TableAccessCol $lhs_type V3>]{source: value.clone(), out: Ref::new(Vector3::from_element($default)) })),
111 #[cfg(all(feature = $type_string, feature = "vector4"))]
112 (Some((ValueKind::$lhs_type,value)),4) => Ok(Box::new([<TableAccessCol $lhs_type V4>]{source: value.clone(), out: Ref::new(Vector4::from_element($default)) })),
113 #[cfg(all(feature = $type_string, feature = "vectord"))]
114 (Some((ValueKind::$lhs_type,value)),n) => Ok(Box::new([<TableAccessCol $lhs_type VD>]{source: value.clone(), out: Ref::new(DVector::from_element(n,$default)) })),
115 )+
116 )+
117 _ => Err(MechError2::new(TableColumnNotFoundError { column_id: k.clone() }, None).with_compiler_loc()),
119 }
120 }
121 (tbl,key) => Err(MechError2::new(UnhandledFunctionArgumentKind2 { arg: (tbl.kind(), key.kind()), fxn_name: "TableAccessColumn".to_string() }, None).with_compiler_loc()),
122 }
123 }
124 }
125}
126
127fn impl_access_column_table_fxn(source: Value, key: Value) -> MResult<Box<dyn MechFunction>> {
128 impl_access_column_table_match_arms!(
129 (source,key),
130 Bool,bool::default(),"bool";
131 I8,i8::default(),"i8";
132 I16,i16::default(),"i16";
133 I32,i32::default(),"i32";
134 I64,i64::default(),"i64";
135 I128,i128::default(),"i128";
136 U8,u8::default(),"u8";
137 U16,u16::default(),"u16";
138 U32,u32::default(),"u32";
139 U64,u64::default(),"u64";
140 U128,u128::default(),"u128";
141 F32,f32::default(),"f32";
142 F64,f64::default(),"f64";
143 String,String::default(),"string";
144 C64,C64::default(),"complex";
145 R64,R64::default(),"rational";
146 )
147}
148
149pub struct TableAccessColumn {}
150impl NativeFunctionCompiler for TableAccessColumn {
151 fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>> {
152 if arguments.len() <= 1 {
153 return Err(MechError2::new(IncorrectNumberOfArguments { expected: 1, found: arguments.len() }, None).with_compiler_loc());
154 }
155 let tbl = arguments[0].clone();
156 let key = arguments[1].clone();
157 match impl_access_column_table_fxn(tbl.clone(), key.clone()) {
158 Ok(fxn) => Ok(fxn),
159 Err(_) => {
160 match (tbl.clone(),&key) {
161 (Value::MutableReference(tbl),_) => { impl_access_column_table_fxn(tbl.borrow().clone(), key.clone()) }
162 x => Err(MechError2::new(UnhandledFunctionArgumentKind2 { arg: (tbl.kind(), key.kind()), fxn_name: "TableAccessColumn".to_string() }, None).with_compiler_loc()),
163 }
164 }
165 }
166 }
167}
168
169#[derive(Debug)]
172pub struct TableAccessSwizzle {
173 pub out: Value,
174}
175
176impl MechFunctionImpl for TableAccessSwizzle {
177 fn solve(&self) {
178 ()
179 }
180 fn out(&self) -> Value { self.out.clone() }
181 fn to_string(&self) -> String { format!("{:#?}", self) }
182}
183#[cfg(feature = "compiler")]
184impl MechFunctionCompiler for TableAccessSwizzle {
185 fn compile(&self, ctx: &mut CompileCtx) -> MResult<Register> {
186 let mut registers = [0];
187 registers[0] = compile_register!(self.out, ctx);
188 ctx.features.insert(FeatureFlag::Builtin(FeatureKind::Swizzle));
189 ctx.emit_nullop(
190 hash_str("TableAccessSwizzle"),
191 registers[0],
192 );
193 Ok(registers[0])
194 }
195}
196
197#[derive(Debug)]
200pub struct TableAccessScalarF {
201 pub source: Ref<MechTable>,
202 pub ix: Ref<usize>,
203 pub out: Ref<MechRecord>,
204}
205
206impl MechFunctionImpl for TableAccessScalarF {
207 fn solve(&self) {
208 let table = self.source.borrow();
209 let mut record = self.out.borrow_mut();
210 let row_ix = *self.ix.borrow();
211 for (key, (kind, matrix)) in table.data.iter() {
212 let value = matrix.index1d(row_ix);
213 record.data.insert(*key, value.clone());
214 }
215 }
216 fn out(&self) -> Value { Value::Record(self.out.clone()) }
217 fn to_string(&self) -> String {format!("{:#?}", self)}
218}
219#[cfg(feature = "compiler")]
220impl MechFunctionCompiler for TableAccessScalarF {
221 fn compile(&self, ctx: &mut CompileCtx) -> MResult<Register> {
222 let mut registers = [0,0,0];
223
224 registers[0] = compile_register_brrw!(self.out, ctx);
225 registers[1] = compile_register_brrw!(self.source, ctx);
226 registers[2] = compile_register_brrw!(self.ix, ctx);
227
228 ctx.features.insert(FeatureFlag::Builtin(FeatureKind::Table));
229 ctx.features.insert(FeatureFlag::Builtin(FeatureKind::Access));
230
231 ctx.emit_binop(
232 hash_str(stringify!("TableAccessScalarF")),
233 registers[0],
234 registers[1],
235 registers[2],
236 );
237
238 return Ok(registers[0])
239 }
240}
241
242pub struct TableAccessScalar{}
243
244impl NativeFunctionCompiler for TableAccessScalar {
245 fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>> {
246 if arguments.len() <= 1 {
247 return Err(MechError2::new(IncorrectNumberOfArguments { expected: 1, found: arguments.len() }, None).with_compiler_loc());
248 }
249 let tbl = arguments[0].clone();
250 let ix1 = arguments[1].clone();
251 match (tbl.clone(), ix1.clone()) {
252 #[cfg(feature = "table")]
253 (Value::Table(source), Value::Index(ix)) => {
254 let record = match source.borrow().get_record(*ix.borrow()) {
255 Some(record) => record,
256 None => return Err(MechError2::new(UnhandledFunctionArgumentKind2 { arg: (tbl.kind(), ix1.kind()), fxn_name: "TableAccessScalar".to_string() }, None).with_compiler_loc()),
257 };
258 Ok(Box::new(TableAccessScalarF{source: source.clone(), ix: ix.clone(), out: Ref::new(record) }))
259 }
260 (Value::MutableReference(src_ref), Value::Index(ix)) => {
261 let src_ref_brrw = src_ref.borrow();
262 match &*src_ref_brrw {
263 #[cfg(feature = "table")]
264 Value::Table(source) => {
265 let record = match source.borrow().get_record(*ix.borrow()) {
266 Some(record) => record,
267 None => return Err(MechError2::new(UnhandledFunctionArgumentKind2 { arg: (tbl.kind(), ix1.kind()), fxn_name: "TableAccessScalar".to_string() }, None).with_compiler_loc()),
268 };
269 Ok(Box::new(TableAccessScalarF{source: source.clone(), ix: ix.clone(), out: Ref::new(record) }))
270 }
271 _ => Err(MechError2::new(UnhandledFunctionArgumentKind2 { arg: (tbl.kind(), ix1.kind()), fxn_name: "TableAccessScalar".to_string() }, None).with_compiler_loc()),
272 }
273 }
274 _ => Err(MechError2::new(UnhandledFunctionArgumentKind2 { arg: (tbl.kind(), ix1.kind()), fxn_name: "TableAccessScalar".to_string() }, None).with_compiler_loc()),
275 }
276 }
277}
278
279#[derive(Debug)]
282pub struct TableAccessRangeIndex {
283 pub source: Ref<MechTable>,
284 pub ix: Ref<DVector<usize>>,
285 pub out: Ref<MechTable>,
286}
287
288impl MechFunctionImpl for TableAccessRangeIndex {
289 fn solve(&self) {
290 let table = self.source.borrow();
291 let mut out_table = self.out.borrow_mut();
292 let ix_brrw = self.ix.borrow();
293
294 for (key, (_kind, matrix)) in table.data.iter() {
295 let (_out_kind, out_matrix) = out_table.data.get_mut(key).unwrap();
296 for (out_i, i) in ix_brrw.iter().enumerate() {
297 let value = matrix.index1d(*i);
298 out_matrix.set_index1d(out_i, value.clone());
299 }
300 }
301 }
302 fn out(&self) -> Value { Value::Table(self.out.clone()) }
303 fn to_string(&self) -> String {format!("{:#?}", self)}
304}
305#[cfg(feature = "compiler")]
306impl MechFunctionCompiler for TableAccessRangeIndex {
307 fn compile(&self, ctx: &mut CompileCtx) -> MResult<Register> {
308 let mut registers = [0,0,0];
309
310 registers[0] = compile_register_brrw!(self.out, ctx);
311 registers[1] = compile_register_brrw!(self.source, ctx);
312 registers[2] = compile_register_brrw!(self.ix, ctx);
313
314 ctx.features.insert(FeatureFlag::Builtin(FeatureKind::Table));
315 ctx.features.insert(FeatureFlag::Builtin(FeatureKind::SubscriptRange));
316
317 ctx.emit_binop(
318 hash_str(stringify!("TableAccessRangeIndex")),
319 registers[0],
320 registers[1],
321 registers[2],
322 );
323
324 return Ok(registers[0])
325 }
326}
327
328#[derive(Debug)]
329pub struct TableAccessRangeBool {
330 pub source: Ref<MechTable>,
331 pub ix: Ref<DVector<bool>>,
332 pub out: Ref<MechTable>,
333}
334
335impl MechFunctionImpl for TableAccessRangeBool {
336 fn solve(&self) {
337 let table = self.source.borrow();
338 let ix_brrw = self.ix.borrow();
339 let true_count = ix_brrw.iter().filter(|&&b| b).count();
340
341 let mut out_table = self.out.borrow_mut();
342
343 for (key, (_kind, matrix)) in table.data.iter() {
344 let (_out_kind, out_matrix) = out_table.data.get_mut(key).unwrap();
345
346 out_matrix.resize_vertically(true_count, Value::Empty);
348
349 let mut push_index = 0;
351 for (i, flag) in ix_brrw.iter().enumerate() {
352 if *flag {
353 let value = matrix.index1d(i + 1); out_matrix.set_index1d(push_index, value.clone());
355 push_index += 1;
356 }
357 }
358 }
359 out_table.rows = true_count;
360 }
361 fn out(&self) -> Value { Value::Table(self.out.clone()) }
362 fn to_string(&self) -> String {format!("{:#?}", self)}
363}
364#[cfg(feature = "compiler")]
365impl MechFunctionCompiler for TableAccessRangeBool {
366 fn compile(&self, ctx: &mut CompileCtx) -> MResult<Register> {
367 let mut registers = [0,0,0];
368
369 registers[0] = compile_register_brrw!(self.out, ctx);
370 registers[1] = compile_register_brrw!(self.source, ctx);
371 registers[2] = compile_register_brrw!(self.ix, ctx);
372
373 ctx.features.insert(FeatureFlag::Builtin(FeatureKind::Table));
374 ctx.features.insert(FeatureFlag::Builtin(FeatureKind::LogicalIndexing));
375
376 ctx.emit_binop(
377 hash_str(stringify!("TableAccessRangeBool")),
378 registers[0],
379 registers[1],
380 registers[2],
381 );
382
383 return Ok(registers[0])
384 }
385}
386
387pub struct TableAccessRange{}
388
389impl NativeFunctionCompiler for TableAccessRange {
390 fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>> {
391 if arguments.len() <= 1 {
392 return Err(MechError2::new(IncorrectNumberOfArguments { expected: 1, found: arguments.len() }, None).with_compiler_loc());
393 }
394 let ixes = arguments.clone().split_off(1);
395 let tbl = arguments[0].clone();
396 match (tbl.clone(), ixes.as_slice()) {
397 #[cfg(all(feature = "table", feature = "matrix"))]
398 (Value::Table(source), [Value::MatrixIndex(Matrix::DVector(ix))]) => {
399 let out_table = source.borrow().empty_table(ix.borrow().len());
400 Ok(Box::new(TableAccessRangeIndex{source: source.clone(), ix: ix.clone(), out: Ref::new(out_table) }))
401 }
402 #[cfg(all(feature = "matrix", feature = "table", feature = "logical_indexing"))]
403 (Value::Table(source), [Value::MatrixBool(Matrix::DVector(ix))]) => {
404 let out_table = source.borrow().empty_table(ix.borrow().len());
405 Ok(Box::new(TableAccessRangeBool{source: source.clone(), ix: ix.clone(), out: Ref::new(out_table) }))
406 }
407 #[cfg(all(feature = "table", feature = "matrix"))]
408 (Value::MutableReference(src_ref), [Value::MatrixIndex(Matrix::DVector(ix))]) => {
409 let src_ref_brrw = src_ref.borrow();
410 match &*src_ref_brrw {
411 Value::Table(source) => {
412 let out_table = source.borrow().empty_table(ix.borrow().len());
413 Ok(Box::new(TableAccessRangeIndex{source: source.clone(), ix: ix.clone(), out: Ref::new(out_table) }))
414 }
415 _ => Err(MechError2::new(UnhandledFunctionArgumentIxesMono { arg: (tbl.kind(), ixes.iter().map(|x| x.kind()).collect()), fxn_name: "TableAccessRange".to_string() }, None).with_compiler_loc()),
416 }
417 }
418 #[cfg(all(feature = "matrix", feature = "table", feature = "logical_indexing"))]
419 (Value::MutableReference(src_ref), [Value::MatrixBool(Matrix::DVector(ix))]) => {
420 let src_ref_brrw = src_ref.borrow();
421 match &*src_ref_brrw {
422 Value::Table(source) => {
423 let out_table = source.borrow().empty_table(ix.borrow().len());
424 Ok(Box::new(TableAccessRangeBool{source: source.clone(), ix: ix.clone(), out: Ref::new(out_table) }))
425 }
426 _ => Err(MechError2::new(UnhandledFunctionArgumentIxesMono { arg: (tbl.kind(), ixes.iter().map(|x| x.kind()).collect()), fxn_name: "TableAccessRange".to_string() }, None).with_compiler_loc()),
427 }
428 }
429 _ => Err(MechError2::new(UnhandledFunctionArgumentIxesMono { arg: (tbl.kind(), ixes.iter().map(|x| x.kind()).collect()), fxn_name: "TableAccessRange".to_string() }, None).with_compiler_loc()),
430 }
431 }
432}