1use crate::*;
2use std::collections::HashMap;
3
4pub fn structure(strct: &Structure, p: &Interpreter) -> MResult<Value> {
8 match strct {
9 Structure::Empty => Ok(Value::Empty),
10 #[cfg(feature = "record")]
11 Structure::Record(x) => record(&x, p),
12 #[cfg(feature = "matrix")]
13 Structure::Matrix(x) => matrix(&x, p),
14 #[cfg(feature = "table")]
15 Structure::Table(x) => table(&x, p),
16 #[cfg(feature = "tuple")]
17 Structure::Tuple(x) => tuple(&x, p),
18 #[cfg(feature = "tuple_struct")]
19 Structure::TupleStruct(x) => todo!(),
20 #[cfg(feature = "set")]
21 Structure::Set(x) => set(&x, p),
22 #[cfg(feature = "map")]
23 Structure::Map(x) => map(&x, p),
24 x => Err(MechError2::new(FeatureNotEnabledError, Some(format!("Feature not enabled for `{:?}`", stringify!(x)))).with_compiler_loc()),
25 }
26}
27
28#[cfg(feature = "tuple")]
29pub fn tuple(tpl: &Tuple, p: &Interpreter) -> MResult<Value> {
30 let mut elements = vec![];
31 for el in &tpl.elements {
32 let result = expression(el,p)?;
33 elements.push(Box::new(result));
34 }
35 let mech_tuple = Ref::new(MechTuple{elements});
36 Ok(Value::Tuple(mech_tuple))
37}
38
39#[cfg(feature = "map")]
40pub fn map(mp: &Map, p: &Interpreter) -> MResult<Value> {
41 let mut m = IndexMap::new();
42 for b in &mp.elements {
43 let key = expression(&b.key, p)?;
44 let val = expression(&b.value, p)?;
45 m.insert(key,val);
46 }
47
48 let key_kind = m.keys().next().unwrap().kind();
49 for k in m.keys() {
51 if k.kind() != key_kind {
52 return Err(MechError2::new(
53 MapKeyKindMismatchError{expected_kind: key_kind.clone(), actual_kind: k.kind().clone()},
54 None
55 ).with_compiler_loc());
56 }
57 }
58
59 let value_kind = m.values().next().unwrap().kind();
60 for v in m.values() {
62 if v.kind() != value_kind {
63 return Err(MechError2::new(
64 MapValueKindMismatchError{expected_kind: value_kind.clone(), actual_kind: v.kind().clone()},
65 None
66 ).with_compiler_loc());
67 }
68 }
69 Ok(Value::Map(Ref::new(MechMap{
70 num_elements: m.len(),
71 key_kind,
72 value_kind,
73 map: m
74 })))
75}
76
77#[cfg(feature = "record")]
78pub fn record(rcrd: &Record, p: &Interpreter) -> MResult<Value> {
79 let mut data: IndexMap<u64,Value> = IndexMap::new();
80 let cols: usize = rcrd.bindings.len();
81 let mut kinds: Vec<ValueKind> = Vec::new();
82 let mut field_names: HashMap<u64,String> = HashMap::new();
83 for b in &rcrd.bindings {
84 let name_hash = b.name.hash();
85 let name_str = b.name.to_string();
86 let val = expression(&b.value, p)?;
87 let knd: ValueKind = match &b.kind {
88 Some(k) => kind_annotation(&k.kind, p)?.to_value_kind(&p.state.borrow().kinds)?,
89 None => val.kind(),
90 };
91 kinds.push(knd.clone());
93 #[cfg(feature = "convert")]
94 if knd != val.kind() {
95 let fxn = ConvertKind{}.compile(&vec![val.clone(), Value::Kind(knd.clone())]);
96 match fxn {
97 Ok(convert_fxn) => {
98 convert_fxn.solve();
99 let converted_result = convert_fxn.out();
100 p.state.borrow_mut().add_plan_step(convert_fxn);
101 data.insert(name_hash, converted_result);
102 },
103 Err(e) => {
104 return Err(MechError2::new(
105 TableColumnKindMismatchError {
106 column_id: name_hash,
107 expected_kind: knd.clone(),
108 actual_kind: val.kind().clone(),
109 },
110 None
111 ).with_compiler_loc());
112 }
113 }
114 } else {
115 data.insert(name_hash, val);
116 }
117 #[cfg(not(feature = "convert"))]
118 if knd != val.kind() {
119 return Err(MechError{file: file!().to_string(), tokens: vec![], msg: "".to_string(), id: line!(), kind: MechErrorKind::KindMismatch(val.kind(),knd)});
120 } else {
121 data.insert(name_hash, val);
122 }
123 field_names.insert(name_hash, name_str);
124 }
125 Ok(Value::Record(Ref::new(MechRecord{
126 cols,
127 kinds,
128 data,
129 field_names,
130 })))
131}
132
133#[cfg(feature = "set")]
138#[derive(Debug)]
139pub struct ValueSet {
140 pub out: Ref<MechSet>,
141}
142#[cfg(feature = "set")]
143#[cfg(feature = "functions")]
144impl MechFunctionImpl for ValueSet {
145 fn solve(&self) {}
146 fn out(&self) -> Value { Value::Set(self.out.clone()) }
147 fn to_string(&self) -> String { format!("{:#?}", self) }
148}
149#[cfg(feature = "set")]
150#[cfg(feature = "functions")]
151impl MechFunctionFactory for ValueSet {
152 fn new(args: FunctionArgs) -> MResult<Box<dyn MechFunction>> {
153 match args {
154 FunctionArgs::Nullary(out) => {
155 let out: Ref<MechSet> = unsafe{ out.as_unchecked().clone() };
156 Ok(Box::new(ValueSet {out}))
157 },
158 _ => Err(MechError2::new(
159 IncorrectNumberOfArguments { expected: 0, found: args.len() },
160 None
161 ).with_compiler_loc()
162 ),
163 }
164 }
165}
166#[cfg(feature = "set")]
167#[cfg(feature = "compiler")]
168impl MechFunctionCompiler for ValueSet {
169 fn compile(&self, ctx: &mut CompileCtx) -> MResult<Register> {
170 compile_nullop!("set/define", self.out, ctx, FeatureFlag::Builtin(FeatureKind::Set));
171 }
172}
173#[cfg(feature = "set")]
174#[cfg(feature = "functions")]
175register_descriptor!{
176 FunctionDescriptor {
177 name: "set/define",
178 ptr: ValueSet::new,
179 }
180}
181
182#[cfg(feature = "set")]
183pub struct SetDefine {}
184#[cfg(feature = "set")]
185#[cfg(feature = "functions")]
186impl NativeFunctionCompiler for SetDefine {
187 fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>> {
188 Ok(Box::new(ValueSet {
189 out: Ref::new(MechSet::from_vec(arguments.clone())),
190 }))
191 }
192}
193#[cfg(feature = "set")]
194#[cfg(feature = "functions")]
195register_descriptor!{
196 FunctionCompilerDescriptor {
197 name: "set/define",
198 ptr: &SetDefine{},
199 }
200}
201
202#[cfg(feature = "set")]
203pub fn set(m: &Set, p: &Interpreter) -> MResult<Value> {
204 let mut elements = Vec::new();
205 for el in &m.elements {
206 let result = expression(el, p)?;
207 elements.push(result.clone());
208 }
209 let element_kind = if elements.len() > 0 {
210 elements[0].kind()
211 } else {
212 ValueKind::Empty
213 };
214 for el in &elements {
216 if el.kind() != element_kind {
217 return Err(MechError2::new(
218 SetKindMismatchError{expected_kind: element_kind.clone(), actual_kind: el.kind().clone()},
219 None
220 ).with_compiler_loc());
221 }
222 }
223 #[cfg(feature = "functions")]
224 {
225 let new_fxn = SetDefine {}.compile(&elements)?;
226 new_fxn.solve();
227 let out = new_fxn.out();
228 let plan = p.plan();
229 let mut plan_brrw = plan.borrow_mut();
230 plan_brrw.push(new_fxn);
231 Ok(out)
232 }
233 #[cfg(not(feature = "functions"))]
234 {
235 Ok(Value::Set(Ref::new(MechSet::from_vec(elements))))
236 }
237}
238
239macro_rules! handle_value_kind {
243 ($value_kind:ident, $val:expr, $field_label:expr, $data_map:expr, $converter:ident) => {{
244 let mut vals = Vec::new();
245 let id = $field_label; for x in $val.as_vec().iter() {
247 match x.$converter() {
248 Ok(u) => vals.push(u.to_value()),
249 Err(_) => {
250 return Err(MechError2::new(
251 TableColumnKindMismatchError {
252 column_id: id,
253 expected_kind: $value_kind.clone(),
254 actual_kind: x.kind()
255 },
256 None
257 ).with_compiler_loc());
258 }
259 }
260 }
261 $data_map.insert(id, ($value_kind.clone(), Value::to_matrixd(vals.clone(), vals.len(), 1)));
262 }};
263}
264
265
266#[cfg(feature = "table")]
267fn handle_column_kind(
268 kind: ValueKind,
269 id: u64,
270 val: Matrix<Value>,
271 data_map: &mut IndexMap<u64,(ValueKind,Matrix<Value>)>
272) -> MResult<()>
273{
274 match kind {
275 #[cfg(feature = "i8")]
276 ValueKind::I8 => handle_value_kind!(kind, val, id, data_map, as_i8),
277 #[cfg(feature = "i16")]
278 ValueKind::I16 => handle_value_kind!(kind, val, id, data_map, as_i16),
279 #[cfg(feature = "i32")]
280 ValueKind::I32 => handle_value_kind!(kind, val, id, data_map, as_i32),
281 #[cfg(feature = "i64")]
282 ValueKind::I64 => handle_value_kind!(kind, val, id, data_map, as_i64),
283 #[cfg(feature = "i128")]
284 ValueKind::I128 => handle_value_kind!(kind, val, id, data_map, as_i128),
285
286 #[cfg(feature = "u8")]
287 ValueKind::U8 => handle_value_kind!(kind, val, id, data_map, as_u8),
288 #[cfg(feature = "u16")]
289 ValueKind::U16 => handle_value_kind!(kind, val, id, data_map, as_u16),
290 #[cfg(feature = "u32")]
291 ValueKind::U32 => handle_value_kind!(kind, val, id, data_map, as_u32),
292 #[cfg(feature = "u64")]
293 ValueKind::U64 => handle_value_kind!(kind, val, id, data_map, as_u64),
294 #[cfg(feature = "u128")]
295 ValueKind::U128 => handle_value_kind!(kind, val, id, data_map, as_u128),
296
297 #[cfg(feature = "f32")]
298 ValueKind::F32 => handle_value_kind!(kind, val, id, data_map, as_f32),
299 #[cfg(feature = "f64")]
300 ValueKind::F64 => handle_value_kind!(kind, val, id, data_map, as_f64),
301
302 #[cfg(feature = "string")]
303 ValueKind::String => handle_value_kind!(kind, val, id, data_map, as_string),
304
305 #[cfg(feature = "complex")]
306 ValueKind::C64 => handle_value_kind!(kind, val, id, data_map, as_c64),
307
308 #[cfg(feature = "rational")]
309 ValueKind::R64 => handle_value_kind!(kind, val, id, data_map, as_r64),
310
311 #[cfg(feature = "bool")]
312 ValueKind::Bool => {
313 let vals: Vec<Value> = val.as_vec()
314 .iter()
315 .map(|x| x.as_bool().unwrap().to_value())
316 .collect();
317 data_map.insert(id, (ValueKind::Bool, Value::to_matrix(vals.clone(), vals.len(), 1)));
318 }
319
320 x => {
321 println!("Unsupported kind in table column: {:?}", x);
322 todo!()
323 }
324 }
325
326 Ok(())
327}
328
329#[cfg(feature = "table")]
330pub fn table(t: &Table, p: &Interpreter) -> MResult<Value> {
331 let mut rows = vec![];
332 let headings = table_header(&t.header, p)?;
333 let mut cols = 0;
334
335 for row in &t.rows {
337 let result = table_row(row, p)?;
338 cols = result.len();
339 rows.push(result);
340 }
341
342 let mut data = vec![Vec::<Value>::new(); cols];
344
345 for row in rows {
347 for (ix, el) in row.into_iter().enumerate() {
348 data[ix].push(el);
349 }
350 }
351
352 let mut data_map: IndexMap<u64,(ValueKind,Matrix<Value>)> = IndexMap::new();
354
355 for ((id, knd, _name), column) in headings.iter().zip(data.iter()) {
356 let id_u64 = id.as_u64().unwrap().borrow().clone();
357
358 let actual_kind = match knd {
360 ValueKind::None => {
361 match column.first() {
362 Some(v) => v.kind(),
363 None => ValueKind::String, }
365 }
366 _ => knd.clone(),
367 };
368
369 let val = Value::to_matrix(column.clone(), column.len(), 1);
371
372 handle_column_kind(actual_kind, id_u64, val, &mut data_map)?;
374 }
375
376 let names: HashMap<u64, String> = headings.iter()
378 .map(|(id, _, name)| (id.as_u64().unwrap().borrow().clone(), name.to_string()))
379 .collect();
380
381 let tbl = MechTable::new(t.rows.len(), cols, data_map.clone(), names);
382 Ok(Value::Table(Ref::new(tbl)))
383}
384
385#[cfg(feature = "kind_annotation")]
386pub fn table_header(fields: &Vec<Field>, p: &Interpreter) -> MResult<Vec<(Value,ValueKind,Identifier)>> {
387 let mut headings: Vec<(Value,ValueKind,Identifier)> = Vec::new();
388 for f in fields {
389 let id = f.name.hash();
390 let kind = match &f.kind {
391 Some(k) => kind_annotation(&k.kind, p)?,
392 None => Kind::None,
393 };
394 headings.push((Value::Id(id),kind.to_value_kind(&p.state.borrow().kinds)?,f.name.clone()));
395 }
396 Ok(headings)
397}
398
399pub fn table_row(r: &TableRow, p: &Interpreter) -> MResult<Vec<Value>> {
400 let mut row: Vec<Value> = Vec::new();
401 for col in &r.columns {
402 let result = table_column(col, p)?;
403 row.push(result);
404 }
405 Ok(row)
406}
407
408pub fn table_column(r: &TableColumn, p: &Interpreter) -> MResult<Value> {
409 expression(&r.element, p)
410}
411
412#[cfg(feature = "matrix")]
416pub fn matrix(m: &Mat, p: &Interpreter) -> MResult<Value> {
417 let plan = p.plan();
418 let mut shape = vec![0, 0];
419 let mut col: Vec<Value> = Vec::new();
420 let mut kind = ValueKind::Empty;
421 #[cfg(feature = "matrix_horzcat")]
422 {
423 for row in &m.rows {
424 let result = matrix_row(row, p)?;
425 if shape == vec![0,0] {
426 shape = result.shape();
427 kind = result.kind();
428 col.push(result);
429 } else if shape[1] == result.shape()[1] {
430 col.push(result);
431 } else {
432 return Err(MechError2::new(
433 DimensionMismatch { dims: vec![shape[1], result.shape()[1]] },
434 None
435 ).with_compiler_loc()
436 );
437 }
438 }
439 if col.is_empty() {
440 return Ok(Value::MatrixValue(Matrix::from_vec(vec![], 0, 0)));
441 } else if col.len() == 1 {
442 return Ok(col[0].clone());
443 }
444 }
445 #[cfg(feature = "matrix_vertcat")]
446 {
447 let new_fxn = MatrixVertCat{}.compile(&col)?;
448 new_fxn.solve();
449 let out = new_fxn.out();
450 let mut plan_brrw = plan.borrow_mut();
451 plan_brrw.push(new_fxn);
452 return Ok(out);
453 }
454 return Err(MechError2::new(
455 FeatureNotEnabledError,
456 Some("matrix/vertcat feature not enabled".to_string())).with_compiler_loc()
457 );
458}
459
460#[cfg(feature = "matrix_horzcat")]
461pub fn matrix_row(r: &MatrixRow, p: &Interpreter) -> MResult<Value> {
462 let plan = p.plan();
463 let mut row: Vec<Value> = Vec::new();
464 let mut shape = vec![0, 0];
465 let mut kind = ValueKind::Empty;
466 for col in &r.columns {
467 let result = matrix_column(col, p)?;
468 if shape == vec![0,0] {
469 shape = result.shape();
470 kind = result.kind();
471 row.push(result);
472 } else if shape[0] == result.shape()[0] {
473 row.push(result);
474 } else {
475 return Err(MechError2::new(
476 DimensionMismatch { dims: vec![shape[0], result.shape()[0]] },
477 None
478 ).with_compiler_loc()
479 );
480 }
481 }
482 let new_fxn = MatrixHorzCat{}.compile(&row)?;
483 new_fxn.solve();
484 let out = new_fxn.out();
485 let mut plan_brrw = plan.borrow_mut();
486 plan_brrw.push(new_fxn);
487 Ok(out)
488}
489
490pub fn matrix_column(r: &MatrixColumn, p: &Interpreter) -> MResult<Value> {
491 expression(&r.element, p)
492}