zig/test/cases/generics.zig

138 lines
3.0 KiB
Zig

const assert = @import("std").debug.assert;
test "simple generic fn" {
assert(max(i32, 3, -1) == 3);
assert(max(f32, 0.123, 0.456) == 0.456);
assert(add(2, 3) == 5);
}
fn max(comptime T: type, a: T, b: T) -> T {
return if (a > b) a else b;
}
fn add(comptime a: i32, b: i32) -> i32 {
return (comptime a) + b;
}
const the_max = max(u32, 1234, 5678);
test "compile time generic eval" {
assert(the_max == 5678);
}
fn gimmeTheBigOne(a: u32, b: u32) -> u32 {
return max(u32, a, b);
}
fn shouldCallSameInstance(a: u32, b: u32) -> u32 {
return max(u32, a, b);
}
fn sameButWithFloats(a: f64, b: f64) -> f64 {
return max(f64, a, b);
}
test "fn with comptime args" {
assert(gimmeTheBigOne(1234, 5678) == 5678);
assert(shouldCallSameInstance(34, 12) == 34);
assert(sameButWithFloats(0.43, 0.49) == 0.49);
}
test "var params" {
assert(max_i32(12, 34) == 34);
assert(max_f64(1.2, 3.4) == 3.4);
}
comptime {
assert(max_i32(12, 34) == 34);
assert(max_f64(1.2, 3.4) == 3.4);
}
fn max_var(a: var, b: var) -> @typeOf(a + b) {
return if (a > b) a else b;
}
fn max_i32(a: i32, b: i32) -> i32 {
return max_var(a, b);
}
fn max_f64(a: f64, b: f64) -> f64 {
return max_var(a, b);
}
pub fn List(comptime T: type) -> type {
return SmallList(T, 8);
}
pub fn SmallList(comptime T: type, comptime STATIC_SIZE: usize) -> type {
return struct {
items: []T,
length: usize,
prealloc_items: [STATIC_SIZE]T,
};
}
test "function with return type type" {
var list: List(i32) = undefined;
var list2: List(i32) = undefined;
list.length = 10;
list2.length = 10;
assert(list.prealloc_items.len == 8);
assert(list2.prealloc_items.len == 8);
}
test "generic struct" {
var a1 = GenNode(i32) {.value = 13, .next = null,};
var b1 = GenNode(bool) {.value = true, .next = null,};
assert(a1.value == 13);
assert(a1.value == a1.getVal());
assert(b1.getVal());
}
fn GenNode(comptime T: type) -> type {
return struct {
value: T,
next: ?&GenNode(T),
fn getVal(n: &const GenNode(T)) -> T { return n.value; }
};
}
test "const decls in struct" {
assert(GenericDataThing(3).count_plus_one == 4);
}
fn GenericDataThing(comptime count: isize) -> type {
return struct {
const count_plus_one = count + 1;
};
}
test "use generic param in generic param" {
assert(aGenericFn(i32, 3, 4) == 7);
}
fn aGenericFn(comptime T: type, comptime a: T, b: T) -> T {
return a + b;
}
test "generic fn with implicit cast" {
assert(getFirstByte(u8, []u8 {13}) == 13);
assert(getFirstByte(u16, []u16 {0, 13}) == 0);
}
fn getByte(ptr: ?&const u8) -> u8 {return *??ptr;}
fn getFirstByte(comptime T: type, mem: []const T) -> u8 {
return getByte(@ptrCast(&const u8, &mem[0]));
}
const foos = []fn(var) -> bool { foo1, foo2 };
fn foo1(arg: var) -> bool { return arg; }
fn foo2(arg: var) -> bool { return !arg; }
test "array of generic fns" {
assert(foos[0](true));
assert(!foos[1](true));
}