1use crate::*;
2use super::*;
3
4#[repr(C)]
20#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
21#[derive(Debug, Clone, Eq, PartialEq)]
22pub struct ByteCodeHeader {
23 pub magic: [u8; 4], pub version: u8, pub mech_ver: u16, pub flags: u16, pub reg_count: u32, pub instr_count: u32, pub feature_count: u32, pub feature_off: u64, pub types_count: u32, pub types_off: u64, pub const_count: u32, pub const_tbl_off: u64, pub const_tbl_len: u64, pub const_blob_off: u64, pub const_blob_len: u64, pub symbols_len: u64, pub symbols_off: u64, pub instr_off: u64, pub instr_len: u64, pub dict_off: u64, pub dict_len: u64, pub reserved: u32, }
53
54impl ByteCodeHeader {
55 pub const HEADER_SIZE: usize = 4 + 1 + 2 + 2 + 4 + 4 + 4 + 8 + 4 + 8 + 4 + 8 + 8 + 8 + 8 + 8 + 8 + 8 + 8 + 8 + 8 + 4; pub fn write_to(&self, w: &mut impl Write) -> MResult<()> {
82 w.write_all(&self.magic)?;
84
85 w.write_u8(self.version)?;
87 w.write_u16::<LittleEndian>(self.mech_ver)?;
88 w.write_u16::<LittleEndian>(self.flags)?;
89
90 w.write_u32::<LittleEndian>(self.reg_count)?;
92 w.write_u32::<LittleEndian>(self.instr_count)?;
93
94 w.write_u32::<LittleEndian>(self.feature_count)?;
96 w.write_u64::<LittleEndian>(self.feature_off)?;
97
98 w.write_u32::<LittleEndian>(self.types_count)?;
100 w.write_u64::<LittleEndian>(self.types_off)?;
101
102 w.write_u32::<LittleEndian>(self.const_count)?;
104 w.write_u64::<LittleEndian>(self.const_tbl_off)?;
105 w.write_u64::<LittleEndian>(self.const_tbl_len)?;
106 w.write_u64::<LittleEndian>(self.const_blob_off)?;
107 w.write_u64::<LittleEndian>(self.const_blob_len)?;
108
109 w.write_u64::<LittleEndian>(self.symbols_len)?;
111 w.write_u64::<LittleEndian>(self.symbols_off)?;
112
113 w.write_u64::<LittleEndian>(self.instr_off)?;
115 w.write_u64::<LittleEndian>(self.instr_len)?;
116
117 w.write_u64::<LittleEndian>(self.dict_off)?;
119 w.write_u64::<LittleEndian>(self.dict_len)?;
120
121 w.write_u32::<LittleEndian>(self.reserved)?;
123 Ok(())
124 }
125
126 pub fn read_from(r: &mut impl Read) -> MResult<Self> {
128 let mut magic = [0u8; 4];
129 r.read_exact(&mut magic)?;
130
131 let version = r.read_u8()?;
132 let mech_ver = r.read_u16::<LittleEndian>()?;
133 let flags = r.read_u16::<LittleEndian>()?;
134
135 let reg_count = r.read_u32::<LittleEndian>()?;
136 let instr_count = r.read_u32::<LittleEndian>()?;
137
138 let feature_count = r.read_u32::<LittleEndian>()?;
139 let feature_off = r.read_u64::<LittleEndian>()?;
140
141 let types_count = r.read_u32::<LittleEndian>()?;
142 let types_off = r.read_u64::<LittleEndian>()?;
143
144 let const_count = r.read_u32::<LittleEndian>()?;
145 let const_tbl_off = r.read_u64::<LittleEndian>()?;
146 let const_tbl_len = r.read_u64::<LittleEndian>()?;
147 let const_blob_off = r.read_u64::<LittleEndian>()?;
148 let const_blob_len = r.read_u64::<LittleEndian>()?;
149
150 let symbols_len = r.read_u64::<LittleEndian>()?;
151 let symbols_off = r.read_u64::<LittleEndian>()?;
152
153 let instr_off = r.read_u64::<LittleEndian>()?;
154 let instr_len = r.read_u64::<LittleEndian>()?;
155
156 let dict_off = r.read_u64::<LittleEndian>()?;
157 let dict_len = r.read_u64::<LittleEndian>()?;
158
159 let reserved = r.read_u32::<LittleEndian>()?;
160
161 Ok(Self {
162 magic,
163 version,
164 mech_ver,
165 flags,
166 reg_count,
167 instr_count,
168 feature_count,
169 feature_off,
170 types_count,
171 types_off,
172 const_count,
173 const_tbl_off,
174 const_tbl_len,
175 const_blob_off,
176 const_blob_len,
177 instr_off,
178 instr_len,
179 symbols_len,
180 symbols_off,
181 dict_off,
182 dict_len,
183 reserved,
184 })
185 }
186
187 pub fn validate_magic(&self, expected: &[u8;4]) -> bool {
189 &self.magic == expected
190 }
191}
192
193#[repr(u16)]
197#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
198pub enum FeatureKind {
199 I8=1, I16, I32, I64, I128,
200 U8, U16, U32, U64, U128,
201
202 F32, F64, C64, R64, Index,
203 String, Bool, Atom, Set, Map,
204
205 Table, Tuple, Record, Enum,
206 VariableDefine, VariableAssign, KindDefine,
207 KindAnnotation, SubscriptRange, SubscriptFormula,
208
209 RangeInclusive, RangeExclusive,
210 DotIndexing, Swizzle, LogicalIndexing,
211 Matrix1, Matrix2, Matrix3, Matrix4, Matrix2x3,
212
213 Matrix3x2, RowVector2, RowVector3, RowVector4,
214 Vector2, Vector3, Vector4, VectorD, MatrixD, RowVectorD,
215
216 HorzCat, VertCat,
217 Compiler, PrettyPrint, Serde,
218 MatMul, Transpose, Dot, Cross, Solve,
219
220 Add, Sub, Mul, Div, Pow, Mod,
221 Neg, OpAssign, LT, LTE, GT,
222
223 GTE, EQ, NEQ, And, Or,
224 Xor, Not, Convert, Assign, Access,
225 Min, Max,
226
227 Union, Intersection, Difference, Complement, Subset,
228 Superset, ProperSubset, ProperSuperset, ElementOf, NotElementOf,
229 SetComprehensions,
230
231 Functions, Formulas,
232 Custom = 0xFFFF,
233}
234
235impl FeatureKind {
236
237 pub fn as_string(&self) -> String {
238 match self {
239 FeatureKind::I8 => "i8".to_string(),
240 FeatureKind::I16 => "i16".to_string(),
241 FeatureKind::I32 => "i32".to_string(),
242 FeatureKind::I64 => "i64".to_string(),
243 FeatureKind::I128 => "i128".to_string(),
244 FeatureKind::U8 => "u8".to_string(),
245 FeatureKind::U16 => "u16".to_string(),
246 FeatureKind::U32 => "u32".to_string(),
247 FeatureKind::U64 => "u64".to_string(),
248 FeatureKind::U128 => "u128".to_string(),
249 FeatureKind::F32 => "f32".to_string(),
250 FeatureKind::F64 => "f64".to_string(),
251 FeatureKind::C64 => "c64".to_string(),
252 FeatureKind::R64 => "r64".to_string(),
253 FeatureKind::Index => "index".to_string(),
254 FeatureKind::String => "string".to_string(),
255 FeatureKind::Bool => "bool".to_string(),
256 FeatureKind::Atom => "atom".to_string(),
257 FeatureKind::Set => "set".to_string(),
258 FeatureKind::Map => "map".to_string(),
259 FeatureKind::Table => "table".to_string(),
260 FeatureKind::Tuple => "tuple".to_string(),
261 FeatureKind::Record => "record".to_string(),
262 FeatureKind::Enum => "enum".to_string(),
263 FeatureKind::VariableDefine => "variable_define".to_string(),
264 FeatureKind::VariableAssign => "variable_assign".to_string(),
265 FeatureKind::KindDefine => "kind_define".to_string(),
266 FeatureKind::KindAnnotation => "kind_annotation".to_string(),
267 FeatureKind::SubscriptRange => "subscript_range".to_string(),
268 FeatureKind::SubscriptFormula => "subscript_formula".to_string(),
269 FeatureKind::RangeInclusive => "range_inclusive".to_string(),
270 FeatureKind::RangeExclusive => "range_exclusive".to_string(),
271 FeatureKind::DotIndexing => "dot_indexing".to_string(),
272 FeatureKind::Swizzle => "swizzle".to_string(),
273 FeatureKind::LogicalIndexing => "logical_indexing".to_string(),
274 FeatureKind::Matrix1 => "matrix1".to_string(),
275 FeatureKind::Matrix2 => "matrix2".to_string(),
276 FeatureKind::Matrix3 => "matrix3".to_string(),
277 FeatureKind::Matrix4 => "matrix4".to_string(),
278 FeatureKind::Matrix2x3 => "matrix2x3".to_string(),
279 FeatureKind::Matrix3x2 => "matrix3x2".to_string(),
280 FeatureKind::RowVector2 => "row_vector2".to_string(),
281 FeatureKind::RowVector3 => "row_vector3".to_string(),
282 FeatureKind::RowVector4 => "row_vector4".to_string(),
283 FeatureKind::Vector2 => "vector2".to_string(),
284 FeatureKind::Vector3 => "vector3".to_string(),
285 FeatureKind::Vector4 => "vector4".to_string(),
286 FeatureKind::VectorD => "vectord".to_string(),
287 FeatureKind::MatrixD => "matrixd".to_string(),
288 FeatureKind::RowVectorD => "row_vectord".to_string(),
289 FeatureKind::HorzCat => "matrix_horzcat".to_string(),
290 FeatureKind::VertCat => "matrix_vertcat".to_string(),
291 FeatureKind::Compiler => "compiler".to_string(),
292 FeatureKind::PrettyPrint => "pretty_print".to_string(),
293 FeatureKind::Serde => "serde".to_string(),
294 FeatureKind::MatMul => "matrix_matmul".to_string(),
295 FeatureKind::Transpose => "matrix_transpose".to_string(),
296 FeatureKind::Dot => "matrix_dot".to_string(),
297 FeatureKind::Solve => "matrix_solve".to_string(),
298 FeatureKind::Cross => "matrix_cross".to_string(),
299 FeatureKind::Add => "math_add".to_string(),
300 FeatureKind::Sub => "math_sub".to_string(),
301 FeatureKind::Mul => "math_mul".to_string(),
302 FeatureKind::Div => "math_div".to_string(),
303 FeatureKind::Pow => "math_pow".to_string(),
304 FeatureKind::Mod => "math_mod".to_string(),
305 FeatureKind::Neg => "math_neg".to_string(),
306 FeatureKind::OpAssign => "math_opassign".to_string(),
307 FeatureKind::LT => "compare_lt".to_string(),
308 FeatureKind::LTE => "compare_lte".to_string(),
309 FeatureKind::GT => "compare_gt".to_string(),
310 FeatureKind::GTE => "compare_gte".to_string(),
311 FeatureKind::EQ => "compare_eq".to_string(),
312 FeatureKind::NEQ => "compare_neq".to_string(),
313 FeatureKind::Min => "compare_min".to_string(),
314 FeatureKind::Max => "compare_max".to_string(),
315 FeatureKind::And => "logic_and".to_string(),
316 FeatureKind::Or => "logic_or".to_string(),
317 FeatureKind::Xor => "logic_xor".to_string(),
318 FeatureKind::Not => "logic_not".to_string(),
319 FeatureKind::Convert => "convert".to_string(),
320 FeatureKind::Assign => "assign".to_string(),
321 FeatureKind::Access => "access".to_string(),
322 FeatureKind::Union => "set_union".to_string(),
323 FeatureKind::Intersection => "set_intersection".to_string(),
324 FeatureKind::Difference => "set_difference".to_string(),
325 FeatureKind::Complement => "set_complement".to_string(),
326 FeatureKind::Subset => "set_subset".to_string(),
327 FeatureKind::Superset => "set_superset".to_string(),
328 FeatureKind::ProperSubset => "set_proper_subset".to_string(),
329 FeatureKind::ProperSuperset => "set_proper_superset".to_string(),
330 FeatureKind::ElementOf => "set_element_of".to_string(),
331 FeatureKind::NotElementOf => "set_not_element_of".to_string(),
332 FeatureKind::SetComprehensions => "set_comprehensions".to_string(),
333 FeatureKind::Functions => "functions".to_string(),
334 FeatureKind::Formulas => "formulas".to_string(),
335 FeatureKind::Custom => "custom".to_string(),
336 }
337 }
338}
339
340#[derive(Debug, Clone, PartialEq, Eq, Hash)]
341pub enum FeatureFlag {
342 Builtin(FeatureKind),
343 Custom(u64),
344}
345
346impl FeatureFlag {
347
348 pub fn as_string(&self) -> String {
349 match self {
350 FeatureFlag::Builtin(f) => f.as_string(),
351 FeatureFlag::Custom(c) => format!("custom({})", c),
352 }
353 }
354}
355
356impl FeatureFlag {
357 pub fn as_u64(&self) -> u64 {
358 match self {
359 FeatureFlag::Builtin(f) => *f as u64,
360 FeatureFlag::Custom(c) => *c,
361 }
362 }
363}
364
365#[repr(u16)]
369#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
370#[derive(Debug, Clone, Copy, Eq, PartialEq)]
371pub enum TypeTag {
372 U8=1, U16, U32, U64, U128, I8, I16, I32, I64, I128,
373 F32, F64, C64, R64, String, Bool, Id, Index, Empty, Any,
374 MatrixU8, MatrixU16, MatrixU32, MatrixU64, MatrixU128,
375 MatrixI8, MatrixI16, MatrixI32, MatrixI64, MatrixI128,
376 MatrixF32, MatrixF64, MatrixC64, MatrixR64, MatrixBool,
377 MatrixString, MatrixIndex,
378 EnumTag, Record, Map, Atom,
379 Table, Tuple, Reference, Set, OptionT, None,
380}
381
382impl TypeTag {
383 pub fn from_u16(tag: u16) -> Option<Self> {
384 match tag {
385 1 => Some(TypeTag::U8), 2 => Some(TypeTag::U16), 3 => Some(TypeTag::U32), 4 => Some(TypeTag::U64), 5 => Some(TypeTag::U128),
386 6 => Some(TypeTag::I8), 7 => Some(TypeTag::I16), 8 => Some(TypeTag::I32), 9 => Some(TypeTag::I64), 10 => Some(TypeTag::I128),
387 11 => Some(TypeTag::F32), 12 => Some(TypeTag::F64), 13 => Some(TypeTag::C64), 14 => Some(TypeTag::R64),
388 15 => Some(TypeTag::String), 16 => Some(TypeTag::Bool), 17 => Some(TypeTag::Id), 18 => Some(TypeTag::Index), 19 => Some(TypeTag::Empty), 20 => Some(TypeTag::Any),
389 21 => Some(TypeTag::MatrixU8), 22 => Some(TypeTag::MatrixU16), 23 => Some(TypeTag::MatrixU32), 24 => Some(TypeTag::MatrixU64), 25 => Some(TypeTag::MatrixU128),
390 26 => Some(TypeTag::MatrixI8), 27 => Some(TypeTag::MatrixI16), 28 => Some(TypeTag::MatrixI32), 29 => Some(TypeTag::MatrixI64), 30 => Some(TypeTag::MatrixI128),
391 31 => Some(TypeTag::MatrixF32), 32 => Some(TypeTag::MatrixF64), 33 => Some(TypeTag::MatrixC64), 34 => Some(TypeTag::MatrixR64), 35 => Some(TypeTag::MatrixBool),
392 36 => Some(TypeTag::MatrixString), 37 => Some(TypeTag::MatrixIndex),
393 38 => Some(TypeTag::EnumTag), 39 => Some(TypeTag::Record), 40 => Some(TypeTag::Map), 41 => Some(TypeTag::Atom),
394 42 => Some(TypeTag::Table), 43 => Some(TypeTag::Tuple), 44 => Some(TypeTag::Reference), 45 => Some(TypeTag::Set), 46 => Some(TypeTag::OptionT), 47 => Some(TypeTag::None),
395 _ => None,
396 }
397 }
398}
399
400#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
401#[derive(Debug, Clone, Eq, PartialEq)]
402pub struct TypeEntry {
403 pub tag: TypeTag,
404 pub bytes: Vec<u8>,
405}
406impl TypeEntry {
407 pub fn byte_len(&self) -> u64 {
408 2 + self.bytes.len() as u64
409 }
410}
411
412pub type TypeId = u32;
413
414#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
415#[derive(Default, Debug, Clone, Eq, PartialEq)]
416pub struct TypeSection {
417 pub interner: HashMap<ValueKind, TypeId>,
418 pub entries: Vec<TypeEntry>, }
420
421impl TypeSection {
422
423 pub fn new() -> Self {
424 Self { interner: HashMap::new(), entries: Vec::new() }
425 }
426
427 pub fn get_or_intern(&mut self, vk: &ValueKind) -> TypeId {
428 if let Some(id) = self.interner.get(vk) { return *id; }
429 let (tag, mut bytes) = encode_value_kind(self, vk);
431 let id = self.entries.len() as u32;
432 self.entries.push(TypeEntry { tag, bytes });
433 self.interner.insert(vk.clone(), id);
434 id
435 }
436
437 pub fn write_to(&self, w: &mut impl Write) -> MResult<()> {
438 w.write_u32::<LittleEndian>(self.entries.len() as u32)?;
439 for e in &self.entries {
440 w.write_u16::<LittleEndian>(e.tag as u16)?;
441 w.write_u16::<LittleEndian>(0)?;
442 w.write_u32::<LittleEndian>(1)?;
443 w.write_u32::<LittleEndian>(e.bytes.len() as u32)?;
444 w.write_all(&e.bytes)?;
445 }
446 Ok(())
447 }
448
449 pub fn byte_len(&self) -> u64 {
450 4 + self.entries.iter().map(|e| 12 + e.bytes.len() as u64).sum::<u64>()
451 }
452}
453
454#[repr(u8)]
458#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
459#[derive(Debug, Clone, Copy, Eq, PartialEq)]
460pub enum ConstEncoding {
461 Inline = 1
462}
463
464#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
465#[derive(Debug, Clone, Eq, PartialEq)]
466pub struct ConstEntry {
467 pub type_id: u32,
468 pub enc: ConstEncoding,
469 pub align: u8,
470 pub flags: u8,
471 pub reserved:u16,
472 pub offset: u64,
473 pub length: u64,
474}
475
476impl ConstEntry {
477 pub fn write_to(&self, w: &mut impl Write) -> MResult<()> {
478 w.write_u32::<LittleEndian>(self.type_id)?;
479 w.write_u8(self.enc as u8)?;
480 w.write_u8(self.align)?;
481 w.write_u8(self.flags)?;
482 w.write_u8(0)?; w.write_u64::<LittleEndian>(self.offset)?;
484 w.write_u64::<LittleEndian>(self.length)?;
485 Ok(())
486 }
487 pub fn byte_len() -> u64 { 4 + 1 + 1 + 1 + 1 + 8 + 8 } }
489
490pub struct SymbolEntry {
494 pub id: u64, pub mutable: bool,
496 pub reg: Register, }
498
499impl SymbolEntry {
500
501 pub fn new(id: u64, mutable: bool, reg: Register) -> Self {
502 Self { id, mutable, reg }
503 }
504
505 pub fn write_to(&self, w: &mut impl Write) -> MResult<()> {
506 w.write_u64::<LittleEndian>(self.id)?;
507 w.write_u8(if self.mutable { 1 } else { 0 })?;
508 w.write_u32::<LittleEndian>(self.reg)?;
509 Ok(())
510 }
511}
512
513#[repr(u8)]
517#[derive(Debug, Clone, Copy, PartialEq, Eq)]
518pub enum OpCode {
519 ConstLoad = 0x01,
520 NullOp = 0x10,
521 Unop = 0x20,
522 Binop = 0x30,
523 Ternop = 0x40,
524 Quadop = 0x50,
525 VarArg = 0x60,
526 Return = 0xFF,
527}
528
529impl std::fmt::Display for OpCode {
530 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
531 let s = match self {
532 OpCode::ConstLoad => "ConstLoad",
533 OpCode::NullOp => "NullOp",
534 OpCode::Unop => "Unop",
535 OpCode::Binop => "Binop",
536 OpCode::Ternop => "Ternop",
537 OpCode::Quadop => "Quadop",
538 OpCode::VarArg => "VarArg",
539 OpCode::Return => "Return",
540 };
541 write!(f, "{}", s)
542 }
543}
544
545impl OpCode {
546 pub fn from_u8(num: u8) -> Option<OpCode> {
547 match num {
548 0x01 => Some(OpCode::ConstLoad),
549 0x10 => Some(OpCode::NullOp),
550 0x20 => Some(OpCode::Unop),
551 0x30 => Some(OpCode::Binop),
552 0x40 => Some(OpCode::Ternop),
553 0x50 => Some(OpCode::Quadop),
554 0x60 => Some(OpCode::VarArg),
555 0xFF => Some(OpCode::Return),
556 _ => None,
557 }
558 }
559}
560
561#[derive(Debug, Clone)]
562pub enum EncodedInstr {
563 ConstLoad { dst: u32, const_id: u32 }, NullOp { fxn_id: u64, dst: u32 }, UnOp { fxn_id: u64, dst: u32, src: u32 }, BinOp { fxn_id: u64, dst: u32, lhs: u32, rhs: u32 }, TernOp { fxn_id: u64, dst: u32, a: u32, b: u32, c: u32 }, QuadOp { fxn_id: u64, dst: u32, a: u32, b: u32, c: u32, d: u32 }, VarArg { fxn_id: u64, dst: u32, args: Vec<u32> }, Ret { src: u32 }, }
572
573impl EncodedInstr {
574 pub fn byte_len(&self) -> u64 {
575 match self {
576 EncodedInstr::ConstLoad{..} => 1 + 4 + 4,
577 EncodedInstr::NullOp{..} => 1 + 8 + 4,
578 EncodedInstr::UnOp{..} => 1 + 8 + 4 + 4,
579 EncodedInstr::BinOp{..} => 1 + 8 + 4 + 4 + 4,
580 EncodedInstr::TernOp{..} => 1 + 8 + 4 + 4 + 4 + 4,
581 EncodedInstr::QuadOp{..} => 1 + 8 + 4 + 4 + 4 + 4 + 4,
582 EncodedInstr::VarArg{ args, .. } => 1 + 8 + 4 + 4 + (4 * args.len() as u64),
583 EncodedInstr::Ret{..} => 1 + 4,
584 }
585 }
586 pub fn write_to(&self, w: &mut impl Write) -> MResult<()> {
587 match self {
588 EncodedInstr::ConstLoad{ dst, const_id } => {
589 w.write_u8(OpCode::ConstLoad as u8)?;
590 w.write_u32::<LittleEndian>(*dst)?;
591 w.write_u32::<LittleEndian>(*const_id)?;
592 }
593 EncodedInstr::NullOp{ fxn_id, dst } => {
594 w.write_u8(OpCode::NullOp as u8)?;
595 w.write_u64::<LittleEndian>(*fxn_id)?;
596 w.write_u32::<LittleEndian>(*dst)?;
597 }
598 EncodedInstr::UnOp{ fxn_id, dst, src } => {
599 w.write_u8(OpCode::Unop as u8)?;
600 w.write_u64::<LittleEndian>(*fxn_id)?;
601 w.write_u32::<LittleEndian>(*dst)?;
602 w.write_u32::<LittleEndian>(*src)?;
603 }
604 EncodedInstr::BinOp{ fxn_id, dst, lhs, rhs } => {
605 w.write_u8(OpCode::Binop as u8)?;
606 w.write_u64::<LittleEndian>(*fxn_id)?;
607 w.write_u32::<LittleEndian>(*dst)?;
608 w.write_u32::<LittleEndian>(*lhs)?;
609 w.write_u32::<LittleEndian>(*rhs)?;
610 }
611 EncodedInstr::TernOp{ fxn_id, dst, a, b, c } => {
612 w.write_u8(OpCode::Ternop as u8)?;
613 w.write_u64::<LittleEndian>(*fxn_id)?;
614 w.write_u32::<LittleEndian>(*dst)?;
615 w.write_u32::<LittleEndian>(*a)?;
616 w.write_u32::<LittleEndian>(*b)?;
617 w.write_u32::<LittleEndian>(*c)?;
618 }
619 EncodedInstr::QuadOp{ fxn_id, dst, a, b, c, d } => {
620 w.write_u8(OpCode::Quadop as u8)?;
621 w.write_u64::<LittleEndian>(*fxn_id)?;
622 w.write_u32::<LittleEndian>(*dst)?;
623 w.write_u32::<LittleEndian>(*a)?;
624 w.write_u32::<LittleEndian>(*b)?;
625 w.write_u32::<LittleEndian>(*c)?;
626 w.write_u32::<LittleEndian>(*d)?;
627 }
628 EncodedInstr::VarArg{ fxn_id, dst, args } => {
629 w.write_u8(OpCode::VarArg as u8)?;
630 w.write_u64::<LittleEndian>(*fxn_id)?;
631 w.write_u32::<LittleEndian>(*dst)?;
632 w.write_u32::<LittleEndian>(args.len() as u32)?;
633 for a in args {
634 w.write_u32::<LittleEndian>(*a)?;
635 }
636 }
637 EncodedInstr::Ret{ src } => {
638 w.write_u8(OpCode::Return as u8)?;
639 w.write_u32::<LittleEndian>(*src)?;
640 }
641 }
642 Ok(())
643 }
644}
645
646#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
650#[derive(Debug, Clone, Eq, PartialEq)]
651pub struct DictEntry {
652 pub id: u64, pub name: String, }
655
656impl DictEntry {
657 pub fn new(id: u64, name: &str) -> Self {
658 Self { id, name: name.to_string() }
659 }
660
661 pub fn write_to(&self, w: &mut impl Write) -> MResult<()> {
662 w.write_u64::<LittleEndian>(self.id)?;
663 let name_bytes = self.name.as_bytes();
664 w.write_u32::<LittleEndian>(name_bytes.len() as u32)?;
665 w.write_all(name_bytes)?;
666 Ok(())
667 }
668}
669
670