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 }