1use crate::global::instruction_codes::InstructionCode;
2use crate::libs::core::CoreLibPointerId;
3use crate::references::reference::ReferenceMutability;
4use crate::utils::buffers::{
5 append_f32, append_f64, append_i8, append_i16, append_i32, append_i64,
6 append_i128, append_u8, append_u32, append_u128,
7};
8use crate::values::core_value::CoreValue;
9use crate::values::core_values::decimal::Decimal;
10use crate::values::core_values::decimal::typed_decimal::TypedDecimal;
11use crate::values::core_values::endpoint::Endpoint;
12use crate::values::core_values::integer::Integer;
13use crate::values::core_values::integer::typed_integer::TypedInteger;
14use crate::values::core_values::integer::utils::smallest_fitting_signed;
15use crate::values::pointer::PointerAddress;
16use crate::values::value::Value;
17use crate::values::value_container::ValueContainer;
18use binrw::BinWrite;
19use itertools::Itertools;
20use std::cell::{Cell, RefCell};
21use std::cmp::PartialEq;
22use std::collections::HashMap;
23use std::io::Cursor;
24
25#[derive(Debug, Clone, Default, Copy, PartialEq, Eq, Hash)]
26pub struct VirtualSlot {
27 pub level: u8, pub virtual_address: u32,
30}
31
32impl VirtualSlot {
33 pub fn local(virtual_address: u32) -> Self {
34 VirtualSlot {
35 level: 0,
36 virtual_address,
37 }
38 }
39 pub fn is_external(&self) -> bool {
40 self.level > 0
41 }
42
43 pub fn external(level: u8, virtual_address: u32) -> Self {
44 VirtualSlot {
45 level,
46 virtual_address,
47 }
48 }
49
50 pub fn downgrade(&self) -> Self {
51 VirtualSlot {
52 level: self.level + 1,
53 virtual_address: self.virtual_address,
54 }
55 }
56
57 pub fn upgrade(&self) -> Self {
58 if self.level > 0 {
59 VirtualSlot {
60 level: self.level - 1,
61 virtual_address: self.virtual_address,
62 }
63 } else {
64 panic!("Cannot upgrade a local slot");
65 }
66 }
67}
68
69pub struct CompilationContext<'a> {
71 pub index: Cell<usize>,
72 pub inserted_value_index: Cell<usize>,
73 pub buffer: RefCell<Vec<u8>>,
74 pub inserted_values: RefCell<&'a [&'a ValueContainer]>,
75 pub has_non_static_value: RefCell<bool>,
77
78 pub is_end_of_source_text: bool,
81
82 slot_indices: RefCell<HashMap<VirtualSlot, Vec<u32>>>,
84}
85
86impl<'a> CompilationContext<'a> {
87 const MAX_INT_32: i64 = 2_147_483_647;
88 const MIN_INT_32: i64 = -2_147_483_648;
89
90 const MAX_INT_8: i64 = 127;
91 const MIN_INT_8: i64 = -128;
92
93 const MAX_INT_16: i64 = 32_767;
94 const MIN_INT_16: i64 = -32_768;
95
96 const MAX_UINT_16: i64 = 65_535;
97
98 const INT_8_BYTES: u8 = 1;
99 const INT_16_BYTES: u8 = 2;
100 const INT_32_BYTES: u8 = 4;
101 const INT_64_BYTES: u8 = 8;
102 const INT_128_BYTES: u8 = 16;
103
104 const FLOAT_32_BYTES: u8 = 4;
105 const FLOAT_64_BYTES: u8 = 8;
106
107 pub fn new(
108 buffer: RefCell<Vec<u8>>,
109 inserted_values: &'a [&'a ValueContainer],
110 is_end_of_source_text: bool,
111 ) -> Self {
112 CompilationContext {
113 index: Cell::new(0),
114 inserted_value_index: Cell::new(0),
115 buffer,
116 inserted_values: RefCell::new(inserted_values),
117 has_non_static_value: RefCell::new(false),
118 slot_indices: RefCell::new(HashMap::new()),
119 is_end_of_source_text,
120 }
121 }
122
123 pub fn external_slots(&self) -> Vec<VirtualSlot> {
124 self.slot_indices
125 .borrow()
126 .iter()
127 .filter(|(slot, _)| slot.is_external())
128 .sorted_by(|a, b| a.0.virtual_address.cmp(&b.0.virtual_address))
129 .map(|(slot, _)| *slot)
130 .collect()
131 }
132
133 pub fn get_slot_byte_indices(
135 &self,
136 match_externals: bool,
137 ) -> Vec<Vec<u32>> {
138 self.slot_indices
139 .borrow()
140 .iter()
141 .filter(|(slot, _)| slot.is_external() == match_externals)
142 .sorted_by(|a, b| a.0.virtual_address.cmp(&b.0.virtual_address))
143 .map(|(_, indices)| indices.clone())
144 .collect()
145 }
146
147 pub fn remap_virtual_slots(&self) {
148 let mut slot_address = 0;
149
150 for byte_indices in self.get_slot_byte_indices(true) {
152 for byte_index in byte_indices {
153 self.set_u32_at_index(slot_address, byte_index as usize);
154 }
155 slot_address += 1;
156 }
157
158 for byte_indices in self.get_slot_byte_indices(false) {
160 for byte_index in byte_indices {
161 self.set_u32_at_index(slot_address, byte_index as usize);
162 }
163 slot_address += 1;
164 }
165 }
166
167 pub fn insert_virtual_slot_address(&self, virtual_slot: VirtualSlot) {
170 let mut slot_indices = self.slot_indices.borrow_mut();
171 if let Some(indices) = slot_indices.get_mut(&virtual_slot) {
172 indices.push(self.index.get() as u32);
173 } else {
174 slot_indices.insert(virtual_slot, vec![self.index.get() as u32]);
175 }
176 self.append_u32(0); }
178
179 pub fn insert_value_container(&self, value_container: &ValueContainer) {
180 self.mark_has_non_static_value();
181 match value_container {
182 ValueContainer::Value(value) => self.insert_value(value),
183 ValueContainer::Reference(reference) => {
184 if reference.mutability() == ReferenceMutability::Mutable {
187 self.append_instruction_code(
188 InstructionCode::CREATE_REF_MUT,
189 );
190 } else {
191 self.append_instruction_code(InstructionCode::CREATE_REF);
192 }
193 self.insert_value(&reference.collapse_to_value().borrow())
196 }
197 }
198 }
199
200 pub fn insert_value(&self, value: &Value) {
201 match &value.inner {
202 CoreValue::Type(ty) => {
203 todo!("#439 Type value not supported in CompilationContext");
204 }
205 CoreValue::Integer(integer) => {
206 let integer = integer.to_smallest_fitting();
207 self.insert_encoded_integer(&integer);
208 }
209 CoreValue::TypedInteger(integer) => {
210 self.insert_typed_integer(integer);
211 }
212
213 CoreValue::Endpoint(endpoint) => self.insert_endpoint(endpoint),
214 CoreValue::Decimal(decimal) => self.insert_decimal(decimal),
215 CoreValue::TypedDecimal(val) => self.insert_typed_decimal(val),
216 CoreValue::Boolean(val) => self.insert_boolean(val.0),
217 CoreValue::Null => {
218 self.append_instruction_code(InstructionCode::NULL)
219 }
220 CoreValue::Text(val) => {
221 self.insert_text(&val.0.clone());
222 }
223 CoreValue::List(val) => {
224 self.append_instruction_code(InstructionCode::LIST_START);
225 for item in val {
226 self.insert_value_container(item);
227 }
228 self.append_instruction_code(InstructionCode::SCOPE_END);
229 }
230 CoreValue::Map(val) => {
231 self.append_instruction_code(InstructionCode::MAP_START);
232 for (key, value) in val {
233 self.insert_key_value_pair(
234 &ValueContainer::from(key),
235 value,
236 );
237 }
238 self.append_instruction_code(InstructionCode::SCOPE_END);
239 }
240 }
241 }
242
243 pub fn insert_boolean(&self, boolean: bool) {
245 if boolean {
246 self.append_instruction_code(InstructionCode::TRUE);
247 } else {
248 self.append_instruction_code(InstructionCode::FALSE);
249 }
250 }
251
252 pub fn insert_text(&self, string: &str) {
253 let bytes = string.as_bytes();
254 let len = bytes.len();
255
256 if len < 256 {
257 self.append_instruction_code(InstructionCode::SHORT_TEXT);
258 self.append_u8(len as u8);
259 } else {
260 self.append_instruction_code(InstructionCode::TEXT);
261 self.append_u32(len as u32);
262 }
263
264 self.append_buffer(bytes);
265 }
266
267 pub fn insert_key_value_pair(
268 &self,
269 key: &ValueContainer,
270 value: &ValueContainer,
271 ) {
272 match key {
274 ValueContainer::Value(Value {
276 inner: CoreValue::Text(text),
277 ..
278 }) => {
279 self.insert_key_string(&text.0);
280 }
281 _ => {
282 self.append_instruction_code(
283 InstructionCode::KEY_VALUE_DYNAMIC,
284 );
285 self.insert_value_container(key);
286 }
287 }
288 self.insert_value_container(value);
290 }
291
292 pub fn insert_struct_key_value_pair(
293 &self,
294 key: String,
295 value: &ValueContainer,
296 ) {
297 self.insert_key_string(&key);
299 self.insert_value_container(value);
301 }
302
303 pub fn insert_key_string(&self, key_string: &str) {
304 let bytes = key_string.as_bytes();
305 let len = bytes.len();
306
307 if len < 256 {
308 self.append_instruction_code(InstructionCode::KEY_VALUE_SHORT_TEXT);
309 self.append_u8(len as u8);
310 self.append_buffer(bytes);
311 } else {
312 self.append_instruction_code(InstructionCode::KEY_VALUE_DYNAMIC);
313 self.insert_text(key_string);
314 }
315 }
316
317 pub fn insert_encoded_decimal(&self, decimal: &TypedDecimal) {
318 fn insert_f32_or_f64(
319 scope: &CompilationContext,
320 decimal: &TypedDecimal,
321 ) {
322 match decimal {
323 TypedDecimal::F32(val) => {
324 scope.insert_float32(val.into_inner());
325 }
326 TypedDecimal::F64(val) => {
327 scope.insert_float64(val.into_inner());
328 }
329 TypedDecimal::Decimal(val) => {
330 scope.insert_decimal(val);
331 }
332 }
333 }
334
335 match decimal.as_integer() {
336 Some(int) => {
337 let smallest = smallest_fitting_signed(int as i128);
338 match smallest {
339 TypedInteger::I8(val) => {
340 self.insert_float_as_i16(val as i16);
341 }
342 TypedInteger::I16(val) => {
343 self.insert_float_as_i16(val);
344 }
345 TypedInteger::I32(val) => {
346 self.insert_float_as_i32(val);
347 }
348 _ => insert_f32_or_f64(self, decimal),
349 }
350 }
351 None => insert_f32_or_f64(self, decimal),
352 }
353 }
354
355 pub fn insert_typed_decimal(&self, decimal: &TypedDecimal) {
356 self.append_instruction_code(InstructionCode::APPLY_SINGLE);
357 self.insert_get_ref(PointerAddress::from(CoreLibPointerId::from(
358 decimal,
359 )));
360 self.insert_encoded_decimal(decimal);
361 }
362
363 pub fn insert_float32(&self, float32: f32) {
364 self.append_instruction_code(InstructionCode::DECIMAL_F32);
365 self.append_f32(float32);
366 }
367 pub fn insert_float64(&self, float64: f64) {
368 self.append_instruction_code(InstructionCode::DECIMAL_F64);
369 self.append_f64(float64);
370 }
371
372 pub fn insert_endpoint(&self, endpoint: &Endpoint) {
373 self.append_instruction_code(InstructionCode::ENDPOINT);
374 self.append_buffer(&endpoint.to_binary());
375 }
376
377 fn insert_union_options(&self, options: Vec<ValueContainer>) {
390 if options.len() == 1 {
392 self.insert_value_container(&options[0]);
393 } else {
394 self.append_instruction_code(InstructionCode::SCOPE_START);
395 self.append_instruction_code(InstructionCode::UNION);
396 self.insert_value_container(&options[0]);
398 self.insert_union_options(options[1..].to_vec());
400 self.append_instruction_code(InstructionCode::SCOPE_END);
401 }
402 }
403
404 pub fn insert_big_integer(&self, integer: &Integer) {
405 let mut buffer = self.buffer.borrow_mut();
408 let original_length = buffer.len();
409 let mut buffer_writer = Cursor::new(&mut *buffer);
410 buffer_writer.set_position(original_length as u64);
412 integer
413 .write_le(&mut buffer_writer)
414 .expect("Failed to write big integer");
415 let byte_count = buffer_writer.position() as usize;
417 self.index.update(|x| x + byte_count - original_length);
419 }
420
421 pub fn insert_encoded_integer(&self, integer: &TypedInteger) {
423 match integer {
424 TypedInteger::I8(val) => {
425 self.insert_i8(*val);
426 }
427 TypedInteger::I16(val) => {
428 self.insert_i16(*val);
429 }
430 TypedInteger::I32(val) => {
431 self.insert_i32(*val);
432 }
433 TypedInteger::I64(val) => {
434 self.insert_i64(*val);
435 }
436 TypedInteger::I128(val) => {
437 self.insert_i128(*val);
438 }
439 TypedInteger::U8(val) => {
440 self.insert_u8(*val);
441 }
442 TypedInteger::U16(val) => {
443 self.insert_u16(*val);
444 }
445 TypedInteger::U32(val) => {
446 self.insert_u32(*val);
447 }
448 TypedInteger::U64(val) => {
449 self.insert_u64(*val);
450 }
451 TypedInteger::U128(val) => {
452 self.insert_u128(*val);
453 }
454 TypedInteger::Big(val) => {
455 self.append_instruction_code(InstructionCode::INT_BIG);
456 self.insert_big_integer(val);
457 }
458 }
459 }
460
461 pub fn insert_typed_integer(&self, integer: &TypedInteger) {
463 self.append_instruction_code(InstructionCode::APPLY_SINGLE);
464 self.insert_get_ref(PointerAddress::from(CoreLibPointerId::from(
465 integer,
466 )));
467 self.insert_encoded_integer(&integer.to_smallest_fitting());
468 }
469
470 pub fn insert_decimal(&self, decimal: &Decimal) {
471 self.append_instruction_code(InstructionCode::DECIMAL_BIG);
472 let mut buffer = self.buffer.borrow_mut();
474 let original_length = buffer.len();
475 let mut buffer_writer = Cursor::new(&mut *buffer);
476 buffer_writer.set_position(original_length as u64);
478 decimal
479 .write_le(&mut buffer_writer)
480 .expect("Failed to write big decimal");
481 let byte_count = buffer_writer.position() as usize;
483 self.index.update(|x| x + byte_count - original_length);
485 }
486
487 pub fn insert_float_as_i16(&self, int: i16) {
488 self.append_instruction_code(InstructionCode::DECIMAL_AS_INT_16);
489 self.append_i16(int);
490 }
491 pub fn insert_float_as_i32(&self, int: i32) {
492 self.append_instruction_code(InstructionCode::DECIMAL_AS_INT_32);
493 self.append_i32(int);
494 }
495 pub fn insert_i8(&self, int8: i8) {
496 self.append_instruction_code(InstructionCode::INT_8);
497 self.append_i8(int8);
498 }
499
500 pub fn insert_i16(&self, int16: i16) {
501 self.append_instruction_code(InstructionCode::INT_16);
502 self.append_i16(int16);
503 }
504 pub fn insert_i32(&self, int32: i32) {
505 self.append_instruction_code(InstructionCode::INT_32);
506 self.append_i32(int32);
507 }
508 pub fn insert_i64(&self, int64: i64) {
509 self.append_instruction_code(InstructionCode::INT_64);
510 self.append_i64(int64);
511 }
512 pub fn insert_i128(&self, int128: i128) {
513 self.append_instruction_code(InstructionCode::INT_128);
514 self.append_i128(int128);
515 }
516 pub fn insert_u8(&self, uint8: u8) {
517 self.append_instruction_code(InstructionCode::INT_16);
518 self.append_i16(uint8 as i16);
519 }
520 pub fn insert_u16(&self, uint16: u16) {
521 self.append_instruction_code(InstructionCode::INT_32);
522 self.append_i32(uint16 as i32);
523 }
524 pub fn insert_u32(&self, uint32: u32) {
525 self.append_instruction_code(InstructionCode::INT_64);
526 self.append_i64(uint32 as i64);
527 }
528 pub fn insert_u64(&self, uint64: u64) {
529 self.append_instruction_code(InstructionCode::INT_128);
530 self.append_i128(uint64 as i128);
531 }
532 pub fn insert_u128(&self, uint128: u128) {
533 self.append_instruction_code(InstructionCode::UINT_128);
534 self.append_i128(uint128 as i128);
535 }
536 pub fn append_u8(&self, u8: u8) {
537 append_u8(self.buffer.borrow_mut().as_mut(), u8);
538 self.index
539 .update(|x| x + CompilationContext::INT_8_BYTES as usize);
540 }
541 pub fn append_u32(&self, u32: u32) {
542 append_u32(self.buffer.borrow_mut().as_mut(), u32);
543 self.index
544 .update(|x| x + CompilationContext::INT_32_BYTES as usize);
545 }
546 pub fn set_u32_at_index(&self, u32: u32, index: usize) {
547 let mut buffer = self.buffer.borrow_mut();
548 buffer[index..index + CompilationContext::INT_32_BYTES as usize]
549 .copy_from_slice(&u32.to_le_bytes());
550 }
551 pub fn append_i8(&self, i8: i8) {
552 append_i8(self.buffer.borrow_mut().as_mut(), i8);
553 self.index
554 .update(|x| x + CompilationContext::INT_8_BYTES as usize);
555 }
556 pub fn append_i16(&self, i16: i16) {
557 append_i16(self.buffer.borrow_mut().as_mut(), i16);
558 self.index
559 .update(|x| x + CompilationContext::INT_16_BYTES as usize);
560 }
561 pub fn append_i32(&self, i32: i32) {
562 append_i32(self.buffer.borrow_mut().as_mut(), i32);
563 self.index
564 .update(|x| x + CompilationContext::INT_32_BYTES as usize);
565 }
566 pub fn append_i64(&self, i64: i64) {
567 append_i64(self.buffer.borrow_mut().as_mut(), i64);
568 self.index
569 .update(|x| x + CompilationContext::INT_64_BYTES as usize);
570 }
571 pub fn append_i128(&self, i128: i128) {
572 append_i128(self.buffer.borrow_mut().as_mut(), i128);
573 self.index
574 .update(|x| x + CompilationContext::INT_128_BYTES as usize);
575 }
576
577 pub fn append_u128(&self, u128: u128) {
578 append_u128(self.buffer.borrow_mut().as_mut(), u128);
579 self.index
580 .update(|x| x + CompilationContext::INT_128_BYTES as usize);
581 }
582
583 pub fn append_f32(&self, f32: f32) {
584 append_f32(self.buffer.borrow_mut().as_mut(), f32);
585 self.index
586 .update(|x| x + CompilationContext::FLOAT_32_BYTES as usize);
587 }
588 pub fn append_f64(&self, f64: f64) {
589 append_f64(self.buffer.borrow_mut().as_mut(), f64);
590 self.index
591 .update(|x| x + CompilationContext::FLOAT_64_BYTES as usize);
592 }
593 pub fn append_string_utf8(&self, string: &str) {
594 let bytes = string.as_bytes();
595 (*self.buffer.borrow_mut()).extend_from_slice(bytes);
596 self.index.update(|x| x + bytes.len());
597 }
598 pub fn append_buffer(&self, buffer: &[u8]) {
599 (*self.buffer.borrow_mut()).extend_from_slice(buffer);
600 self.index.update(|x| x + buffer.len());
601 }
602
603 pub fn insert_get_ref(&self, address: PointerAddress) {
604 match address {
605 PointerAddress::Internal(id) => {
606 self.append_instruction_code(InstructionCode::GET_INTERNAL_REF);
607 self.append_buffer(&id);
608 }
609 PointerAddress::Local(id) => {
610 self.append_instruction_code(InstructionCode::GET_LOCAL_REF);
611 self.append_buffer(&id);
612 }
613 PointerAddress::Remote(id) => {
614 self.append_instruction_code(InstructionCode::GET_REF);
615 self.append_buffer(&id);
616 }
617 }
618 }
619
620 pub fn mark_has_non_static_value(&self) {
621 self.has_non_static_value.replace(true);
622 }
623
624 pub fn append_instruction_code(&self, code: InstructionCode) {
625 self.append_u8(code as u8);
626 }
627}