swamp_vm_types/
lib.rs

1/*
2 * Copyright (c) Peter Bjorklund. All rights reserved. https://github.com/swamp/swamp
3 * Licensed under the MIT License. See LICENSE in the project root for license information.
4 */
5
6use crate::aligner::align;
7use std::fmt::{Alignment, Display, Formatter};
8
9pub mod aligner;
10pub mod opcode;
11
12#[repr(C, packed)]
13#[derive(Clone)]
14pub struct BinaryInstruction {
15    pub opcode: u8,
16    pub operands: [u16; 5],
17}
18
19#[derive(Copy, Clone, Debug)]
20pub struct MemoryAddress(pub u16);
21
22#[derive(Copy, Clone)]
23pub struct StackMemoryAddress(pub u16);
24
25#[derive(Copy, Clone)]
26pub struct CountU16(pub u16);
27
28impl StackMemoryAddress {
29    #[must_use]
30    pub const fn add(&self, memory_size: MemorySize) -> Self {
31        Self(self.0 + memory_size.0)
32    }
33}
34
35#[derive(Debug, Copy, Clone)]
36pub struct ConstantMemoryAddress(pub u32);
37
38#[derive(Debug, Copy, Clone)]
39pub struct HeapMemoryAddress(pub u32);
40
41#[derive(Debug, Copy, Clone)]
42pub struct FrameMemoryAddress(pub u16);
43
44impl Display for FrameMemoryAddress {
45    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
46        write!(f, "[frame {:04X} ({})]", self.0, self.0)
47    }
48}
49
50#[derive(Debug, Copy, Clone)]
51pub struct FrameMemoryAddressIndirectPointer(pub FrameMemoryAddress);
52
53#[derive(Debug, Copy, Clone)]
54pub struct TempFrameMemoryAddress(pub FrameMemoryAddress);
55
56impl TempFrameMemoryAddress {
57    #[must_use]
58    pub const fn to_addr(&self) -> FrameMemoryAddress {
59        self.0
60    }
61}
62
63impl FrameMemoryAddress {
64    #[must_use]
65    pub fn advance(&self, memory_offset: MemoryOffset) -> FrameMemoryAddress {
66        FrameMemoryAddress(self.0 + memory_offset.0)
67    }
68}
69
70/// relative to the frame pointer
71impl FrameMemoryAddress {
72    #[must_use]
73    pub const fn add(&self, memory_size: MemorySize) -> Self {
74        Self(self.0 + memory_size.0)
75    }
76
77    pub const fn add_offset(&self, memory_offset: MemoryOffset) -> Self {
78        Self(self.0 + memory_offset.0)
79    }
80    #[must_use]
81    pub const fn as_size(&self) -> FrameMemorySize {
82        FrameMemorySize(self.0)
83    }
84}
85
86impl MemoryAddress {
87    #[must_use]
88    pub const fn space(&self, memory_size: MemorySize, _alignment: Alignment) -> Self {
89        Self(self.0 + memory_size.0)
90    }
91}
92
93#[derive(Debug, Copy, Clone)]
94pub struct MemoryOffset(pub u16);
95
96impl MemoryOffset {
97    pub fn space(&mut self, memory_size: MemorySize, alignment: MemoryAlignment) -> Self {
98        let start = align(self.0 as usize, alignment.into()) as u16;
99        self.0 = start + memory_size.0;
100        MemoryOffset(start)
101    }
102}
103
104impl MemoryOffset {
105    pub fn as_size(&self) -> MemorySize {
106        MemorySize(self.0)
107    }
108}
109
110impl MemoryOffset {
111    pub fn add(&self, size: MemorySize, alignment: MemoryAlignment) -> MemoryOffset {
112        let new_start = align(self.0 as usize, alignment.into());
113        MemoryOffset(new_start as u16 + size.0)
114    }
115}
116
117#[derive(Debug, Copy, Clone)]
118pub struct MemorySize(pub u16);
119
120#[derive(Debug, Copy, Clone)]
121pub enum MemoryAlignment {
122    U8,
123    U16,
124    U32,
125    U64,
126}
127
128impl MemoryAlignment {
129    #[must_use]
130    const fn rank(&self) -> usize {
131        match self {
132            Self::U8 => 1,
133            Self::U16 => 2,
134            Self::U32 => 3,
135            Self::U64 => 4,
136        }
137    }
138    #[must_use]
139    pub const fn greater_than(&self, other: MemoryAlignment) -> bool {
140        self.rank() > other.rank()
141    }
142}
143
144impl Into<usize> for MemoryAlignment {
145    fn into(self) -> usize {
146        match self {
147            Self::U8 => 1,
148            Self::U16 => 2,
149            Self::U32 => 4,
150            Self::U64 => 8,
151        }
152    }
153}
154
155impl Into<MemoryOffset> for MemoryAlignment {
156    fn into(self) -> MemoryOffset {
157        let octets: usize = self.into();
158        MemoryOffset(octets as u16)
159    }
160}
161
162#[must_use]
163pub fn align_frame_addr(
164    memory_address: FrameMemoryAddress,
165    alignment: MemoryAlignment,
166) -> FrameMemoryAddress {
167    let raw_addr = align(memory_address.0 as usize, alignment.into());
168
169    FrameMemoryAddress(raw_addr as u16)
170}
171
172#[must_use]
173pub fn align_offset(memory_address: MemoryOffset, alignment: MemoryAlignment) -> MemoryOffset {
174    let raw_addr = align(memory_address.0 as usize, alignment.into());
175
176    MemoryOffset(raw_addr as u16)
177}
178
179#[derive(Copy, Clone)]
180pub struct FrameMemorySize(pub u16);
181
182impl Display for FrameMemorySize {
183    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
184        write!(f, "frame size: {:04X}", self.0)
185    }
186}
187
188impl FrameMemorySize {
189    #[must_use]
190    pub const fn add(&self, inc: MemorySize) -> Self {
191        Self(self.0 + inc.0)
192    }
193}
194
195#[derive(Debug, Clone, Eq, PartialEq, Hash)]
196pub struct InstructionPosition(pub u16);
197
198pub const INT_SIZE: u16 = 4;
199pub const FLOAT_SIZE: u16 = 4;
200pub const BOOL_SIZE: u16 = 1;
201
202pub const PTR_SIZE: u16 = 2;
203pub const HEAP_PTR_SIZE: u16 = 4;
204pub const HEAP_PTR_ALIGNMENT: MemoryAlignment = MemoryAlignment::U32;
205
206pub const VEC_ITERATOR_ALIGNMENT: MemoryAlignment = MemoryAlignment::U32;
207
208pub const STR_SIZE: u16 = VEC_HEADER_SIZE; // TODO: FIX THIS
209
210#[repr(C)]
211pub struct VecHeader {
212    pub count: u16, // useful for iterator
213    pub capacity: u16,
214    pub heap_offset: u32, // "pointer" to the allocated slice (an offset into memory)
215    pub size: u16,        // size (in bytes) of each element; useful for iterator
216}
217pub const VEC_HEADER_SIZE: u16 = size_of::<VecHeader>() as u16;
218pub const VEC_REFERENCE_SIZE: u16 = HEAP_PTR_SIZE;
219
220pub struct VecIterator {
221    pub data_heap_offset: u32,
222    pub count: u16,
223    pub element_size: u16,
224    pub index: u16,
225}
226
227pub const VEC_ITERATOR_SIZE: u16 = size_of::<VecIterator>() as u16;
228
229pub const MAP_SIZE: u16 = 2 + 2 + 2 + 2 + 2;
230pub const MAP_REFERENCE_SIZE: u16 = HEAP_PTR_SIZE;
231
232pub struct StringHeader {
233    pub byte_count: u16,
234    pub capacity: u16,
235    pub heap_offset: u32, // "pointer" to the allocated slice (an offset into memory)
236}
237pub const STRING_HEADER_SIZE: u16 = size_of::<StringHeader>() as u16;
238pub const STRING_REFERENCE_SIZE: u16 = HEAP_PTR_SIZE;