aboutsummaryrefslogtreecommitdiffstats
path: root/bytecode/src/heap.rs
diff options
context:
space:
mode:
authorRose Hogenson <rhogenson@posteo.net>2022-01-09 08:40:09 -0800
committerRose Hogenson <rhogenson@posteo.net>2022-01-09 08:40:09 -0800
commit3ff7aac2d2eb2cbf2f854793fc0d7bc6f1f7d927 (patch)
treecef8ca0e77c40a70daaca40af25572437d563105 /bytecode/src/heap.rs
downloadchromatopelma-3ff7aac2d2eb2cbf2f854793fc0d7bc6f1f7d927.tar.zst
Initial commit.
Not sure if everything here will be needed eventually, but we have a working bytecode interpreter. Next I will write the linker, then the core compiler, and finish with the macro expander.
Diffstat (limited to 'bytecode/src/heap.rs')
-rw-r--r--bytecode/src/heap.rs82
1 files changed, 82 insertions, 0 deletions
diff --git a/bytecode/src/heap.rs b/bytecode/src/heap.rs
new file mode 100644
index 0000000..d76456a
--- /dev/null
+++ b/bytecode/src/heap.rs
@@ -0,0 +1,82 @@
+fn transmute(p: &u8) -> Result<&u64, String> {
+ let u8_p = p as *const u8;
+ let u64_p = u8_p as *const u64;
+ if u64_p as usize % 8 != 0 {
+ return Err(String::from("not aligned"));
+ }
+ unsafe {
+ return Ok(&*u64_p);
+ }
+}
+
+fn transmute_mut(p: &mut u8) -> Result<&mut u64, String> {
+ let u8_p = p as *mut u8;
+ let u64_p = u8_p as *mut u64;
+ if u64_p as usize % 8 != 0 {
+ return Err(String::from("not aligned"));
+ }
+ unsafe {
+ return Ok(&mut *u64_p);
+ }
+}
+
+pub struct Heap {
+ heap: Vec<u8>,
+}
+
+pub struct Pointer(usize);
+
+impl Heap {
+ pub fn new() -> Self {
+ Heap {
+ heap: vec![0; 128], // 1 kB
+ }
+ }
+
+ pub fn alloc(&mut self, n: usize) -> Pointer {
+ let p = Pointer(self.heap.len());
+ self.heap.append(&mut vec![0; n]);
+ p
+ }
+
+ pub fn peek(&self, p: Pointer) -> Result<u64, String> {
+ let Pointer(x) = p;
+ let u8_p = &self.heap[x];
+ let u64_p = transmute(u8_p)?;
+ Ok(*u64_p)
+ }
+
+ pub fn poke(&mut self, u: u64, p: Pointer) -> Result<(), String> {
+ let Pointer(x) = p;
+ let u8_p = &mut self.heap[x];
+ let u64_p = transmute_mut(u8_p)?;
+ *u64_p = u;
+ Ok(())
+ }
+
+ pub fn peek_byte(&self, p: Pointer) -> u8 {
+ let Pointer(x) = p;
+ self.heap[x]
+ }
+
+ pub fn poke_byte(&mut self, u: u8, p: Pointer) {
+ let Pointer(x) = p;
+ self.heap[x] = u;
+ }
+}
+
+impl Pointer {
+ pub fn from_bytes(p: u64) -> Self {
+ Pointer(usize::try_from(p).unwrap() >> 1)
+ }
+
+ pub fn bytes(&self) -> u64 {
+ let Pointer(x) = self;
+ u64::try_from(*x).unwrap() << 1
+ }
+
+ pub fn offset(&self, off: u8) -> Pointer {
+ let Pointer(x) = self;
+ Pointer(*x + usize::from(off))
+ }
+}