1use crate::global::binary_codes::InstructionCode;
2use crate::utils::buffers::{
3 append_f32, append_f64, append_i8, append_i16, append_i32, append_i64,
4 append_i128, append_u8, append_u32, append_u128,
5};
6use crate::values::core_value::CoreValue;
7use crate::values::core_values::decimal::decimal::Decimal;
8use crate::values::core_values::decimal::typed_decimal::TypedDecimal;
9use crate::values::core_values::endpoint::Endpoint;
10use crate::values::core_values::integer::integer::Integer;
11use crate::values::core_values::integer::typed_integer::TypedInteger;
12use crate::values::core_values::integer::utils::smallest_fitting_signed;
13use crate::values::value::Value;
14use crate::values::value_container::ValueContainer;
15use binrw::BinWrite;
16use itertools::Itertools;
17use std::cell::{Cell, RefCell};
18use std::collections::HashMap;
19use std::io::Cursor;
20use log::info;
21use datex_core::decompiler::decompile_body;
22
23#[derive(Debug, Clone, Default, Copy, PartialEq, Eq, Hash)]
24pub struct VirtualSlot {
25 pub level: u8, pub virtual_address: u32,
28}
29
30impl VirtualSlot {
31 pub fn local(virtual_address: u32) -> Self {
32 VirtualSlot {
33 level: 0,
34 virtual_address,
35 }
36 }
37 pub fn is_external(&self) -> bool {
38 self.level > 0
39 }
40
41 pub fn external(level: u8, virtual_address: u32) -> Self {
42 VirtualSlot {
43 level,
44 virtual_address,
45 }
46 }
47
48 pub fn downgrade(&self) -> Self {
49 VirtualSlot {
50 level: self.level + 1,
51 virtual_address: self.virtual_address,
52 }
53 }
54
55 pub fn upgrade(&self) -> Self {
56 if self.level > 0 {
57 VirtualSlot {
58 level: self.level - 1,
59 virtual_address: self.virtual_address,
60 }
61 } else {
62 panic!("Cannot upgrade a local slot");
63 }
64 }
65}
66
67
68pub struct CompilationContext<'a> {
70 pub index: Cell<usize>,
71 pub inserted_value_index: Cell<usize>,
72 pub buffer: RefCell<Vec<u8>>,
73 pub inserted_values: RefCell<&'a [&'a ValueContainer]>,
74 pub has_non_static_value: RefCell<bool>,
76
77 pub is_end_of_source_text: bool,
80
81 slot_indices: RefCell<HashMap<VirtualSlot, Vec<u32>>>,
83}
84
85impl<'a> CompilationContext<'a> {
86 const MAX_INT_32: i64 = 2_147_483_647;
87 const MIN_INT_32: i64 = -2_147_483_648;
88
89 const MAX_INT_8: i64 = 127;
90 const MIN_INT_8: i64 = -128;
91
92 const MAX_INT_16: i64 = 32_767;
93 const MIN_INT_16: i64 = -32_768;
94
95 const MAX_UINT_16: i64 = 65_535;
96
97 const INT_8_BYTES: u8 = 1;
98 const INT_16_BYTES: u8 = 2;
99 const INT_32_BYTES: u8 = 4;
100 const INT_64_BYTES: u8 = 8;
101 const INT_128_BYTES: u8 = 16;
102
103 const FLOAT_32_BYTES: u8 = 4;
104 const FLOAT_64_BYTES: u8 = 8;
105
106 pub fn new(
107 buffer: RefCell<Vec<u8>>,
108 inserted_values: &'a [&'a ValueContainer],
109 is_end_of_source_text: bool,
110 ) -> Self {
111 CompilationContext {
112 index: Cell::new(0),
113 inserted_value_index: Cell::new(0),
114 buffer,
115 inserted_values: RefCell::new(inserted_values),
116 has_non_static_value: RefCell::new(false),
117 slot_indices: RefCell::new(HashMap::new()),
118 is_end_of_source_text,
119 }
120 }
121
122 pub fn external_slots(&self) -> Vec<VirtualSlot> {
123 self.slot_indices
124 .borrow()
125 .iter()
126 .filter(|(slot, _)| slot.is_external())
127 .sorted_by(|a, b| a.0.virtual_address.cmp(&b.0.virtual_address))
128 .map(|(slot, _)| *slot)
129 .collect()
130 }
131
132 pub fn get_slot_byte_indices(
134 &self,
135 match_externals: bool,
136 ) -> Vec<Vec<u32>> {
137 self.slot_indices
138 .borrow()
139 .iter()
140 .filter(|(slot, _)| slot.is_external() == match_externals)
141 .sorted_by(|a, b| a.0.virtual_address.cmp(&b.0.virtual_address))
142 .map(|(_, indices)| indices.clone())
143 .collect()
144 }
145
146 pub fn remap_virtual_slots(&self) {
147 info!("remapping, bytes before: {:?}", self.buffer.borrow());
148 info!("decompiled: {:?}", decompile_body(&self.buffer.borrow(), Default::default())
149 .expect("Failed to decompile body"));
150
151 info!("slot indices: {:#?}", self.slot_indices.borrow());
152
153 let mut slot_address = 0;
154
155 for byte_indices in self.get_slot_byte_indices(true) {
157 info!("remapping slot address: {slot_address}, indices: {byte_indices:?}");
158 for byte_index in byte_indices {
159 self.set_u32_at_index(slot_address, byte_index as usize);
160 }
161 slot_address += 1;
162 }
163
164 for byte_indices in self.get_slot_byte_indices(false) {
166 info!("remapping local slot address: {slot_address}, indices: {byte_indices:?}");
167 for byte_index in byte_indices {
168 self.set_u32_at_index(slot_address, byte_index as usize);
169 }
170 slot_address += 1;
171 }
172 info!("decompiled after: {:?}", decompile_body(&self.buffer.borrow(), Default::default())
173 .expect("Failed to decompile body"));
174 }
175
176 pub fn insert_virtual_slot_address(&self, virtual_slot: VirtualSlot) {
179 let mut slot_indices = self.slot_indices.borrow_mut();
180 if let Some(indices) = slot_indices.get_mut(&virtual_slot) {
181 indices.push(self.index.get() as u32);
182 } else {
183 slot_indices.insert(virtual_slot, vec![self.index.get() as u32]);
184 }
185 self.append_u32(0); }
187
188 pub fn insert_value_container(&self, value_container: &ValueContainer) {
189 self.mark_has_non_static_value();
190 match value_container {
191 ValueContainer::Value(value) => self.insert_value(value),
192 ValueContainer::Reference(reference) => {
193 self.append_binary_code(InstructionCode::CREATE_REF);
196 self.insert_value(
197 &reference.borrow().current_resolved_value().borrow(),
198 )
199 }
200 }
201 }
202
203 pub fn insert_value(&self, value: &Value) {
204 match &value.inner {
205 CoreValue::TypedInteger(val) | CoreValue::Integer(Integer(val)) => {
206 match val.to_smallest_fitting() {
207 TypedInteger::I8(val) => {
208 self.insert_i8(val);
209 }
210 TypedInteger::I16(val) => {
211 self.insert_i16(val);
212 }
213 TypedInteger::I32(val) => {
214 self.insert_i32(val);
215 }
216 TypedInteger::I64(val) => {
217 self.insert_i64(val);
218 }
219 TypedInteger::I128(val) => {
220 self.insert_i128(val);
221 }
222 TypedInteger::U8(val) => {
223 self.insert_u8(val);
224 }
225 TypedInteger::U16(val) => {
226 self.insert_u16(val);
227 }
228 TypedInteger::U32(val) => {
229 self.insert_u32(val);
230 }
231 TypedInteger::U64(val) => {
232 self.insert_u64(val);
233 }
234 TypedInteger::U128(val) => {
235 self.insert_u128(val);
236 }
237 }
238 }
239 CoreValue::Endpoint(endpoint) => self.insert_endpoint(endpoint),
240 CoreValue::Decimal(decimal) => self.insert_decimal(decimal),
241 CoreValue::TypedDecimal(val) => self.insert_typed_decimal(val),
242 CoreValue::Bool(val) => self.insert_boolean(val.0),
243 CoreValue::Null => self.append_binary_code(InstructionCode::NULL),
244 CoreValue::Text(val) => {
245 self.insert_text(&val.0.clone());
246 }
247 CoreValue::Array(val) => {
248 self.append_binary_code(InstructionCode::ARRAY_START);
249 for item in val {
250 self.insert_value_container(item);
251 }
252 self.append_binary_code(InstructionCode::SCOPE_END);
253 }
254 CoreValue::Object(val) => {
255 self.append_binary_code(InstructionCode::OBJECT_START);
256 for (key, value) in val {
258 self.insert_key_string(key);
259 self.insert_value_container(value);
260 }
261 self.append_binary_code(InstructionCode::SCOPE_END);
262 }
263 CoreValue::Tuple(val) => {
264 self.append_binary_code(InstructionCode::TUPLE_START);
265 let mut next_expected_integer_key: i128 = 0;
266 for (key, value) in val {
267 if let ValueContainer::Value(key) = key
269 && let CoreValue::Integer(Integer(integer)) = key.inner
270 && let Some(int) = integer.as_i128()
271 && int == next_expected_integer_key
272 {
273 next_expected_integer_key += 1;
274 self.insert_value_container(value);
275 } else {
276 self.insert_key_value_pair(key, value);
277 }
278 }
279 self.append_binary_code(InstructionCode::SCOPE_END);
280 }
281 }
282 }
283
284 pub fn insert_boolean(&self, boolean: bool) {
286 if boolean {
287 self.append_binary_code(InstructionCode::TRUE);
288 } else {
289 self.append_binary_code(InstructionCode::FALSE);
290 }
291 }
292
293 pub fn insert_text(&self, string: &str) {
294 let bytes = string.as_bytes();
295 let len = bytes.len();
296
297 if len < 256 {
298 self.append_binary_code(InstructionCode::SHORT_TEXT);
299 self.append_u8(len as u8);
300 } else {
301 self.append_binary_code(InstructionCode::TEXT);
302 self.append_u32(len as u32);
303 }
304
305 self.append_buffer(bytes);
306 }
307
308 pub fn insert_key_value_pair(
309 &self,
310 key: &ValueContainer,
311 value: &ValueContainer,
312 ) {
313 match key {
315 ValueContainer::Value(Value {
317 inner: CoreValue::Text(text),
318 ..
319 }) => {
320 self.insert_key_string(&text.0);
321 }
322 _ => {
323 self.append_binary_code(InstructionCode::KEY_VALUE_DYNAMIC);
324 self.insert_value_container(key);
325 }
326 }
327 self.insert_value_container(value);
329 }
330
331 pub fn insert_key_string(&self, key_string: &str) {
332 let bytes = key_string.as_bytes();
333 let len = bytes.len();
334
335 if len < 256 {
336 self.append_binary_code(InstructionCode::KEY_VALUE_SHORT_TEXT);
337 self.append_u8(len as u8);
338 self.append_buffer(bytes);
339 } else {
340 self.append_binary_code(InstructionCode::KEY_VALUE_DYNAMIC);
341 self.insert_text(key_string);
342 }
343 }
344
345 pub fn insert_typed_decimal(&self, decimal: &TypedDecimal) {
346 fn insert_f32_or_f64(scope: &CompilationContext, decimal: &TypedDecimal) {
347 match decimal {
348 TypedDecimal::F32(val) => {
349 scope.insert_float32(val.into_inner());
350 }
351 TypedDecimal::F64(val) => {
352 scope.insert_float64(val.into_inner());
353 }
354 TypedDecimal::Decimal(val) => {
355 scope.insert_decimal(val);
356 }
357 }
358 }
359
360 match decimal.as_integer() {
361 Some(int) => {
362 let smallest = smallest_fitting_signed(int as i128);
363 match smallest {
364 TypedInteger::I8(val) => {
365 self.insert_float_as_i16(val as i16);
366 }
367 TypedInteger::I16(val) => {
368 self.insert_float_as_i16(val);
369 }
370 TypedInteger::I32(val) => {
371 self.insert_float_as_i32(val);
372 }
373 _ => insert_f32_or_f64(self, decimal),
374 }
375 }
376 None => insert_f32_or_f64(self, decimal),
377 }
378 }
379
380 pub fn insert_float32(&self, float32: f32) {
381 self.append_binary_code(InstructionCode::DECIMAL_F32);
382 self.append_f32(float32);
383 }
384 pub fn insert_float64(&self, float64: f64) {
385 self.append_binary_code(InstructionCode::DECIMAL_F64);
386 self.append_f64(float64);
387 }
388
389 pub fn insert_endpoint(&self, endpoint: &Endpoint) {
390 self.append_binary_code(InstructionCode::ENDPOINT);
391 self.append_buffer(&endpoint.to_binary());
392 }
393
394 pub fn insert_decimal(&self, decimal: &Decimal) {
395 self.append_binary_code(InstructionCode::DECIMAL_BIG);
396 let mut buffer = self.buffer.borrow_mut();
398 let original_length = buffer.len();
399 let mut buffer_writer = Cursor::new(&mut *buffer);
400 buffer_writer.set_position(original_length as u64);
402 decimal
403 .write_le(&mut buffer_writer)
404 .expect("Failed to write big decimal");
405 let byte_count = buffer_writer.position() as usize;
407 self.index.update(|x| x + byte_count - original_length);
409 }
410
411 pub fn insert_float_as_i16(&self, int: i16) {
412 self.append_binary_code(InstructionCode::DECIMAL_AS_INT_16);
413 self.append_i16(int);
414 }
415 pub fn insert_float_as_i32(&self, int: i32) {
416 self.append_binary_code(InstructionCode::DECIMAL_AS_INT_32);
417 self.append_i32(int);
418 }
419
420 pub fn insert_int(&self, int: i64) {
421 if (CompilationContext::MIN_INT_8..=CompilationContext::MAX_INT_8).contains(&int) {
422 self.insert_i8(int as i8)
423 } else if (CompilationContext::MIN_INT_16..=CompilationContext::MAX_INT_16).contains(&int) {
424 self.insert_i16(int as i16)
425 } else if (CompilationContext::MIN_INT_32..=CompilationContext::MAX_INT_32).contains(&int) {
426 self.insert_i32(int as i32)
427 } else {
428 self.insert_i64(int)
429 }
430 }
431
432 pub fn insert_i8(&self, int8: i8) {
433 self.append_binary_code(InstructionCode::INT_8);
434 self.append_i8(int8);
435 }
436
437 pub fn insert_i16(&self, int16: i16) {
438 self.append_binary_code(InstructionCode::INT_16);
439 self.append_i16(int16);
440 }
441 pub fn insert_i32(&self, int32: i32) {
442 self.append_binary_code(InstructionCode::INT_32);
443 self.append_i32(int32);
444 }
445 pub fn insert_i64(&self, int64: i64) {
446 self.append_binary_code(InstructionCode::INT_64);
447 self.append_i64(int64);
448 }
449 pub fn insert_i128(&self, int128: i128) {
450 self.append_binary_code(InstructionCode::INT_128);
451 self.append_i128(int128);
452 }
453 pub fn insert_u8(&self, uint8: u8) {
454 self.append_binary_code(InstructionCode::INT_16);
455 self.append_i16(uint8 as i16);
456 }
457 pub fn insert_u16(&self, uint16: u16) {
458 self.append_binary_code(InstructionCode::INT_32);
459 self.append_i32(uint16 as i32);
460 }
461 pub fn insert_u32(&self, uint32: u32) {
462 self.append_binary_code(InstructionCode::INT_64);
463 self.append_i64(uint32 as i64);
464 }
465 pub fn insert_u64(&self, uint64: u64) {
466 self.append_binary_code(InstructionCode::INT_128);
467 self.append_i128(uint64 as i128);
468 }
469 pub fn insert_u128(&self, uint128: u128) {
470 self.append_binary_code(InstructionCode::UINT_128);
471 self.append_i128(uint128 as i128);
472 }
473 pub fn append_u8(&self, u8: u8) {
474 append_u8(self.buffer.borrow_mut().as_mut(), u8);
475 self.index.update(|x| x + CompilationContext::INT_8_BYTES as usize);
476 }
477 pub fn append_u32(&self, u32: u32) {
478 append_u32(self.buffer.borrow_mut().as_mut(), u32);
479 self.index.update(|x| x + CompilationContext::INT_32_BYTES as usize);
480 }
481 pub fn set_u32_at_index(&self, u32: u32, index: usize) {
482 let mut buffer = self.buffer.borrow_mut();
483 buffer[index..index + CompilationContext::INT_32_BYTES as usize]
484 .copy_from_slice(&u32.to_le_bytes());
485 }
486 pub fn append_i8(&self, i8: i8) {
487 append_i8(self.buffer.borrow_mut().as_mut(), i8);
488 self.index.update(|x| x + CompilationContext::INT_8_BYTES as usize);
489 }
490 pub fn append_i16(&self, i16: i16) {
491 append_i16(self.buffer.borrow_mut().as_mut(), i16);
492 self.index.update(|x| x + CompilationContext::INT_16_BYTES as usize);
493 }
494 pub fn append_i32(&self, i32: i32) {
495 append_i32(self.buffer.borrow_mut().as_mut(), i32);
496 self.index.update(|x| x + CompilationContext::INT_32_BYTES as usize);
497 }
498 pub fn append_i64(&self, i64: i64) {
499 append_i64(self.buffer.borrow_mut().as_mut(), i64);
500 self.index.update(|x| x + CompilationContext::INT_64_BYTES as usize);
501 }
502 pub fn append_i128(&self, i128: i128) {
503 append_i128(self.buffer.borrow_mut().as_mut(), i128);
504 self.index.update(|x| x + CompilationContext::INT_128_BYTES as usize);
505 }
506
507 pub fn append_u128(&self, u128: u128) {
508 append_u128(self.buffer.borrow_mut().as_mut(), u128);
509 self.index.update(|x| x + CompilationContext::INT_128_BYTES as usize);
510 }
511
512 pub fn append_f32(&self, f32: f32) {
513 append_f32(self.buffer.borrow_mut().as_mut(), f32);
514 self.index.update(|x| x + CompilationContext::FLOAT_32_BYTES as usize);
515 }
516 pub fn append_f64(&self, f64: f64) {
517 append_f64(self.buffer.borrow_mut().as_mut(), f64);
518 self.index.update(|x| x + CompilationContext::FLOAT_64_BYTES as usize);
519 }
520 pub fn append_string_utf8(&self, string: &str) {
521 let bytes = string.as_bytes();
522 (*self.buffer.borrow_mut()).extend_from_slice(bytes);
523 self.index.update(|x| x + bytes.len());
524 }
525 pub fn append_buffer(&self, buffer: &[u8]) {
526 (*self.buffer.borrow_mut()).extend_from_slice(buffer);
527 self.index.update(|x| x + buffer.len());
528 }
529
530 pub fn mark_has_non_static_value(&self) {
531 self.has_non_static_value.replace(true);
532 }
533
534 pub fn append_binary_code(&self, binary_code: InstructionCode) {
535 self.append_u8(binary_code as u8);
536 }
537}