Skip to main content

datex_core/global/protocol_structures/
instructions.rs

1use crate::{
2    global::{
3        operators::AssignmentOperator,
4        type_instruction_codes::TypeMutabilityCode,
5    },
6    values::core_values::{
7        decimal::{Decimal, utils::decimal_to_string},
8        endpoint::{Endpoint, EndpointParsingError},
9        integer::Integer,
10    },
11};
12
13use crate::{prelude::*, values::pointer::PointerAddress};
14use binrw::{BinRead, BinWrite};
15use core::{fmt::Display, prelude::rust_2024::*};
16use serde::{Deserialize, Serialize};
17
18#[derive(Clone, Debug, PartialEq)]
19pub enum Instruction {
20    // regular instruction
21    RegularInstruction(RegularInstruction),
22    // Type instruction that yields a type
23    TypeInstruction(TypeInstruction),
24}
25
26impl Display for Instruction {
27    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
28        match self {
29            Instruction::RegularInstruction(instr) => {
30                core::write!(f, "{}", instr)
31            }
32            Instruction::TypeInstruction(instr) => {
33                core::write!(f, "TYPE_INSTRUCTION {}", instr)
34            }
35        }
36    }
37}
38
39impl From<RegularInstruction> for Instruction {
40    fn from(instruction: RegularInstruction) -> Self {
41        Instruction::RegularInstruction(instruction)
42    }
43}
44
45impl From<TypeInstruction> for Instruction {
46    fn from(instruction: TypeInstruction) -> Self {
47        Instruction::TypeInstruction(instruction)
48    }
49}
50
51#[derive(Clone, Debug, PartialEq)]
52pub enum RegularInstruction {
53    // signed integers
54    Int8(Int8Data),
55    Int16(Int16Data),
56    Int32(Int32Data),
57    Int64(Int64Data),
58    Int128(Int128Data),
59
60    // unsigned integers
61    UInt8(UInt8Data),
62    UInt16(UInt16Data),
63    UInt32(UInt32Data),
64    UInt64(UInt64Data),
65    UInt128(UInt128Data),
66
67    // big integers
68    BigInteger(IntegerData),
69
70    // default integer
71    Integer(IntegerData),
72    Range,
73
74    Endpoint(Endpoint),
75
76    DecimalF32(Float32Data),
77    DecimalF64(Float64Data),
78    DecimalAsInt16(FloatAsInt16Data),
79    DecimalAsInt32(FloatAsInt32Data),
80    BigDecimal(DecimalData),
81    // default decimal
82    Decimal(DecimalData),
83
84    RemoteExecution(InstructionBlockData),
85
86    ShortText(ShortTextData),
87    Text(TextData),
88    True,
89    False,
90    Null,
91    Statements(StatementsData),
92    ShortStatements(StatementsData),
93    UnboundedStatements,
94    UnboundedStatementsEnd(bool),
95    List(ListData),
96    ShortList(ListData),
97    Map(MapData),
98    ShortMap(MapData),
99
100    KeyValueDynamic,
101    KeyValueShortText(ShortTextData),
102
103    // binary operator
104    Add,
105    Subtract,
106    Multiply,
107    Divide,
108
109    // unary operator
110    // TODO #432 add missing unary operators
111    UnaryMinus,
112    // TODO #433: Do we need this for op overloading or can we avoid?
113    UnaryPlus,
114    BitwiseNot,
115
116    Apply(ApplyData),
117
118    GetPropertyText(ShortTextData),
119    SetPropertyText(ShortTextData),
120    SetPropertyDynamic,
121
122    GetPropertyIndex(UInt32Data),
123    SetPropertyIndex(UInt32Data),
124    GetPropertyDynamic,
125
126    // comparison operator
127    Is,
128    Matches,
129    StructuralEqual,
130    Equal,
131    NotStructuralEqual,
132    NotEqual,
133
134    // assignment operator
135    AddAssign(SlotAddress),
136    SubtractAssign(SlotAddress),
137    MultiplyAssign(SlotAddress),
138    DivideAssign(SlotAddress),
139
140    CreateRef,
141    CreateRefMut,
142
143    // &ABCDE
144    GetRef(RawFullPointerAddress),
145    GetLocalRef(RawLocalPointerAddress),
146    GetInternalRef(RawInternalPointerAddress),
147
148    // &ABCDE := ...
149    GetOrCreateRef(GetOrCreateRefData),
150    // &mut ABCDE := ...
151    GetOrCreateRefMut(GetOrCreateRefData),
152
153    AllocateSlot(SlotAddress),
154    GetSlot(SlotAddress),
155    DropSlot(SlotAddress),
156    SetSlot(SlotAddress),
157
158    GetInternalSlot(SlotAddress),
159
160    SetReferenceValue(AssignmentOperator),
161    Deref,
162
163    TypedValue,
164    TypeExpression,
165}
166
167impl Display for RegularInstruction {
168    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
169        match self {
170            RegularInstruction::Int8(data) => {
171                core::write!(f, "INT_8 {}", data.0)
172            }
173            RegularInstruction::Int16(data) => {
174                core::write!(f, "INT_16 {}", data.0)
175            }
176            RegularInstruction::Int32(data) => {
177                core::write!(f, "INT_32 {}", data.0)
178            }
179            RegularInstruction::Int64(data) => {
180                core::write!(f, "INT_64 {}", data.0)
181            }
182            RegularInstruction::Int128(data) => {
183                core::write!(f, "INT_128 {}", data.0)
184            }
185
186            RegularInstruction::UInt8(data) => {
187                core::write!(f, "UINT_8 {}", data.0)
188            }
189            RegularInstruction::UInt16(data) => {
190                core::write!(f, "UINT_16 {}", data.0)
191            }
192            RegularInstruction::UInt32(data) => {
193                core::write!(f, "UINT_32 {}", data.0)
194            }
195            RegularInstruction::UInt64(data) => {
196                core::write!(f, "UINT_64 {}", data.0)
197            }
198            RegularInstruction::UInt128(data) => {
199                core::write!(f, "UINT_128 {}", data.0)
200            }
201            RegularInstruction::Range => {
202                core::write!(f, "RANGE regular instruction")
203            }
204            RegularInstruction::Apply(count) => {
205                core::write!(f, "APPLY {}", count.arg_count)
206            }
207            RegularInstruction::BigInteger(data) => {
208                core::write!(f, "BIG_INTEGER {}", data.0)
209            }
210            RegularInstruction::Integer(data) => {
211                core::write!(f, "INTEGER {}", data.0)
212            }
213            RegularInstruction::Endpoint(data) => {
214                core::write!(f, "ENDPOINT {data}")
215            }
216
217            RegularInstruction::DecimalAsInt16(data) => {
218                core::write!(f, "DECIMAL_AS_INT_16 {}", data.0)
219            }
220            RegularInstruction::DecimalAsInt32(data) => {
221                core::write!(f, "DECIMAL_AS_INT_32 {}", data.0)
222            }
223            RegularInstruction::DecimalF32(data) => {
224                core::write!(
225                    f,
226                    "DECIMAL_F32 {}",
227                    decimal_to_string(data.0, false)
228                )
229            }
230            RegularInstruction::DecimalF64(data) => {
231                core::write!(
232                    f,
233                    "DECIMAL_F64 {}",
234                    decimal_to_string(data.0, false)
235                )
236            }
237            RegularInstruction::BigDecimal(data) => {
238                core::write!(f, "DECIMAL_BIG {}", data.0)
239            }
240            RegularInstruction::Decimal(data) => {
241                core::write!(f, "DECIMAL {}", data.0)
242            }
243            RegularInstruction::ShortText(data) => {
244                core::write!(f, "SHORT_TEXT {}", data.0)
245            }
246            RegularInstruction::Text(data) => {
247                core::write!(f, "TEXT {}", data.0)
248            }
249            RegularInstruction::True => core::write!(f, "TRUE"),
250            RegularInstruction::False => core::write!(f, "FALSE"),
251            RegularInstruction::Null => core::write!(f, "NULL"),
252            RegularInstruction::Statements(data) => {
253                core::write!(f, "STATEMENTS {}", data.statements_count)
254            }
255            RegularInstruction::ShortStatements(data) => {
256                core::write!(f, "SHORT_STATEMENTS {}", data.statements_count)
257            }
258            RegularInstruction::UnboundedStatements => {
259                core::write!(f, "UNBOUNDED_STATEMENTS")
260            }
261            RegularInstruction::UnboundedStatementsEnd(_) => {
262                core::write!(f, "STATEMENTS_END")
263            }
264            RegularInstruction::List(data) => {
265                core::write!(f, "LIST {}", data.element_count)
266            }
267            RegularInstruction::ShortList(data) => {
268                core::write!(f, "SHORT_LIST {}", data.element_count)
269            }
270            RegularInstruction::Map(data) => {
271                core::write!(f, "MAP {}", data.element_count)
272            }
273            RegularInstruction::ShortMap(data) => {
274                core::write!(f, "SHORT_MAP {}", data.element_count)
275            }
276            RegularInstruction::KeyValueDynamic => {
277                core::write!(f, "KEY_VALUE_DYNAMIC")
278            }
279            RegularInstruction::KeyValueShortText(data) => {
280                core::write!(f, "KEY_VALUE_SHORT_TEXT {}", data.0)
281            }
282            // operations
283            RegularInstruction::Add => core::write!(f, "ADD"),
284            RegularInstruction::Subtract => core::write!(f, "SUBTRACT"),
285            RegularInstruction::Multiply => core::write!(f, "MULTIPLY"),
286            RegularInstruction::Divide => core::write!(f, "DIVIDE"),
287
288            // equality checks
289            RegularInstruction::StructuralEqual => {
290                core::write!(f, "STRUCTURAL_EQUAL")
291            }
292            RegularInstruction::Equal => core::write!(f, "EQUAL"),
293            RegularInstruction::NotStructuralEqual => {
294                core::write!(f, "NOT_STRUCTURAL_EQUAL")
295            }
296            RegularInstruction::NotEqual => core::write!(f, "NOT_EQUAL"),
297            RegularInstruction::Is => core::write!(f, "IS"),
298            RegularInstruction::Matches => core::write!(f, "MATCHES"),
299
300            RegularInstruction::AllocateSlot(address) => {
301                core::write!(f, "ALLOCATE_SLOT {}", address.0)
302            }
303            RegularInstruction::GetSlot(address) => {
304                core::write!(f, "GET_SLOT {}", address.0)
305            }
306            RegularInstruction::GetInternalSlot(address) => {
307                core::write!(f, "GET_INTERNAL_SLOT {}", address.0)
308            }
309            RegularInstruction::DropSlot(address) => {
310                core::write!(f, "DROP_SLOT {}", address.0)
311            }
312            RegularInstruction::SetSlot(address) => {
313                core::write!(f, "SET_SLOT {}", address.0)
314            }
315            RegularInstruction::SetReferenceValue(operator) => {
316                core::write!(f, "SET_REFERENCE_VALUE ({})", operator)
317            }
318            RegularInstruction::Deref => core::write!(f, "DEREF"),
319            RegularInstruction::GetRef(address) => {
320                core::write!(
321                    f,
322                    "GET_REF [{}:{}]",
323                    address.endpoint().expect("Invalid endpoint"),
324                    hex::encode(address.id)
325                )
326            }
327            RegularInstruction::GetLocalRef(address) => {
328                core::write!(
329                    f,
330                    "GET_LOCAL_REF [origin_id: {}]",
331                    hex::encode(address.id)
332                )
333            }
334            RegularInstruction::GetInternalRef(address) => {
335                core::write!(
336                    f,
337                    "GET_INTERNAL_REF [internal_id: {}]",
338                    hex::encode(address.id)
339                )
340            }
341            RegularInstruction::CreateRef => core::write!(f, "CREATE_REF"),
342            RegularInstruction::CreateRefMut => {
343                core::write!(f, "CREATE_REF_MUT")
344            }
345            RegularInstruction::GetOrCreateRef(data) => {
346                core::write!(
347                    f,
348                    "GET_OR_CREATE_REF [{}, block_size: {}]",
349                    hex::encode(data.address.id),
350                    data.create_block_size
351                )
352            }
353            RegularInstruction::GetOrCreateRefMut(data) => {
354                core::write!(
355                    f,
356                    "GET_OR_CREATE_REF_MUT [{}, block_size: {}]",
357                    hex::encode(data.address.id),
358                    data.create_block_size
359                )
360            }
361            RegularInstruction::RemoteExecution(block) => {
362                core::write!(
363                    f,
364                    "REMOTE_EXECUTION (length: {}, injected_slot_count: {})",
365                    block.length,
366                    block.injected_slot_count
367                )
368            }
369            RegularInstruction::AddAssign(address) => {
370                core::write!(f, "ADD_ASSIGN {}", address.0)
371            }
372            RegularInstruction::SubtractAssign(address) => {
373                core::write!(f, "SUBTRACT_ASSIGN {}", address.0)
374            }
375            RegularInstruction::MultiplyAssign(address) => {
376                core::write!(f, "MULTIPLY_ASSIGN {}", address.0)
377            }
378            RegularInstruction::DivideAssign(address) => {
379                core::write!(f, "DIVIDE_ASSIGN {}", address.0)
380            }
381            RegularInstruction::UnaryMinus => core::write!(f, "-"),
382            RegularInstruction::UnaryPlus => core::write!(f, "+"),
383            RegularInstruction::BitwiseNot => core::write!(f, "BITWISE_NOT"),
384            RegularInstruction::TypedValue => core::write!(f, "TYPED_VALUE"),
385            RegularInstruction::TypeExpression => {
386                core::write!(f, "TYPE_EXPRESSION")
387            }
388            RegularInstruction::GetPropertyIndex(uint_32_data) => {
389                core::write!(f, "GET_PROPERTY_INDEX {}", uint_32_data.0)
390            }
391            RegularInstruction::SetPropertyIndex(uint_32_data) => {
392                core::write!(f, "SET_PROPERTY_INDEX {}", uint_32_data.0)
393            }
394            RegularInstruction::GetPropertyText(short_text_data) => {
395                core::write!(f, "GET_PROPERTY_TEXT {}", short_text_data.0)
396            }
397            RegularInstruction::SetPropertyText(short_text_data) => {
398                core::write!(f, "SET_PROPERTY_TEXT {}", short_text_data.0)
399            }
400            RegularInstruction::GetPropertyDynamic => {
401                core::write!(f, "GET_PROPERTY_DYNAMIC")
402            }
403            RegularInstruction::SetPropertyDynamic => {
404                core::write!(f, "SET_PROPERTY_DYNAMIC")
405            }
406        }
407    }
408}
409
410#[derive(Clone, Debug, PartialEq)]
411pub enum TypeInstruction {
412    ImplType(ImplTypeData),
413    TypeReference(TypeReferenceData),
414    LiteralText(TextData),
415    LiteralInteger(IntegerData),
416    List(ListData),
417    Range, // TODO #670: add more type instructions
418}
419
420impl Display for TypeInstruction {
421    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
422        match self {
423            TypeInstruction::LiteralText(data) => {
424                core::write!(f, "LITERAL_TEXT {}", data.0)
425            }
426            TypeInstruction::LiteralInteger(data) => {
427                core::write!(f, "LITERAL_INTEGER {}", data.0)
428            }
429            TypeInstruction::List(data) => {
430                core::write!(f, "LIST {}", data.element_count)
431            }
432            TypeInstruction::TypeReference(reference_data) => {
433                core::write!(
434                    f,
435                    "TYPE_REFERENCE mutability: {}, address: {}",
436                    reference_data.metadata.mutability,
437                    PointerAddress::from(&reference_data.address)
438                )
439            }
440            TypeInstruction::ImplType(data) => {
441                core::write!(f, "IMPL_TYPE ({} impls)", data.impl_count)
442            }
443            TypeInstruction::Range => {
444                core::write!(f, "Range type instruction")
445            }
446        }
447    }
448}
449
450#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
451#[brw(little)]
452pub struct Int8Data(pub i8);
453
454#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
455#[brw(little)]
456pub struct Int16Data(pub i16);
457
458#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
459#[brw(little)]
460pub struct Int32Data(pub i32);
461
462#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
463#[brw(little)]
464pub struct Int64Data(pub i64);
465
466#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
467#[brw(little)]
468pub struct Int128Data(pub i128);
469
470#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
471#[brw(little)]
472pub struct UInt8Data(pub u8);
473
474#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
475#[brw(little)]
476pub struct UInt16Data(pub u16);
477
478#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
479#[brw(little)]
480pub struct UInt32Data(pub u32);
481
482#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
483#[brw(little)]
484pub struct UInt64Data(pub u64);
485
486#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
487#[brw(little)]
488pub struct UInt128Data(pub u128);
489
490#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
491#[brw(little)]
492pub struct Float32Data(pub f32);
493
494#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
495#[brw(little)]
496pub struct Float64Data(pub f64);
497
498#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
499#[brw(little)]
500pub struct FloatAsInt16Data(pub i16);
501
502#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
503#[brw(little)]
504pub struct FloatAsInt32Data(pub i32);
505
506#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
507#[brw(little)]
508pub struct DecimalData(pub Decimal);
509
510#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
511#[brw(little)]
512pub struct IntegerData(pub Integer);
513
514#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
515#[brw(little)]
516pub struct ShortTextDataRaw {
517    pub length: u8,
518    #[br(count = length)]
519    pub text: Vec<u8>,
520}
521
522#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
523#[brw(little)]
524pub struct TextDataRaw {
525    pub length: u32,
526    #[br(count = length)]
527    pub text: Vec<u8>,
528}
529
530#[derive(Clone, Debug, PartialEq)]
531pub struct ShortTextData(pub String);
532
533#[derive(Clone, Debug, PartialEq)]
534pub struct TextData(pub String);
535
536#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
537#[brw(little)]
538pub struct ShortListData {
539    pub element_count: u8,
540}
541
542#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
543#[brw(little)]
544pub struct StatementsData {
545    pub statements_count: u32,
546    #[br(map = |x: u8| x != 0)]
547    #[bw(map = |b: &bool| if *b { 1u8 } else { 0u8 })]
548    pub terminated: bool,
549}
550
551#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
552#[brw(little)]
553pub struct UnboundedStatementsData {
554    #[br(map = |x: u8| x != 0)]
555    #[bw(map = |b: &bool| if *b { 1u8 } else { 0u8 })]
556    pub terminated: bool,
557}
558
559#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
560#[brw(little)]
561pub struct ShortStatementsData {
562    pub statements_count: u8,
563    #[br(map = |x: u8| x != 0)]
564    #[bw(map = |b: &bool| if *b { 1u8 } else { 0u8 })]
565    pub terminated: bool,
566}
567
568#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
569#[brw(little)]
570pub struct ListData {
571    pub element_count: u32,
572}
573
574#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
575#[brw(little)]
576pub struct ShortMapData {
577    pub element_count: u8,
578}
579
580#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
581#[brw(little)]
582pub struct MapData {
583    pub element_count: u32,
584}
585
586#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
587#[brw(little)]
588pub struct InstructionCloseAndStore {
589    pub instruction: Int8Data,
590}
591
592#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
593#[brw(little)]
594pub struct SlotAddress(pub u32);
595
596#[derive(
597    BinRead, BinWrite, Clone, Debug, PartialEq, Serialize, Deserialize,
598)]
599#[brw(little)]
600pub struct RawFullPointerAddress {
601    pub id: [u8; 26],
602}
603impl RawFullPointerAddress {
604    pub fn endpoint(&self) -> Result<Endpoint, EndpointParsingError> {
605        let mut endpoint = [0u8; 21];
606        endpoint.copy_from_slice(&self.id[0..21]);
607        Endpoint::from_slice(endpoint)
608    }
609}
610
611#[derive(Debug, Clone, PartialEq)]
612pub struct PointerAddressConversionError;
613
614impl TryFrom<PointerAddress> for RawFullPointerAddress {
615    type Error = PointerAddressConversionError;
616    fn try_from(ptr: PointerAddress) -> Result<Self, Self::Error> {
617        match ptr {
618            PointerAddress::Remote(bytes) => {
619                Ok(RawFullPointerAddress { id: bytes })
620            }
621            _ => Err(PointerAddressConversionError),
622        }
623    }
624}
625
626#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
627#[brw(little)]
628pub struct RawLocalPointerAddress {
629    pub id: [u8; 5],
630}
631
632#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
633#[brw(little)]
634pub struct RawInternalPointerAddress {
635    pub id: [u8; 3],
636}
637
638#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
639#[brw(little)]
640pub enum RawPointerAddress {
641    #[br(magic = 120u8)] // InstructionCode::GET_REF
642    Full(RawFullPointerAddress),
643    #[br(magic = 121u8)] // InstructionCode::GET_INTERNAL_REF
644    Internal(RawInternalPointerAddress),
645    #[br(magic = 122u8)] // InstructionCode::GET_LOCAL_REF
646    Local(RawLocalPointerAddress),
647}
648
649#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
650#[brw(little)]
651pub struct GetOrCreateRefData {
652    pub address: RawFullPointerAddress,
653    pub create_block_size: u64,
654}
655
656#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
657#[brw(little)]
658pub struct InstructionBlockData {
659    pub length: u32,
660    pub injected_slot_count: u32,
661    #[br(count = injected_slot_count)]
662    pub injected_slots: Vec<u32>,
663    #[br(count = length)]
664    pub body: Vec<u8>,
665}
666
667#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
668#[brw(little)]
669pub struct ApplyData {
670    pub arg_count: u16,
671}
672
673#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
674#[brw(little)]
675pub struct ImplTypeData {
676    pub metadata: TypeMetadata,
677    pub impl_count: u8,
678    #[br(count = impl_count)]
679    pub impls: Vec<RawPointerAddress>,
680}
681
682#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
683#[brw(little)]
684pub struct TypeReferenceData {
685    pub metadata: TypeMetadata,
686    pub address: RawPointerAddress,
687}
688
689#[derive(BinRead, BinWrite, Clone, Debug, PartialEq)]
690#[brw(little)]
691pub struct TypeMetadata {
692    pub mutability: TypeMutabilityCode,
693}