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, Exp, Mod,
221 Neg, OpAssign, LT, LTE, GT,
222
223 GTE, EQ, NEQ, And, Or,
224 Xor, Not, Convert, Assign, Access,
225
226 Union, Intersection, Difference, Complement, Subset,
227 Superset, ProperSubset, ProperSuperset, ElementOf, NotElementOf,
228
229 Functions, Formulas,
230 Custom = 0xFFFF,
231}
232
233impl FeatureKind {
234
235 pub fn as_string(&self) -> String {
236 match self {
237 FeatureKind::I8 => "i8".to_string(),
238 FeatureKind::I16 => "i16".to_string(),
239 FeatureKind::I32 => "i32".to_string(),
240 FeatureKind::I64 => "i64".to_string(),
241 FeatureKind::I128 => "i128".to_string(),
242 FeatureKind::U8 => "u8".to_string(),
243 FeatureKind::U16 => "u16".to_string(),
244 FeatureKind::U32 => "u32".to_string(),
245 FeatureKind::U64 => "u64".to_string(),
246 FeatureKind::U128 => "u128".to_string(),
247 FeatureKind::F32 => "f32".to_string(),
248 FeatureKind::F64 => "f64".to_string(),
249 FeatureKind::C64 => "c64".to_string(),
250 FeatureKind::R64 => "r64".to_string(),
251 FeatureKind::Index => "index".to_string(),
252 FeatureKind::String => "string".to_string(),
253 FeatureKind::Bool => "bool".to_string(),
254 FeatureKind::Atom => "atom".to_string(),
255 FeatureKind::Set => "set".to_string(),
256 FeatureKind::Map => "map".to_string(),
257 FeatureKind::Table => "table".to_string(),
258 FeatureKind::Tuple => "tuple".to_string(),
259 FeatureKind::Record => "record".to_string(),
260 FeatureKind::Enum => "enum".to_string(),
261 FeatureKind::VariableDefine => "variable_define".to_string(),
262 FeatureKind::VariableAssign => "variable_assign".to_string(),
263 FeatureKind::KindDefine => "kind_define".to_string(),
264 FeatureKind::KindAnnotation => "kind_annotation".to_string(),
265 FeatureKind::SubscriptRange => "subscript_range".to_string(),
266 FeatureKind::SubscriptFormula => "subscript_formula".to_string(),
267 FeatureKind::RangeInclusive => "range_inclusive".to_string(),
268 FeatureKind::RangeExclusive => "range_exclusive".to_string(),
269 FeatureKind::DotIndexing => "dot_indexing".to_string(),
270 FeatureKind::Swizzle => "swizzle".to_string(),
271 FeatureKind::LogicalIndexing => "logical_indexing".to_string(),
272 FeatureKind::Matrix1 => "matrix1".to_string(),
273 FeatureKind::Matrix2 => "matrix2".to_string(),
274 FeatureKind::Matrix3 => "matrix3".to_string(),
275 FeatureKind::Matrix4 => "matrix4".to_string(),
276 FeatureKind::Matrix2x3 => "matrix2x3".to_string(),
277 FeatureKind::Matrix3x2 => "matrix3x2".to_string(),
278 FeatureKind::RowVector2 => "row_vector2".to_string(),
279 FeatureKind::RowVector3 => "row_vector3".to_string(),
280 FeatureKind::RowVector4 => "row_vector4".to_string(),
281 FeatureKind::Vector2 => "vector2".to_string(),
282 FeatureKind::Vector3 => "vector3".to_string(),
283 FeatureKind::Vector4 => "vector4".to_string(),
284 FeatureKind::VectorD => "vectord".to_string(),
285 FeatureKind::MatrixD => "matrixd".to_string(),
286 FeatureKind::RowVectorD => "row_vectord".to_string(),
287 FeatureKind::HorzCat => "matrix_horzcat".to_string(),
288 FeatureKind::VertCat => "matrix_vertcat".to_string(),
289 FeatureKind::Compiler => "compiler".to_string(),
290 FeatureKind::PrettyPrint => "pretty_print".to_string(),
291 FeatureKind::Serde => "serde".to_string(),
292 FeatureKind::MatMul => "matrix_matmul".to_string(),
293 FeatureKind::Transpose => "matrix_transpose".to_string(),
294 FeatureKind::Dot => "matrix_dot".to_string(),
295 FeatureKind::Solve => "matrix_solve".to_string(),
296 FeatureKind::Cross => "matrix_cross".to_string(),
297 FeatureKind::Add => "math_add".to_string(),
298 FeatureKind::Sub => "math_sub".to_string(),
299 FeatureKind::Mul => "math_mul".to_string(),
300 FeatureKind::Div => "math_div".to_string(),
301 FeatureKind::Exp => "math_exp".to_string(),
302 FeatureKind::Mod => "math_mod".to_string(),
303 FeatureKind::Neg => "math_neg".to_string(),
304 FeatureKind::OpAssign => "math_opassign".to_string(),
305 FeatureKind::LT => "compare_lt".to_string(),
306 FeatureKind::LTE => "compare_lte".to_string(),
307 FeatureKind::GT => "compare_gt".to_string(),
308 FeatureKind::GTE => "compare_gte".to_string(),
309 FeatureKind::EQ => "compare_eq".to_string(),
310 FeatureKind::NEQ => "compare_neq".to_string(),
311 FeatureKind::And => "logic_and".to_string(),
312 FeatureKind::Or => "logic_or".to_string(),
313 FeatureKind::Xor => "logic_xor".to_string(),
314 FeatureKind::Not => "logic_not".to_string(),
315 FeatureKind::Convert => "convert".to_string(),
316 FeatureKind::Assign => "assign".to_string(),
317 FeatureKind::Access => "access".to_string(),
318 FeatureKind::Union => "set_union".to_string(),
319 FeatureKind::Intersection => "set_intersection".to_string(),
320 FeatureKind::Difference => "set_difference".to_string(),
321 FeatureKind::Complement => "set_complement".to_string(),
322 FeatureKind::Subset => "set_subset".to_string(),
323 FeatureKind::Superset => "set_superset".to_string(),
324 FeatureKind::ProperSubset => "set_proper_subset".to_string(),
325 FeatureKind::ProperSuperset => "set_proper_superset".to_string(),
326 FeatureKind::ElementOf => "set_element_of".to_string(),
327 FeatureKind::NotElementOf => "set_not_element_of".to_string(),
328 FeatureKind::Functions => "functions".to_string(),
329 FeatureKind::Formulas => "formulas".to_string(),
330 FeatureKind::Custom => "custom".to_string(),
331 }
332 }
333}
334
335#[derive(Debug, Clone, PartialEq, Eq, Hash)]
336pub enum FeatureFlag {
337 Builtin(FeatureKind),
338 Custom(u64),
339}
340
341impl FeatureFlag {
342
343 pub fn as_string(&self) -> String {
344 match self {
345 FeatureFlag::Builtin(f) => f.as_string(),
346 FeatureFlag::Custom(c) => format!("custom({})", c),
347 }
348 }
349}
350
351impl FeatureFlag {
352 pub fn as_u64(&self) -> u64 {
353 match self {
354 FeatureFlag::Builtin(f) => *f as u64,
355 FeatureFlag::Custom(c) => *c,
356 }
357 }
358}
359
360#[repr(u16)]
364#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
365#[derive(Debug, Clone, Copy, Eq, PartialEq)]
366pub enum TypeTag {
367 U8=1, U16, U32, U64, U128, I8, I16, I32, I64, I128,
368 F32, F64, C64, R64, String, Bool, Id, Index, Empty, Any,
369 MatrixU8, MatrixU16, MatrixU32, MatrixU64, MatrixU128,
370 MatrixI8, MatrixI16, MatrixI32, MatrixI64, MatrixI128,
371 MatrixF32, MatrixF64, MatrixC64, MatrixR64, MatrixBool,
372 MatrixString, MatrixIndex,
373 EnumTag, Record, Map, Atom,
374 Table, Tuple, Reference, Set, OptionT, None,
375}
376
377impl TypeTag {
378 pub fn from_u16(tag: u16) -> Option<Self> {
379 match tag {
380 1 => Some(TypeTag::U8), 2 => Some(TypeTag::U16), 3 => Some(TypeTag::U32), 4 => Some(TypeTag::U64), 5 => Some(TypeTag::U128),
381 6 => Some(TypeTag::I8), 7 => Some(TypeTag::I16), 8 => Some(TypeTag::I32), 9 => Some(TypeTag::I64), 10 => Some(TypeTag::I128),
382 11 => Some(TypeTag::F32), 12 => Some(TypeTag::F64), 13 => Some(TypeTag::C64), 14 => Some(TypeTag::R64),
383 15 => Some(TypeTag::String), 16 => Some(TypeTag::Bool), 17 => Some(TypeTag::Id), 18 => Some(TypeTag::Index), 19 => Some(TypeTag::Empty), 20 => Some(TypeTag::Any),
384 21 => Some(TypeTag::MatrixU8), 22 => Some(TypeTag::MatrixU16), 23 => Some(TypeTag::MatrixU32), 24 => Some(TypeTag::MatrixU64), 25 => Some(TypeTag::MatrixU128),
385 26 => Some(TypeTag::MatrixI8), 27 => Some(TypeTag::MatrixI16), 28 => Some(TypeTag::MatrixI32), 29 => Some(TypeTag::MatrixI64), 30 => Some(TypeTag::MatrixI128),
386 31 => Some(TypeTag::MatrixF32), 32 => Some(TypeTag::MatrixF64), 33 => Some(TypeTag::MatrixC64), 34 => Some(TypeTag::MatrixR64), 35 => Some(TypeTag::MatrixBool),
387 36 => Some(TypeTag::MatrixString), 37 => Some(TypeTag::MatrixIndex),
388 38 => Some(TypeTag::EnumTag), 39 => Some(TypeTag::Record), 40 => Some(TypeTag::Map), 41 => Some(TypeTag::Atom),
389 42 => Some(TypeTag::Table), 43 => Some(TypeTag::Tuple), 44 => Some(TypeTag::Reference), 45 => Some(TypeTag::Set), 46 => Some(TypeTag::OptionT), 47 => Some(TypeTag::None),
390 _ => None,
391 }
392 }
393}
394
395#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
396#[derive(Debug, Clone, Eq, PartialEq)]
397pub struct TypeEntry {
398 pub tag: TypeTag,
399 pub bytes: Vec<u8>,
400}
401impl TypeEntry {
402 pub fn byte_len(&self) -> u64 {
403 2 + self.bytes.len() as u64
404 }
405}
406
407pub type TypeId = u32;
408
409#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
410#[derive(Default, Debug, Clone, Eq, PartialEq)]
411pub struct TypeSection {
412 pub interner: HashMap<ValueKind, TypeId>,
413 pub entries: Vec<TypeEntry>, }
415
416impl TypeSection {
417
418 pub fn new() -> Self {
419 Self { interner: HashMap::new(), entries: Vec::new() }
420 }
421
422 pub fn get_or_intern(&mut self, vk: &ValueKind) -> TypeId {
423 if let Some(id) = self.interner.get(vk) { return *id; }
424 let (tag, mut bytes) = encode_value_kind(self, vk);
426 let id = self.entries.len() as u32;
427 self.entries.push(TypeEntry { tag, bytes });
428 self.interner.insert(vk.clone(), id);
429 id
430 }
431
432 pub fn write_to(&self, w: &mut impl Write) -> MResult<()> {
433 w.write_u32::<LittleEndian>(self.entries.len() as u32)?;
434 for e in &self.entries {
435 w.write_u16::<LittleEndian>(e.tag as u16)?;
436 w.write_u16::<LittleEndian>(0)?;
437 w.write_u32::<LittleEndian>(1)?;
438 w.write_u32::<LittleEndian>(e.bytes.len() as u32)?;
439 w.write_all(&e.bytes)?;
440 }
441 Ok(())
442 }
443
444 pub fn byte_len(&self) -> u64 {
445 4 + self.entries.iter().map(|e| 12 + e.bytes.len() as u64).sum::<u64>()
446 }
447}
448
449#[repr(u8)]
453#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
454#[derive(Debug, Clone, Copy, Eq, PartialEq)]
455pub enum ConstEncoding {
456 Inline = 1
457}
458
459#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
460#[derive(Debug, Clone, Eq, PartialEq)]
461pub struct ConstEntry {
462 pub type_id: u32,
463 pub enc: ConstEncoding,
464 pub align: u8,
465 pub flags: u8,
466 pub reserved:u16,
467 pub offset: u64,
468 pub length: u64,
469}
470
471impl ConstEntry {
472 pub fn write_to(&self, w: &mut impl Write) -> MResult<()> {
473 w.write_u32::<LittleEndian>(self.type_id)?;
474 w.write_u8(self.enc as u8)?;
475 w.write_u8(self.align)?;
476 w.write_u8(self.flags)?;
477 w.write_u8(0)?; w.write_u64::<LittleEndian>(self.offset)?;
479 w.write_u64::<LittleEndian>(self.length)?;
480 Ok(())
481 }
482 pub fn byte_len() -> u64 { 4 + 1 + 1 + 1 + 1 + 8 + 8 } }
484
485pub struct SymbolEntry {
489 pub id: u64, pub mutable: bool,
491 pub reg: Register, }
493
494impl SymbolEntry {
495
496 pub fn new(id: u64, mutable: bool, reg: Register) -> Self {
497 Self { id, mutable, reg }
498 }
499
500 pub fn write_to(&self, w: &mut impl Write) -> MResult<()> {
501 w.write_u64::<LittleEndian>(self.id)?;
502 w.write_u8(if self.mutable { 1 } else { 0 })?;
503 w.write_u32::<LittleEndian>(self.reg)?;
504 Ok(())
505 }
506}
507
508#[repr(u8)]
512#[derive(Debug, Clone, Copy, PartialEq, Eq)]
513pub enum OpCode {
514 ConstLoad = 0x01,
515 NullOp = 0x10,
516 Unop = 0x20,
517 Binop = 0x30,
518 Ternop = 0x40,
519 Quadop = 0x50,
520 VarArg = 0x60,
521 Return = 0xFF,
522}
523
524impl std::fmt::Display for OpCode {
525 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
526 let s = match self {
527 OpCode::ConstLoad => "ConstLoad",
528 OpCode::NullOp => "NullOp",
529 OpCode::Unop => "Unop",
530 OpCode::Binop => "Binop",
531 OpCode::Ternop => "Ternop",
532 OpCode::Quadop => "Quadop",
533 OpCode::VarArg => "VarArg",
534 OpCode::Return => "Return",
535 };
536 write!(f, "{}", s)
537 }
538}
539
540impl OpCode {
541 pub fn from_u8(num: u8) -> Option<OpCode> {
542 match num {
543 0x01 => Some(OpCode::ConstLoad),
544 0x10 => Some(OpCode::NullOp),
545 0x20 => Some(OpCode::Unop),
546 0x30 => Some(OpCode::Binop),
547 0x40 => Some(OpCode::Ternop),
548 0x50 => Some(OpCode::Quadop),
549 0x60 => Some(OpCode::VarArg),
550 0xFF => Some(OpCode::Return),
551 _ => None,
552 }
553 }
554}
555
556#[derive(Debug, Clone)]
557pub enum EncodedInstr {
558 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 }, }
567
568impl EncodedInstr {
569 pub fn byte_len(&self) -> u64 {
570 match self {
571 EncodedInstr::ConstLoad{..} => 1 + 4 + 4,
572 EncodedInstr::NullOp{..} => 1 + 8 + 4,
573 EncodedInstr::UnOp{..} => 1 + 8 + 4 + 4,
574 EncodedInstr::BinOp{..} => 1 + 8 + 4 + 4 + 4,
575 EncodedInstr::TernOp{..} => 1 + 8 + 4 + 4 + 4 + 4,
576 EncodedInstr::QuadOp{..} => 1 + 8 + 4 + 4 + 4 + 4 + 4,
577 EncodedInstr::VarArg{ args, .. } => 1 + 8 + 4 + 4 + (4 * args.len() as u64),
578 EncodedInstr::Ret{..} => 1 + 4,
579 }
580 }
581 pub fn write_to(&self, w: &mut impl Write) -> MResult<()> {
582 match self {
583 EncodedInstr::ConstLoad{ dst, const_id } => {
584 w.write_u8(OpCode::ConstLoad as u8)?;
585 w.write_u32::<LittleEndian>(*dst)?;
586 w.write_u32::<LittleEndian>(*const_id)?;
587 }
588 EncodedInstr::NullOp{ fxn_id, dst } => {
589 w.write_u8(OpCode::NullOp as u8)?;
590 w.write_u64::<LittleEndian>(*fxn_id)?;
591 w.write_u32::<LittleEndian>(*dst)?;
592 }
593 EncodedInstr::UnOp{ fxn_id, dst, src } => {
594 w.write_u8(OpCode::Unop as u8)?;
595 w.write_u64::<LittleEndian>(*fxn_id)?;
596 w.write_u32::<LittleEndian>(*dst)?;
597 w.write_u32::<LittleEndian>(*src)?;
598 }
599 EncodedInstr::BinOp{ fxn_id, dst, lhs, rhs } => {
600 w.write_u8(OpCode::Binop as u8)?;
601 w.write_u64::<LittleEndian>(*fxn_id)?;
602 w.write_u32::<LittleEndian>(*dst)?;
603 w.write_u32::<LittleEndian>(*lhs)?;
604 w.write_u32::<LittleEndian>(*rhs)?;
605 }
606 EncodedInstr::TernOp{ fxn_id, dst, a, b, c } => {
607 w.write_u8(OpCode::Ternop as u8)?;
608 w.write_u64::<LittleEndian>(*fxn_id)?;
609 w.write_u32::<LittleEndian>(*dst)?;
610 w.write_u32::<LittleEndian>(*a)?;
611 w.write_u32::<LittleEndian>(*b)?;
612 w.write_u32::<LittleEndian>(*c)?;
613 }
614 EncodedInstr::QuadOp{ fxn_id, dst, a, b, c, d } => {
615 w.write_u8(OpCode::Quadop as u8)?;
616 w.write_u64::<LittleEndian>(*fxn_id)?;
617 w.write_u32::<LittleEndian>(*dst)?;
618 w.write_u32::<LittleEndian>(*a)?;
619 w.write_u32::<LittleEndian>(*b)?;
620 w.write_u32::<LittleEndian>(*c)?;
621 w.write_u32::<LittleEndian>(*d)?;
622 }
623 EncodedInstr::VarArg{ fxn_id, dst, args } => {
624 w.write_u8(OpCode::VarArg as u8)?;
625 w.write_u64::<LittleEndian>(*fxn_id)?;
626 w.write_u32::<LittleEndian>(*dst)?;
627 w.write_u32::<LittleEndian>(args.len() as u32)?;
628 for a in args {
629 w.write_u32::<LittleEndian>(*a)?;
630 }
631 }
632 EncodedInstr::Ret{ src } => {
633 w.write_u8(OpCode::Return as u8)?;
634 w.write_u32::<LittleEndian>(*src)?;
635 }
636 }
637 Ok(())
638 }
639}
640
641#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
645#[derive(Debug, Clone, Eq, PartialEq)]
646pub struct DictEntry {
647 pub id: u64, pub name: String, }
650
651impl DictEntry {
652 pub fn new(id: u64, name: &str) -> Self {
653 Self { id, name: name.to_string() }
654 }
655
656 pub fn write_to(&self, w: &mut impl Write) -> MResult<()> {
657 w.write_u64::<LittleEndian>(self.id)?;
658 let name_bytes = self.name.as_bytes();
659 w.write_u32::<LittleEndian>(name_bytes.len() as u32)?;
660 w.write_all(name_bytes)?;
661 Ok(())
662 }
663}
664
665