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