import "std/mem.zc" // ** Globals ** var DROP_COUNT = 0; // ** Structs & Helpers ** // trait Drop defined in std/mem.zc struct Resource { id: int; } impl Drop for Resource { fn drop(self) { println "Dropping Resource {self.id}"; DROP_COUNT = DROP_COUNT + 1; } } fn create_resource(id: int) { var r = Resource{id: id}; println "Created Resource {r.id}"; } struct Point { x: int; y: int; } fn distance(p1: Point, p2: Point) -> int { var dx = p2.x - p1.x; var dy = p2.y - p1.y; return dx * dx + dy * dy; } fn accumulate(start: int, count: int) -> int { var sum = start; var i = 0; while (i < count) { sum += i; i++; } return sum; } fn process_point(p: Point) -> Point { var result = Point { x: p.x * 2, y: p.y * 2 }; return result; } fn counter_immut() { var count = 0; { var inner = 10; inner = inner + 5; count = count + inner; } } struct Permissions { mask: U8; } impl Permissions { fn new(m: U8) -> Permissions { return Permissions { mask: m }; } fn bitor(self, other: Permissions) -> Permissions { return Permissions { mask: self.mask | other.mask }; } fn has(self, flag: U8) -> U8 { return (self.mask & flag) == flag; } } fn get_resource() -> int { println "resource opened"; return 42; } fn release_resource(id: int) { if (id == 42) println "resource 42 released"; else println "resource released (unknown)"; } fn test_defer_logic() { println "start test"; var x = get_resource() defer release_resource(it); println "using resource {x}"; } test "test_alloc" { "Testing alloc..."; var p = alloc(); *p = 42; f" alloc(): {*p}"; assert(*p == 42, "alloc failed"); free(p); var arr = alloc_n(5); for var i = 0; i < 5; i++ { arr[i] = i * 10; } f" alloc_n(5): [{arr[0]}, {arr[1]}, {arr[2]}, {arr[3]}, {arr[4]}]"; free(arr); " ✓ alloc works!"; } test "test_box" { "Testing Box..."; var b = Box::new(); *b.get() = 100; var val = *b.get(); f" Box value: {val}"; assert(val == 100, "Box failed"); b.free(); " ✓ Box works!"; } test "test_slice" { "Testing Slice..."; var data: int[5] = [1, 2, 3, 4, 5]; var s = Slice::new(&data[0], 5); f" Slice len: {(int)s.len}"; var v2 = s.get(2); f" Slice[2]: {v2}"; assert(v2 == 3, "Slice get failed"); s.set(0, 99); var v0 = s.get(0); f" After set: Slice[0] = {v0}"; assert(v0 == 99, "Slice set failed"); " ✓ Slice works!"; } test "test_swap" { "Testing swap..."; var a = 10; var b = 20; f" Before: a={a}, b={b}"; swap(&a, &b); f" After: a={a}, b={b}"; assert(a == 20 && b == 10, "swap failed"); " ✓ swap works!"; } test "test_autofree" { println "Testing autofree..."; { autofree var p = malloc(1024); if (p == NULL) { eprintln "Malloc failed!"; } strcpy(p, "Auto-freed string"); print f"Allocated: {p}"; println ""; } println "Exited block successfully (hopefully freed)"; { autofree var p1 = malloc(10); autofree var p2 = malloc(20); } } test "test_raii_drop" { DROP_COUNT = 0; "Entering scope..."; create_resource(1); "Exited scope."; assert(DROP_COUNT == 1, "Expected Drop to be called once"); { var r2 = Resource{id: 2}; var r3 = Resource{id: 3}; } assert(DROP_COUNT == 3, "Expected 3 total drops"); } test "test_immutable" { var p1 = Point { x: 0, y: 0 }; var p2 = Point { x: 3, y: 4 }; var dist = distance(p1, p2); "Distance: {dist}"; var sum = accumulate(10, 5); "Accumulate: {sum}"; var p3 = process_point(Point { x: 0, y: 0 }); "Processed: ({p3.x}, {p3.y})"; counter_immut(); } test "test_permissions" { const READ : U8 = 0b100; const WRITE : U8 = 0b010; const EXEC : U8 = 0b001; var p1 = Permissions::new(READ); "Start: {p1.mask} (Read)"; var p2 = Permissions::new(WRITE); var p_rw = p1 | p2; "Combined: {p_rw.mask} (Read + Write)"; if (p_rw.has(EXEC)) { " > Has Execute access"; } else { " > No Execute access"; } if (p_rw.has(READ)) { " > Has Read access"; } var p_all = p_rw | Permissions::new(EXEC); "Final: {p_all.mask} (All)"; } test "test_value_defer" { test_defer_logic(); println "end test"; }