mech_interpreter/stdlib/access/
mod.rs

1// ----------------------------------------------------------------------------
2// Access 
3// ----------------------------------------------------------------------------
4
5#[cfg(feature = "matrix")]
6pub mod matrix;
7#[cfg(feature = "record")]
8pub mod record;
9#[cfg(feature = "table")]
10pub mod table;
11#[cfg(feature = "tuple")]
12pub mod tuple;
13
14#[cfg(feature = "matrix")]
15pub use self::matrix::*;
16#[cfg(feature = "record")]
17pub use self::record::*;
18#[cfg(feature = "table")]
19pub use self::table::*;
20#[cfg(feature = "tuple")]
21pub use self::tuple::*;
22
23#[macro_use]
24use crate::stdlib::*;
25
26pub struct AccessScalar {}
27impl NativeFunctionCompiler for AccessScalar {
28  fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>> {
29    if arguments.len() != 2 {
30      return Err(MechError2::new(IncorrectNumberOfArguments { expected: 1, found: arguments.len() }, None).with_compiler_loc());
31    }
32    let src = &arguments[0];
33    let index = &arguments[1];
34    match src.kind().deref_kind() {
35      #[cfg(feature = "matrix")]
36      ValueKind::Matrix(mat,_) => MatrixAccessScalar{}.compile(&arguments),
37      #[cfg(feature = "table")]
38      ValueKind::Table(tble,_) => TableAccessScalar{}.compile(&arguments),
39      _ => Err(MechError2::new(UnhandledFunctionArgumentKind2 { arg: (src.kind(), index.kind()), fxn_name: "access/scalar".to_string() }, None).with_compiler_loc()),
40    }
41  }
42}
43
44pub struct AccessRange {}
45impl NativeFunctionCompiler for AccessRange {
46  fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>> {
47    if arguments.len() != 2 {
48      return Err(MechError2::new(IncorrectNumberOfArguments { expected: 1, found: arguments.len() }, None).with_compiler_loc());
49    }
50    let src = &arguments[0];
51    let index = &arguments[1];
52    match src.kind().deref_kind() {
53      #[cfg(feature = "matrix")]
54      ValueKind::Matrix(mat,_) => MatrixAccessRange{}.compile(&arguments),
55      #[cfg(feature = "table")]
56      ValueKind::Table(tble,_) => TableAccessRange{}.compile(&arguments),
57      _ => Err(MechError2::new(UnhandledFunctionArgumentKind2 { arg: (src.kind(), index.kind()), fxn_name: "access/range".to_string() }, None).with_compiler_loc()),
58    }
59  }
60}
61
62pub struct AccessSwizzle {}
63impl NativeFunctionCompiler for AccessSwizzle {
64  fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>> {
65    if arguments.len() < 3 {
66      return Err(MechError2::new(IncorrectNumberOfArguments { expected: 1, found: arguments.len() }, None).with_compiler_loc());
67    }
68    let keys = &arguments.clone().split_off(1);
69    let src = &arguments[0];
70    match src {
71      #[cfg(feature = "record")]
72      Value::Record(rcrd) => {
73        let mut values = vec![];
74        for key in keys {
75          let k = key.as_u64().unwrap().borrow().clone();
76          match rcrd.borrow().get(&k) {
77            Some(value) => values.push(value.clone()),
78            None => { 
79              return Err(MechError2::new(
80                UndefinedRecordFieldError { id: k.clone() },
81                None
82              ).with_compiler_loc());
83            }
84          }
85        }
86        Ok(Box::new(RecordAccessSwizzle{source: Value::Tuple(Ref::new(MechTuple::from_vec(values)))}))
87      }
88      #[cfg(feature = "table")]
89      Value::Table(tbl) => {
90        let mut elements = vec![];
91        for k in keys {
92          match k {
93            Value::Id(k) => {
94              match tbl.borrow().get(&k) {
95                Some((kind, mat_values)) => {
96                  elements.push(Box::new(mat_values.to_value()));
97                }
98                None => { return Err(MechError2::new(
99                  UndefinedRecordFieldError { id: k.clone() },
100                  None
101                ).with_compiler_loc()); }
102              }
103            }
104            _ => return Err(MechError2::new(UnhandledFunctionArgumentIxesMono { arg: (src.kind(), keys.iter().map(|x| x.kind()).collect()), fxn_name: "access/swizzle".to_string() }, None).with_compiler_loc()),
105          }
106        }
107        todo!("Table swizzle needs to be fixed.");
108        let tuple = Value::Tuple(Ref::new(MechTuple{elements}));
109        Ok(Box::new(TableAccessSwizzle{out: tuple}))
110      }
111      Value::MutableReference(r) => match &*r.borrow() {
112        #[cfg(feature = "record")]
113        Value::Record(rcrd) => {
114          let mut values = vec![];
115          for key in keys {
116            let k = key.as_u64().unwrap().borrow().clone();
117            match rcrd.borrow().get(&k) {
118              Some(value) => values.push(value.clone()),
119              None => { return Err(MechError2::new(
120                  UndefinedRecordFieldError { id: k.clone() },
121                  None
122                ).with_compiler_loc());
123              }
124            }
125          }
126          Ok(Box::new(RecordAccessSwizzle{source: Value::Tuple(Ref::new(MechTuple::from_vec(values)))}))
127        }
128        #[cfg(feature = "table")]
129        Value::Table(tbl) => {
130          let mut elements = vec![];
131          for key in keys {
132            let k = key.as_u64().unwrap().borrow().clone();
133            match tbl.borrow().get(&k) {
134              Some((kind, mat_values)) => {
135                elements.push(Box::new(mat_values.to_value()));
136              }
137              None => { return Err(MechError2::new(
138                  UndefinedTableColumnError { id: k.clone() },
139                  None
140                ).with_compiler_loc());
141              }
142            }
143          }
144          let tuple = Value::Tuple(Ref::new(MechTuple{elements}));
145          Ok(Box::new(TableAccessSwizzle{out: tuple}))
146        }
147        _ => todo!(),
148      }
149      _ => todo!(),
150    }
151  }
152}
153
154// ----------------------------------------------------------------------------
155
156// Access Column
157
158pub fn impl_access_column_fxn(source: Value, key: Value) -> MResult<Box<dyn MechFunction>> {
159  match source.kind().deref_kind() {
160    #[cfg(feature = "record")]
161    ValueKind::Record(_) => RecordAccess{}.compile(&vec![source,key]),
162    #[cfg(feature = "table")]
163    ValueKind::Table(_,_) => TableAccessColumn{}.compile(&vec![source,key]),
164    _ => Err(MechError2::new(
165        UnhandledFunctionArgumentKind2 { arg: (source.kind(), key.kind()), fxn_name: "access/column".to_string() },
166        None
167      ).with_compiler_loc()
168    ),
169  }
170}
171
172pub struct AccessColumn {}
173impl NativeFunctionCompiler for AccessColumn {
174  fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>> {
175    if arguments.len() != 2 {
176      return Err(MechError2::new(IncorrectNumberOfArguments { expected: 1, found: arguments.len() }, None).with_compiler_loc());
177    }
178    let src = arguments[0].clone();
179    let key = arguments[1].clone();
180    match impl_access_column_fxn(src.clone(), key.clone()) {
181      Ok(fxn) => Ok(fxn),
182      Err(_) => {
183        match (src.clone(),&key.clone()) {
184          (Value::MutableReference(src),_) => { impl_access_column_fxn(src.borrow().clone(), key.clone()) }
185          _ => Err(MechError2::new(
186              UnhandledFunctionArgumentKind2 { arg: (src.kind(), key.kind()), fxn_name: "access/column".to_string() },
187              None
188            ).with_compiler_loc()
189          ),
190        }
191      }
192    }
193  }
194}