mech_core/program/compiler/
constants.rs

1use crate::*;
2use super::*;
3
4// CompileConst Trait
5// ----------------------------------------------------------------------------
6
7pub trait CompileConst {
8  fn compile_const(&self, ctx: &mut CompileCtx) -> MResult<u32>;
9}
10
11#[cfg(feature = "compiler")]
12impl CompileConst for Value {
13
14  fn compile_const(&self, ctx: &mut CompileCtx) -> MResult<u32> {
15    let mut payload = Vec::<u8>::new();
16
17    match self {
18      #[cfg(feature = "bool")]
19      Value::Bool(x) => payload.write_u8(if *x.borrow() { 1 } else { 0 })?,
20      #[cfg(feature = "string")]
21      Value::String(x) => {
22        let string_brrw = x.borrow();
23        let bytes = string_brrw.as_bytes();
24        payload.write_u32::<LittleEndian>(bytes.len() as u32)?;
25        payload.extend_from_slice(bytes);
26      },
27      #[cfg(feature = "u8")]
28      Value::U8(x) => payload.write_u8(*x.borrow())?,
29      #[cfg(feature = "u16")]
30      Value::U16(x) => payload.write_u16::<LittleEndian>(*x.borrow())?,
31      #[cfg(feature = "u32")]
32      Value::U32(x) => payload.write_u32::<LittleEndian>(*x.borrow())?,
33      #[cfg(feature = "u64")]
34      Value::U64(x) => payload.write_u64::<LittleEndian>(*x.borrow())?,
35      #[cfg(feature = "u128")]
36      Value::U128(x) => payload.write_u128::<LittleEndian>(*x.borrow())?,
37      #[cfg(feature = "i8")]
38      Value::I8(x) => payload.write_i8(*x.borrow())?,
39      #[cfg(feature = "i16")]
40      Value::I16(x) => payload.write_i16::<LittleEndian>(*x.borrow())?,
41      #[cfg(feature = "i32")]
42      Value::I32(x) => payload.write_i32::<LittleEndian>(*x.borrow())?,
43      #[cfg(feature = "i64")]
44      Value::I64(x) => payload.write_i64::<LittleEndian>(*x.borrow())?,
45      #[cfg(feature = "i128")]
46      Value::I128(x) => payload.write_i128::<LittleEndian>(*x.borrow())?,
47      #[cfg(feature = "f32")]
48      Value::F32(x) => payload.write_f32::<LittleEndian>(x.borrow().0)?,
49      #[cfg(feature = "f64")]
50      Value::F64(x) => payload.write_f64::<LittleEndian>(x.borrow().0)?,
51      #[cfg(feature = "atom")]
52      Value::Atom(x) => payload.write_u64::<LittleEndian>(*x)?,
53      #[cfg(feature = "index")]
54      Value::Index(x) => payload.write_u64::<LittleEndian>(*x.borrow() as u64)?,
55      #[cfg(feature = "complex")]
56      Value::ComplexNumber(x) => {
57        let c = x.borrow();
58        payload.write_f64::<LittleEndian>(c.0.re)?;
59        payload.write_f64::<LittleEndian>(c.0.im)?;
60      },
61      #[cfg(feature = "rational")]
62      Value::RationalNumber(x) => {
63        let r = x.borrow();
64        payload.write_i64::<LittleEndian>(*r.numer())?;
65        payload.write_i64::<LittleEndian>(*r.denom())?;
66      },
67      #[cfg(all(feature = "matrix", feature = "f64"))]
68      Value::MatrixF64(x) => todo!(), //{return x.compile_const(ctx);}
69      _ => todo!(),
70    }
71    ctx.compile_const(&payload, self.kind())
72  }
73}
74
75#[cfg(feature = "compiler")]
76#[cfg(feature = "f64")]
77impl CompileConst for F64 {
78  fn compile_const(&self, ctx: &mut CompileCtx) -> MResult<u32> {
79    let mut payload = Vec::<u8>::new();
80    payload.write_f64::<LittleEndian>(self.0)?;
81    ctx.compile_const(&payload, ValueKind::F64)
82  }
83}
84
85#[cfg(feature = "f32")]
86impl CompileConst for F32 {
87  fn compile_const(&self, ctx: &mut CompileCtx) -> MResult<u32> {
88    let mut payload = Vec::<u8>::new();
89    payload.write_f32::<LittleEndian>(self.0)?;
90    ctx.compile_const(&payload, ValueKind::F32)
91  }
92}
93
94#[cfg(feature = "u8")]
95impl CompileConst for u8 {
96  fn compile_const(&self, ctx: &mut CompileCtx) -> MResult<u32> {
97    let mut payload = Vec::<u8>::new();
98    payload.write_u8(*self)?;
99    ctx.compile_const(&payload, ValueKind::U8)
100  }
101}
102
103#[cfg(feature = "i8")]
104impl CompileConst for i8 {
105  fn compile_const(&self, ctx: &mut CompileCtx) -> MResult<u32> {
106    let mut payload = Vec::<u8>::new();
107    payload.write_i8(*self)?;
108    ctx.compile_const(&payload, ValueKind::I8)
109  }
110}
111
112macro_rules! impl_compile_const {
113  ($feature:literal, $t:tt) => {
114    paste! {
115      #[cfg(feature = $feature)]
116      impl CompileConst for $t {
117        fn compile_const(&self, ctx: &mut CompileCtx) -> MResult<u32> {
118          let mut payload = Vec::<u8>::new();
119          payload.[<write_ $t>]::<LittleEndian>(*self)?;
120          ctx.compile_const(&payload, ValueKind::[<$t:upper>])
121        }
122      }
123    }
124  };
125}
126
127impl_compile_const!("u16", u16);
128impl_compile_const!("u32", u32);
129impl_compile_const!("u64", u64);
130impl_compile_const!("u128", u128);
131impl_compile_const!("i16", i16);
132impl_compile_const!("i32", i32);
133impl_compile_const!("i64", i64);
134impl_compile_const!("i128", i128);
135
136#[cfg(feature = "bool")]
137impl CompileConst for bool {
138  fn compile_const(&self, ctx: &mut CompileCtx) -> MResult<u32> {
139    let mut payload = Vec::<u8>::new();
140    payload.write_u8(if *self { 1 } else { 0 })?;
141    ctx.compile_const(&payload, ValueKind::Bool)
142  }
143}
144
145#[cfg(feature = "string")]
146impl CompileConst for String {
147  fn compile_const(&self, ctx: &mut CompileCtx) -> MResult<u32> {
148    let mut payload = Vec::<u8>::new();
149    payload.write_u32::<LittleEndian>(self.len() as u32)?;
150    payload.extend_from_slice(self.as_bytes());
151    ctx.compile_const(&payload, ValueKind::String)
152  }
153}
154
155#[cfg(feature = "rational")]
156impl CompileConst for RationalNumber {
157  fn compile_const(&self, ctx: &mut CompileCtx) -> MResult<u32> {
158    let mut payload = Vec::<u8>::new();
159    payload.write_i64::<LittleEndian>(*self.numer())?;
160    payload.write_i64::<LittleEndian>(*self.denom())?;
161    ctx.compile_const(&payload, ValueKind::RationalNumber)
162  }
163}
164
165#[cfg(feature = "complex")]
166impl CompileConst for ComplexNumber {
167  fn compile_const(&self, ctx: &mut CompileCtx) -> MResult<u32> {
168    let mut payload = Vec::<u8>::new();
169    payload.write_f64::<LittleEndian>(self.0.re)?;
170    payload.write_f64::<LittleEndian>(self.0.im)?;
171    ctx.compile_const(&payload, ValueKind::ComplexNumber)
172  }
173}
174
175macro_rules! impl_compile_const_matrix {
176  ($matrix_type:ty) => {
177    impl<T> CompileConst for $matrix_type
178    where
179      T: ConstElem,
180    {
181      fn compile_const(&self, ctx: &mut CompileCtx) -> MResult<u32> {
182        let rows = self.nrows() as u32;
183        let cols = self.ncols() as u32;
184        let mut payload = Vec::<u8>::with_capacity((rows * cols) as usize * 8);
185
186        // write header: rows, cols
187        payload.write_u32::<LittleEndian>(rows)?;
188        payload.write_u32::<LittleEndian>(cols)?;
189
190        // write elements column-major
191        for c in 0..cols as usize {
192          for r in 0..rows as usize {
193            self[(r, c)].write_le(&mut payload);
194          }
195        }
196        let elem_vk = T::value_kind();
197        let mat_vk = ValueKind::Matrix(Box::new(elem_vk), vec![rows as usize, cols as usize]);
198        ctx.compile_const(&payload, mat_vk)
199      }
200    }
201  };
202}
203
204#[cfg(feature = "matrix1")]
205impl_compile_const_matrix!(na::Matrix1<T>);
206#[cfg(feature = "matrix2")]
207impl_compile_const_matrix!(na::Matrix2<T>);
208#[cfg(feature = "matrix3")]
209impl_compile_const_matrix!(na::Matrix3<T>);
210#[cfg(feature = "matrix4")]
211impl_compile_const_matrix!(na::Matrix4<T>);
212#[cfg(feature = "matrix2x3")]
213impl_compile_const_matrix!(na::Matrix2x3<T>);
214#[cfg(feature = "matrix3x2")]
215impl_compile_const_matrix!(na::Matrix3x2<T>);
216#[cfg(feature = "row_vector2")]
217impl_compile_const_matrix!(na::RowVector2<T>);
218#[cfg(feature = "row_vector3")]
219impl_compile_const_matrix!(na::RowVector3<T>);
220#[cfg(feature = "row_vector4")]
221impl_compile_const_matrix!(na::RowVector4<T>);
222#[cfg(feature = "vector2")]
223impl_compile_const_matrix!(na::Vector2<T>);
224#[cfg(feature = "vector3")]
225impl_compile_const_matrix!(na::Vector3<T>);
226#[cfg(feature = "vector4")]
227impl_compile_const_matrix!(na::Vector4<T>);
228#[cfg(feature = "matrixd")]
229impl_compile_const_matrix!(na::DMatrix<T>);
230#[cfg(feature = "vectord")]
231impl_compile_const_matrix!(na::DVector<T>);
232#[cfg(feature = "row_vectord")]
233impl_compile_const_matrix!(na::RowDVector<T>);
234
235// ConstElem Trait
236// ----------------------------------------------------------------------------
237
238pub trait ConstElem {
239  fn write_le(&self, out: &mut Vec<u8>);
240  fn value_kind() -> ValueKind;
241  fn align() -> u8 { 1 }
242}
243
244#[cfg(feature = "f64")]
245impl ConstElem for F64 {
246  fn write_le(&self, out: &mut Vec<u8>) {
247    out.write_f64::<LittleEndian>(self.0).expect("write f64");
248  }
249  fn value_kind() -> ValueKind { ValueKind::F64 }
250  fn align() -> u8 { 8 }
251}
252
253#[cfg(feature = "f32")]
254impl ConstElem for F32 {
255  fn write_le(&self, out: &mut Vec<u8>) {
256    out.write_f32::<LittleEndian>(self.0).expect("write f32");
257  }
258  fn value_kind() -> ValueKind { ValueKind::F32 }
259  fn align() -> u8 { 4 }
260} 
261
262macro_rules! impl_const_elem {
263  ($feature:literal, $t:ty, $align:expr) => {
264    paste!{
265      #[cfg(feature = $feature)]
266      impl ConstElem for $t {
267        fn write_le(&self, out: &mut Vec<u8>) {
268          out.[<write_ $t>]::<LittleEndian>(*self).expect(concat!("write ", stringify!($t)));
269        }
270        fn value_kind() -> ValueKind { ValueKind::[<$t:upper>] }
271        fn align() -> u8 { $align }
272      }
273    }
274  };
275}
276
277impl_const_elem!("u16", u16, 2);
278impl_const_elem!("u32", u32, 4);
279impl_const_elem!("u64", u64, 8);
280impl_const_elem!("u128", u128, 16);
281impl_const_elem!("i16", i16, 2);
282impl_const_elem!("i32", i32, 4);
283impl_const_elem!("i64", i64, 8);
284impl_const_elem!("i128", i128, 16);
285
286#[cfg(feature = "u8")]
287impl ConstElem for u8 {
288  fn write_le(&self, out: &mut Vec<u8>) {
289    out.write_u8(*self).expect("write u8");
290  }
291  fn value_kind() -> ValueKind { ValueKind::U8 }
292  fn align() -> u8 { 1 }
293} 
294
295#[cfg(feature = "i8")]
296impl ConstElem for i8 {
297  fn write_le(&self, out: &mut Vec<u8>) {
298    out.write_i8(*self).expect("write i8");
299  }
300  fn value_kind() -> ValueKind { ValueKind::I8 }
301  fn align() -> u8 { 1 }
302}
303
304#[cfg(feature = "rational")]
305impl ConstElem for RationalNumber {
306  fn write_le(&self, out: &mut Vec<u8>) {
307    out.write_i64::<LittleEndian>(*self.numer()).expect("write rational numer");
308    out.write_i64::<LittleEndian>(*self.denom()).expect("write rational denom");
309  }
310  fn value_kind() -> ValueKind { ValueKind::RationalNumber }
311  fn align() -> u8 { 16 }
312}
313
314#[cfg(feature = "complex")]
315impl ConstElem for ComplexNumber {
316  fn write_le(&self, out: &mut Vec<u8>) {
317    out.write_f64::<LittleEndian>(self.0.re).expect("write complex real");
318    out.write_f64::<LittleEndian>(self.0.im).expect("write complex imag");
319  }
320  fn value_kind() -> ValueKind { ValueKind::ComplexNumber }
321  fn align() -> u8 { 16 }
322}
323
324#[cfg(feature = "string")]
325impl ConstElem for String {
326  fn write_le(&self, out: &mut Vec<u8>) {
327    out.write_u32::<LittleEndian>(self.len() as u32).expect("write string length");
328    out.extend_from_slice(self.as_bytes());
329  }
330  fn value_kind() -> ValueKind { ValueKind::String }
331  fn align() -> u8 { 1 }
332}
333
334#[cfg(feature = "bool")]
335impl ConstElem for bool {
336  fn write_le(&self, out: &mut Vec<u8>) {
337    out.write_u8(if *self { 1 } else { 0 }).expect("write bool");
338  }
339  fn value_kind() -> ValueKind { ValueKind::Bool }
340  fn align() -> u8 { 1 }
341}