datex_core/compiler/
context.rs1use crate::collections::HashMap;
2use crate::core_compiler::value_compiler::append_instruction_code;
3use crate::core_compiler::value_compiler::append_value_container;
4use crate::global::instruction_codes::InstructionCode;
5use crate::runtime::execution::context::ExecutionMode;
6use crate::utils::buffers::append_u32;
7use crate::values::value_container::ValueContainer;
8use core::cmp::PartialEq;
9use itertools::Itertools;
10
11#[derive(Debug, Clone, Default, Copy, PartialEq, Eq, Hash)]
12pub struct VirtualSlot {
13 pub level: u8, pub virtual_address: u32,
16}
17
18impl VirtualSlot {
19 pub fn local(virtual_address: u32) -> Self {
20 VirtualSlot {
21 level: 0,
22 virtual_address,
23 }
24 }
25 pub fn is_external(&self) -> bool {
26 self.level > 0
27 }
28
29 pub fn external(level: u8, virtual_address: u32) -> Self {
30 VirtualSlot {
31 level,
32 virtual_address,
33 }
34 }
35
36 pub fn downgrade(&self) -> Self {
37 VirtualSlot {
38 level: self.level + 1,
39 virtual_address: self.virtual_address,
40 }
41 }
42
43 pub fn upgrade(&self) -> Self {
44 if self.level > 0 {
45 VirtualSlot {
46 level: self.level - 1,
47 virtual_address: self.virtual_address,
48 }
49 } else {
50 core::panic!("Cannot upgrade a local slot");
51 }
52 }
53}
54
55pub struct CompilationContext {
57 pub inserted_value_index: usize,
58 pub buffer: Vec<u8>,
59 pub inserted_values: Vec<ValueContainer>,
60 pub has_non_static_value: bool,
62 pub execution_mode: ExecutionMode,
63
64 slot_indices: HashMap<VirtualSlot, Vec<u32>>,
66}
67
68impl CompilationContext {
69 const MAX_INT_32: i64 = 2_147_483_647;
70 const MIN_INT_32: i64 = -2_147_483_648;
71
72 const MAX_INT_8: i64 = 127;
73 const MIN_INT_8: i64 = -128;
74
75 const MAX_INT_16: i64 = 32_767;
76 const MIN_INT_16: i64 = -32_768;
77
78 const MAX_UINT_16: i64 = 65_535;
79
80 const INT_8_BYTES: u8 = 1;
81 const INT_16_BYTES: u8 = 2;
82 const INT_32_BYTES: u8 = 4;
83 const INT_64_BYTES: u8 = 8;
84 const INT_128_BYTES: u8 = 16;
85
86 const FLOAT_32_BYTES: u8 = 4;
87 const FLOAT_64_BYTES: u8 = 8;
88
89 pub fn new(
90 buffer: Vec<u8>,
91 inserted_values: Vec<ValueContainer>,
92 execution_mode: ExecutionMode,
93 ) -> Self {
94 CompilationContext {
95 inserted_value_index: 0,
96 buffer,
97 inserted_values,
98 has_non_static_value: false,
99 slot_indices: HashMap::new(),
100 execution_mode,
101 }
102 }
103
104 pub fn buffer_index(&self) -> usize {
105 self.buffer.len()
106 }
107
108 fn insert_value_container(&mut self, value_container: &ValueContainer) {
109 append_value_container(&mut self.buffer, value_container);
110 }
111
112 pub fn external_slots(&self) -> Vec<VirtualSlot> {
113 self.slot_indices
114 .iter()
115 .filter(|(slot, _)| slot.is_external())
116 .sorted_by(|a, b| a.0.virtual_address.cmp(&b.0.virtual_address))
117 .map(|(slot, _)| *slot)
118 .collect()
119 }
120
121 pub fn get_slot_byte_indices(
123 &self,
124 match_externals: bool,
125 ) -> Vec<Vec<u32>> {
126 self.slot_indices
127 .iter()
128 .filter(|(slot, _)| slot.is_external() == match_externals)
129 .sorted_by(|a, b| a.0.virtual_address.cmp(&b.0.virtual_address))
130 .map(|(_, indices)| indices.clone())
131 .collect()
132 }
133
134 pub fn remap_virtual_slots(&mut self) {
135 let mut slot_address = 0;
136
137 for byte_indices in self.get_slot_byte_indices(true) {
139 for byte_index in byte_indices {
140 self.set_u32_at_index(slot_address, byte_index as usize);
141 }
142 slot_address += 1;
143 }
144
145 for byte_indices in self.get_slot_byte_indices(false) {
147 for byte_index in byte_indices {
148 self.set_u32_at_index(slot_address, byte_index as usize);
149 }
150 slot_address += 1;
151 }
152 }
153
154 pub fn insert_virtual_slot_address(&mut self, virtual_slot: VirtualSlot) {
157 let buffer_index = self.buffer_index() as u32;
158 if let Some(indices) = self.slot_indices.get_mut(&virtual_slot) {
159 indices.push(buffer_index);
160 } else {
161 self.slot_indices.insert(virtual_slot, vec![buffer_index]);
162 }
163 append_u32(&mut self.buffer, 0); }
165
166 pub fn set_u32_at_index(&mut self, u32: u32, index: usize) {
167 self.buffer[index..index + CompilationContext::INT_32_BYTES as usize]
168 .copy_from_slice(&u32.to_le_bytes());
169 }
170
171 pub fn mark_has_non_static_value(&mut self) {
172 self.has_non_static_value = true;
173 }
174
175 pub fn append_instruction_code(&mut self, code: InstructionCode) {
176 append_instruction_code(&mut self.buffer, code);
177 }
178}