Created
August 2, 2022 11:21
-
-
Save mbillingr/af865c28eff77b1d8eaf957824458712 to your computer and use it in GitHub Desktop.
Memory/Pointer simulation in Python
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from abc import ABC, abstractmethod | |
from dataclasses import dataclass | |
from typing import Literal, Any | |
BYTEORDER: Literal["little", "big"] = "big" | |
class Type(ABC): | |
@abstractmethod | |
def load(self, offset, memory): | |
pass | |
@abstractmethod | |
def store(self, value, offset, memory): | |
pass | |
class U64(Type): | |
def load(self, offset, memory): | |
return memory.get_int(offset) | |
def store(self, value, offset, memory): | |
assert isinstance(value, int) | |
assert 0 <= value < 2**64 | |
return memory.set_int(offset, value) | |
class U64List(Type): | |
def load(self, offset, memory): | |
car = memory.get_int(offset) | |
cdr = memory.get_int(offset + 8) | |
return (car, Pointer(cdr, self, memory)) | |
def store(self, value, offset, memory): | |
assert isinstance(value, tuple) | |
assert len(value) == 2 | |
assert isinstance(value[0], int) | |
assert isinstance(value[1], Pointer) | |
memory.set_int(offset, value[0]) | |
memory.set_int(offset + 8, value[1].address) | |
class Memory(bytearray): | |
def __init__(self, n_bytes): | |
super().__init__(b"\x00" * n_bytes) | |
def set_int(self, offset, value: int, n_bytes=8): | |
self.set_bytes(offset, value.to_bytes(n_bytes, BYTEORDER)) | |
def get_int(self, offset, n_bytes=8) -> int: | |
return int.from_bytes(self.get_bytes(offset, n_bytes), BYTEORDER) | |
def set_bytes(self, offset, data): | |
self[offset : offset + len(data)] = data | |
def get_bytes(self, offset, length) -> bytes: | |
return self[offset : offset + length] | |
@dataclass | |
class Pointer: | |
address: int | |
type: Type | |
mem: Memory | |
def read(self) -> Any: | |
return self.type.load(self.address, self.mem) | |
def write(self, value: Any): | |
return self.type.store(value, self.address, self.mem) | |
mem = Memory(50) | |
nil = Pointer(0, U64List(), mem) | |
p1 = Pointer(1, U64List(), mem) | |
p1.write((10, nil)) | |
p2 = Pointer(17, U64List(), mem) | |
p2.write((20, p1)) | |
print(mem) | |
print(p2.read()) | |
print(p1.read()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment