lang: opt-in UFCS — ufcs-marked fns + alias dot-dispatch, generic binding via receiver; one binding builder for plan-side generic returns
This commit is contained in:
@@ -4,16 +4,16 @@
|
||||
//
|
||||
// The user-facing allocation surface over the Allocator protocol's
|
||||
// bytes-level primitives (`alloc_bytes` / `dealloc_bytes`). Free
|
||||
// functions — call directly or fluently via the pipe operator:
|
||||
// functions declared `ufcs` — dot-call, pipe, or call directly:
|
||||
//
|
||||
// s := context.allocator |> create(Session);
|
||||
// s := context.allocator.create(Session);
|
||||
// s.* = Session.{}; // no zero-init (Zig-aligned)
|
||||
// defer context.allocator |> destroy(s);
|
||||
// defer context.allocator.destroy(s);
|
||||
//
|
||||
// moves := context.allocator |> alloc(Move, 64);
|
||||
// defer context.allocator |> free(moves);
|
||||
// moves := context.allocator.alloc(Move, 64);
|
||||
// defer context.allocator.free(moves);
|
||||
//
|
||||
// copied := bytes |> clone(context.allocator);
|
||||
// copied := bytes.clone(context.allocator);
|
||||
//
|
||||
// Bodies are complete for the 2-method protocol era: `mem_realloc` is
|
||||
// alloc+copy+dealloc (the only shape without resize/remap primitives),
|
||||
@@ -21,17 +21,17 @@
|
||||
// allocation lands with the protocol expansion.
|
||||
|
||||
// Allocate one T. Contents are UNINITIALISED — assign before reading.
|
||||
create :: (a: Allocator, $T: Type) -> *T {
|
||||
create :: ufcs (a: Allocator, $T: Type) -> *T {
|
||||
xx a.alloc_bytes(size_of(T))
|
||||
}
|
||||
|
||||
// Free a *T obtained from `create`.
|
||||
destroy :: (a: Allocator, ptr: *$T) {
|
||||
destroy :: ufcs (a: Allocator, ptr: *$T) {
|
||||
a.dealloc_bytes(xx ptr);
|
||||
}
|
||||
|
||||
// Allocate a []T of `count` elements. Contents are UNINITIALISED.
|
||||
alloc :: (a: Allocator, $T: Type, count: s64) -> []T {
|
||||
alloc :: ufcs (a: Allocator, $T: Type, count: s64) -> []T {
|
||||
raw := a.alloc_bytes(count * size_of(T));
|
||||
s : []T = ---;
|
||||
s.ptr = xx raw;
|
||||
@@ -40,12 +40,12 @@ alloc :: (a: Allocator, $T: Type, count: s64) -> []T {
|
||||
}
|
||||
|
||||
// Free a []T obtained from `alloc` / `clone` / `resize`.
|
||||
free :: (a: Allocator, slice: []$T) {
|
||||
free :: ufcs (a: Allocator, slice: []$T) {
|
||||
a.dealloc_bytes(xx slice.ptr);
|
||||
}
|
||||
|
||||
// Copy a slice into fresh storage owned by `a`.
|
||||
clone :: (src: []$T, a: Allocator) -> []T {
|
||||
clone :: ufcs (src: []$T, a: Allocator) -> []T {
|
||||
raw := a.alloc_bytes(src.len * size_of(T));
|
||||
memcpy(raw, xx src.ptr, src.len * size_of(T));
|
||||
s : []T = ---;
|
||||
@@ -57,7 +57,7 @@ clone :: (src: []$T, a: Allocator) -> []T {
|
||||
// Reallocate a slice to `new_count` elements: fresh storage, contents
|
||||
// copied up to min(len, new_count), old backing freed. The returned
|
||||
// slice replaces the operand — the old slice is dangling after this.
|
||||
resize :: (slice: []$T, a: Allocator, new_count: s64) -> []T {
|
||||
resize :: ufcs (slice: []$T, a: Allocator, new_count: s64) -> []T {
|
||||
raw := a.alloc_bytes(new_count * size_of(T));
|
||||
n := if slice.len < new_count then slice.len else new_count;
|
||||
memcpy(raw, xx slice.ptr, n * size_of(T));
|
||||
@@ -72,7 +72,7 @@ resize :: (slice: []$T, a: Allocator, new_count: s64) -> []T {
|
||||
// dealloc — there is no in-place grow primitive to try yet, and
|
||||
// `align` beyond the heap's natural 8 is not honored until the
|
||||
// protocol carries alignment.
|
||||
mem_realloc :: (a: Allocator, ptr: *void, old: s64, new: s64, align: s64) -> *void {
|
||||
mem_realloc :: ufcs (a: Allocator, ptr: *void, old: s64, new: s64, align: s64) -> *void {
|
||||
raw := a.alloc_bytes(new);
|
||||
n := if old < new then old else new;
|
||||
memcpy(raw, ptr, n);
|
||||
|
||||
Reference in New Issue
Block a user