/// Allocate `size` bytes from the arena.
pub fn (Arena) alloc(arena: self, size: usize) option[ref void] = {
guarded pre {
pre_size_positive : size > 0
}
val off: mut usize = trust @load(@ptradd(arena, 8))
val cap: usize = trust @load(@ptradd(arena, 16))
val aligned: usize = (size + 7) - ((size + 7) % 8)
if (off + aligned > cap) {
return none
}
val buf: mut ref void = trust @load(arena)
val ptr: ref void = trust @ptradd(buf, off)
trust @store(@ptradd(arena, 8), off + aligned)
return some ptr
}
/// Return bytes remaining. Subtraction is safe because used <= cap.
pub fn (Arena) remaining(arena: self) usize = {
pre {
used_le_cap : trust @load(@ptradd(arena, 8)) <= trust @load(@ptradd(arena, 16))
}
val off: usize = trust @load(@ptradd(arena, 8))
val cap: usize = trust @load(@ptradd(arena, 16))
post {
result_le_cap : off <= cap
}
return cap - off
}
enum Status = {
Ok,
NotFound,
PermissionDenied
}
union Payload = {
i32 | i64 | ref char
}
fn describe(x: Payload) void! = {
match x {
i32 => { std.io.put("32-bit integer") }
i64 => { std.io.put("64-bit integer") }
else => { std.io.put("string pointer") }
}
}
/// Open a file; mode must be non-empty in all build configurations.
pub fn open(path: ref char, mode: ref char) option[ref void] = {
guarded pre {
mode_nonempty : mode != ""
}
val f: ref void = trust fopen(path, mode)
if f == none { return none }
return some f
}