Maybe it's better if I just explain it via kind of translating it into
rust, rust and 1ml share a similar heritage (with the original rust
compiler bootstrapping from ML),
they are similar enough that we can mangle the high level concepts
into something representative enough. However 1ml did not have rusts
borrow checker, or ownership
rules... The implementation I wrote in 1ml would not satisfy the rust
borrow checker, the underlying machine pointer representation didn't
have mut and immutable variants.
Maybe we should step away from the notion of a tree representation,
and basically I'm going to make 3 different types for each permission,
but they'll all share a underlying machine representation. From the
*inside* when these have the same generic parameters, they share the
same underlying
machine representation. Thus, these types can convert between
themselves, and the only differences between them is the permissions
that we expose to the outside.
For simplicity i'm just going to use a generic type `T` as the machine rep...
```rust
struct PtrEq<T>(*T);
struct PtrRead<T>(*T);
// the pseudocode translation falls apart in the borrow checker
because we have both a *mut T for the `PtrWrite` and the `PtrRead` in
scope
struct PtrWrite<T>(*mut T);
struct PtrReadWrite<T>(*mut T);
impl PtrEq<T> {
fn eq(self, other: Self) -> bool;
}
impl PtrRead<T> {
fn modus_ponents<Q>(self, f: T -> Q) -> Q;
fn to_eq(self) -> PtrEq<T> {
PtrEq(self.0)
}
}
impl PtrWrite<T> {
fn write(self, t: T) -> ();
fn modus_ponents<Q>(self, f: T -> Q) -> Q;
fn eq(self, other: Self) -> bool;
fn to_eq(self) -> PtrEq<T> {
PtrEq(self.0.as_ptr())
}
}
impl PtrReadWrite<T> {
fn modus_ponents<Q>(self, f: T -> Q) -> Q;
fn write(self, t: T) -> ();
fn from_read_write(r: PtrRead<T>, w: PtrWrite<T>) -> Option<Self> {
if self.to_eq().eq(other.to_eq()) {
Some(PtrReadWrite(other.0))
} else {
None
}
}
}
```
This has a lot more boilerplate in rust, in 1ml we can copy the
read/write methods from the PtrRead/PtrWrite implementations, and we
don't have to manually
generate a bunch of newtypes, it's more like working in rusts macro
language, anyhow that is roughly how it worked...