mech_core/program/compiler/
constants.rs1use crate::*;
2use super::*;
3
4pub 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!(), _ => 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 payload.write_u32::<LittleEndian>(rows)?;
188 payload.write_u32::<LittleEndian>(cols)?;
189
190 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
235pub 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}