import stdio import testcheck # ============================================================ # Test 1: generic function with different int type specializations # ============================================================ def square[T](x: T) -> T: return x * x def test_generic_square_types(): testcheck.section("Test 1: generic square with different types") r1: int = square(5) r2: int = square(10) testcheck.check(r1 == 25 and r2 == 100, "square (5^2=25 10^2=100)", "square expect 25 100") # ============================================================ # Test 2: generic function with three parameters # ============================================================ def clamp[T](val: T, lo: T, hi: T) -> T: if val < lo: return lo if val > hi: return hi return val def test_generic_clamp(): testcheck.section("Test 2: generic clamp") r1: int = clamp(5, 0, 10) r2: int = clamp(-3, 0, 10) r3: int = clamp(15, 0, 10) testcheck.check(r1 == 5 and r2 == 0 and r3 == 10, "clamp (5 0 10)", "clamp expect 5 0 10") # ============================================================ # Test 3: generic class Stack[T] # ============================================================ class Stack[T](): data: t.CArray[int, 16] top: int def __init__(self): self.top = 0 def push(self, val: T): self.data[self.top] = int(val) self.top += 1 def pop(self) -> T: self.top -= 1 return T(self.data[self.top]) def is_empty(self) -> int: if self.top == 0: return 1 return 0 def size_of(self) -> sizet: return self.__sizeof__() def type_size(self) -> sizet: return Stack[T].__sizeof__() def test_generic_stack(): testcheck.section("Test 3: generic Stack[T]") # Annotate Stack[int] explicitly: T is not inferable (no-arg __init__) and # sets push/pop element width; implicit int default is forbidden. s = Stack[int]() s.push(10) s.push(20) s.push(30) r1: int = s.pop() r2: int = s.pop() r3: int = s.pop() testcheck.check(r1 == 30 and r2 == 20 and r3 == 10, "Stack (pop=30 20 10)", "Stack expect 30 20 10") # ============================================================ # Test 4: generic swap via pointer # ============================================================ class IntPair: a: int b: int def generic_swap(p: IntPair*): tmp: int = (*p).a (*p).a = (*p).b (*p).b = tmp def test_generic_swap(): testcheck.section("Test 4: generic swap via pointer") p: IntPair = IntPair() p.a = 100 p.b = 200 generic_swap(&p) testcheck.check(p.a == 200 and p.b == 100, "swap (a=200 b=100)", "swap expect 200 100") # ============================================================ # Test 5: generic iterable class Range[T] # ============================================================ class Range[T](): start: T end_val: T step: T def __init__(self, s: T, e: T, st: T): self.start = T(s) self.end_val = T(e) self.step = T(st) def sum_all(self) -> T: result: T = T(0) i: T = self.start while i < self.end_val: result = result + i i = i + self.step return result def test_generic_range(): testcheck.section("Test 5: generic Range[T]") r = Range(0, 10, 1) # sum 0..9 = 45 s: int = r.sum_all() testcheck.check(s == 45, "Range sum (0..9=45)", "Range sum expect 45") # ============================================================ # Test 6: generic function summing a fixed-size array argument # ============================================================ def array_sum(arr: [8]int, n: int) -> int: result: int = 0 for i in range(n): result += arr[i] return result def test_generic_array_sum(): testcheck.section("Test 6: array sum") arr: [8]int = [0] for i in range(8): arr[i] = (i + 1) * 10 s: int = array_sum(arr, 8) testcheck.check(s == 360, "array sum (360)", "array sum expect 360") # ============================================================ # Test 7: generic function returning the max of three values # ============================================================ def max_of_three[T](a: T, b: T, c_val: T) -> T: m: T = a if b > m: m = b if c_val > m: m = c_val return m def test_generic_max_three(): testcheck.section("Test 7: generic max of three") r1: int = max_of_three(1, 2, 3) r2: int = max_of_three(10, 30, 20) r3: int = max_of_three(50, 50, 50) testcheck.check(r1 == 3 and r2 == 30 and r3 == 50, "max3 (3 30 50)", "max3 expect 3 30 50") # ============================================================ # Test 8: generic container class with methods # ============================================================ class Container[T](): values: [8]int size: int def __init__(self): self.size = 0 def add(self, v: T): self.values[self.size] = int(v) self.size += 1 def get(self, idx: int) -> T: return T(self.values[idx]) def contains(self, v: T) -> int: for i in range(self.size): if self.values[i] == int(v): return 1 return 0 def total(self) -> T: result: T = T(0) for i in range(self.size): result = result + T(self.values[i]) return result def test_generic_container(): testcheck.section("Test 8: generic Container[T]") # Annotate Container[int] explicitly: no-arg __init__ gives no T to infer; # int is inferred from usage; storage is CArray[int, 8]. c = Container[int]() c.add(10) c.add(20) c.add(30) has20: int = c.contains(20) has99: int = c.contains(99) total: int = c.total() testcheck.check(has20 == 1 and has99 == 0 and total == 60, "Container (has20=1 has99=0 total=60)", "Container expect 1 0 60") # ============================================================ # Test 9: generic factorial # ============================================================ def factorial[T](n: T) -> T: result: T = T(1) i: T = T(2) while i <= n: result = result * i i = i + T(1) return result def test_generic_factorial(): testcheck.section("Test 9: generic factorial") r1: int = factorial(5) r2: int = factorial(10) testcheck.check(r1 == 120 and r2 == 3628800, "factorial (5!=120 10!=3628800)", "factorial expect 120 3628800") # ============================================================ # Test 10: generic accumulator class # ============================================================ class Accumulator[T](): total: T def __init__(self, start: T): self.total = T(start) def add_val(self, v: T): self.total = self.total + v def get_result(self) -> T: return self.total def test_generic_accumulator(): testcheck.section("Test 10: generic Accumulator[T]") a = Accumulator(0) a.add_val(10) a.add_val(20) a.add_val(30) r: int = a.get_result() testcheck.check(r == 60, "Accumulator (result=60)", "Accumulator expect 60") # ============================================================ # Test 11: generic struct sizeof; specialized Stack[int] is 68 bytes. # Checks obj.__sizeof__() and in-class self.__sizeof__(). # ============================================================ def test_generic_sizeof_bug(): testcheck.section("Test 11: generic sizeof (fixed)") # Same as Test 3: no-arg construction needs an explicit type argument; Stack[int] = 68 bytes. s = Stack[int]() s.push(10) sz: sizet = s.__sizeof__() inner_sz: sizet = s.size_of() type_sz: sizet = s.type_size() stdio.printf("Stack[int] obj.__sizeof__() = %lu, self.__sizeof__() = %lu, Stack[T].__sizeof__() = %lu (expect 68)\n", sz, inner_sz, type_sz) testcheck.check(sz == 68, "obj.__sizeof__() == 68 OK", "obj.__sizeof__() FAILED") testcheck.check(inner_sz == 68, "self.__sizeof__() == 68 OK", "self.__sizeof__() FAILED") testcheck.check(type_sz == 68, "Stack[T].__sizeof__() == 68 OK", "Stack[T].__sizeof__() FAILED") def main() -> int: testcheck.begin("GenericTest2: Advanced Generic Tests") test_generic_square_types() test_generic_clamp() test_generic_stack() test_generic_swap() test_generic_range() test_generic_array_sum() test_generic_max_three() test_generic_container() test_generic_factorial() test_generic_accumulator() test_generic_sizeof_bug() return testcheck.end()