Skip to content

Instantly share code, notes, and snippets.

@brandonbloom
Last active February 16, 2016 01:47
Show Gist options
  • Save brandonbloom/1740b94e842b0c64bdfd to your computer and use it in GitHub Desktop.
Save brandonbloom/1740b94e842b0c64bdfd to your computer and use it in GitHub Desktop.
// Consider a "relative" pointer to some offset within
// a buffer with some base address.
struct RelativePtr {
void* base;
int offset;
}
// Now consider some operation to compute the relative address:
void* absolute(RelativePtr p) {
return p.base + p.offset;
}
// Is there any language out there that would let me
// abstract over when and where the value of `base` is known?
// For example, let's say you have a structure with
// two relative pointers with the same offset:
struct Foo {
RelativePtr a;
RelativePtr b;
}
// Ideally, the runtime representation of Foo would be:
struct Foo {
void* base;
int offsetA;
int offsetB;
}
// And the absolute function should still work:
Foo foo = ...;
void* p = absolute(foo.a);
// There needs to be some way to express the shared-base pointer
// constraint, but no language that I know of offers this.
// Does this exist somewhere? Is there relavant literature?
@caindy
Copy link

caindy commented Feb 14, 2016

I figured there was a dependent typing scheme, but I don't read Idris yet. I suspect you could do something similar in F*. In F# it is fairly common to make the concrete representation opaque, and to use Active Patterns and constructor functions to provide the appropriate semantics. Of course it requires that Foo and Relative have to be defined in the same scope, limiting its utility somewhat. But if you squint it kind of looks like a fancy type system solution. 😉

module Pointers

type Foo            = private { Base : Ptr; A : Offset; B : Offset }
and Relative        = private { Base : Ptr; Offset : Offset }
and private Ptr     = Address ref
and private Offset  = uint32
and Address = uint64

let mkFoo ptr a b = { Foo.Base = ref ptr; A = a; B = b } // TODO bounds checking
let (|Pointers|) (f : Foo) = { Base = f.Base; Offset = f.A }, { Base = f.Base; Offset = f.B }
let dereference (rp : Relative) (f : Address -> 'o) : 'o =
  // lock rp.Base
  !rp.Base + (uint64 rp.Offset) |> f
let move (f : Foo) (a' : Address) =
  // lock f.Base
  let a = f.Base
  a := a'
  f

It's just a sketch of the semantics, but I think that's germane when thinking about the shared base address constraint. Anyway, I know the above is not what you're positing, but it was fun nonetheless. Cheers!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment