itsy/bytecode/
builtins.rs1use crate::prelude::*;
4use crate::StackAddress;
5use crate::bytecode::{HeapRef, runtime::heap::{HeapOp, HeapRefOp}};
6
7impl_builtins! {
8
9 fn <
10 array_push8<T: u8>(this: HeapRef, value: u8),
11 array_push16<T: u16>(this: HeapRef, value: u16),
12 array_push32<T: u32>(this: HeapRef, value: u32),
13 array_push64<T: u64>(this: HeapRef, value: u64),
14 >(&mut vm) {
15 vm.heap.item_mut(this.index()).data.extend_from_slice(&value.to_ne_bytes());
16 }
17
18 fn array_pushx(&mut vm + constructor, this: HeapRef, value: HeapRef) {
19 vm.heap.item_mut(this.index()).data.extend_from_slice(&value.to_ne_bytes());
20 vm.refcount_value(value, constructor, HeapRefOp::Inc);
21 }
22
23 fn <
24 array_pop8<T: u8>(this: HeapRef) -> u8,
25 array_pop16<T: u16>(this: HeapRef) -> u16,
26 array_pop32<T: u32>(this: HeapRef) -> u32,
27 array_pop64<T: u64>(this: HeapRef) -> u64,
28 >(&mut vm) {
29 let index = this.index();
30 let offset = vm.heap.item(index).data.len() - size_of::<T>();
31 let result = vm.heap.read(HeapRef::new(index as StackAddress, offset as StackAddress));
32 vm.heap.item_mut(index).data.truncate(offset);
33 result
34 }
35
36 fn array_popx(&mut vm + constructor, this: HeapRef) -> HeapRef { let index = this.index();
38 let offset = vm.heap.item(index).data.len() - size_of::<HeapRef>();
39 let result = vm.heap.read(HeapRef::new(index as StackAddress, offset as StackAddress));
40 vm.heap.item_mut(index).data.truncate(offset);
41 vm.refcount_value(result, constructor, HeapRefOp::DecNoFree);
42 result
43 }
44
45 fn <
46 array_truncate8<T: u8>(this: HeapRef, size: StackAddress),
47 array_truncate16<T: u16>(this: HeapRef, size: StackAddress),
48 array_truncate32<T: u32>(this: HeapRef, size: StackAddress),
49 array_truncate64<T: u64>(this: HeapRef, size: StackAddress),
50 >(&mut vm) {
51 let index = this.index();
52 let current_size = vm.heap.item(index).data.len();
53 let new_size = size_of::<T>() * size as usize;
54 if new_size < current_size {
55 vm.heap.item_mut(index).data.truncate(new_size);
56 }
57 }
58
59 fn array_truncatex(&mut vm + constructor, this: HeapRef, size: StackAddress) {
60 let index = this.index();
61 let current_size = vm.heap.item(index).data.len();
62 let new_size = size_of::<HeapRef>() * size as usize;
63 if new_size < current_size {
64 let mut cursor = HeapRef::new(index, new_size as StackAddress);
65 let end = HeapRef::new(index, current_size as StackAddress);
66 while cursor < end {
67 let item: HeapRef = vm.heap.read_seq(&mut cursor);
68 vm.refcount_value(item, constructor, HeapRefOp::Dec);
69 }
70 vm.heap.item_mut(index).data.truncate(new_size);
71 }
72 }
73
74 fn <
75 array_remove8<T: u8>(this: HeapRef, element: StackAddress) -> u8,
76 array_remove16<T: u16>(this: HeapRef, element: StackAddress) -> u16,
77 array_remove32<T: u32>(this: HeapRef, element: StackAddress) -> u32,
78 array_remove64<T: u64>(this: HeapRef, element: StackAddress) -> u64,
79 >(&mut vm) {
80 const ELEMENT_SIZE: usize = size_of::<T>();
81 let offset = element as usize * ELEMENT_SIZE;
82 let index = this.index();
83 let result: T = vm.heap.read(HeapRef::new(index, offset as StackAddress));
84 let data = &mut vm.heap.item_mut(index).data;
85 data.copy_within(offset + ELEMENT_SIZE .., offset);
86 data.truncate(data.len() - ELEMENT_SIZE);
87 result
88 }
89
90 fn array_removex(&mut vm + constructor, this: HeapRef, element: StackAddress) -> HeapRef {
91 const ELEMENT_SIZE: usize = size_of::<HeapRef>();
92 let offset = element as usize * ELEMENT_SIZE;
93 let index = this.index();
94 let result: HeapRef = vm.heap.read(HeapRef::new(index, offset as StackAddress));
95 let data = &mut vm.heap.item_mut(index).data;
96 data.copy_within(offset + ELEMENT_SIZE .., offset);
97 data.truncate(data.len() - ELEMENT_SIZE);
98 vm.refcount_value(result, constructor, HeapRefOp::DecNoFree);
99 result
100 }
101}