datex_core/global/protocol_structures/
instructions.rs

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