reintroduce spec
This commit is contained in:
parent
138060e27a
commit
c7bb6be547
|
@ -1,10 +1,10 @@
|
|||
# Lily
|
||||
# lily
|
||||
an attempt at a cross-platform standard library for hblang.
|
||||
|
||||
> [!CAUTION]
|
||||
> [!caution]
|
||||
> 0.1.x currently only supports ableos target, as the new hblang compiler does not support native compilation yet.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> [!important]
|
||||
> all features, targets, modules, etc, are provisional and may be subject to change or deletion
|
||||
|
||||
# working Features
|
||||
|
|
4
TODO.md
Normal file
4
TODO.md
Normal file
|
@ -0,0 +1,4 @@
|
|||
see [here](<README.md#todo-features>) for feature todos.<br>
|
||||
this is strictly for dev todos.
|
||||
|
||||
- replace `idk` in places with Type(T).uninit()
|
9
docs/spec.md
Normal file
9
docs/spec.md
Normal file
|
@ -0,0 +1,9 @@
|
|||
# lily specification
|
||||
> [!important]
|
||||
> before lily version 1.0.0, the spec is provisional and may be subject to change.
|
||||
|
||||
a collection of guidelines for programmers to use to create lily-compatible implementations.
|
||||
|
||||
the following files define the spec:
|
||||
- [allocators](./spec/alloc.md)
|
||||
- [iterators](./spec/iter.md)
|
26
docs/spec/alloc.md
Normal file
26
docs/spec/alloc.md
Normal file
|
@ -0,0 +1,26 @@
|
|||
# allocators
|
||||
|
||||
1. all spec compliant allocators should implement:
|
||||
> unless otherwise stated, functions can be optionally inline.<br>
|
||||
> names of arguments are up to programmer discretion.<br>
|
||||
> names and signature of functions must be identical to shown below.
|
||||
|
||||
```rust
|
||||
Allocator := struct {
|
||||
new := fn(): Self
|
||||
/// prepare to be deallocated.
|
||||
deinit := fn(self: ^Self): void
|
||||
/// should return null on failure.
|
||||
/// should dealloc any intermediate allocations on failure.
|
||||
alloc := fn(self: ^Self, $T: type, count: uint): ?[]T
|
||||
/// same behaviour as alloc, except:
|
||||
/// must be zeroed.
|
||||
alloc_zeroed := fn(self: ^Self, $T: type, count: uint): ?[]T
|
||||
/// same behaviour as alloc, except:
|
||||
/// must move data to new allocation,
|
||||
/// must ensure the old allocation is freed at some point.
|
||||
realloc := fn(self: ^Self, $T: type, ptr: ^T, new_count: uint): ?[]T
|
||||
/// must dealloc or schedule the freeing of the given allocation
|
||||
dealloc := fn(self: ^Self, $T: type, ptr: ^T): void
|
||||
}
|
||||
```
|
11
docs/spec/iter.md
Normal file
11
docs/spec/iter.md
Normal file
|
@ -0,0 +1,11 @@
|
|||
# iterators
|
||||
|
||||
> [!note]
|
||||
> spec tbd
|
||||
|
||||
```rust
|
||||
iter.{Iterator, Next} := @use("lily").iter
|
||||
|
||||
Iterable := struct {
|
||||
next := fn(self: ^Self): Next(T)
|
||||
}
|
2
main.hb
2
main.hb
|
@ -13,7 +13,7 @@ main := fn(): void {
|
|||
// i += 1
|
||||
// }
|
||||
|
||||
b = alloc.Arena.alloc(&arena, u8, 1000).?
|
||||
b = alloc.Arena.alloc_zeroed(&arena, u8, 1000).?
|
||||
|
||||
mem.bytes(mem.reverse("Hello, World!")[1..]).take(5).for_each(fn(x: u8): void {
|
||||
len := fmt.fmt_int(b, x, 16)
|
||||
|
|
|
@ -3,15 +3,17 @@ lily.{target, mem} := @use("../lib.hb")
|
|||
AllocationHeader := struct {
|
||||
.cap: uint;
|
||||
.len: uint;
|
||||
.next: ?^AllocationHeader
|
||||
.next: ?^Self
|
||||
|
||||
new := fn(size: uint): ?^AllocationHeader {
|
||||
total_size := size + @size_of(AllocationHeader)
|
||||
ptr: ?^AllocationHeader = @bit_cast(target.alloc(total_size))
|
||||
Self := @CurrentScope()
|
||||
|
||||
$new := fn(size: uint): ?^Self {
|
||||
total_size := size + @size_of(Self)
|
||||
ptr: ?^Self = @bit_cast(target.alloc(total_size))
|
||||
if ptr == null return null
|
||||
header: ^AllocationHeader = @bit_cast(ptr)
|
||||
header: ^Self = @bit_cast(ptr)
|
||||
header.* = .(
|
||||
target.pages(total_size) * target.page_len() - @size_of(AllocationHeader),
|
||||
target.pages(total_size) * target.page_len() - @size_of(Self),
|
||||
0,
|
||||
null,
|
||||
)
|
||||
|
@ -22,11 +24,13 @@ AllocationHeader := struct {
|
|||
Arena := struct {
|
||||
.allocation: ?^AllocationHeader
|
||||
|
||||
Self := @CurrentScope()
|
||||
|
||||
$new := fn(): @CurrentScope() {
|
||||
return .(null)
|
||||
}
|
||||
// todo: handle alignment
|
||||
alloc := fn(self: ^Arena, $T: type, count: uint): ?[]T {
|
||||
alloc := fn(self: ^Self, $T: type, count: uint): ?[]T {
|
||||
size := mem.size(T, count)
|
||||
header: ^AllocationHeader = idk
|
||||
if self.allocation == null {
|
||||
|
@ -51,7 +55,19 @@ Arena := struct {
|
|||
}
|
||||
return @as(^T, @bit_cast(@as(^u8, @bit_cast(header + 1)) + header.len - size))[0..count]
|
||||
}
|
||||
deinit := fn(self: ^Arena): void {
|
||||
$alloc_zeroed := fn(self: ^Self, $T: type, count: uint): ?[]T {
|
||||
// todo: change back after struct method fix
|
||||
slice := Self.alloc(self, T, count)
|
||||
if slice == null return null
|
||||
mem.set(slice.?.ptr, 0, slice.?.len)
|
||||
return slice
|
||||
}
|
||||
$realloc := fn(self: ^Self, $T: type, ptr_old: ^T, count_new: uint): ?[]T {
|
||||
@error("todo: ", Self.realloc)
|
||||
return null
|
||||
}
|
||||
$dealloc := fn(self: ^Self, $T: type, ptr: ^T): void {}
|
||||
deinit := fn(self: ^Self): void {
|
||||
if self.allocation == null {
|
||||
lily.log.error("fixme: double free arena. can't fix due to compiler.")
|
||||
die
|
||||
|
|
|
@ -4,7 +4,12 @@ Vec := fn(T: type, A: type): type return struct {
|
|||
.cap: uint;
|
||||
.allocator: ^A
|
||||
|
||||
new := fn(allocator: ^A): @CurrentScope() {
|
||||
Self := @CurrentScope()
|
||||
|
||||
$new := fn(allocator: ^A): Self {
|
||||
return .(idk, 0, allocator)
|
||||
}
|
||||
|
||||
deinit := fn(self: ^Self): void {
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue