std: Adopt explicit generics

b3e2f8924fc671ea03a13f2f9b1a82e7b8a3e14fa44dcc8df5e451b2c98abdb3
Provide a typed vector interface and standard-library coverage using the completed generic contract, then advance the bootstrap seed to the self-hosted generic compiler.

Assisted-by: Codex:gpt-5.6
Alexis Sellier committed ago 1 parent 2034127d
lib/std/tests.rad +81 -163
4 4
use std::mem;
5 5
use std::vec;
6 6
use std::testing;
7 7
use std::sys::unix;
8 8
9 -
// Data types //////////////////////////////////////////////////////////////////
10 -
11 -
record Point {
12 -
    x: i32,
13 -
    y: i32,
14 -
}
15 -
16 9
// fmt /////////////////////////////////////////////////////////////////////////
17 10
18 11
@test fn testFormatU32Zero() throws (testing::TestError) {
19 12
    let mut buffer: [u8; 11] = [0; 11];
20 13
    let result: *[u8] = fmt::formatU32(0, &mut buffer[..]);
338 331
    try testing::expect(mem::cmp("abcd", "abc") > 0);
339 332
}
340 333
341 334
// vec /////////////////////////////////////////////////////////////////////////
342 335
343 -
@test fn testVecInitialState() throws (testing::TestError) {
344 -
    let mut arena: [u8; 16] align(4) = undefined;
345 -
    let mut v = vec::new(&mut arena[..], @sizeOf(i32), @alignOf(i32));
346 -
347 -
    try testing::expect(vec::len(&v) == 0);
348 -
    try testing::expect(vec::capacity(&v) == 4);
349 -
}
350 -
351 -
@test fn testVecPushAndGet() throws (testing::TestError) {
352 -
    let mut arena: [u8; 16] align(4) = undefined;
353 -
    let mut v = vec::new(&mut arena[..], @sizeOf(i32), @alignOf(i32));
354 -
355 -
    let val1: i32 = 42;
356 -
    try testing::expect(vec::push(&mut v, &val1));
357 -
    try testing::expect(vec::len(&v) == 1);
358 -
359 -
    let ptr = vec::get(&v, 0) else {
360 -
        throw testing::TestError::Failed;
361 -
    };
362 -
    let i32ptr: *i32 = ptr as *i32;
363 -
    let value: i32 = *i32ptr;
364 -
    try testing::expect(value == 42);
365 -
}
366 -
367 -
@test fn testVecPushPop() throws (testing::TestError) {
368 -
    let mut arena: [u8; 16] align(4) = undefined;
369 -
    let mut v = vec::new(&mut arena[..], @sizeOf(i32), @alignOf(i32));
370 -
371 -
    let val1: i32 = 42;
372 -
    let val2: i32 = 100;
373 -
    let val3: i32 = -5;
374 -
375 -
    try testing::expect(vec::push(&mut v, &val1));
376 -
    try testing::expect(vec::len(&v) == 1);
377 -
378 -
    try testing::expect(vec::push(&mut v, &val2));
379 -
    try testing::expect(vec::len(&v) == 2);
380 -
381 -
    try testing::expect(vec::push(&mut v, &val3));
382 -
    try testing::expect(vec::len(&v) == 3);
383 -
384 -
    let mut popped: i32 = 0;
385 -
386 -
    try testing::expect(vec::pop(&mut v, &mut popped));
387 -
    try testing::expect(popped == -5);
388 -
    try testing::expect(vec::len(&v) == 2);
389 -
390 -
    try testing::expect(vec::pop(&mut v, &mut popped));
391 -
    try testing::expect(popped == 100);
392 -
    try testing::expect(vec::len(&v) == 1);
393 -
394 -
    try testing::expect(vec::pop(&mut v, &mut popped));
395 -
    try testing::expect(popped == 42);
396 -
    try testing::expect(vec::len(&v) == 0);
397 -
398 -
    try testing::expectNot(vec::pop(&mut v, &mut popped));
399 -
}
400 -
401 -
@test fn testVecGetSet() throws (testing::TestError) {
402 -
    let mut arena: [u8; 32] align(4) = undefined;
403 -
    let mut v = vec::new(&mut arena[..], @sizeOf(i32), @alignOf(i32));
404 -
405 -
    let val1: i32 = 10;
406 -
    let val2: i32 = 20;
407 -
    let val3: i32 = 30;
408 -
409 -
    vec::push(&mut v, &val1);
410 -
    vec::push(&mut v, &val2);
411 -
    vec::push(&mut v, &val3);
412 -
413 -
    if let ptr = vec::get(&v, 0) {
414 -
        let value: i32 = *(ptr as *i32);
415 -
        try testing::expect(value == 10);
416 -
    } else {
417 -
        throw testing::TestError::Failed;
418 -
    }
419 -
420 -
    if let ptr = vec::get(&v, 1) {
421 -
        let value: i32 = *(ptr as *i32);
422 -
        try testing::expect(value == 20);
423 -
    } else {
424 -
        throw testing::TestError::Failed;
425 -
    }
426 -
427 -
    if let ptr = vec::get(&v, 2) {
428 -
        let value: i32 = *(ptr as *i32);
429 -
        try testing::expect(value == 30);
430 -
    } else {
431 -
        throw testing::TestError::Failed;
432 -
    }
433 -
    try testing::expect(vec::get(&v, 3) == nil);
434 -
435 -
    let new: i32 = 999;
436 -
    try testing::expect(vec::put(&mut v, 1, &new));
437 -
438 -
    if let ptr = vec::get(&v, 1) {
439 -
        let value: i32 = *(ptr as *i32);
440 -
        try testing::expect(value == 999);
441 -
    } else {
442 -
        throw testing::TestError::Failed;
443 -
    }
444 -
    try testing::expectNot(vec::put(&mut v, 5, &new));
445 -
}
446 -
447 -
@test fn testVecCapacity() throws (testing::TestError) {
448 -
    let mut arena: [u8; 16] align(4) = undefined;
449 -
    let mut v = vec::new(&mut arena[..], @sizeOf(i32), @alignOf(i32));
450 -
451 -
    let val: i32 = 7;
452 -
    try testing::expect(vec::push(&mut v, &val));
453 -
    try testing::expect(vec::push(&mut v, &val));
454 -
    try testing::expect(vec::push(&mut v, &val));
455 -
    try testing::expect(vec::push(&mut v, &val));
456 -
    try testing::expect(vec::len(&v) == 4);
336 +
/// Mixed-width value used by vector tests.
337 +
record Obj {
338 +
    /// Wide field.
339 +
    wide: u64,
340 +
    /// Narrow field.
341 +
    narrow: u8,
342 +
}
343 +
344 +
instantiate vec::Vec⟨i32⟩,
345 +
            vec::init⟨i32⟩,
346 +
            vec::len⟨i32⟩,
347 +
            vec::capacity⟨i32⟩,
348 +
            vec::reset⟨i32⟩,
349 +
            vec::get⟨i32⟩,
350 +
            vec::push⟨i32⟩,
351 +
            vec::put⟨i32⟩,
352 +
            vec::pop⟨i32⟩;
353 +
354 +
instantiate vec::Vec⟨Obj⟩,
355 +
            vec::init⟨Obj⟩,
356 +
            vec::get⟨Obj⟩,
357 +
            vec::push⟨Obj⟩,
358 +
            vec::put⟨Obj⟩;
457 359
458 -
    try testing::expectNot(vec::push(&mut v, &val));
459 -
    try testing::expect(vec::len(&v) == 4);
460 -
}
461 -
462 -
@test fn testVecReset() throws (testing::TestError) {
463 -
    let mut arena: [u8; 16] align(4) = undefined;
464 -
    let mut v = vec::new(&mut arena[..], @sizeOf(i32), @alignOf(i32));
465 -
466 -
    let val: i32 = 123;
467 -
    vec::push(&mut v, &val);
468 -
    vec::push(&mut v, &val);
469 -
    try testing::expect(vec::len(&v) == 2);
470 -
471 -
    vec::reset(&mut v);
472 -
    try testing::expect(vec::len(&v) == 0);
473 -
474 -
    try testing::expect(vec::push(&mut v, &val));
475 -
    try testing::expect(vec::len(&v) == 1);
476 -
}
477 -
478 -
@test fn testVecStruct() throws (testing::TestError) {
479 -
    let mut arena: [u8; 64] align(4) = undefined;
480 -
    let mut v = vec::new(&mut arena[..], @sizeOf(Point), @alignOf(Point));
481 -
482 -
    let p1: Point = Point { x: 1, y: 2 };
483 -
    let p2: Point = Point { x: 3, y: 4 };
484 -
485 -
    try testing::expect(vec::push(&mut v, &p1));
486 -
    try testing::expect(vec::push(&mut v, &p2));
487 -
488 -
    if let ptr = vec::get(&v, 0) {
489 -
        let p: *Point = ptr as *Point;
490 -
        try testing::expect(p.x == 1);
491 -
        try testing::expect(p.y == 2);
492 -
    } else {
493 -
        throw testing::TestError::Failed;
494 -
    }
495 -
    let mut popped: Point = Point { x: 0, y: 0 };
496 -
497 -
    try testing::expect(vec::pop(&mut v, &mut popped));
498 -
    try testing::expect(popped.x == 3);
499 -
    try testing::expect(popped.y == 4);
360 +
@test fn testVecInitialState() throws (testing::TestError) {
361 +
    let mut arena: [i32; 4] = undefined;
362 +
    let mut v: vec::Vec⟨i32= undefined;
363 +
    vec::init⟨i32(&mut v, &mut arena[..]);
364 +
365 +
    assert vec::len⟨i32(&v) == 0;
366 +
    assert vec::capacity⟨i32(&v) == 4;
367 +
}
368 +
369 +
@test fn testVecGetPut() throws (testing::TestError) {
370 +
    let mut arena: [i32; 3] = undefined;
371 +
    let mut v: vec::Vec⟨i32= undefined;
372 +
    vec::init⟨i32(&mut v, &mut arena[..]);
373 +
374 +
    assert vec::push⟨i32(&mut v, 10);
375 +
    assert vec::push⟨i32(&mut v, 20);
376 +
    assert vec::push⟨i32(&mut v, 30);
377 +
    assert not vec::push⟨i32(&mut v, 40);
378 +
379 +
    let first = vec::get⟨i32(&v, 0)
380 +
        else throw testing::TestError::Failed;
381 +
    assert *first == 10;
382 +
    assert vec::get⟨i32(&v, 3) == nil;
383 +
384 +
    assert vec::put⟨i32(&mut v, 1, 999);
385 +
    let replaced = vec::get⟨i32(&v, 1)
386 +
        else throw testing::TestError::Failed;
387 +
    assert *replaced == 999;
388 +
    assert not vec::put⟨i32(&mut v, 3, 1);
389 +
}
390 +
391 +
@test fn testVecPopReset() throws (testing::TestError) {
392 +
    let mut arena: [i32; 2] = undefined;
393 +
    let mut v: vec::Vec⟨i32= undefined;
394 +
    vec::init⟨i32(&mut v, &mut arena[..]);
395 +
396 +
    assert vec::push⟨i32(&mut v, 42);
397 +
    assert vec::push⟨i32(&mut v, 100);
398 +
    assert vec::pop⟨i32(&mut v) == 100;
399 +
    assert vec::pop⟨i32(&mut v) == 42;
400 +
    assert vec::pop⟨i32(&mut v) == nil;
401 +
402 +
    assert vec::push⟨i32(&mut v, 7);
403 +
    vec::reset⟨i32(&mut v);
404 +
    assert vec::len⟨i32(&v) == 0;
405 +
}
406 +
407 +
@test fn testVecRecordElements() throws (testing::TestError) {
408 +
    let mut arena: [Obj; 2] = undefined;
409 +
    let mut v: vec::Vec⟨Obj⟩ = undefined;
410 +
    vec::init⟨Obj⟩(&mut v, &mut arena[..]);
411 +
412 +
    assert vec::push⟨Obj⟩(&mut v, Obj { wide: 9, narrow: 1 });
413 +
    assert vec::put⟨Obj⟩(&mut v, 0, Obj { wide: 12, narrow: 2 });
414 +
    let pair = vec::get⟨Obj⟩(&v, 0)
415 +
        else throw testing::TestError::Failed;
416 +
    assert pair.wide == 12;
417 +
    assert pair.narrow == 2;
500 418
}
lib/std/vec.rad +33 -87
1 -
//! Raw vector: type-unsafe dynamic array backed by static storage.
2 -
//!
3 -
//! Users provide their own arena (static array) and the vector manages
4 -
//! element count within that arena. The arena should be aligned according
5 -
//! to the element type's requirements.
1 +
//! Typed vector backed by caller-owned static storage.
6 2
7 -
/// Raw vector metadata structure.
8 -
///
9 -
/// Does not own storage, points to user-provided arena.
10 -
export record RawVec {
11 -
    /// Pointer to user-provided byte arena.
12 -
    data: *mut [u8],
13 -
    /// Current number of elements stored.
3 +
/// Typed vector metadata backed by caller-owned storage.
4 +
export record Vec⟨T⟩ {
5 +
    /// Typed slice containing the vector's storage.
6 +
    data: *mut [T],
7 +
    /// Number of initialized elements.
14 8
    len: u32,
15 -
    /// Size of each element in bytes (stride between elements).
16 -
    stride: u32,
17 -
    /// Alignment in bytes required by element type (>= 1).
18 -
    alignment: u32,
19 9
}
20 10
21 -
/// Create a new raw vector with external arena.
22 -
///
23 -
/// * `arena` is a pointer to static array backing storage.
24 -
/// * `stride` is the size of each element.
25 -
/// * `alignment` is the required alignment for elements.
26 -
export fn new(arena: *mut [u8], stride: u32, alignment: u32) -> RawVec {
27 -
    assert stride > 0;
28 -
    assert alignment > 0;
29 -
    assert (arena.ptr as u32) % alignment == 0;
30 -
    assert (arena.len % stride) == 0;
31 -
32 -
    return RawVec { data: arena, len: 0, stride, alignment };
11 +
/// Initialize a vector over caller-owned storage.
12 +
export fn init⟨T⟩(vec: *mut Vec⟨T⟩, arena: *mut [T]) {
13 +
    set vec.data = arena;
14 +
    set vec.len = 0;
33 15
}
34 16
35 -
/// Get the current number of elements in the vector.
36 -
export fn len(vec: *RawVec) -> u32 {
17 +
/// Return the number of initialized elements.
18 +
export fn len⟨T⟩(vec: *Vec⟨T⟩) -> u32 {
37 19
    return vec.len;
38 20
}
39 21
40 -
/// Get the maximum capacity of the vector.
41 -
export fn capacity(vec: *RawVec) -> u32 {
42 -
    return vec.data.len / vec.stride;
22 +
/// Return the storage capacity in elements.
23 +
export fn capacity⟨T⟩(vec: *Vec⟨T⟩) -> u32 {
24 +
    return vec.data.len;
43 25
}
44 26
45 -
/// Reset the vector to empty (does not clear memory).
46 -
export fn reset(vec: *mut RawVec) {
27 +
/// Reset a vector without clearing its storage.
28 +
export fn reset⟨T⟩(vec: *mut Vec⟨T⟩) {
47 29
    set vec.len = 0;
48 30
}
49 31
50 -
/// Get a pointer to the element at the given index.
51 -
///
52 -
/// Returns nil if index is out of bounds.
53 -
export fn get(vec: *RawVec, index: u32) -> ?*opaque {
32 +
/// Return a typed pointer to an element, or `nil` when out of bounds.
33 +
export fn get⟨T⟩(vec: *Vec⟨T⟩, index: u32) -> ?*T {
54 34
    if index >= vec.len {
55 35
        return nil;
56 36
    }
57 -
    let offset: u32 = index * vec.stride;
58 -
    let ptr: *u8 = &vec.data[offset];
59 -
60 -
    return ptr as *opaque;
37 +
    return &vec.data[index];
61 38
}
62 39
63 -
/// Push an element onto the end of the vector.
64 -
///
65 -
/// Returns false if the vector is at capacity.
66 -
export fn push(vec: *mut RawVec, elem: *opaque) -> bool {
67 -
    if vec.len >= capacity(vec) {
40 +
/// Append an element, returning `false` when the vector is full.
41 +
export fn push⟨T⟩(vec: *mut Vec⟨T⟩, value: T) -> bool {
42 +
    if vec.len >= vec.data.len {
68 43
        return false;
69 44
    }
70 -
    let off: u32 = vec.len * vec.stride;
71 -
    let dst: *mut u8 = &mut vec.data[off];
72 -
    let src: *u8 = elem as *u8;
73 -
74 -
    copyBytes(dst, src, vec.stride);
45 +
    set vec.data[vec.len] = value;
75 46
    set vec.len += 1;
76 -
77 -
    return true;
78 -
}
79 -
80 -
/// Pop an element from the end of the vector.
81 -
///
82 -
/// Copies the element into the provided output pointer.
83 -
/// Returns false if the vector is empty.
84 -
export fn pop(vec: *mut RawVec, out: *mut opaque) -> bool {
85 -
    if vec.len == 0 {
86 -
        return false;
87 -
    }
88 -
    set vec.len -= 1;
89 -
90 -
    let off: u32 = vec.len * vec.stride;
91 -
    let src: *u8 = &vec.data[off];
92 -
    let dst: *mut u8 = out as *mut u8;
93 -
94 -
    copyBytes(dst, src, vec.stride);
95 -
96 47
    return true;
97 48
}
98 49
99 -
/// Set the element at the given index.
100 -
///
101 -
/// Returns false if index is out of bounds.
102 -
export fn put(vec: *mut RawVec, index: u32, elem: *opaque) -> bool {
50 +
/// Replace an initialized element, returning `false` when out of bounds.
51 +
export fn put⟨T⟩(vec: *mut Vec⟨T⟩, index: u32, value: T) -> bool {
103 52
    if index >= vec.len {
104 53
        return false;
105 54
    }
106 -
    let off: u32 = index * vec.stride;
107 -
    let dst: *mut u8 = &mut vec.data[off];
108 -
    let src: *u8 = elem as *u8;
109 -
110 -
    copyBytes(dst, src, vec.stride);
111 -
55 +
    set vec.data[index] = value;
112 56
    return true;
113 57
}
114 58
115 -
/// Copy bytes from source to destination.
116 -
fn copyBytes(dst: *mut u8, src: *u8, count: u32) {
117 -
    for i in 0..count {
118 -
        set *(dst + i) = *(src + i);
59 +
/// Remove and return the last element, or `nil` when empty.
60 +
export fn pop⟨T⟩(vec: *mut Vec⟨T⟩) -> ?T {
61 +
    if vec.len == 0 {
62 +
        return nil;
119 63
    }
64 +
    set vec.len -= 1;
65 +
    return vec.data[vec.len];
120 66
}
seed/radiance.rv64 +0 -0

Binary file changed.

seed/radiance.rv64.git +1 -1
1 -
b7b6da266e8ca28f893af0150567147d72c3bd9d4899c5e7a07e1a2309584aa2
1 +
f102340ee2c496ef3ae997c4a449df1e805d63e30eef07fe7aa562bf2884eab3