const std = @import("std");
fn max(comptime T: type, a: T, b: T) T {
return if (a > b) a else b;
}
test "comptime max" {
const result_i32 = max(i32, 10, 20);
const result_f64 = max(f64, 3.14, 2.71);
try std.testing.expectEqual(result_i32, 20);
try std.testing.expect(result_f64 == 3.14);
}
fn createArray(comptime T: type, comptime size: usize) [size]T {
var arr: [size]T = undefined;
for (0..size) |i| {
arr[i] = @intCast(i);
}
return arr;
}
test "comptime array creation" {
const arr = createArray(u8, 5);
try std.testing.expectEqual(arr[0], 0);
try std.testing.expectEqual(arr[4], 4);
}
fn Factorial(comptime n: u32) u32 {
if (n == 0) return 1;
return n * Factorial(n - 1);
}
test "comptime factorial" {
try std.testing.expectEqual(Factorial(0), 1);
try std.testing.expectEqual(Factorial(5), 120);
try std.testing.expectEqual(Factorial(10), 3628800);
}
fn Fibonacci(comptime n: u32) u32 {
if (n <= 1) return n;
return Fibonacci(n - 1) + Fibonacci(n - 2);
}
test "comptime fibonacci" {
try std.testing.expectEqual(Fibonacci(0), 0);
try std.testing.expectEqual(Fibonacci(1), 1);
try std.testing.expectEqual(Fibonacci(10), 55);
}
fn has_method(comptime T: type, comptime name: []const u8) bool {
return @hasDecl(T, name);
}
const Person = struct {
name: []const u8,
age: u32,
pub fn greet(self: @This()) void {
std.debug.print("Hello, I'm {s}!\n", .{self.name});
}
pub fn get_age(self: @This()) u32 {
return self.age;
}
};
test "has_method check" {
try std.testing.expect(has_method(Person, "greet"));
try std.testing.expect(has_method(Person, "get_age"));
try std.testing.expect(!has_method(Person, "nonexistent"));
}
fn make_interface(comptime T: type, comptime methods: anytype) type {
return struct {
pub usingnamespace methods;
pub fn get_type() type {
return T;
}
};
}
fn SizedContainer(comptime T: type) type {
return struct {
pub fn len(self: T) usize {
return self.items.len;
}
pub fn is_empty(self: T) bool {
return self.len() == 0;
}
};
}
const MyList = struct {
items: []const i32,
pub usingnamespace SizedContainer(@This());
};
test "sized container" {
const list = MyList{ .items = &[_]i32{ 1, 2, 3, 4, 5 } };
try std.testing.expectEqual(list.len(), 5);
try std.testing.expect(!list.is_empty());
}
fn make_enum_with_values(comptime name: []const u8, comptime values: anytype) type {
_ = name;
const Type = @Type(.{
.Int = .{
.signedness = .unsigned,
.bits = 8,
},
});
_ = Type;
var enum_fields: [values.len]std.builtin.Type.EnumField = undefined;
for (values, 0..) |value, i| {
enum_fields[i] = .{
.name = value,
.value = i,
};
}
return @Type(.{
.Enum = .{
.tag_type = u8,
.fields = &enum_fields,
.decls = &.{},
.is_exhaustive = true,
},
});
}
test "comptime enum creation" {
const Color = make_enum_with_values("Color", &[_][]const u8{ "Red", "Green", "Blue" });
try std.testing.expectEqual(@intFromEnum(Color.Red), 0);
try std.testing.expectEqual(@intFromEnum(Color.Green), 1);
try std.testing.expectEqual(@intFromEnum(Color.Blue), 2);
}
fn make_bitflags(comptime T: type) type {
return struct {
pub const FlagType = T;
value: T,
pub fn init() @This() {
return .{ .value = 0 };
}
pub fn set(self: *@This(), flag: T) void {
self.value |= flag;
}
pub fn clear(self: *@This(), flag: T) void {
self.value &= ~flag;
}
pub fn is_set(self: @This(), flag: T) bool {
return (self.value & flag) != 0;
}
pub fn toggle(self: *@This(), flag: T) void {
self.value ^= flag;
}
};
}
const FileFlags = make_bitflags(u8);
const FileFlag = enum(u8) {
read = 1,
write = 2,
create = 4,
truncate = 8,
};
test "bitflags" {
var flags = FileFlags.init();
flags.set(@intFromEnum(FileFlag.read));
flags.set(@intFromEnum(FileFlag.write));
try std.testing.expect(flags.is_set(@intFromEnum(FileFlag.read)));
try std.testing.expect(flags.is_set(@intFromEnum(FileFlag.write)));
try std.testing.expect(!flags.is_set(@intFromEnum(FileFlag.create)));
}
fn Vector(comptime T: type, comptime size: usize) type {
return struct {
data: [size]T,
const Self = @This();
pub fn add(a: Self, b: Self) Self {
var result: Self = undefined;
for (0..size) |i| {
result.data[i] = a.data[i] + b.data[i];
}
return result;
}
pub fn scale(self: Self, scalar: T) Self {
var result: Self = undefined;
for (0..size) |i| {
result.data[i] = self.data[i] * scalar;
}
return result;
}
pub fn dot(a: Self, b: Self) T {
var result: T = 0;
for (0..size) |i| {
result += a.data[i] * b.data[i];
}
return result;
}
};
}
test "vector operations" {
const Vec3 = Vector(f32, 3);
const v1 = Vec3{ .data = .{ 1.0, 2.0, 3.0 } };
const v2 = Vec3{ .data = .{ 4.0, 5.0, 6.0 } };
const sum = Vec3.add(v1, v2);
try std.testing.expectApproxEqAbs(sum.data[0], 5.0, 0.001);
const scaled = v1.scale(2.0);
try std.testing.expectApproxEqAbs(scaled.data[0], 2.0, 0.001);
const dot = Vec3.dot(v1, v2);
try std.testing.expectApproxEqAbs(dot, 32.0, 0.001);
}
fn make_string_switch(comptime strings: []const []const u8) fn ([]const u8) ?usize {
return struct {
fn match(input: []const u8) ?usize {
inline for (strings, 0..) |str, i| {
if (std.mem.eql(u8, input, str)) {
return i;
}
}
return null;
}
}.match;
}
test "string switch" {
const matcher = make_string_switch(&[_][]const u8{ "one", "two", "three" });
try std.testing.expectEqual(matcher("one"), 0);
try std.testing.expectEqual(matcher("two"), 1);
try std.testing.expectEqual(matcher("four"), null);
}
fn generate_lookup_table(comptime size: usize) [size]u8 {
var table: [size]u8 = undefined;
for (0..size) |i| {
table[i] = @intCast(i * i);
}
return table;
}
const squares_table = generate_lookup_table(16);
test "lookup table" {
try std.testing.expectEqual(squares_table[5], 25);
try std.testing.expectEqual(squares_table[10], 100);
}
pub fn main() !void {
std.debug.print("Comptime examples compiled successfully\n", .{});
}