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(MechError{file: file!().to_string(), tokens: vec![], msg: "".to_string(), id: line!(), kind: MechErrorKind::IncorrectNumberOfArguments});
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(MechError{file: file!().to_string(), tokens: vec![], msg: "".to_string(), id: line!(), kind: MechErrorKind::UnhandledFunctionArgumentKind}),
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(MechError{file: file!().to_string(), tokens: vec![], msg: "".to_string(), id: line!(), kind: MechErrorKind::IncorrectNumberOfArguments});
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(MechError{file: file!().to_string(), tokens: vec![], msg: "".to_string(), id: line!(), kind: MechErrorKind::UnhandledFunctionArgumentKind}),
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(MechError{file: file!().to_string(), tokens: vec![], msg: "".to_string(), id: line!(), kind: MechErrorKind::IncorrectNumberOfArguments});
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 => { return Err(MechError{file: file!().to_string(), tokens: vec![], msg: "".to_string(), id: line!(), kind: MechErrorKind::UndefinedField(k)});}
79          }
80        }
81        Ok(Box::new(RecordAccessSwizzle{source: Value::Tuple(MechTuple::from_vec(values))}))
82      }
83      #[cfg(feature = "table")]
84      Value::Table(tbl) => {
85        let mut elements = vec![];
86        for k in keys {
87          match k {
88            Value::Id(k) => {
89              match tbl.borrow().get(&k) {
90                Some((kind, mat_values)) => {
91                  elements.push(Box::new(mat_values.to_value()));
92                }
93                None => { return Err(MechError{file: file!().to_string(), tokens: vec![], msg: "".to_string(), id: line!(), kind: MechErrorKind::UndefinedField(*k)});}
94              }
95            }
96            _ => return Err(MechError{file: file!().to_string(), tokens: vec![], msg: "".to_string(), id: line!(), kind: MechErrorKind::UnhandledFunctionArgumentKind}),
97          }
98        }
99        todo!("Table swizzle needs to be fixed.");
100        let tuple = Value::Tuple(MechTuple{elements});
101        Ok(Box::new(TableAccessSwizzle{out: tuple}))
102      }
103      Value::MutableReference(r) => match &*r.borrow() {
104        #[cfg(feature = "record")]
105        Value::Record(rcrd) => {
106          let mut values = vec![];
107          for key in keys {
108            let k = key.as_u64().unwrap().borrow().clone();
109            match rcrd.borrow().get(&k) {
110              Some(value) => values.push(value.clone()),
111              None => { return Err(MechError{file: file!().to_string(), tokens: vec![], msg: "".to_string(), id: line!(), kind: MechErrorKind::UndefinedField(k)});}
112            }
113          }
114          Ok(Box::new(RecordAccessSwizzle{source: Value::Tuple(MechTuple::from_vec(values))}))
115        }
116        #[cfg(feature = "table")]
117        Value::Table(tbl) => {
118          let mut elements = vec![];
119          for key in keys {
120            let k = key.as_u64().unwrap().borrow().clone();
121            match tbl.borrow().get(&k) {
122              Some((kind, mat_values)) => {
123                elements.push(Box::new(mat_values.to_value()));
124              }
125              None => { return Err(MechError{file: file!().to_string(), tokens: vec![], msg: "".to_string(), id: line!(), kind: MechErrorKind::UndefinedField(k)});}
126            }
127          }
128          let tuple = Value::Tuple(MechTuple{elements});
129          Ok(Box::new(TableAccessSwizzle{out: tuple}))
130        }
131        _ => todo!(),
132      }
133      _ => todo!(),
134    }
135  }
136}
137
138// ----------------------------------------------------------------------------
139
140// Access Column
141
142pub fn impl_access_column_fxn(source: Value, key: Value) -> MResult<Box<dyn MechFunction>> {
143  match source.kind().deref_kind() {
144    #[cfg(feature = "record")]
145    ValueKind::Record(_) => RecordAccess{}.compile(&vec![source,key]),
146    #[cfg(feature = "table")]
147    ValueKind::Table(_,_) => TableAccessColumn{}.compile(&vec![source,key]),
148    _ => Err(MechError{file: file!().to_string(),tokens: vec![],msg: format!("Unhandled args {:?}, {:?}", source, key),id: line!(),kind: MechErrorKind::UnhandledFunctionArgumentKind,}),
149  }
150}
151
152pub struct AccessColumn {}
153impl NativeFunctionCompiler for AccessColumn {
154  fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>> {
155    if arguments.len() != 2 {
156      return Err(MechError{file: file!().to_string(), tokens: vec![], msg: "".to_string(), id: line!(), kind: MechErrorKind::IncorrectNumberOfArguments});
157    }
158    let src = arguments[0].clone();
159    let key = arguments[1].clone();
160    match impl_access_column_fxn(src.clone(), key.clone()) {
161      Ok(fxn) => Ok(fxn),
162      Err(_) => {
163        match (src,&key) {
164          (Value::MutableReference(src),_) => { impl_access_column_fxn(src.borrow().clone(), key.clone()) }
165          _ => Err(MechError{file: file!().to_string(),  tokens: vec![], msg: "".to_string(), id: line!(), kind: MechErrorKind::UnhandledFunctionArgumentKind }),
166        }
167      }
168    }
169  }
170}