From 6644d6ce3b19db9944ffbfc2be50d5c3a22a2967 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Sun, 9 Aug 2026 04:06:26 +0800 Subject: [PATCH] =?UTF-8?q?test:=20TestProject/2/3=20=E6=8B=86=E5=88=86?= =?UTF-8?q?=E4=B8=BA=2010=20=E4=B8=AA=E5=85=B7=E4=BD=93=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E9=A1=B9=E7=9B=AE;=20ZlibTest=20=E5=B9=B6=E5=85=A5=E6=A0=87?= =?UTF-8?q?=E5=87=86=20zlib=20=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新项目(各含 project.json + App/main.vp): - LoopMathTest/LogicFlowTest/ClassArrayTest/NumpyTest (原 TestProject) - HashLibTest (原 TestProject2 去 zlib) - GenericOopTest/EnumTest/MpoolOopTest/VectorGenericTest/FileIoTest (原 TestProject3) ZlibTest 增加"标准 zlib 库(zlib.pyzlib)" section 与 __zlib 并存验证。 --- Test/ClassArrayTest/App/class_test.vp | 245 +++++ Test/ClassArrayTest/App/main.vp | 47 + Test/ClassArrayTest/project.json | 29 + Test/EnumTest/App/enumtest.vp | 95 ++ Test/EnumTest/App/main.vp | 11 + Test/EnumTest/project.json | 29 + Test/FileIoTest/App/fileiotest.vp | 395 ++++++++ Test/FileIoTest/App/main.vp | 11 + Test/FileIoTest/project.json | 29 + Test/GenericOopTest/App/main.vp | 490 ++++++++++ Test/GenericOopTest/project.json | 29 + Test/HashLibTest/App/main.vp | 26 + Test/HashLibTest/project.json | 29 + Test/LogicFlowTest/App/config.vp | 24 + Test/LogicFlowTest/App/logic_test.vp | 372 ++++++++ Test/LogicFlowTest/App/main.vp | 106 +++ Test/LogicFlowTest/project.json | 29 + Test/LoopMathTest/App/config.vp | 24 + Test/LoopMathTest/App/main.vp | 79 ++ Test/LoopMathTest/App/test.vp | 298 ++++++ Test/LoopMathTest/project.json | 29 + Test/MpoolOopTest/App/main.vp | 11 + Test/MpoolOopTest/App/mpooltest.vp | 91 ++ Test/MpoolOopTest/project.json | 29 + Test/NumpyTest/App/main.vp | 11 + Test/NumpyTest/App/test_numpy.vp | 1087 ++++++++++++++++++++++ Test/NumpyTest/project.json | 29 + Test/VectorGenericTest/App/main.vp | 11 + Test/VectorGenericTest/App/vectortest.vp | 43 + Test/VectorGenericTest/project.json | 29 + Test/ZlibTest/App/main.vp | 7 + 31 files changed, 3774 insertions(+) create mode 100644 Test/ClassArrayTest/App/class_test.vp create mode 100644 Test/ClassArrayTest/App/main.vp create mode 100644 Test/ClassArrayTest/project.json create mode 100644 Test/EnumTest/App/enumtest.vp create mode 100644 Test/EnumTest/App/main.vp create mode 100644 Test/EnumTest/project.json create mode 100644 Test/FileIoTest/App/fileiotest.vp create mode 100644 Test/FileIoTest/App/main.vp create mode 100644 Test/FileIoTest/project.json create mode 100644 Test/GenericOopTest/App/main.vp create mode 100644 Test/GenericOopTest/project.json create mode 100644 Test/HashLibTest/App/main.vp create mode 100644 Test/HashLibTest/project.json create mode 100644 Test/LogicFlowTest/App/config.vp create mode 100644 Test/LogicFlowTest/App/logic_test.vp create mode 100644 Test/LogicFlowTest/App/main.vp create mode 100644 Test/LogicFlowTest/project.json create mode 100644 Test/LoopMathTest/App/config.vp create mode 100644 Test/LoopMathTest/App/main.vp create mode 100644 Test/LoopMathTest/App/test.vp create mode 100644 Test/LoopMathTest/project.json create mode 100644 Test/MpoolOopTest/App/main.vp create mode 100644 Test/MpoolOopTest/App/mpooltest.vp create mode 100644 Test/MpoolOopTest/project.json create mode 100644 Test/NumpyTest/App/main.vp create mode 100644 Test/NumpyTest/App/test_numpy.vp create mode 100644 Test/NumpyTest/project.json create mode 100644 Test/VectorGenericTest/App/main.vp create mode 100644 Test/VectorGenericTest/App/vectortest.vp create mode 100644 Test/VectorGenericTest/project.json diff --git a/Test/ClassArrayTest/App/class_test.vp b/Test/ClassArrayTest/App/class_test.vp new file mode 100644 index 0000000..4594f8b --- /dev/null +++ b/Test/ClassArrayTest/App/class_test.vp @@ -0,0 +1,245 @@ +import stdio +import stdint +import t, c + + +class SimpleData(t.Object): + x: t.CInt + y: t.CInt + + +class Point3D(t.Object): + x: t.CFloat + y: t.CFloat + z: t.CFloat + + +class Student(t.Object): + name: t.CChar | t.CPtr + age: t.CInt + score: t.CInt + + def __init__(self, n: t.CChar | t.CPtr, a: t.CInt, s: t.CInt): + self.name = n + self.age = a + self.score = s + + def get_age(self) -> t.CInt: + return self.age + + def get_score(self) -> t.CInt: + return self.score + + +class Counter(t.Object): + value: t.CInt + + def __init__(self, initial: t.CInt): + self.value = initial + + def increment(self): + self.value += 1 + + def get_value(self) -> t.CInt: + return self.value + + +class StackObj(t.Object): + data: t.CInt + next_ptr: t.CVoid | t.CPtr + + +def TestBasicDataClass(): + stdio.printf("=== Test Basic Data Class ===\n") + p: SimpleData = SimpleData() + p.x = 10 + p.y = 20 + stdio.printf("SimpleData: x=%d, y=%d\n", p.x, p.y) + + +def TestPoint3DClass(): + stdio.printf("=== Test Point3D Class ===\n") + pt: Point3D = Point3D() + pt.x = 1.5 + pt.y = 2.5 + pt.z = 3.5 + stdio.printf("Point3D: x=%.1f, y=%.1f, z=%.1f\n", pt.x, pt.y, pt.z) + + +def TestStudentClass(): + stdio.printf("=== Test Student Class ===\n") + s: Student = Student("Alice", 20, 95) + stdio.printf("Student: name=%s, age=%d, score=%d\n", s.name, s.age, s.score) + stdio.printf(" get_age()=%d, get_score()=%d\n", s.get_age(), s.get_score()) + + +def TestCounterClass(): + stdio.printf("=== Test Counter Class ===\n") + cnt: Counter = Counter(0) + stdio.printf("Initial value: %d\n", cnt.get_value()) + cnt.increment() + cnt.increment() + cnt.increment() + stdio.printf("After 3 increments: %d\n", cnt.get_value()) + + +def TestStackAllocation(): + stdio.printf("=== Test Stack Allocation ===\n") + obj1: SimpleData = SimpleData() + obj1.x = 100 + obj1.y = 200 + stdio.printf("Stack obj1: x=%d, y=%d\n", obj1.x, obj1.y) + + obj2: Point3D = Point3D() + obj2.x = 10.0 + obj2.y = 20.0 + obj2.z = 30.0 + stdio.printf("Stack obj2: x=%.1f, y=%.1f, z=%.1f\n", obj2.x, obj2.y, obj2.z) + + +def TestHeapAllocation(): + stdio.printf("=== Test Heap Allocation ===\n") + ptr: t.CVoid | t.CPtr = c.malloc(1024) + if ptr != 0: + stdio.printf("Allocated 1024 bytes at %p\n", ptr) + c.free(ptr) + stdio.printf("Freed memory\n") + else: + stdio.printf("malloc failed\n") + + +def TestHeapObjectWithInit(): + stdio.printf("=== Test Heap Object with Init ===\n") + mem_size: t.CSizeT = 256 + ptr: t.CVoid | t.CPtr = c.malloc(mem_size) + if ptr != 0: + stdio.printf("Allocated %d bytes\n", mem_size) + c.free(ptr) + else: + stdio.printf("malloc failed\n") + + +def TestMultipleStackObjects(): + stdio.printf("=== Test Multiple Stack Objects ===\n") + objs: SimpleData = SimpleData() + objs.x = 1 + objs.y = 2 + obj2: Point3D = Point3D() + obj2.x = 5.0 + obj2.y = 10.0 + obj2.z = 15.0 + obj3: Counter = Counter(42) + stdio.printf("objs: x=%d, y=%d\n", objs.x, objs.y) + stdio.printf("obj2: x=%.1f, y=%.1f, z=%.1f\n", obj2.x, obj2.y, obj2.z) + stdio.printf("obj3 initial: %d\n", obj3.get_value()) + obj3.increment() + obj3.increment() + stdio.printf("obj3 after 2 increments: %d\n", obj3.get_value()) + + +def TestImplicitInitCall(): + stdio.printf("=== Test Implicit Init Call ===\n") + stu1: Student = Student("Bob", 22, 88) + stu2: Student = Student("Charlie", 19, 77) + stdio.printf("stu1: name=%s, age=%d, score=%d\n", stu1.name, stu1.age, stu1.score) + stdio.printf("stu2: name=%s, age=%d, score=%d\n", stu2.name, stu2.age, stu2.score) + + +def TestClassWithBitFields(): + stdio.printf("=== Test Class with Bit Fields ===\n") + flags: StackObj = StackObj() + flags.data = 0 + flags.next_ptr = 0 + stdio.printf("StackObj: data=%d, next_ptr=%p\n", flags.data, flags.next_ptr) + + +def TestIntArray(): + stdio.printf("=== Test Int Array ===\n") + arr: t.CArray[t.CInt, 5] = t.CArray[t.CInt, 5]() + i: t.CInt = 0 + while i < 5: + arr[i] = i * 10 + i += 1 + i = 0 + while i < 5: + stdio.printf("arr[%d]=%d\n", i, arr[i]) + i += 1 + + +def TestFloatArray(): + stdio.printf("=== Test Float Array ===\n") + farr: t.CArray[t.CFloat, 4] = t.CArray[t.CFloat, 4]() + farr[0] = 1.5 + farr[1] = 2.5 + farr[2] = 3.5 + farr[3] = 4.5 + i: t.CInt = 0 + while i < 4: + stdio.printf("farr[%d]=%.1f\n", i, farr[i]) + i += 1 + + +def TestCharArray(): + stdio.printf("=== Test Char Array (String) ===\n") + str_arr: t.CArray[t.CChar, 32] = t.CArray[t.CChar, 32]() + str_arr[0] = 'H' + str_arr[1] = 'e' + str_arr[2] = 'l' + str_arr[3] = 'l' + str_arr[4] = 'o' + str_arr[5] = '\0' + stdio.printf("String: %s\n", str_arr) + + +def TestNestedArray(): + stdio.printf("=== Test Nested Array (Array of Arrays) ===\n") + row0: t.CArray[t.CInt, 3] = t.CArray[t.CInt, 3]() + row1: t.CArray[t.CInt, 3] = t.CArray[t.CInt, 3]() + row0[0] = 0 + row0[1] = 1 + row0[2] = 2 + row1[0] = 10 + row1[1] = 11 + row1[2] = 12 + i: t.CInt = 0 + while i < 3: + stdio.printf("row0[%d]=%d ", i, row0[i]) + i += 1 + stdio.printf("\n") + i = 0 + while i < 3: + stdio.printf("row1[%d]=%d ", i, row1[i]) + i += 1 + stdio.printf("\n") + + +def TestArrayWithStruct(): + stdio.printf("=== Test Array with Struct ===\n") + points: t.CArray[SimpleData, 3] = t.CArray[SimpleData, 3]() + i: t.CInt = 0 + while i < 3: + points[i].x = i * 10 + points[i].y = i * 100 + i += 1 + i = 0 + while i < 3: + stdio.printf("Point[%d]: x=%d, y=%d\n", i, points[i].x, points[i].y) + i += 1 + + +def TestArrayPointer(): + stdio.printf("=== Test Array Pointer ===\n") + data: t.CArray[t.CInt, 8] = t.CArray[t.CInt, 8]() + data[0] = 100 + data[1] = 200 + data[2] = 300 + ptr: t.CInt | t.CPtr = data + stdio.printf("ptr[0]=%d\n", ptr[0]) + stdio.printf("ptr[1]=%d\n", ptr[1]) + stdio.printf("ptr[2]=%d\n", ptr[2]) + + +def TestDynamicString(): + stdio.printf("=== Test Dynamic String ===\n") + name: str = "TransPyC" + stdio.printf("Hello %s!\n", name) \ No newline at end of file diff --git a/Test/ClassArrayTest/App/main.vp b/Test/ClassArrayTest/App/main.vp new file mode 100644 index 0000000..31b6121 --- /dev/null +++ b/Test/ClassArrayTest/App/main.vp @@ -0,0 +1,47 @@ +import t, c +import testcheck +import class_test + + +def main() -> t.CInt: + testcheck.begin("ClassArrayTest: 类与数组测试") + + testcheck.section("CLASS TESTS") + class_test.TestBasicDataClass() + testcheck.ok("TestBasicDataClass") + class_test.TestPoint3DClass() + testcheck.ok("TestPoint3DClass") + class_test.TestStudentClass() + testcheck.ok("TestStudentClass") + class_test.TestCounterClass() + testcheck.ok("TestCounterClass") + class_test.TestStackAllocation() + testcheck.ok("TestStackAllocation") + class_test.TestHeapAllocation() + testcheck.ok("TestHeapAllocation") + class_test.TestHeapObjectWithInit() + testcheck.ok("TestHeapObjectWithInit") + class_test.TestMultipleStackObjects() + testcheck.ok("TestMultipleStackObjects") + class_test.TestImplicitInitCall() + testcheck.ok("TestImplicitInitCall") + class_test.TestClassWithBitFields() + testcheck.ok("TestClassWithBitFields") + + testcheck.section("ARRAY TESTS") + class_test.TestIntArray() + testcheck.ok("TestIntArray") + class_test.TestFloatArray() + testcheck.ok("TestFloatArray") + class_test.TestCharArray() + testcheck.ok("TestCharArray") + class_test.TestNestedArray() + testcheck.ok("TestNestedArray") + class_test.TestArrayWithStruct() + testcheck.ok("TestArrayWithStruct") + class_test.TestArrayPointer() + testcheck.ok("TestArrayPointer") + class_test.TestDynamicString() + testcheck.ok("TestDynamicString") + + return testcheck.end() diff --git a/Test/ClassArrayTest/project.json b/Test/ClassArrayTest/project.json new file mode 100644 index 0000000..788543d --- /dev/null +++ b/Test/ClassArrayTest/project.json @@ -0,0 +1,29 @@ +{ + "$schema": "https://raw.githubusercontent.com/TermiNexus/TransPyC/main/schemas/project-schema.json", + "name": "ClassArrayTest", + "version": "1.0.0", + "source_dir": "./App", + "build_dir": "./.tpv_build", + "compiler": { + "cmd": "llc", + "flags": ["-filetype=obj", "-relocation-model=pic"] + }, + "linker": { + "cmd": "clang++", + "flags": ["-Wl,--allow-multiple-definition", "-Wl,--unresolved-symbols=ignore-in-object-files", "-lmsvcrt", "-lucrt", "-lpthread", "-lmingwex", "-lkernel32", "-luser32", "-latomic"], + "output": "ClassArrayTest.exe" + }, + "includes": [ + "../../includes" + ], + "target": { + "triple": "x86_64-pc-windows-gnu", + "datalayout": "e-m:w-p270:32:32-p271:32:32-p272:64:64-f80:128-n8:16:32:64-S128" + }, + "options": { + "slice_level": 3, + "sha1_slice_level": 1, + "target": "llvm", + "strict_mode": true + } +} diff --git a/Test/EnumTest/App/enumtest.vp b/Test/EnumTest/App/enumtest.vp new file mode 100644 index 0000000..c935a48 --- /dev/null +++ b/Test/EnumTest/App/enumtest.vp @@ -0,0 +1,95 @@ +import t, c +from t import CInt, CPtr, CChar, CInt32T, CExport +import viperlib +import stdlib + + +class Color(t.CEnum): + Red = 0 + Green = 1 + Blue = 2 + + +class Option(t.REnum): + class Some: + value: CInt + Empty = 1 + + +class Result(t.REnum): + class Ok: + value: CInt + class Err: + msg: t.CChar | CPtr + + +class GeoShape(t.REnum): + class GCircle: + radius: CInt + class GRect: + w: CInt + h: CInt + class GPoint: + x: CInt + y: CInt + + +def enum_main() -> CInt: + buf: CChar | CPtr = CPtr(stdlib.malloc(256)) + + c1: CInt = Color.Red + c2: CInt = Color.Green + c3: CInt = Color.Blue + viperlib.snprintf(buf, 256, "CEnum: Red=%d Green=%d Blue=%d", c1, c2, c3) + print(buf) + + opt: Option = Option.Some(42) + match opt: + case Option.Some(v): + viperlib.snprintf(buf, 256, "Option.Some: value=%d", v) + print(buf) + case Option.Empty(): + pass + + res1: Result = Result.Ok(100) + match res1: + case Result.Ok(v): + viperlib.snprintf(buf, 256, "Result.Ok: value=%d", v) + print(buf) + case Result.Err(e): + pass + + res2: Result = Result.Err("not found") + match res2: + case Result.Ok(v): + pass + case Result.Err(e): + viperlib.snprintf(buf, 256, "Result.Err: msg=%s", e) + print(buf) + + s1: GeoShape = GeoShape.GCircle(5) + match s1: + case GeoShape.GCircle(r): + viperlib.snprintf(buf, 256, "GeoShape.GCircle: radius=%d", r) + print(buf) + case _: + pass + + s2: GeoShape = GeoShape.GRect(10, 20) + match s2: + case GeoShape.GRect(w, h): + viperlib.snprintf(buf, 256, "GeoShape.GRect: w=%d h=%d", w, h) + print(buf) + case _: + pass + + s3: GeoShape = GeoShape.GPoint(3, 4) + match s3: + case GeoShape.GPoint(x, y): + viperlib.snprintf(buf, 256, "GeoShape.GPoint: x=%d y=%d", x, y) + print(buf) + case _: + pass + + stdlib.free(buf) + return 0 diff --git a/Test/EnumTest/App/main.vp b/Test/EnumTest/App/main.vp new file mode 100644 index 0000000..dd8eb58 --- /dev/null +++ b/Test/EnumTest/App/main.vp @@ -0,0 +1,11 @@ +import t, c +import testcheck +import enumtest + + +def main() -> t.CInt | t.CExport: + testcheck.begin("EnumTest: 枚举类型测试") + testcheck.section("Enum") + enumtest.enum_main() + testcheck.ok("Enum 测试完成") + return testcheck.end() diff --git a/Test/EnumTest/project.json b/Test/EnumTest/project.json new file mode 100644 index 0000000..95654dc --- /dev/null +++ b/Test/EnumTest/project.json @@ -0,0 +1,29 @@ +{ + "$schema": "https://raw.githubusercontent.com/TermiNexus/TransPyC/main/schemas/project-schema.json", + "name": "EnumTest", + "version": "1.0.0", + "source_dir": "./App", + "build_dir": "./.tpv_build", + "compiler": { + "cmd": "llc", + "flags": ["-filetype=obj", "-relocation-model=pic"] + }, + "linker": { + "cmd": "clang++", + "flags": ["-Wl,--allow-multiple-definition", "-Wl,--unresolved-symbols=ignore-in-object-files", "-lmsvcrt", "-lucrt", "-lpthread", "-lmingwex", "-lkernel32", "-luser32", "-latomic"], + "output": "EnumTest.exe" + }, + "includes": [ + "../../includes" + ], + "target": { + "triple": "x86_64-pc-windows-gnu", + "datalayout": "e-m:w-p270:32:32-p271:32:32-p272:64:64-f80:128-n8:16:32:64-S128" + }, + "options": { + "slice_level": 3, + "sha1_slice_level": 1, + "target": "llvm", + "strict_mode": true + } +} diff --git a/Test/FileIoTest/App/fileiotest.vp b/Test/FileIoTest/App/fileiotest.vp new file mode 100644 index 0000000..98d6e77 --- /dev/null +++ b/Test/FileIoTest/App/fileiotest.vp @@ -0,0 +1,395 @@ +import t, c +from t import CInt, CInt32T, CUInt32T, CPtr, CChar, CExport +from stdint import * +import stdlib +import viperlib +import w32.win32base +import w32.win32file +import w32.win32console +import w32.fileio +from w32.fileio import File, FileW, MODE, FRESULT, SEEK_SET, SEEK_CUR, SEEK_END + + +BUF_SIZE: t.CDefine = 4096 + + +def fileio_main(): + buf: bytes = stdlib.malloc(256) + write_buf: bytes = stdlib.malloc(BUF_SIZE) + read_buf: bytes = stdlib.malloc(BUF_SIZE) + bytes_written: ULONG = 0 + bytes_read: ULONG = 0 + + w32.win32console.SetConsoleCP(65001) + w32.win32console.SetConsoleOutputCP(65001) + + hFile: w32.win32base.HANDLE = w32.win32file.CreateFileA( + "testfile.txt", + w32.win32file.GENERIC_WRITE, + w32.win32file.FILE_SHARE_READ, + None, + w32.win32file.CREATE_ALWAYS, + w32.win32file.FILE_ATTRIBUTE_NORMAL, + None + ) + + if hFile == w32.win32base.INVALID_HANDLE_VALUE: + print("Failed to create file") + return + + viperlib.snprintf(write_buf, BUF_SIZE, "Hello from TransPyC Win32 FileIO!\nLine 2: %d + %d = %d\n", 10, 20, 30) + write_len: ULONG = 0 + i: CInt = 0 + ch: bytes = write_buf + while i < BUF_SIZE: + if CInt(c.Deref(ch)) == 0: + break + write_len = write_len + 1 + i = i + 1 + ch = ch + 1 + + result: BOOL = w32.win32file.WriteFile(hFile, write_buf, write_len, c.Addr(bytes_written), None) + if result == 0: + print("WriteFile failed") + else: + viperlib.snprintf(buf, 256, "Written %d bytes to testfile.txt", bytes_written) + print(buf) + + w32.win32file.FlushFileBuffers(hFile) + w32.win32base.CloseHandle(hFile) + + hFile = w32.win32file.CreateFileA( + "testfile.txt", + w32.win32file.GENERIC_READ, + w32.win32file.FILE_SHARE_READ, + None, + w32.win32file.OPEN_EXISTING, + w32.win32file.FILE_ATTRIBUTE_NORMAL, + None + ) + + if hFile == w32.win32base.INVALID_HANDLE_VALUE: + print("Failed to open file for reading") + return + + read_len: ULONG = 0 + result = w32.win32file.ReadFile(hFile, read_buf, BUF_SIZE - 1, c.Addr(read_len), None) + if result == 0: + print("ReadFile failed") + else: + viperlib.snprintf(buf, 256, "Read %d bytes from testfile.txt", read_len) + print(buf) + + read_ptr: bytes = read_buf + read_ptr = read_ptr + read_len + c.DerefAs(read_ptr, 0) + print("--- File content ---") + print(read_buf) + print("--- End ---") + + fileSize: ULONG = w32.win32file.GetFileSize(hFile, None) + viperlib.snprintf(buf, 256, "File size: %d bytes", fileSize) + print(buf) + + w32.win32base.CloseHandle(hFile) + + attrs: ULONG = w32.win32file.GetFileAttributesA("testfile.txt") + if attrs == w32.win32base.INVALID_HANDLE_VALUE: + print("GetFileAttributes failed") + else: + viperlib.snprintf(buf, 256, "File attributes: 0x%X", attrs) + print(buf) + + w32.win32file.DeleteFileA("testfile.txt") + print("File deleted") + + stdlib.free(write_buf) + stdlib.free(read_buf) + + print("=== OOP FileIO: with context manager ===") + fileio_with_test() + + print("=== OOP FileIO: f handle style ===") + fileio_handle_test() + + print("=== OOP FileIO: RP/WP/AP modes ===") + fileio_rw_test() + + +def fileio_with_test(): + buf: bytes = stdlib.malloc(256) + write_buf: bytes = stdlib.malloc(BUF_SIZE) + read_buf: bytes = stdlib.malloc(BUF_SIZE) + + with File("oop_with.txt", MODE.W) as f: + viperlib.snprintf(write_buf, BUF_SIZE, "with context manager test!\nLine 2: %d\n", 42) + n: LONG = f.write_str(write_buf) + if n < 0: + print("[with] write failed") + else: + viperlib.snprintf(buf, 256, "[with] wrote %d bytes", n) + print(buf) + + with File("oop_with.txt", MODE.R) as f: + n = f.read_all(read_buf, BUF_SIZE) + if n < 0: + print("[with] read failed") + else: + viperlib.snprintf(buf, 256, "[with] read %d bytes", n) + print(buf) + print("[with] content:") + print(read_buf) + + with File("oop_with.txt", MODE.R) as f: + line1_len: LONG = f.readline(buf, 256) + viperlib.snprintf(read_buf, BUF_SIZE, "[with] Line1(%d): ", line1_len) + print(read_buf) + print(buf) + line2_len: LONG = f.readline(buf, 256) + viperlib.snprintf(read_buf, BUF_SIZE, "[with] Line2(%d): ", line2_len) + print(read_buf) + print(buf) + + with File("oop_with.txt", MODE.A) as f: + f.write_str("Appended line!\n") + + with File("oop_with.txt", MODE.R) as f: + n = f.read_all(read_buf, BUF_SIZE) + print("[with] after append:") + print(read_buf) + + with File("oop_with.txt", MODE.R) as f: + sz: LONGLONG = f.size() + pos: LONG = f.tell() + viperlib.snprintf(buf, 256, "[with] Size=%lld Pos=%d", sz, pos) + print(buf) + f.seek(5, SEEK_SET) + pos = f.tell() + viperlib.snprintf(buf, 256, "[with] After seek: Pos=%d", pos) + print(buf) + + w32.win32file.DeleteFileA("oop_with.txt") + print("[with] test file deleted") + + stdlib.free(buf) + stdlib.free(write_buf) + stdlib.free(read_buf) + + +def fileio_handle_test(): + buf: bytes = stdlib.malloc(256) + write_buf: bytes = stdlib.malloc(BUF_SIZE) + read_buf: bytes = stdlib.malloc(BUF_SIZE) + + fw: File = File("oop_handle.txt", MODE.W) + viperlib.snprintf(write_buf, BUF_SIZE, "f handle style test!\nLine 2: %d\n", 99) + n: LONG = fw.write_str(write_buf) + viperlib.snprintf(buf, 256, "[handle] wrote %d bytes", n) + print(buf) + fw.flush() + fw.close() + + fr: File = File("oop_handle.txt", MODE.R) + n = fr.read_all(read_buf, BUF_SIZE) + viperlib.snprintf(buf, 256, "[handle] read %d bytes", n) + print(buf) + print("[handle] content:") + print(read_buf) + fr.close() + + fr2: File = File("oop_handle.txt", MODE.R) + line1_len: LONG = fr2.readline(buf, 256) + viperlib.snprintf(read_buf, BUF_SIZE, "[handle] Line1(%d): ", line1_len) + print(read_buf) + print(buf) + line2_len: LONG = fr2.readline(buf, 256) + viperlib.snprintf(read_buf, BUF_SIZE, "[handle] Line2(%d): ", line2_len) + print(read_buf) + print(buf) + fr2.close() + + fa: File = File("oop_handle.txt", MODE.A) + fa.write_str("Appended by handle!\n") + fa.close() + + fr3: File = File("oop_handle.txt", MODE.R) + n = fr3.read_all(read_buf, BUF_SIZE) + print("[handle] after append:") + print(read_buf) + fr3.close() + + fr4: File = File("oop_handle.txt", MODE.R) + sz: LONGLONG = fr4.size() + pos: LONG = fr4.tell() + viperlib.snprintf(buf, 256, "[handle] Size=%lld Pos=%d", sz, pos) + print(buf) + fr4.seek(5, SEEK_SET) + pos = fr4.tell() + viperlib.snprintf(buf, 256, "[handle] After seek: Pos=%d", pos) + print(buf) + fr4.close() + + w32.win32file.DeleteFileA("oop_handle.txt") + print("[handle] test file deleted") + + stdlib.free(buf) + stdlib.free(write_buf) + stdlib.free(read_buf) + + +def fileio_rw_test(): + buf: bytes = stdlib.malloc(256) + + fw: File = File("rw_test.txt", MODE.W) + fw.write_str("original content\n") + fw.close() + + frp: File = File("rw_test.txt", MODE.RP) + n: LONG = frp.read_all(buf, 256) + viperlib.snprintf(buf, 256, "[rp] read %d bytes", n) + print(buf) + + frp.seek(0, SEEK_END) + frp.write_str("appended via RP\n") + frp.seek(0, SEEK_SET) + n = frp.read_all(buf, 256) + print("[rp] after RP append:") + print(buf) + frp.close() + + fwp: File = File("rw_test.txt", MODE.WP) + fwp.write_str("truncated + new\n") + fwp.seek(0, SEEK_SET) + n = fwp.read_all(buf, 256) + print("[wp] WP (truncate+read):") + print(buf) + fwp.close() + + fap: File = File("rw_test.txt", MODE.AP) + fap.write_str("a+ appended\n") + fap.seek(0, SEEK_SET) + n = fap.read_all(buf, 256) + print("[ap] AP (append+read):") + print(buf) + fap.close() + + w32.win32file.DeleteFileA("rw_test.txt") + print("[rw] test file deleted") + + print("=== OOP FileIO: wide char (u\"...\") ===") + fileio_wide_test() + + stdlib.free(buf) + + +def fileio_wide_test(): + buf: bytes = stdlib.malloc(256) + + fw: File = File("wide_test.txt", MODE.W) + fw.write_str("wide char test\n") + fw.close() + + fw2: FileW = FileW(u"wide_test.txt", MODE.R) + n: LONG = fw2.read_all(buf, 256) + viperlib.snprintf(buf, 256, "[wide] read %d bytes", n) + print(buf) + fw2.close() + + w32.win32file.DeleteFileA("wide_test.txt") + print("[wide] test file deleted") + + stdlib.free(buf) + + print("=== OOP FileIO: Chinese filename & content (u\"...\" = WCHAR_T) ===") + fileio_chinese_test() + + +def fileio_chinese_test(): + buf: bytes = stdlib.malloc(512) + bytes_written: ULONG = 0 + + # === T1: Chinese filename (WCHAR_T) + ANSI content === + print("[chinese] T1: Chinese filename + ANSI content") + fw: FileW = FileW(u"中文文件.txt", MODE.W) + if fw.closed: + print("[chinese] T1: create failed") + else: + fw.write_str("Hello from Chinese filename!\n") + fw.close() + + fr: FileW = FileW(u"中文文件.txt", MODE.R) + n: LONG = fr.read_all(buf, 512) + viperlib.snprintf(buf, 256, "[chinese] T1: read %d bytes", n) + print(buf) + print("[chinese] T1 content:") + print(buf) + fr.close() + + w32.win32file.DeleteFileW(u"中文文件.txt") + print("[chinese] T1: deleted") + + # === T2: Chinese filename + Chinese wide content (WCHAR_T) === + print("[chinese] T2: Chinese filename + Chinese wide content") + fw2: FileW = FileW(u"中文内容.txt", MODE.W) + if fw2.closed: + print("[chinese] T2: create failed") + else: + # u"你好世界\n" = 5 WCHARs = 10 bytes (UTF-16LE) + w32.win32file.WriteFile(fw2.handle, u"你好世界\n", 10, c.Addr(bytes_written), None) + viperlib.snprintf(buf, 256, "[chinese] T2: wrote %d WCHAR bytes", bytes_written) + print(buf) + fw2.close() + + fr2: FileW = FileW(u"中文内容.txt", MODE.R) + n = fr2.read_all(buf, 512) + viperlib.snprintf(buf, 256, "[chinese] T2: read %d bytes (UTF-16LE)", n) + print(buf) + fr2.close() + + w32.win32file.DeleteFileW(u"中文内容.txt") + print("[chinese] T2: deleted") + + # === T3: Chinese filename + mixed ANSI + wide content === + print("[chinese] T3: Chinese filename + mixed content") + fw3: FileW = FileW(u"混合测试.txt", MODE.WP) + if fw3.closed: + print("[chinese] T3: create failed") + else: + fw3.write_str("ASCII line\n") + # u"中文行\n" = 4 WCHARs = 8 bytes (UTF-16LE) + w32.win32file.WriteFile(fw3.handle, u"中文行\n", 8, c.Addr(bytes_written), None) + fw3.seek(0, SEEK_SET) + n: LONG = fw3.read_all(buf, 512) + viperlib.snprintf(buf, 256, "[chinese] T3: total %d bytes", n) + print(buf) + fw3.close() + + w32.win32file.DeleteFileW(u"混合测试.txt") + print("[chinese] T3: deleted") + + # === T4: Chinese filename + Chinese content via WriteConsoleW === + print("[chinese] T4: Write wide content and print via WriteConsoleW") + fw4: FileW = FileW(u"控制台测试.txt", MODE.W) + if fw4.closed: + print("[chinese] T4: create failed") + else: + # u"你好,世界!\n" = 7 WCHARs = 14 bytes (UTF-16LE) + w32.win32file.WriteFile(fw4.handle, u"你好,世界!\n", 14, c.Addr(bytes_written), None) + viperlib.snprintf(buf, 256, "[chinese] T4: wrote %d WCHAR bytes", bytes_written) + print(buf) + fw4.close() + + fr4: FileW = FileW(u"控制台测试.txt", MODE.R) + n = fr4.read_all(buf, 512) + viperlib.snprintf(buf, 256, "[chinese] T4: read %d bytes", n) + print(buf) + # Print wide content to console using WriteConsoleW + chars_written: ULONG = 0 + hOut: w32.win32base.HANDLE = w32.win32file.GetStdHandle(w32.win32file.STD_OUTPUT_HANDLE) + w32.win32console.WriteConsoleW(hOut, u"你好,世界!\n", 7, c.Addr(chars_written), None) + fr4.close() + + w32.win32file.DeleteFileW(u"控制台测试.txt") + print("[chinese] T4: deleted") + + stdlib.free(buf) diff --git a/Test/FileIoTest/App/main.vp b/Test/FileIoTest/App/main.vp new file mode 100644 index 0000000..6394d79 --- /dev/null +++ b/Test/FileIoTest/App/main.vp @@ -0,0 +1,11 @@ +import t, c +import testcheck +import fileiotest + + +def main() -> t.CInt | t.CExport: + testcheck.begin("FileIoTest: Win32 FileIO 测试") + testcheck.section("Win32 FileIO") + fileiotest.fileio_main() + testcheck.ok("Win32 FileIO 测试完成") + return testcheck.end() diff --git a/Test/FileIoTest/project.json b/Test/FileIoTest/project.json new file mode 100644 index 0000000..7d1b9b7 --- /dev/null +++ b/Test/FileIoTest/project.json @@ -0,0 +1,29 @@ +{ + "$schema": "https://raw.githubusercontent.com/TermiNexus/TransPyC/main/schemas/project-schema.json", + "name": "FileIoTest", + "version": "1.0.0", + "source_dir": "./App", + "build_dir": "./.tpv_build", + "compiler": { + "cmd": "llc", + "flags": ["-filetype=obj", "-relocation-model=pic"] + }, + "linker": { + "cmd": "clang++", + "flags": ["-Wl,--allow-multiple-definition", "-Wl,--unresolved-symbols=ignore-in-object-files", "-lmsvcrt", "-lucrt", "-lpthread", "-lmingwex", "-lkernel32", "-luser32", "-latomic"], + "output": "FileIoTest.exe" + }, + "includes": [ + "../../includes" + ], + "target": { + "triple": "x86_64-pc-windows-gnu", + "datalayout": "e-m:w-p270:32:32-p271:32:32-p272:64:64-f80:128-n8:16:32:64-S128" + }, + "options": { + "slice_level": 3, + "sha1_slice_level": 1, + "target": "llvm", + "strict_mode": true + } +} diff --git a/Test/GenericOopTest/App/main.vp b/Test/GenericOopTest/App/main.vp new file mode 100644 index 0000000..fa7af94 --- /dev/null +++ b/Test/GenericOopTest/App/main.vp @@ -0,0 +1,490 @@ +from stdint import * +import w32.win32console +import t, c +from t import CInt, CPtr, CChar, CInt32T, CUInt64T, CFloat64T, CExport, State +import viperlib +import stdlib +import testcheck + + +# === 函数泛型 === + +def add[T](a: T, b: T) -> T: + return a + b + +def add_u64[T](a: T, b: T, c: CUInt64T) -> T: + return a + b + T(c) + +def fxi[T1, T2](a: T1, b: T2) -> T1: + return a + fxi2(a, b, CUInt64T(178900)) + +def fxi2[T1, T2, T3](a: T1, b: T2, c: T3) -> T1: + return a + T1(b) + T1(c) + +def wrap_add[T](a: T, b: T) -> T: + return add(a, b) + +def double_add[T](a: T, b: T) -> T: + return add(a, b) + add(a, b) + + +# === 结构体泛型 === + +class A[T](): + def __init__(self, a: T): + self.a = T(a) + def get_a(self) -> T: + return self.a + +class Pair[T1, T2](): + def __init__(self, first: T1, second: T2): + self.first = T1(first) + self.second = T2(second) + def get_first(self) -> T1: + return self.first + def get_second(self) -> T2: + return self.second + +class Calculator[T](): + def __init__(self, init_val: T): + self.val = T(init_val) + def compute(self, other: T) -> T: + return add(self.val, other) + def double_compute(self, other: T) -> T: + return double_add(self.val, other) + +class Container[T](): + def __init__(self, v: T): + self.value = T(v) + self.flag = CInt32T(1) + def get_value(self) -> T: + return self.value + def get_flag(self) -> CInt32T: + return self.flag + + +# === OOP 继承 + 虚方法 === + +@t.CVTable +class Shape: + def __init__(self, x: CFloat64T, y: CFloat64T): + self.x = x + self.y = y + def area(self) -> CFloat64T: + return 0.0 + def perimeter(self) -> CFloat64T: + return 0.0 + def describe(self) -> CFloat64T: + return self.area() + self.perimeter() + +@t.CVTable +class Circle(Shape): + def __init__(self, x: CFloat64T, y: CFloat64T, r: CFloat64T): + self.x = x + self.y = y + self.r = r + def area(self) -> CFloat64T: + return 3.14159265 * self.r * self.r + def perimeter(self) -> CFloat64T: + return 2.0 * 3.14159265 * self.r + def scale(self, factor: CFloat64T) -> 'Circle' | CPtr: + self.r = self.r * factor + return t.CVoid(c.Addr(self), CPtr) + def move(self, dx: CFloat64T, dy: CFloat64T) -> 'Circle' | CPtr: + self.x = self.x + dx + self.y = self.y + dy + return t.CVoid(c.Addr(self), CPtr) + +@t.CVTable +class Rect(Shape): + def __init__(self, x: CFloat64T, y: CFloat64T, w: CFloat64T, h: CFloat64T): + self.x = x + self.y = y + self.w = w + self.h = h + def area(self) -> CFloat64T: + return self.w * self.h + def perimeter(self) -> CFloat64T: + return 2.0 * (self.w + self.h) + def scale(self, factor: CFloat64T) -> 'Rect' | CPtr: + self.w = self.w * factor + self.h = self.h * factor + return t.CVoid(c.Addr(self), CPtr) + + +# === 运算符重载 + 链式调用(堆分配) === + +class Vec2: + x: CFloat64T + y: CFloat64T + + def __new__() -> 'Vec2' | CPtr: + return t.CVoid(t.CUInt64T(stdlib.malloc(16)), CPtr) + + def __init__(self, x: CFloat64T, y: CFloat64T): + self.x = x + self.y = y + + def __add__(self, b: 'Vec2' | CPtr) -> 'Vec2' | CPtr: + return Vec2(self.x + b.x, self.y + b.y) + + def __sub__(self, b: 'Vec2' | CPtr) -> 'Vec2' | CPtr: + return Vec2(self.x - b.x, self.y - b.y) + + def __mul__(self, s: CFloat64T) -> 'Vec2' | CPtr: + return Vec2(self.x * s, self.y * s) + + def __neg__(self) -> 'Vec2' | CPtr: + return Vec2(-self.x, -self.y) + + def dot(self, b: 'Vec2' | CPtr) -> CFloat64T: + return self.x * b.x + self.y * b.y + + def len_sq(self) -> CFloat64T: + return self.x * self.x + self.y * self.y + + +class Vec3: + x: CFloat64T + y: CFloat64T + z: CFloat64T + + def __new__() -> 'Vec3' | CPtr: + return t.CVoid(t.CUInt64T(stdlib.malloc(24)), CPtr) + + def __init__(self, x: CFloat64T, y: CFloat64T, z: CFloat64T): + self.x = x + self.y = y + self.z = z + + def __add__(self, b: 'Vec3' | CPtr) -> 'Vec3' | CPtr: + return Vec3(self.x + b.x, self.y + b.y, self.z + b.z) + + def __sub__(self, b: 'Vec3' | CPtr) -> 'Vec3' | CPtr: + return Vec3(self.x - b.x, self.y - b.y, self.z - b.z) + + def __mul__(self, s: CFloat64T) -> 'Vec3' | CPtr: + return Vec3(self.x * s, self.y * s, self.z * s) + + def __neg__(self) -> 'Vec3' | CPtr: + return Vec3(-self.x, -self.y, -self.z) + + def dot(self, b: 'Vec3' | CPtr) -> CFloat64T: + return self.x * b.x + self.y * b.y + self.z * b.z + + def cross(self, b: 'Vec3' | CPtr) -> 'Vec3' | CPtr: + return Vec3(self.y * b.z - self.z * b.y, + self.z * b.x - self.x * b.z, + self.x * b.y - self.y * b.x) + + def len_sq(self) -> CFloat64T: + return self.dot(self) + + +# === 独立类(非继承) === + +@t.CVTable +class Dog: + def __init__(self, name_val: CInt, bark_power: CInt32T): + self.name_val = name_val + self.health = CInt32T(100) + self.bark_power = bark_power + def speak(self) -> CInt: + return 1 + def bite(self) -> CInt32T: + return self.bark_power + def take_damage(self, dmg: CInt32T) -> 'Dog' | CPtr: + self.health = self.health - dmg + return t.CVoid(c.Addr(self), CPtr) + def is_alive(self) -> CInt: + if self.health > 0: + return 1 + return 0 + +@t.CVTable +class Cat: + def __init__(self, name_val: CInt, lives: CInt32T): + self.name_val = name_val + self.health = CInt32T(80) + self.lives = lives + def speak(self) -> CInt: + return 2 + def scratch(self) -> CInt32T: + return CInt32T(15) + def take_damage(self, dmg: CInt32T) -> 'Cat' | CPtr: + self.health = self.health - dmg + return t.CVoid(c.Addr(self), CPtr) + def is_alive(self) -> CInt: + if self.health > 0: + return 1 + return 0 + + +# === 嵌套对象组合(堆分配) === + +class Transform: + px: CFloat64T + py: CFloat64T + pz: CFloat64T + scale_x: CFloat64T + scale_y: CFloat64T + scale_z: CFloat64T + + def __new__() -> 'Transform' | CPtr: + return t.CVoid(t.CUInt64T(stdlib.malloc(48)), CPtr) + + def __init__(self, px: CFloat64T, py: CFloat64T, pz: CFloat64T): + self.px = px + self.py = py + self.pz = pz + self.scale_x = 1.0 + self.scale_y = 1.0 + self.scale_z = 1.0 + + def apply_scale(self, sx: CFloat64T, sy: CFloat64T, sz: CFloat64T) -> 'Transform' | CPtr: + self.scale_x = self.scale_x * sx + self.scale_y = self.scale_y * sy + self.scale_z = self.scale_z * sz + return t.CVoid(c.Addr(self), CPtr) + + def world_position(self) -> 'Vec3' | CPtr: + return Vec3(self.px * self.scale_x, self.py * self.scale_y, self.pz * self.scale_z) + + +# === 多层继承(子类只重写需要的方法) === + +@t.CVTable +class Vehicle: + def __init__(self, speed: CInt32T): + self.speed = speed + self.fuel = CInt32T(100) + def move(self) -> CInt: + self.fuel = self.fuel - CInt32T(10) + return self.speed + def is_running(self) -> CInt: + if self.fuel > 0: + return 1 + return 0 + +@t.CVTable +class Car(Vehicle): + def __init__(self, speed: CInt32T, doors: CInt32T): + self.speed = speed + self.fuel = CInt32T(100) + self.doors = doors + def honk(self) -> CInt: + return 1 + +@t.CVTable +class ElectricCar(Car): + def __init__(self, speed: CInt32T, doors: CInt32T, battery: CInt32T): + self.speed = speed + self.fuel = CInt32T(100) + self.doors = doors + self.battery = battery + def charge(self): + self.battery = self.battery + CInt32T(20) + def move(self) -> CInt: + self.battery = self.battery - CInt32T(5) + return self.speed + + +def main() -> CInt | CExport: + w32.win32console.SetConsoleCP(65001) + w32.win32console.SetConsoleOutputCP(65001) + + testcheck.begin("GenericOopTest: 泛型与OOP综合测试") + + buf: CChar | CPtr = CPtr(stdlib.malloc(256)) + + # === 基础函数泛型 === + testcheck.section("基础函数泛型") + print(add(3, 5)) + print(add(1.5, 2.5)) + print(add_u64(1, 2, CUInt64T(3000000000000000))) + print(fxi(0.2, 6)) + print(wrap_add(10, 20)) + print(double_add(5, 7)) + testcheck.ok("基础函数泛型测试完成") + + # === 基础结构体泛型 === + testcheck.section("基础结构体泛型") + a = A(100) + print(a.get_a()) + p1 = Pair(10, 20) + print(p1.get_first()) + print(p1.get_second()) + testcheck.ok("基础结构体泛型测试完成") + + # === OOP 继承测试 === + testcheck.section("OOP 继承测试") + c1 = Circle(0.0, 0.0, 5.0) + viperlib.snprintf(buf, 256, "Circle area=%.2f perim=%.2f", c1.area(), c1.perimeter()) + print(buf) + + r1 = Rect(0.0, 0.0, 4.0, 3.0) + viperlib.snprintf(buf, 256, "Rect area=%.2f perim=%.2f", r1.area(), r1.perimeter()) + print(buf) + + # 链式调用: scale -> move + c2 = Circle(1.0, 2.0, 3.0) + c2.scale(2.0).move(10.0, 20.0) + viperlib.snprintf(buf, 256, "Circle after scale+move: x=%.1f y=%.1f r=%.1f area=%.2f", + c2.x, c2.y, c2.r, c2.area()) + print(buf) + + r2 = Rect(0.0, 0.0, 10.0, 5.0) + r2.scale(2.0).scale(0.5) + viperlib.snprintf(buf, 256, "Rect after double scale: w=%.1f h=%.1f area=%.2f", + r2.w, r2.h, r2.area()) + print(buf) + testcheck.ok("OOP 继承测试完成") + + # === Vec2 运算符重载 + 链式调用(堆分配) === + testcheck.section("Vec2 运算符重载 + 链式调用") + v1 = Vec2(3.0, 4.0) + v2 = Vec2(1.0, 2.0) + v3 = v1 + v2 + viperlib.snprintf(buf, 256, "Vec2 add: (%.1f, %.1f)", v3.x, v3.y) + print(buf) + + v4 = v1 - v2 + viperlib.snprintf(buf, 256, "Vec2 sub: (%.1f, %.1f)", v4.x, v4.y) + print(buf) + + v5 = v1 * 2.0 + viperlib.snprintf(buf, 256, "Vec2 mul: (%.1f, %.1f)", v5.x, v5.y) + print(buf) + + v6 = -v1 + viperlib.snprintf(buf, 256, "Vec2 neg: (%.1f, %.1f)", v6.x, v6.y) + print(buf) + + d = v1.dot(v2) + viperlib.snprintf(buf, 256, "Vec2 dot: %.1f", d) + print(buf) + + # 链式运算: (v1 + v2) * 3.0 + v_chain = (v1 + v2) * 3.0 + viperlib.snprintf(buf, 256, "Vec2 chain (v1+v2)*3: (%.1f, %.1f)", v_chain.x, v_chain.y) + print(buf) + testcheck.ok("Vec2 运算符重载测试完成") + + # === Vec3 运算符重载 + 链式调用(堆分配) === + testcheck.section("Vec3 运算符重载 + 链式调用") + a1 = Vec3(1.0, 0.0, 0.0) + a2 = Vec3(0.0, 1.0, 0.0) + cross_v = a1.cross(a2) + viperlib.snprintf(buf, 256, "Vec3 cross: (%.1f, %.1f, %.1f)", cross_v.x, cross_v.y, cross_v.z) + print(buf) + + dot_v = a1.dot(a2) + viperlib.snprintf(buf, 256, "Vec3 dot: %.1f", dot_v) + print(buf) + + # 链式: (a + b).dot(c) + a3 = Vec3(1.0, 2.0, 3.0) + a4 = Vec3(4.0, 5.0, 6.0) + a5 = Vec3(7.0, 8.0, 9.0) + chain_dot = (a3 + a4).dot(a5) + viperlib.snprintf(buf, 256, "Vec3 chain dot: %.1f", chain_dot) + print(buf) + + # 链式: (a * 2.0 - b).cross(c) + chain_cross = (a3 * 2.0 - a4).cross(a5) + viperlib.snprintf(buf, 256, "Vec3 chain cross: (%.1f, %.1f, %.1f)", chain_cross.x, chain_cross.y, chain_cross.z) + print(buf) + + # len_sq 链式 + lsq = a3.len_sq() + viperlib.snprintf(buf, 256, "Vec3 len_sq: %.1f", lsq) + print(buf) + testcheck.ok("Vec3 运算符重载测试完成") + + # === Dog/Cat 虚方法 === + testcheck.section("Dog/Cat 虚方法") + dog = Dog(1, CInt32T(30)) + cat = Cat(2, CInt32T(9)) + + viperlib.snprintf(buf, 256, "Dog speak=%d bite=%d alive=%d", dog.speak(), dog.bite(), dog.is_alive()) + print(buf) + viperlib.snprintf(buf, 256, "Cat speak=%d scratch=%d alive=%d", cat.speak(), cat.scratch(), cat.is_alive()) + print(buf) + + dog.take_damage(CInt32T(40)).take_damage(CInt32T(30)) + viperlib.snprintf(buf, 256, "Dog after 70dmg: health=%d alive=%d", dog.health, dog.is_alive()) + print(buf) + + cat.take_damage(CInt32T(50)) + viperlib.snprintf(buf, 256, "Cat after 50dmg: health=%d alive=%d", cat.health, cat.is_alive()) + print(buf) + testcheck.ok("Dog/Cat 虚方法测试完成") + + # === Transform 嵌套组合(堆分配,链式调用) === + testcheck.section("Transform 嵌套组合") + tr = Transform(10.0, 20.0, 30.0) + tr.apply_scale(2.0, 3.0, 4.0) + pos = tr.world_position() + viperlib.snprintf(buf, 256, "Transform pos: (%.1f, %.1f, %.1f)", pos.x, pos.y, pos.z) + print(buf) + + tr2 = Transform(5.0, 10.0, 15.0) + tr2.apply_scale(2.0, 2.0, 2.0) + pos2 = tr2.world_position() + viperlib.snprintf(buf, 256, "Transform2 pos: (%.1f, %.1f, %.1f)", pos2.x, pos2.y, pos2.z) + print(buf) + testcheck.ok("Transform 嵌套组合测试完成") + + # === 多层继承 === + testcheck.section("多层继承") + ec = ElectricCar(CInt32T(120), CInt32T(4), CInt32T(80)) + viperlib.snprintf(buf, 256, "ECar speed=%d doors=%d battery=%d", ec.speed, ec.doors, ec.battery) + print(buf) + ec.charge() + viperlib.snprintf(buf, 256, "ECar after charge: battery=%d", ec.battery) + print(buf) + spd = ec.move() + viperlib.snprintf(buf, 256, "ECar move: speed=%d battery=%d", spd, ec.battery) + print(buf) + viperlib.snprintf(buf, 256, "ECar honk=%d running=%d", ec.honk(), ec.is_running()) + print(buf) + testcheck.ok("多层继承测试完成") + + # === 泛型 + OOP 组合 === + testcheck.section("泛型 + OOP 组合") + calc1 = Calculator(10) + print(calc1.compute(5)) + calc2 = Calculator(1.5) + print(calc2.compute(2.5)) + + c1_gen = Container(42) + print(c1_gen.get_value()) + print(c1_gen.get_flag()) + testcheck.ok("泛型 + OOP 组合测试完成") + + # === snprintf 格式化 === + testcheck.section("snprintf 格式化") + viperlib.snprintf(buf, 256, "int=%d, float=%.2f", 42, 3.14) + print(buf) + viperlib.snprintf(buf, 256, "result=%d", add(100, 200)) + print(buf) + testcheck.ok("snprintf 格式化测试完成") + + # === 新语法类型强转 (t1|t2)(x) === + testcheck.section("新语法类型强转 (t1|t2)(x)") + val_i64: CUInt64T = CUInt64T(42) + val_i32 = (t.CInt)(val_i64) + print(val_i32) + + ptr_raw = stdlib.malloc(8) + ptr_typed = (t.CInt | t.CPtr)(ptr_raw) + viperlib.snprintf(buf, 256, "cast ptr=%p", ptr_typed) + print(buf) + + val_f = (t.CDouble)(42) + viperlib.snprintf(buf, 256, "cast float=%.1f", val_f) + print(buf) + testcheck.ok("新语法类型强转测试完成") + + stdlib.free(buf) + return testcheck.end() diff --git a/Test/GenericOopTest/project.json b/Test/GenericOopTest/project.json new file mode 100644 index 0000000..efc426a --- /dev/null +++ b/Test/GenericOopTest/project.json @@ -0,0 +1,29 @@ +{ + "$schema": "https://raw.githubusercontent.com/TermiNexus/TransPyC/main/schemas/project-schema.json", + "name": "GenericOopTest", + "version": "1.0.0", + "source_dir": "./App", + "build_dir": "./.tpv_build", + "compiler": { + "cmd": "llc", + "flags": ["-filetype=obj", "-relocation-model=pic"] + }, + "linker": { + "cmd": "clang++", + "flags": ["-Wl,--allow-multiple-definition", "-Wl,--unresolved-symbols=ignore-in-object-files", "-lmsvcrt", "-lucrt", "-lpthread", "-lmingwex", "-lkernel32", "-luser32", "-latomic"], + "output": "GenericOopTest.exe" + }, + "includes": [ + "../../includes" + ], + "target": { + "triple": "x86_64-pc-windows-gnu", + "datalayout": "e-m:w-p270:32:32-p271:32:32-p272:64:64-f80:128-n8:16:32:64-S128" + }, + "options": { + "slice_level": 3, + "sha1_slice_level": 1, + "target": "llvm", + "strict_mode": true + } +} diff --git a/Test/HashLibTest/App/main.vp b/Test/HashLibTest/App/main.vp new file mode 100644 index 0000000..ac111ff --- /dev/null +++ b/Test/HashLibTest/App/main.vp @@ -0,0 +1,26 @@ +import t, c +import testcheck +import hashlib +import binascii +import w32.win32console + + +def main() -> t.CInt | t.CExport: + w32.win32console.SetConsoleCP(65001) + w32.win32console.SetConsoleOutputCP(65001) + + testcheck.begin("HashLibTest: 哈希与校验测试") + + testcheck.section("HASHLIB") + md5_buf: t.CArray[t.CUInt8T, hashlib.MD5_DIGEST_LEN] + mctx = hashlib.md5() + mctx.update("hello") + mctx.final(md5_buf) + testcheck.ok("HASHLIB md5 completed") + + testcheck.section("BINASCII") + binascii.init_binascii() + crc_val: t.CUnsignedInt = binascii.crc32("hello", 5, 0) + testcheck.ok("BINASCII crc32 completed") + + return testcheck.end() diff --git a/Test/HashLibTest/project.json b/Test/HashLibTest/project.json new file mode 100644 index 0000000..69bb3f3 --- /dev/null +++ b/Test/HashLibTest/project.json @@ -0,0 +1,29 @@ +{ + "$schema": "https://raw.githubusercontent.com/TermiNexus/TransPyC/main/schemas/project-schema.json", + "name": "HashLibTest", + "version": "1.0.0", + "source_dir": "./App", + "build_dir": "./.tpv_build", + "compiler": { + "cmd": "llc", + "flags": ["-filetype=obj", "-relocation-model=pic"] + }, + "linker": { + "cmd": "clang++", + "flags": ["-Wl,--allow-multiple-definition", "-Wl,--unresolved-symbols=ignore-in-object-files", "-lmsvcrt", "-lucrt", "-lpthread", "-lmingwex", "-lkernel32", "-luser32", "-latomic"], + "output": "HashLibTest.exe" + }, + "includes": [ + "../../includes" + ], + "target": { + "triple": "x86_64-pc-windows-gnu", + "datalayout": "e-m:w-p270:32:32-p271:32:32-p272:64:64-f80:128-n8:16:32:64-S128" + }, + "options": { + "slice_level": 3, + "sha1_slice_level": 1, + "target": "llvm", + "strict_mode": true + } +} diff --git a/Test/LogicFlowTest/App/config.vp b/Test/LogicFlowTest/App/config.vp new file mode 100644 index 0000000..1b4e36f --- /dev/null +++ b/Test/LogicFlowTest/App/config.vp @@ -0,0 +1,24 @@ +import t, c + + +POSMAX: t.CDefine = 100 +MAX_RETRY: t.CDefine = 5 +BUFFER_SIZE: t.CDefine = 256 +PI: t.CDefine = 3.14159 +EULER: t.CDefine = 2.71828 +TRUE: t.CDefine = 1 +FALSE: t.CDefine = 0 +NULL: t.CDefine = 0 + + +MATH_OFFSET: t.CDefine = 10 +MATH_SCALE: t.CDefine = 2 +THRESHOLD: t.CDefine = 50 +LOOP_LIMIT: t.CDefine = 20 +SHIFT_AMOUNT: t.CDefine = 2 +MASK_VALUE: t.CDefine = 0xFF +BIT_RANGE: t.CDefine = 4 +EXPONENT_BASE: t.CDefine = 3 +MODULO_DIVISOR: t.CDefine = 7 +SCALE_SHIFT: t.CDefine = 4 +HALF_SCALE: t.CDefine = 0.5 \ No newline at end of file diff --git a/Test/LogicFlowTest/App/logic_test.vp b/Test/LogicFlowTest/App/logic_test.vp new file mode 100644 index 0000000..4d5c266 --- /dev/null +++ b/Test/LogicFlowTest/App/logic_test.vp @@ -0,0 +1,372 @@ +import config +import t, c + + +def ForRangeBasicTest(stop: t.CInt): + i: t.CInt = 0 + for i in range(stop): + print("For range: ", i) + print("Done") + + +def ForRangeWithStartStop(start: t.CInt, stop: t.CInt, step: t.CInt): + i: t.CInt = 0 + for i in range(start, stop, step): + print("Range: ", i) + print("Done") + + +def NestedForRangeTest(rows: t.CInt, cols: t.CInt): + r: t.CInt = 0 + c_val: t.CInt = 0 + for r in range(rows): + for c_val in range(cols): + print("Cell: ", r, c_val) + print("Grid done") + + +def ForWithIfBreakTest(data_size: t.CInt): + i: t.CInt = 0 + found: t.CInt = 0 + for i in range(data_size): + if i == 5: + print("Found at: ", i) + found = 1 + break + print("Checking: ", i) + if found == 0: + print("Not found") + + +def ForWithIfContinueTest(n: t.CInt): + i: t.CInt = 0 + count: t.CInt = 0 + for i in range(n): + if i % 2 == 0: + continue + print("Odd: ", i) + count += 1 + print("Total odd: ", count) + + +def ForWithElifBranchTest(value: t.CInt): + i: t.CInt = 0 + result: t.CInt = 0 + for i in range(value): + if i < 3: + result += 1 + elif i < 6: + result += 2 + elif i < 9: + result += 3 + else: + result += 4 + print("Elif branch result: ", result) + + +def WhileWithIfElifElseTest(iterations: t.CInt): + counter: t.CInt = 0 + while counter < iterations: + if counter < 2: + print("Phase 1: ", counter) + elif counter < 4: + print("Phase 2: ", counter) + elif counter < 6: + print("Phase 3: ", counter) + else: + print("Phase 4: ", counter) + counter += 1 + print("While done") + + +def WhileWithNestedIfTest(limit: t.CInt): + outer: t.CInt = 0 + while outer < limit: + inner: t.CInt = 0 + while inner < limit: + if inner == 2 and outer == 1: + print("Target: ", outer, inner) + inner += 1 + continue + if inner > 3: + break + print("Inner: ", inner) + inner += 1 + outer += 1 + + +def WhileWithMatchCaseTest(value: t.CInt): + result: t.CInt = 0 + match value: + case 1: + result = 100 + print("Case 1") + case 2: + result = 200 + print("Case 2") + case 3: + result = 300 + print("Case 3") + case _: + result = 999 + print("Default case") + print("Match result: ", result) + + +def WhileWithMatchCaseNoBreakTest(value: t.CInt): + result: t.CInt = 0 + match value: + case 1: + result = 10 + print("Case 1: ", result) + case 2: + result = 20 + print("Case 2: ", result) + result += 5 + case 3: + result = 30 + print("Case 3: ", result) + case _: + result = 0 + print("No break match result: ", result) + + +def ComplexForWhileMatchTest(outer_limit: t.CInt, inner_limit: t.CInt): + i: t.CInt = 0 + j: t.CInt = 0 + result: t.CInt = 0 + for i in range(outer_limit): + j = 0 + while j < inner_limit: + match (i, j): + case (0, 0): + result += 1 + case (1, 1): + result += 10 + case (2, _): + result += 100 + case (_, 0): + result += 1000 + case _: + result += 10000 + j += 1 + print("Complex match result: ", result) + + +def ForWithCaseAndNoBreakTest(n: t.CInt): + i: t.CInt = 0 + result: t.CInt = 0 + for i in range(n): + match i: + case 0: + result += 1 + case 1: + result += 2 + case 2: + result += 3 + result += 10 + case _: + result += i + c.NoBreak + print("NoBreak result: ", result) + + +def WhileWithBreakConditionTest(limit: t.CInt): + i: t.CInt = 0 + early_exit: t.CInt = 0 + while i < limit: + if i == 3: + early_exit = 1 + break + if i == 2: + i += 1 + continue + print("While i: ", i) + i += 1 + + +def NestedWhileWithMultipleBreakPoints(depth: t.CInt, width: t.CInt): + d: t.CInt = 0 + w: t.CInt = 0 + count: t.CInt = 0 + while d < depth: + w = 0 + while w < width: + if w == 2: + break + if d == 1 and w == 1: + c.Break + count += 1 + w += 1 + d += 1 + print("Nested break count: ", count) + + +def ForWithMatchCaseInLoopTest(iterations: t.CInt): + i: t.CInt = 0 + sum_even: t.CInt = 0 + sum_odd: t.CInt = 0 + for i in range(iterations): + match i % 3: + case 0: + sum_even += i + case 1: + sum_odd += i + case 2: + sum_even += i * 2 + case _: + pass + print("Sum even: ", sum_even) + print("Sum odd: ", sum_odd) + + +def ComplexLogicWithElifChains(a: t.CInt, b: t.CInt, c_val: t.CInt): + i: t.CInt = 0 + result: t.CInt = 0 + while i < 10: + if i < a: + if i < b: + result += 1 + elif i < c_val: + result += 2 + else: + result += 3 + elif i < b: + if i < c_val: + result += 4 + else: + result += 5 + elif i < c_val: + result += 6 + else: + result += 7 + i += 1 + print("Complex elif chain result: ", result) + + +def ForRangeWithStepAndCondition(n: t.CInt, step: t.CInt): + i: t.CInt = 0 + count: t.CInt = 0 + for i in range(0, n, step): + if i % 2 == 0: + print("Even step: ", i) + count += 1 + else: + if i > 5: + print("Large odd: ", i) + else: + print("Small odd: ", i) + print("Total steps: ", count) + + +def MatchCaseWithGuardConditions(value: t.CInt): + result: t.CInt = 0 + match value: + case 1 if config.TRUE == 1: + result = 100 + case 2 if config.FALSE == 0: + result = 200 + case 3: + result = 300 + case _: + result = 0 + print("Guard match result: ", result) + + +def WhileWithMultipleMatchCases(iterations: t.CInt): + i: t.CInt = 0 + state: t.CInt = 0 + while i < iterations: + match state: + case 0: + if i > 3: + state = 1 + case 1: + if i > 6: + state = 2 + case 2: + if i > 9: + state = 0 + print("State at i=", i, ": ", state) + i += 1 + + +def ForWhileMixWithBreakAndContinue(n: t.CInt): + i: t.CInt = 0 + j: t.CInt = 0 + count: t.CInt = 0 + for i in range(n): + j = 0 + while j < n: + if j == 2: + j += 1 + continue + if i == 3 and j == 3: + break + count += 1 + j += 1 + print("Mix break continue count: ", count) + + +def ComplexCaseMatchingWithRanges(start: t.CInt, end: t.CInt): + i: t.CInt = 0 + bucket0: t.CInt = 0 + bucket1: t.CInt = 0 + bucket2: t.CInt = 0 + bucket3: t.CInt = 0 + for i in range(start, end): + match i: + case _ if i < 10: + bucket0 += 1 + case _ if i < 20: + bucket1 += 1 + case _ if i < 30: + bucket2 += 1 + case _: + bucket3 += 1 + print("Bucket0 (<10): ", bucket0) + print("Bucket1 (10-19): ", bucket1) + print("Bucket2 (20-29): ", bucket2) + print("Bucket3 (>=30): ", bucket3) + + +def WhileWithElifInElifChain(limit: t.CInt): + i: t.CInt = 0 + result: t.CInt = 0 + while i < limit: + if i < 2: + if i == 0: + result = 1 + else: + result = 2 + elif i < 4: + if i == 2: + result = 3 + else: + result = 4 + elif i < 6: + if i == 4: + result = 5 + else: + result = 6 + else: + result = 7 + print("Chain result[", i, "]: ", result) + i += 1 + + +def ForWithCaseNoBreakNested(inner_limit: t.CInt): + i: t.CInt = 0 + j: t.CInt = 0 + result: t.CInt = 0 + for i in range(3): + for j in range(inner_limit): + match j: + case 0: + result += 1 + case 1: + result += 2 + case _: + result += 3 + c.NoBreak + print("Nested NoBreak result: ", result) \ No newline at end of file diff --git a/Test/LogicFlowTest/App/main.vp b/Test/LogicFlowTest/App/main.vp new file mode 100644 index 0000000..78154c4 --- /dev/null +++ b/Test/LogicFlowTest/App/main.vp @@ -0,0 +1,106 @@ +import t, c +import config +import logic_test +import testcheck + + +def main() -> t.CInt: + testcheck.begin("LogicFlowTest: For/While/Match/控制流测试") + + testcheck.section("For Range Basic Test (stop=5)") + logic_test.ForRangeBasicTest(5) + testcheck.ok("For Range Basic Test (5)") + + testcheck.section("For Range With Start Stop Step (start=1, stop=10, step=2)") + logic_test.ForRangeWithStartStop(1, 10, 2) + testcheck.ok("For Range With Start Stop (1, 10, 2)") + + testcheck.section("Nested For Range Test (rows=2, cols=3)") + logic_test.NestedForRangeTest(2, 3) + testcheck.ok("Nested For Range Test (2, 3)") + + testcheck.section("For With If Break Test (size=8)") + logic_test.ForWithIfBreakTest(8) + testcheck.ok("For With If Break Test (8)") + + testcheck.section("For With If Continue Test (n=10)") + logic_test.ForWithIfContinueTest(10) + testcheck.ok("For With If Continue Test (10)") + + testcheck.section("For With Elif Branch Test (value=10)") + logic_test.ForWithElifBranchTest(10) + testcheck.ok("For With Elif Branch Test (10)") + + testcheck.section("While With If Elif Else Test (iterations=7)") + logic_test.WhileWithIfElifElseTest(7) + testcheck.ok("While With If Elif Else Test (7)") + + testcheck.section("While With Nested If Test (limit=4)") + logic_test.WhileWithNestedIfTest(4) + testcheck.ok("While With Nested If Test (4)") + + testcheck.section("While With Match Case Test (value=2)") + logic_test.WhileWithMatchCaseTest(2) + testcheck.ok("While With Match Case Test (2)") + + testcheck.section("While With Match Case Test (value=99)") + logic_test.WhileWithMatchCaseTest(99) + testcheck.ok("While With Match Case Test (99)") + + testcheck.section("While With Match Case NoBreak Test (value=3)") + logic_test.WhileWithMatchCaseNoBreakTest(3) + testcheck.ok("While With Match Case NoBreak Test (3)") + + testcheck.section("Complex For While Match Test (outer=3, inner=3)") + logic_test.ComplexForWhileMatchTest(3, 3) + testcheck.ok("Complex For While Match Test (3, 3)") + + testcheck.section("For With Case And NoBreak Test (n=5)") + logic_test.ForWithCaseAndNoBreakTest(5) + testcheck.ok("For With Case And NoBreak Test (5)") + + testcheck.section("While With Break Condition Test (limit=6)") + logic_test.WhileWithBreakConditionTest(6) + testcheck.ok("While With Break Condition Test (6)") + + testcheck.section("Nested While With Multiple BreakPoints (depth=3, width=4)") + logic_test.NestedWhileWithMultipleBreakPoints(3, 4) + testcheck.ok("Nested While With Multiple BreakPoints (3, 4)") + + testcheck.section("For With Match Case In Loop Test (iterations=9)") + logic_test.ForWithMatchCaseInLoopTest(9) + testcheck.ok("For With Match Case In Loop Test (9)") + + testcheck.section("Complex Logic With Elif Chains (a=3, b=5, c=7)") + logic_test.ComplexLogicWithElifChains(3, 5, 7) + testcheck.ok("Complex Logic With Elif Chains (3, 5, 7)") + + testcheck.section("For Range With Step And Condition (n=12, step=2)") + logic_test.ForRangeWithStepAndCondition(12, 2) + testcheck.ok("For Range With Step And Condition (12, 2)") + + testcheck.section("Match Case With Guard Conditions (value=1)") + logic_test.MatchCaseWithGuardConditions(1) + testcheck.ok("Match Case With Guard Conditions (1)") + + testcheck.section("While With Multiple Match Cases (iterations=12)") + logic_test.WhileWithMultipleMatchCases(12) + testcheck.ok("While With Multiple Match Cases (12)") + + testcheck.section("For While Mix With Break And Continue (n=5)") + logic_test.ForWhileMixWithBreakAndContinue(5) + testcheck.ok("For While Mix With Break And Continue (5)") + + testcheck.section("Complex Case Matching With Ranges (start=0, end=35)") + logic_test.ComplexCaseMatchingWithRanges(0, 35) + testcheck.ok("Complex Case Matching With Ranges (0, 35)") + + testcheck.section("While With Elif In Elif Chain (limit=7)") + logic_test.WhileWithElifInElifChain(7) + testcheck.ok("While With Elif In Elif Chain (7)") + + testcheck.section("For With Case NoBreak Nested (inner_limit=4)") + logic_test.ForWithCaseNoBreakNested(4) + testcheck.ok("For With Case NoBreak Nested (4)") + + return testcheck.end() diff --git a/Test/LogicFlowTest/project.json b/Test/LogicFlowTest/project.json new file mode 100644 index 0000000..c951a8d --- /dev/null +++ b/Test/LogicFlowTest/project.json @@ -0,0 +1,29 @@ +{ + "$schema": "https://raw.githubusercontent.com/TermiNexus/TransPyC/main/schemas/project-schema.json", + "name": "LogicFlowTest", + "version": "1.0.0", + "source_dir": "./App", + "build_dir": "./.tpv_build", + "compiler": { + "cmd": "llc", + "flags": ["-filetype=obj", "-relocation-model=pic"] + }, + "linker": { + "cmd": "clang++", + "flags": ["-Wl,--allow-multiple-definition", "-Wl,--unresolved-symbols=ignore-in-object-files", "-lmsvcrt", "-lucrt", "-lpthread", "-lmingwex", "-lkernel32", "-luser32", "-latomic"], + "output": "LogicFlowTest.exe" + }, + "includes": [ + "../../includes" + ], + "target": { + "triple": "x86_64-pc-windows-gnu", + "datalayout": "e-m:w-p270:32:32-p271:32:32-p272:64:64-f80:128-n8:16:32:64-S128" + }, + "options": { + "slice_level": 3, + "sha1_slice_level": 1, + "target": "llvm", + "strict_mode": true + } +} diff --git a/Test/LoopMathTest/App/config.vp b/Test/LoopMathTest/App/config.vp new file mode 100644 index 0000000..1b4e36f --- /dev/null +++ b/Test/LoopMathTest/App/config.vp @@ -0,0 +1,24 @@ +import t, c + + +POSMAX: t.CDefine = 100 +MAX_RETRY: t.CDefine = 5 +BUFFER_SIZE: t.CDefine = 256 +PI: t.CDefine = 3.14159 +EULER: t.CDefine = 2.71828 +TRUE: t.CDefine = 1 +FALSE: t.CDefine = 0 +NULL: t.CDefine = 0 + + +MATH_OFFSET: t.CDefine = 10 +MATH_SCALE: t.CDefine = 2 +THRESHOLD: t.CDefine = 50 +LOOP_LIMIT: t.CDefine = 20 +SHIFT_AMOUNT: t.CDefine = 2 +MASK_VALUE: t.CDefine = 0xFF +BIT_RANGE: t.CDefine = 4 +EXPONENT_BASE: t.CDefine = 3 +MODULO_DIVISOR: t.CDefine = 7 +SCALE_SHIFT: t.CDefine = 4 +HALF_SCALE: t.CDefine = 0.5 \ No newline at end of file diff --git a/Test/LoopMathTest/App/main.vp b/Test/LoopMathTest/App/main.vp new file mode 100644 index 0000000..40c70ef --- /dev/null +++ b/Test/LoopMathTest/App/main.vp @@ -0,0 +1,79 @@ +import stdio +import t, c +import config +import test +import testcheck + + +def main() -> t.CInt: + testcheck.begin("LoopMathTest: While/数学/跨模块宏测试") + + testcheck.section("Cross-module macros") + stdio.printf(" POSMAX: %d\n", config.POSMAX) + stdio.printf(" MATH_SCALE: %d\n", config.MATH_SCALE) + stdio.printf(" THRESHOLD: %d\n", config.THRESHOLD) + stdio.printf(" SHIFT_AMOUNT: %d\n", config.SHIFT_AMOUNT) + stdio.printf(" MASK_VALUE: 0x%x\n", config.MASK_VALUE) + testcheck.ok("config macros accessible") + + testcheck.section("While Loop Test") + test.AboutSizeTWhileTest(10) + testcheck.ok("While Loop Test (10)") + + testcheck.section("Math Basic Test (20, 6)") + test.MathBasicTest(20, 6) + testcheck.ok("Math Basic Test (20, 6)") + + testcheck.section("Math Advanced Test (value=15)") + test.MathAdvancedTest(15) + testcheck.ok("Math Advanced Test (value=15)") + + testcheck.section("While with Elif-Else Test (-2 to 12)") + test.WhileWithElifElseTest(-2, 12) + testcheck.ok("While with Elif-Else Test (-2 to 12)") + + testcheck.section("Nested While with Macros Test") + test.NestedWhileWithMacrosTest(3, 4) + testcheck.ok("Nested While with Macros Test (3, 4)") + + testcheck.section("Complex Condition Test (1, 2, 3)") + test.ComplexConditionTest(1, 2, 3) + testcheck.ok("Complex Condition Test (1, 2, 3)") + + testcheck.section("Retry Loop Test (8)") + test.RetryLoopTest(8) + testcheck.ok("Retry Loop Test (8)") + + testcheck.section("Bitwise Operations Test (0b1101101)") + test.BitwiseOperationsTest(109) + testcheck.ok("Bitwise Operations Test (109)") + + testcheck.section("Compound Assignment Math Test (15, 4)") + test.CompoundAssignmentMathTest(15, 4) + testcheck.ok("Compound Assignment Math Test (15, 4)") + + testcheck.section("Power and Modulo Test (2, 8)") + test.PowerAndModuloTest(2, 8) + testcheck.ok("Power and Modulo Test (2, 8)") + + testcheck.section("Mixed Arithmetic Test (5, 3, 4)") + test.MixedArithmeticTest(5, 3, 4) + testcheck.ok("Mixed Arithmetic Test (5, 3, 4)") + + testcheck.section("Math with While Loop Test (start=1, count=5)") + test.MathWithWhileLoopTest(1, 5) + testcheck.ok("Math with While Loop Test (1, 5)") + + testcheck.section("Complex Nested Math Test (7, 3)") + test.ComplexNestedMathTest(7, 3) + testcheck.ok("Complex Nested Math Test (7, 3)") + + testcheck.section("Conditional Math Chain Test (value=10)") + test.ConditionalMathChainTest(10) + testcheck.ok("Conditional Math Chain Test (value=10)") + + testcheck.section("Bit Manipulation Math Test (0xABCD)") + test.BitManipulationMathTest(0xABCD) + testcheck.ok("Bit Manipulation Math Test (0xABCD)") + + return testcheck.end() diff --git a/Test/LoopMathTest/App/test.vp b/Test/LoopMathTest/App/test.vp new file mode 100644 index 0000000..24a08a8 --- /dev/null +++ b/Test/LoopMathTest/App/test.vp @@ -0,0 +1,298 @@ +import config +import t, c + + +def AboutSizeTWhileTest(length: t.CSizeT): + pos: t.CSizeT = 0 + while pos < length: + print("Pos: ", pos) + if pos > config.POSMAX: break + pos += 1 + while pos < length: + if pos > config.POSMAX: + print("Pos: ", pos) + pos += 1 + else: + print("Pos: ", pos) + pos += 1 + if pos > config.POSMAX: break + else: + pos += 1 + print("Pos: ", pos) + while pos < length: + print("Pos: ", pos) + pos += 1 + + +def MathBasicTest(x: t.CInt, y: t.CInt) -> t.CInt: + result: t.CInt = 0 + result = x + y + print("Add: ", result) + result = x - y + print("Sub: ", result) + result = x * y + print("Mul: ", result) + if y != 0: + result = x / y + print("Div: ", result) + result = x % y if y != 0 else 0 + print("Mod: ", result) + return result + + +def MathAdvancedTest(value: t.CInt) -> t.CInt: + counter: t.CInt = 0 + scaled: t.CInt = 0 + offset: t.CInt = 0 + scaled = value * config.MATH_SCALE + print("Scaled: ", scaled) + offset = scaled + config.MATH_OFFSET + print("Offset: ", offset) + threshold: t.CInt = config.THRESHOLD + if offset > threshold: + print("Above threshold") + counter = 1 + elif offset == threshold: + print("At threshold") + counter = 0 + else: + print("Below threshold") + counter = -1 + return counter + + +def WhileWithElifElseTest(start: t.CInt, end: t.CInt): + idx: t.CInt = start + while idx < end: + if idx < 0: + print("Negative: ", idx) + elif idx == 0: + print("Zero: ", idx) + elif idx > 0 and idx < 5: + print("Small positive: ", idx) + elif idx >= 5 and idx < 10: + print("Medium positive: ", idx) + else: + print("Large: ", idx) + idx += 1 + + +def NestedWhileWithMacrosTest(outer_limit: t.CInt, inner_limit: t.CInt): + outer: t.CInt = 0 + inner: t.CInt = 0 + total_ops: t.CInt = 0 + while outer < outer_limit: + inner = 0 + while inner < inner_limit: + if inner == config.TRUE: + print("Inner loop break condition at: ", inner) + total_ops += 1 + inner += 1 + outer += 1 + print("Total operations: ", total_ops) + + +def ComplexConditionTest(a: t.CInt, b: t.CInt, c_val: t.CInt): + x: t.CInt = a + y: t.CInt = b + z: t.CInt = c_val + while x < config.LOOP_LIMIT: + if x > 0 and y > 0 and z > 0: + print("All positive: ", x, y, z) + elif x <= 0 and y <= 0 and z <= 0: + print("All non-positive: ", x, y, z) + else: + if x > 0: + print("X positive") + elif y > 0: + print("Y positive") + else: + print("Z positive") + x += 1 + y += 1 + z += 1 + + +def RetryLoopTest(retry_count: t.CInt) -> t.CInt: + attempt: t.CInt = 0 + success: t.CInt = 0 + while attempt < retry_count: + if attempt < config.MAX_RETRY: + print("Attempt: ", attempt, " less than max") + success = attempt * 2 + elif attempt == config.MAX_RETRY: + print("At max retry") + success = -1 + else: + print("Beyond max retry") + success = -2 + attempt += 1 + return success + + +def BitwiseOperationsTest(value: t.CInt) -> t.CInt: + shifted: t.CInt = 0 + masked: t.CInt = 0 + xored: t.CInt = 0 + anded: t.CInt = 0 + ored: t.CInt = 0 + shifted = value << config.SHIFT_AMOUNT + print("Left shift: ", shifted) + shifted = value >> config.SHIFT_AMOUNT + print("Right shift: ", shifted) + masked = value & config.MASK_VALUE + print("Bitwise AND mask: ", masked) + xored = value ^ config.MASK_VALUE + print("Bitwise XOR: ", xored) + anded = value & (config.MASK_VALUE >> config.SHIFT_AMOUNT) + print("Bitwise AND shifted mask: ", anded) + ored = value | config.SHIFT_AMOUNT + print("Bitwise OR shift: ", ored) + return masked + + +def CompoundAssignmentMathTest(a: t.CInt, b: t.CInt) -> t.CInt: + x: t.CInt = a + y: t.CInt = b + result: t.CInt = 0 + x += y + print("x += y: ", x) + x -= y + print("x -= y: ", x) + x *= y + print("x *= y: ", x) + x = a + y = b + if b != 0: + x /= b + print("x /= y: ", x) + x = a + if b != 0: + x %= b + print("x %%= y: ", x) + x = a + x <<= config.SHIFT_AMOUNT + print("x <<= shift: ", x) + x >>= config.SHIFT_AMOUNT + print("x >>= shift: ", x) + x &= config.MASK_VALUE + print("x &= mask: ", x) + x |= config.SHIFT_AMOUNT + print("x |= shift: ", x) + result = (a + b) * config.MATH_SCALE - config.MATH_OFFSET + print("Compound: (a+b)*scale-offset: ", result) + result = (a * b) + (config.MATH_OFFSET / 2) + print("Compound: a*b+offset/2: ", result) + return result + + +def PowerAndModuloTest(base: t.CInt, exponent: t.CInt) -> t.CInt: + result: t.CInt = 1 + temp: t.CInt = 0 + i: t.CInt = 0 + while i < exponent: + result *= base + i += 1 + print("Power: ", result) + temp = result % config.MODULO_DIVISOR + print("Power mod: ", temp) + temp = (base * config.EXPONENT_BASE) % config.MODULO_DIVISOR + print("base*exp %% divisor: ", temp) + temp = ((base + config.MATH_OFFSET) * config.MATH_SCALE) % config.MODULO_DIVISOR + print("(base+offset)*scale %% divisor: ", temp) + return result + + +def MixedArithmeticTest(x: t.CInt, y: t.CInt, z: t.CInt) -> t.CInt: + result: t.CInt = 0 + result = (x + y) * z + print("(x+y)*z: ", result) + result = x + (y * z) + print("x+(y*z): ", result) + result = ((x + y) * config.MATH_SCALE) - config.MATH_OFFSET + print("((x+y)*scale)-offset: ", result) + result = (x * config.MATH_SCALE) + (y * config.MATH_SCALE) + print("x*scale + y*scale: ", result) + result = ((x % config.MODULO_DIVISOR) + (y % config.MODULO_DIVISOR)) * config.MATH_SCALE + print("(x%%mod + y%%mod)*scale: ", result) + temp: t.CInt = 0 + temp = x | y & z + print("x | y & z: ", temp) + temp = (x | y) & z + print("(x | y) & z: ", temp) + temp = x ^ y ^ z + print("x ^ y ^ z: ", temp) + return result + + +def MathWithWhileLoopTest(start: t.CInt, count: t.CInt) -> t.CInt: + idx: t.CInt = 0 + accumulator: t.CInt = 0 + multiplier: t.CInt = config.MATH_SCALE + while idx < count: + temp: t.CInt = (start + idx) * multiplier + temp = temp + config.MATH_OFFSET + if temp > config.THRESHOLD: + temp = config.THRESHOLD + accumulator += temp + multiplier += 1 + idx += 1 + print("Accumulator: ", accumulator) + return accumulator + + +def ComplexNestedMathTest(a: t.CInt, b: t.CInt) -> t.CInt: + layer1: t.CInt = 0 + layer2: t.CInt = 0 + layer3: t.CInt = 0 + i: t.CInt = 0 + layer1 = (a + b) * config.MATH_SCALE + print("Layer1: ", layer1) + while i < config.BIT_RANGE: + layer2 += layer1 >> 1 + i += 1 + print("Layer2: ", layer2) + layer3 = layer1 + layer2 - config.MATH_OFFSET + print("Layer3: ", layer3) + layer3 = layer3 * config.MATH_SCALE / 2 if config.MATH_SCALE != 0 else layer3 + print("Layer3 scaled: ", layer3) + return layer3 + + +def ConditionalMathChainTest(value: t.CInt) -> t.CInt: + result: t.CInt = 0 + step: t.CInt = 0 + while step < config.LOOP_LIMIT: + if step < 5: + result += step * config.MATH_SCALE + print("step<5: ", result) + elif step < 10: + result -= step - config.MATH_OFFSET + print("step<10: ", result) + elif step < 15: + result += (step * config.MATH_OFFSET) / config.MATH_SCALE + print("step<15: ", result) + else: + result = result * config.EXPONENT_BASE % config.MODULO_DIVISOR + print("step>=15: ", result) + step += 1 + return result + + +def BitManipulationMathTest(value: t.CInt) -> t.CInt: + original: t.CInt = value + nibble: t.CInt = 0 + result: t.CInt = 0 + result = (value << config.SHIFT_AMOUNT) | (value >> (8 - config.SHIFT_AMOUNT)) + print("Rotate left: ", result) + result = (value >> config.SHIFT_AMOUNT) | (value << (8 - config.SHIFT_AMOUNT)) + print("Rotate right: ", result) + nibble = value & 0xF + print("Lower nibble: ", nibble) + nibble = (value >> config.BIT_RANGE) & 0xF + print("Upper nibble: ", nibble) + result = ((value & config.MASK_VALUE) + config.MATH_OFFSET) * config.MATH_SCALE + print("Masked and scaled: ", result) + result = ((original << config.SHIFT_AMOUNT) ^ original) & config.MASK_VALUE + print("XOR shifted: ", result) + return result \ No newline at end of file diff --git a/Test/LoopMathTest/project.json b/Test/LoopMathTest/project.json new file mode 100644 index 0000000..cb1d3cc --- /dev/null +++ b/Test/LoopMathTest/project.json @@ -0,0 +1,29 @@ +{ + "$schema": "https://raw.githubusercontent.com/TermiNexus/TransPyC/main/schemas/project-schema.json", + "name": "LoopMathTest", + "version": "1.0.0", + "source_dir": "./App", + "build_dir": "./.tpv_build", + "compiler": { + "cmd": "llc", + "flags": ["-filetype=obj", "-relocation-model=pic"] + }, + "linker": { + "cmd": "clang++", + "flags": ["-Wl,--allow-multiple-definition", "-Wl,--unresolved-symbols=ignore-in-object-files", "-lmsvcrt", "-lucrt", "-lpthread", "-lmingwex", "-lkernel32", "-luser32", "-latomic"], + "output": "LoopMathTest.exe" + }, + "includes": [ + "../../includes" + ], + "target": { + "triple": "x86_64-pc-windows-gnu", + "datalayout": "e-m:w-p270:32:32-p271:32:32-p272:64:64-f80:128-n8:16:32:64-S128" + }, + "options": { + "slice_level": 3, + "sha1_slice_level": 1, + "target": "llvm", + "strict_mode": true + } +} diff --git a/Test/MpoolOopTest/App/main.vp b/Test/MpoolOopTest/App/main.vp new file mode 100644 index 0000000..4d9dbd7 --- /dev/null +++ b/Test/MpoolOopTest/App/main.vp @@ -0,0 +1,11 @@ +import t, c +import testcheck +import mpooltest + + +def main() -> t.CInt | t.CExport: + testcheck.begin("MpoolOopTest: MemPool OOP 测试") + testcheck.section("MPool OOP") + mpooltest.mpool_main() + testcheck.ok("MPool OOP 测试完成") + return testcheck.end() diff --git a/Test/MpoolOopTest/App/mpooltest.vp b/Test/MpoolOopTest/App/mpooltest.vp new file mode 100644 index 0000000..90012b8 --- /dev/null +++ b/Test/MpoolOopTest/App/mpooltest.vp @@ -0,0 +1,91 @@ +import t, c +from t import CInt, CPtr, CChar +import viperlib +import viperio +import stdlib +import memhub + + +def mpool_main() -> CInt: + buf: bytes = stdlib.malloc(256) + + arena: bytes = stdlib.malloc(4096) + with memhub.MemPool(arena, 4096) as pool: + p1: bytes = pool.alloc(32) + p2: bytes = pool.alloc(64) + p3: bytes = pool.alloc(128) + if p1 != None and p2 != None and p3 != None: + viperlib.snprintf(buf, 256, "MPool bump: 3 allocs OK") + print(buf) + else: + viperlib.snprintf(buf, 256, "MPool bump: alloc FAILED") + print(buf) + + pool.reset() + p4: bytes = pool.alloc(256) + if p4 != None: + viperlib.snprintf(buf, 256, "MPool bump: reset+alloc OK") + print(buf) + else: + viperlib.snprintf(buf, 256, "MPool bump: reset+alloc FAILED") + print(buf) + + stdlib.free(arena) + + arena2: bytes = stdlib.malloc(4096) + with memhub.MemSlab(arena2, 4096, 64) as spool: + b1: bytes = spool.alloc(64) + b2: bytes = spool.alloc(64) + b3: bytes = spool.alloc(64) + if b1 != None and b2 != None and b3 != None: + viperlib.snprintf(buf, 256, "MPool slab: 3 allocs OK") + print(buf) + else: + viperlib.snprintf(buf, 256, "MPool slab: alloc FAILED") + print(buf) + + spool.free(b2) + b4: bytes = spool.alloc(64) + if b4 != None: + viperlib.snprintf(buf, 256, "MPool slab: free+realloc OK") + print(buf) + else: + viperlib.snprintf(buf, 256, "MPool slab: free+realloc FAILED") + print(buf) + + stdlib.free(arena2) + + arena3: bytes = stdlib.malloc(4096) + hpool: memhub.MemPool | CPtr = memhub.MemPool(arena3, 4096) + h1: bytes = hpool.alloc(32) + h2: bytes = hpool.alloc(64) + if h1 != None and h2 != None: + viperlib.snprintf(buf, 256, "MPool manual: 2 allocs OK") + print(buf) + else: + viperlib.snprintf(buf, 256, "MPool manual: alloc FAILED") + print(buf) + hpool.reset() + h3: bytes = hpool.alloc(128) + if h3 != None: + viperlib.snprintf(buf, 256, "MPool manual: reset+alloc OK") + print(buf) + else: + viperlib.snprintf(buf, 256, "MPool manual: reset+alloc FAILED") + print(buf) + + stdlib.free(arena3) + + arena4: bytes = stdlib.malloc(4096) + with memhub.MemPool(arena4, 4096) as bpool: + wb: viperio.Buf | CPtr = bpool.alloc_buf(128) + if wb.data != None: + viperlib.snprintf(wb.cstr(), 128, "MPool alloc_buf: hello from Buf!") + print(wb.cstr()) + else: + viperlib.snprintf(buf, 256, "MPool alloc_buf: FAILED") + print(buf) + + stdlib.free(arena4) + stdlib.free(buf) + return 0 diff --git a/Test/MpoolOopTest/project.json b/Test/MpoolOopTest/project.json new file mode 100644 index 0000000..8edfb13 --- /dev/null +++ b/Test/MpoolOopTest/project.json @@ -0,0 +1,29 @@ +{ + "$schema": "https://raw.githubusercontent.com/TermiNexus/TransPyC/main/schemas/project-schema.json", + "name": "MpoolOopTest", + "version": "1.0.0", + "source_dir": "./App", + "build_dir": "./.tpv_build", + "compiler": { + "cmd": "llc", + "flags": ["-filetype=obj", "-relocation-model=pic"] + }, + "linker": { + "cmd": "clang++", + "flags": ["-Wl,--allow-multiple-definition", "-Wl,--unresolved-symbols=ignore-in-object-files", "-lmsvcrt", "-lucrt", "-lpthread", "-lmingwex", "-lkernel32", "-luser32", "-latomic"], + "output": "MpoolOopTest.exe" + }, + "includes": [ + "../../includes" + ], + "target": { + "triple": "x86_64-pc-windows-gnu", + "datalayout": "e-m:w-p270:32:32-p271:32:32-p272:64:64-f80:128-n8:16:32:64-S128" + }, + "options": { + "slice_level": 3, + "sha1_slice_level": 1, + "target": "llvm", + "strict_mode": true + } +} diff --git a/Test/NumpyTest/App/main.vp b/Test/NumpyTest/App/main.vp new file mode 100644 index 0000000..8db7688 --- /dev/null +++ b/Test/NumpyTest/App/main.vp @@ -0,0 +1,11 @@ +import t, c +import testcheck +import test_numpy + + +def main() -> t.CInt | t.CExport: + testcheck.begin("NumpyTest: numpy 正确性测试") + testcheck.section("numpy Correctness Tests") + test_numpy.test_numpy_correct() + testcheck.ok("numpy 正确性测试完成") + return testcheck.end() diff --git a/Test/NumpyTest/App/test_numpy.vp b/Test/NumpyTest/App/test_numpy.vp new file mode 100644 index 0000000..91cf870 --- /dev/null +++ b/Test/NumpyTest/App/test_numpy.vp @@ -0,0 +1,1087 @@ +from stdint import * +import numpy +from stdio import printf +from stdlib import calloc, free +import string +import vipermath +import memhub +import t, c + +# ============================================================ +# Constants +# ============================================================ +EPS: t.CDouble = t.CDouble(1e-9) +EPS_LOOSE: t.CDouble = t.CDouble(1e-5) +SIMD_BLOCK: t.CSizeT = 4 + +# ============================================================ +# Global state +# ============================================================ +arena: t.CUInt8T | t.CPtr = None +pool: memhub.MemPool | t.CPtr = None + +test_passed: t.CInt = 0 +test_failed: t.CInt = 0 + +# ============================================================ +# Global check function +# ============================================================ +def check(name: str, condition: t.CInt, detail: str): + global test_passed, test_failed + if condition: + test_passed += 1 + printf(" [PASS] %s\n", name) + else: + test_failed += 1 + printf(" [FAIL] %s -- %s\n", name, detail if detail else "") + + +# ============================================================ +# Approximate comparison (top-level, uses vipermath.fabs) +# ============================================================ +def approx_eq(a: t.CDouble, b: t.CDouble) -> t.CInt: + d: t.CDouble = a - b + if d < t.CDouble(0.0): + d = t.CDouble(0.0) - d + if d < EPS: + return 1 + return 0 + +def approx_loose(a: t.CDouble, b: t.CDouble) -> t.CInt: + d: t.CDouble = a - b + if d < t.CDouble(0.0): + d = t.CDouble(0.0) - d + if d < EPS_LOOSE: + return 1 + return 0 + + +# ============================================================ +# Section headers +# ============================================================ +def section_header(title: str): + printf("\n+-- %s --+\n", title) + +def section_footer(): + printf("+--------------------------------------------+\n") + + +# ============================================================ +# Utility: quick array creation +# ============================================================ +def vec4(p: memhub.MemPool | t.CPtr, v0: t.CDouble, v1: t.CDouble, v2: t.CDouble, v3: t.CDouble) -> numpy.ndarray | t.CPtr: + a: numpy.ndarray | t.CPtr = numpy.zeros(p, 4) + a.data[0] = v0; a.data[1] = v1; a.data[2] = v2; a.data[3] = v3 + return a + +def vec3(p: memhub.MemPool | t.CPtr, v0: t.CDouble, v1: t.CDouble, v2: t.CDouble) -> numpy.ndarray | t.CPtr: + a: numpy.ndarray | t.CPtr = numpy.zeros(p, 3) + a.data[0] = v0; a.data[1] = v1; a.data[2] = v2 + return a + +def vec2(p: memhub.MemPool | t.CPtr, v0: t.CDouble, v1: t.CDouble) -> numpy.ndarray | t.CPtr: + a: numpy.ndarray | t.CPtr = numpy.zeros(p, 2) + a.data[0] = v0; a.data[1] = v1 + return a + + +# ============================================================ +# 1. Array creation +# ============================================================ +def test_zeros_ones(): + section_header("zeros / ones / full") + + a: numpy.ndarray | t.CPtr = numpy.zeros(pool, 5) + check("zeros not None", a != None, "zeros returned None") + check("zeros size == 5", a.size == 5, "size mismatch") + check("zeros [0]==0", a.data[0] == t.CDouble(0.0), "not zero") + check("zeros [4]==0", a.data[4] == t.CDouble(0.0), "not zero") + + b: numpy.ndarray | t.CPtr = numpy.ones(pool, 4) + check("ones not None", b != None, "ones returned None") + check("ones [0]==1", b.data[0] == t.CDouble(1.0), "not one") + check("ones [3]==1", b.data[3] == t.CDouble(1.0), "not one") + + c: numpy.ndarray | t.CPtr = numpy.full(pool, 3, t.CDouble(7.5)) + check("full not None", c != None, "full returned None") + check("full value", c.data[0] == t.CDouble(7.5), "value mismatch") + + a.delete() + b.delete() + c.delete() + section_footer() + + +def test_arange_linspace(): + section_header("arange / linspace") + + a: numpy.ndarray | t.CPtr = numpy.arange(pool, t.CDouble(0.0), t.CDouble(5.0), t.CDouble(1.0)) + check("arange not None", a != None, "arange returned None") + check("arange size == 5", a.size == 5, "size mismatch") + check("arange [0]==0", approx_eq(a.data[0], t.CDouble(0.0)), "mismatch") + check("arange [4]==4", approx_eq(a.data[4], t.CDouble(4.0)), "mismatch") + + b: numpy.ndarray | t.CPtr = numpy.linspace(pool, t.CDouble(0.0), t.CDouble(1.0), 5) + check("linspace not None", b != None, "linspace returned None") + check("linspace size == 5", b.size == 5, "size mismatch") + check("linspace [0]==0", approx_eq(b.data[0], t.CDouble(0.0)), "mismatch") + check("linspace [4]==1", approx_eq(b.data[4], t.CDouble(1.0)), "mismatch") + + a.delete() + b.delete() + section_footer() + + +def test_eye_diag(): + section_header("eye / diag") + + e: numpy.ndarray | t.CPtr = numpy.eye(pool, 3) + check("eye not None", e != None, "eye returned None") + check("eye ndim == 2", e.ndim == 2, "ndim mismatch") + check("eye [0,0]==1", e.at2d(0, 0) == t.CDouble(1.0), "mismatch") + check("eye [0,1]==0", e.at2d(0, 1) == t.CDouble(0.0), "mismatch") + check("eye [1,1]==1", e.at2d(1, 1) == t.CDouble(1.0), "mismatch") + + vals: numpy.ndarray | t.CPtr = vec3(pool, t.CDouble(1.0), t.CDouble(2.0), t.CDouble(3.0)) + d: numpy.ndarray | t.CPtr = numpy.diag(pool, vals) + check("diag not None", d != None, "diag returned None") + check("diag [0,0]==1", d.at2d(0, 0) == t.CDouble(1.0), "mismatch") + check("diag [1,1]==2", d.at2d(1, 1) == t.CDouble(2.0), "mismatch") + check("diag [2,2]==3", d.at2d(2, 2) == t.CDouble(3.0), "mismatch") + + e.delete() + vals.delete() + d.delete() + section_footer() + + +# ============================================================ +# 2. Methods +# ============================================================ +def test_sum_mean_min_max(): + section_header("sum / mean / min / max / argmax / argmin") + + a: numpy.ndarray | t.CPtr = numpy.arange(pool, t.CDouble(1.0), t.CDouble(6.0), t.CDouble(1.0)) + check("sum == 15", approx_eq(a.sum(), t.CDouble(15.0)), "mismatch") + check("mean == 3", approx_eq(a.mean(), t.CDouble(3.0)), "mismatch") + check("min == 1", approx_eq(a.min(), t.CDouble(1.0)), "mismatch") + check("max == 5", approx_eq(a.max(), t.CDouble(5.0)), "mismatch") + check("argmax == 4", a.argmax() == 4, "mismatch") + check("argmin == 0", a.argmin() == 0, "mismatch") + + a.delete() + section_footer() + + +def test_fill_copy(): + section_header("fill / copy") + + a: numpy.ndarray | t.CPtr = numpy.zeros(pool, 3) + a.fill(t.CDouble(9.0)) + check("fill [0]==9", a.data[0] == t.CDouble(9.0), "mismatch") + check("fill [2]==9", a.data[2] == t.CDouble(9.0), "mismatch") + + b: numpy.ndarray | t.CPtr = a.copy() + check("copy not None", b != None, "copy returned None") + check("copy [0]==9", b.data[0] == t.CDouble(9.0), "mismatch") + + b.data[0] = t.CDouble(0.0) + check("copy is independent", a.data[0] == t.CDouble(9.0), "copy not independent") + + a.delete() + b.delete() + section_footer() + + +# ============================================================ +# 3. Operator overloading +# ============================================================ +def test_add_sub_mul_div(): + section_header("__add__ / __sub__ / __mul__ / __truediv__") + + a: numpy.ndarray | t.CPtr = vec3(pool, t.CDouble(1.0), t.CDouble(2.0), t.CDouble(3.0)) + b: numpy.ndarray | t.CPtr = vec3(pool, t.CDouble(4.0), t.CDouble(5.0), t.CDouble(6.0)) + + c_add: numpy.ndarray | t.CPtr = a + b + check("a+b not None", c_add != None, "add returned None") + check("a+b [0]==5", c_add.data[0] == t.CDouble(5.0), "mismatch") + check("a+b [2]==9", c_add.data[2] == t.CDouble(9.0), "mismatch") + + c_sub: numpy.ndarray | t.CPtr = a - b + check("a-b [0]==-3", c_sub.data[0] == t.CDouble(-3.0), "mismatch") + + c_mul: numpy.ndarray | t.CPtr = a * b + check("a*b [1]==10", c_mul.data[1] == t.CDouble(10.0), "mismatch") + + c_div: numpy.ndarray | t.CPtr = b / a + check("b/a [0]==4", c_div.data[0] == t.CDouble(4.0), "mismatch") + check("b/a [2]==2", c_div.data[2] == t.CDouble(2.0), "mismatch") + + a.delete() + b.delete() + c_add.delete() + c_sub.delete() + c_mul.delete() + c_div.delete() + section_footer() + + +def test_neg(): + section_header("__neg__") + + a: numpy.ndarray | t.CPtr = vec3(pool, t.CDouble(1.0), t.CDouble(-2.0), t.CDouble(3.0)) + neg_a: numpy.ndarray | t.CPtr = -a + check("neg not None", neg_a != None, "neg returned None") + check("neg [0]==-1", neg_a.data[0] == t.CDouble(-1.0), "mismatch") + check("neg [1]==2", neg_a.data[1] == t.CDouble(2.0), "mismatch") + + a.delete() + neg_a.delete() + section_footer() + + +def test_len(): + section_header("__len__") + + a: numpy.ndarray | t.CPtr = numpy.zeros(pool, 10) + check("len == 10", len(a) == 10, "mismatch") + + a.delete() + section_footer() + + +# ============================================================ +# 4. Scalar operations +# ============================================================ +def test_scalar_ops(): + section_header("add_scalar / mul_scalar / sub_scalar / div_scalar") + + a: numpy.ndarray | t.CPtr = numpy.ones(pool, 3) + + r1: numpy.ndarray | t.CPtr = numpy.add_scalar(a, t.CDouble(2.0)) + check("add_scalar [0]==3", r1.data[0] == t.CDouble(3.0), "mismatch") + + r2: numpy.ndarray | t.CPtr = numpy.mul_scalar(a, t.CDouble(5.0)) + check("mul_scalar [0]==5", r2.data[0] == t.CDouble(5.0), "mismatch") + + r3: numpy.ndarray | t.CPtr = numpy.sub_scalar(a, t.CDouble(0.5)) + check("sub_scalar [0]==0.5", r3.data[0] == t.CDouble(0.5), "mismatch") + + r4: numpy.ndarray | t.CPtr = numpy.div_scalar(a, t.CDouble(2.0)) + check("div_scalar [0]==0.5", r4.data[0] == t.CDouble(0.5), "mismatch") + + a.delete() + r1.delete() + r2.delete() + r3.delete() + r4.delete() + section_footer() + + +# ============================================================ +# 5. Math functions +# ============================================================ +def test_math_funcs(): + section_header("np_abs / np_sqrt / np_pow") + + a: numpy.ndarray | t.CPtr = vec3(pool, t.CDouble(1.0), t.CDouble(4.0), t.CDouble(9.0)) + + r_sqrt: numpy.ndarray | t.CPtr = numpy.np_sqrt(a) + check("sqrt [0]==1", approx_eq(r_sqrt.data[0], t.CDouble(1.0)), "mismatch") + check("sqrt [1]==2", approx_eq(r_sqrt.data[1], t.CDouble(2.0)), "mismatch") + check("sqrt [2]==3", approx_eq(r_sqrt.data[2], t.CDouble(3.0)), "mismatch") + + b: numpy.ndarray | t.CPtr = vec3(pool, t.CDouble(-1.0), t.CDouble(-4.0), t.CDouble(9.0)) + r_abs: numpy.ndarray | t.CPtr = numpy.np_abs(b) + check("abs [0]==1", approx_eq(r_abs.data[0], t.CDouble(1.0)), "mismatch") + check("abs [1]==4", approx_eq(r_abs.data[1], t.CDouble(4.0)), "mismatch") + + c: numpy.ndarray | t.CPtr = vec3(pool, t.CDouble(1.0), t.CDouble(2.0), t.CDouble(3.0)) + r_pow: numpy.ndarray | t.CPtr = numpy.np_pow(c, t.CDouble(2.0)) + check("pow [0]==1", approx_eq(r_pow.data[0], t.CDouble(1.0)), "mismatch") + check("pow [1]==4", approx_eq(r_pow.data[1], t.CDouble(4.0)), "mismatch") + check("pow [2]==9", approx_eq(r_pow.data[2], t.CDouble(9.0)), "mismatch") + + a.delete() + b.delete() + c.delete() + r_sqrt.delete() + r_abs.delete() + r_pow.delete() + section_footer() + + +# ============================================================ +# 6. Matrix operations +# ============================================================ +def test_matmul(): + section_header("matmul") + + # [1,2;3,4] x [5,6;7,8] = [19,22;43,50] + a: numpy.ndarray | t.CPtr = numpy.empty2d(pool, 2, 2) + a.set2d(0, 0, t.CDouble(1.0)); a.set2d(0, 1, t.CDouble(2.0)) + a.set2d(1, 0, t.CDouble(3.0)); a.set2d(1, 1, t.CDouble(4.0)) + + b: numpy.ndarray | t.CPtr = numpy.empty2d(pool, 2, 2) + b.set2d(0, 0, t.CDouble(5.0)); b.set2d(0, 1, t.CDouble(6.0)) + b.set2d(1, 0, t.CDouble(7.0)); b.set2d(1, 1, t.CDouble(8.0)) + + c: numpy.ndarray | t.CPtr = numpy.matmul(a, b) + check("matmul not None", c != None, "matmul returned None") + check("matmul [0,0]==19", c.at2d(0, 0) == t.CDouble(19.0), "mismatch") + check("matmul [0,1]==22", c.at2d(0, 1) == t.CDouble(22.0), "mismatch") + check("matmul [1,0]==43", c.at2d(1, 0) == t.CDouble(43.0), "mismatch") + check("matmul [1,1]==50", c.at2d(1, 1) == t.CDouble(50.0), "mismatch") + + a.delete() + b.delete() + c.delete() + section_footer() + + +def test_dot(): + section_header("dot / dot_product") + + a: numpy.ndarray | t.CPtr = vec3(pool, t.CDouble(1.0), t.CDouble(2.0), t.CDouble(3.0)) + b: numpy.ndarray | t.CPtr = vec3(pool, t.CDouble(4.0), t.CDouble(5.0), t.CDouble(6.0)) + + d: t.CDouble = a.dot(b) + check("dot == 32", approx_eq(d, t.CDouble(32.0)), "mismatch") + + d2: t.CDouble = numpy.dot_product(a, b) + check("dot_product == 32", approx_eq(d2, t.CDouble(32.0)), "mismatch") + + a.delete() + b.delete() + section_footer() + + +def test_transpose(): + section_header("T (transpose)") + + a: numpy.ndarray | t.CPtr = numpy.empty2d(pool, 2, 3) + a.set2d(0, 0, t.CDouble(1.0)); a.set2d(0, 1, t.CDouble(2.0)); a.set2d(0, 2, t.CDouble(3.0)) + a.set2d(1, 0, t.CDouble(4.0)); a.set2d(1, 1, t.CDouble(5.0)); a.set2d(1, 2, t.CDouble(6.0)) + + at: numpy.ndarray | t.CPtr = a.T() + check("T not None", at != None, "T returned None") + check("T shape[0]==3", at.shape[0] == 3, "shape mismatch") + check("T shape[1]==2", at.shape[1] == 2, "shape mismatch") + check("T [0,0]==1", at.at2d(0, 0) == t.CDouble(1.0), "mismatch") + check("T [0,1]==4", at.at2d(0, 1) == t.CDouble(4.0), "mismatch") + check("T [1,0]==2", at.at2d(1, 0) == t.CDouble(2.0), "mismatch") + + a.delete() + at.delete() + section_footer() + + +# ============================================================ +# 7. Utility +# ============================================================ +def test_var_std_norm(): + section_header("var / std / norm") + + # [2,4,4,4,5,5,7,9] mean=5, var=4, std=2 + a: numpy.ndarray | t.CPtr = numpy.zeros(pool, 8) + a.data[0] = t.CDouble(2.0); a.data[1] = t.CDouble(4.0) + a.data[2] = t.CDouble(4.0); a.data[3] = t.CDouble(4.0) + a.data[4] = t.CDouble(5.0); a.data[5] = t.CDouble(5.0) + a.data[6] = t.CDouble(7.0); a.data[7] = t.CDouble(9.0) + + v: t.CDouble = numpy.var(a) + printf(" var = %.6f (expect 4.0)\n", v) + check("var ~= 4", approx_eq(v, t.CDouble(4.0)), "mismatch") + + s: t.CDouble = numpy.std(a) + printf(" std = %.6f (expect 2.0)\n", s) + check("std ~= 2", approx_eq(s, t.CDouble(2.0)), "mismatch") + + b: numpy.ndarray | t.CPtr = vec2(pool, t.CDouble(3.0), t.CDouble(4.0)) + n: t.CDouble = numpy.norm(b) + printf(" norm = %.6f (expect 5.0)\n", n) + check("norm ~= 5", approx_eq(n, t.CDouble(5.0)), "mismatch") + + a.delete() + b.delete() + section_footer() + + +def test_clip_concatenate(): + section_header("clip / concatenate") + + a: numpy.ndarray | t.CPtr = vec3(pool, t.CDouble(1.0), t.CDouble(5.0), t.CDouble(10.0)) + r: numpy.ndarray | t.CPtr = numpy.clip(a, t.CDouble(2.0), t.CDouble(8.0)) + check("clip [0]==2", r.data[0] == t.CDouble(2.0), "mismatch") + check("clip [1]==5", r.data[1] == t.CDouble(5.0), "mismatch") + check("clip [2]==8", r.data[2] == t.CDouble(8.0), "mismatch") + + b: numpy.ndarray | t.CPtr = vec2(pool, t.CDouble(1.0), t.CDouble(2.0)) + c: numpy.ndarray | t.CPtr = vec2(pool, t.CDouble(3.0), t.CDouble(4.0)) + cat: numpy.ndarray | t.CPtr = numpy.concatenate(b, c) + check("concatenate not None", cat != None, "concatenate returned None") + check("concatenate size == 4", cat.size == 4, "size mismatch") + check("concatenate [0]==1", cat.data[0] == t.CDouble(1.0), "mismatch") + check("concatenate [3]==4", cat.data[3] == t.CDouble(4.0), "mismatch") + + a.delete() + r.delete() + b.delete() + c.delete() + cat.delete() + section_footer() + + +def test_sort_reverse(): + section_header("sort_arr / reverse") + + a: numpy.ndarray | t.CPtr = vec3(pool, t.CDouble(3.0), t.CDouble(1.0), t.CDouble(2.0)) + s: numpy.ndarray | t.CPtr = numpy.sort_arr(a) + check("sort not None", s != None, "sort returned None") + check("sort [0]==1", s.data[0] == t.CDouble(1.0), "mismatch") + check("sort [1]==2", s.data[1] == t.CDouble(2.0), "mismatch") + check("sort [2]==3", s.data[2] == t.CDouble(3.0), "mismatch") + + r: numpy.ndarray | t.CPtr = numpy.reverse(a) + check("reverse not None", r != None, "reverse returned None") + check("reverse [0]==2", r.data[0] == t.CDouble(2.0), "mismatch") + check("reverse [1]==1", r.data[1] == t.CDouble(1.0), "mismatch") + check("reverse [2]==3", r.data[2] == t.CDouble(3.0), "mismatch") + + a.delete() + s.delete() + r.delete() + section_footer() + + +def test_print_arr(): + section_header("print_arr") + + a: numpy.ndarray | t.CPtr = vec3(pool, t.CDouble(1.0), t.CDouble(2.0), t.CDouble(3.0)) + printf(" 1D array: ") + a.print_arr() + + b: numpy.ndarray | t.CPtr = numpy.eye(pool, 3) + printf(" 2D eye(3):\n") + b.print_arr() + + a.delete() + b.delete() + section_footer() + + +# ============================================================ +# 8. Additional operator overloading +# ============================================================ +def test_floordiv_mod(): + section_header("__floordiv__ / __mod__") + + a: numpy.ndarray | t.CPtr = vec3(pool, t.CDouble(7.0), t.CDouble(10.0), t.CDouble(15.0)) + b: numpy.ndarray | t.CPtr = vec3(pool, t.CDouble(2.0), t.CDouble(3.0), t.CDouble(4.0)) + + c_fd: numpy.ndarray | t.CPtr = a // b + check("7//2==3", c_fd.data[0] == t.CDouble(3.0), "mismatch") + check("10//3==3", c_fd.data[1] == t.CDouble(3.0), "mismatch") + check("15//4==3", c_fd.data[2] == t.CDouble(3.0), "mismatch") + + c_mod: numpy.ndarray | t.CPtr = a % b + check("7%%2==1", c_mod.data[0] == t.CDouble(1.0), "mismatch") + check("10%%3==1", c_mod.data[1] == t.CDouble(1.0), "mismatch") + check("15%%4==3", c_mod.data[2] == t.CDouble(3.0), "mismatch") + + a.delete() + b.delete() + c_fd.delete() + c_mod.delete() + section_footer() + + +# ============================================================ +# 9. Additional math functions +# ============================================================ +def test_additional_math(): + section_header("np_log10 / np_log2 / np_floor / np_ceil / np_round / np_sign") + + a: numpy.ndarray | t.CPtr = vec3(pool, t.CDouble(10.0), t.CDouble(100.0), t.CDouble(1000.0)) + r_log10: numpy.ndarray | t.CPtr = numpy.np_log10(a) + check("log10(10)~=1", approx_loose(r_log10.data[0], t.CDouble(1.0)), "mismatch") + check("log10(100)~=2", approx_loose(r_log10.data[1], t.CDouble(2.0)), "mismatch") + + b: numpy.ndarray | t.CPtr = vec3(pool, t.CDouble(2.0), t.CDouble(4.0), t.CDouble(8.0)) + r_log2: numpy.ndarray | t.CPtr = numpy.np_log2(b) + check("log2(2)~=1", approx_loose(r_log2.data[0], t.CDouble(1.0)), "mismatch") + check("log2(4)~=2", approx_loose(r_log2.data[1], t.CDouble(2.0)), "mismatch") + + c: numpy.ndarray | t.CPtr = vec3(pool, t.CDouble(1.5), t.CDouble(2.7), t.CDouble(-1.3)) + r_floor: numpy.ndarray | t.CPtr = numpy.np_floor(c) + check("floor(1.5)==1", r_floor.data[0] == t.CDouble(1.0), "mismatch") + check("floor(2.7)==2", r_floor.data[1] == t.CDouble(2.0), "mismatch") + check("floor(-1.3)==-2", r_floor.data[2] == t.CDouble(-2.0), "mismatch") + + r_ceil: numpy.ndarray | t.CPtr = numpy.np_ceil(c) + check("ceil(1.5)==2", r_ceil.data[0] == t.CDouble(2.0), "mismatch") + check("ceil(2.7)==3", r_ceil.data[1] == t.CDouble(3.0), "mismatch") + check("ceil(-1.3)==-1", r_ceil.data[2] == t.CDouble(-1.0), "mismatch") + + d: numpy.ndarray | t.CPtr = vec3(pool, t.CDouble(1.4), t.CDouble(2.5), t.CDouble(3.6)) + r_round: numpy.ndarray | t.CPtr = numpy.np_round(d) + check("round(1.4)==1", r_round.data[0] == t.CDouble(1.0), "mismatch") + check("round(3.6)==4", r_round.data[2] == t.CDouble(4.0), "mismatch") + + e: numpy.ndarray | t.CPtr = numpy.zeros(pool, 4) + e.data[0] = t.CDouble(-3.0); e.data[1] = t.CDouble(0.0); e.data[2] = t.CDouble(5.0); e.data[3] = t.CDouble(-0.1) + r_sign: numpy.ndarray | t.CPtr = numpy.np_sign(e) + check("sign(-3)==-1", r_sign.data[0] == t.CDouble(-1.0), "mismatch") + check("sign(0)==0", r_sign.data[1] == t.CDouble(0.0), "mismatch") + check("sign(5)==1", r_sign.data[2] == t.CDouble(1.0), "mismatch") + + a.delete() + b.delete() + c.delete() + d.delete() + e.delete() + r_log10.delete() + r_log2.delete() + r_floor.delete() + r_ceil.delete() + r_round.delete() + r_sign.delete() + section_footer() + + +def test_trig_hyperbolic(): + section_header("np_tanh / np_sinh / np_cosh / np_arcsin / np_arccos / np_arctan") + + a: numpy.ndarray | t.CPtr = vec3(pool, t.CDouble(0.0), t.CDouble(1.0), t.CDouble(-1.0)) + + r_tanh: numpy.ndarray | t.CPtr = numpy.np_tanh(a) + check("tanh(0)~=0", approx_loose(r_tanh.data[0], t.CDouble(0.0)), "mismatch") + + r_sinh: numpy.ndarray | t.CPtr = numpy.np_sinh(a) + check("sinh(0)~=0", approx_loose(r_sinh.data[0], t.CDouble(0.0)), "mismatch") + + r_cosh: numpy.ndarray | t.CPtr = numpy.np_cosh(a) + check("cosh(0)~=1", approx_loose(r_cosh.data[0], t.CDouble(1.0)), "mismatch") + + b: numpy.ndarray | t.CPtr = vec2(pool, t.CDouble(0.0), t.CDouble(0.5)) + r_asin: numpy.ndarray | t.CPtr = numpy.np_arcsin(b) + check("arcsin(0)~=0", approx_loose(r_asin.data[0], t.CDouble(0.0)), "mismatch") + + r_acos: numpy.ndarray | t.CPtr = numpy.np_arccos(b) + check("arccos(0)~=pi/2", approx_loose(r_acos.data[0], t.CDouble(1.5707963)), "mismatch") + + r_atan: numpy.ndarray | t.CPtr = numpy.np_arctan(b) + check("arctan(0)~=0", approx_loose(r_atan.data[0], t.CDouble(0.0)), "mismatch") + + a.delete() + b.delete() + r_tanh.delete() + r_sinh.delete() + r_cosh.delete() + r_asin.delete() + r_acos.delete() + r_atan.delete() + section_footer() + + +def test_degrees_radians(): + section_header("np_degrees / np_radians") + + a: numpy.ndarray | t.CPtr = vec2(pool, t.CDouble(0.0), t.CDouble(1.5707963267948966)) + + r_deg: numpy.ndarray | t.CPtr = numpy.np_degrees(a) + check("deg(0)~=0", approx_loose(r_deg.data[0], t.CDouble(0.0)), "mismatch") + check("deg(pi/2)~=90", approx_loose(r_deg.data[1], t.CDouble(90.0)), "mismatch") + + b: numpy.ndarray | t.CPtr = vec2(pool, t.CDouble(0.0), t.CDouble(90.0)) + r_rad: numpy.ndarray | t.CPtr = numpy.np_radians(b) + check("rad(0)~=0", approx_loose(r_rad.data[0], t.CDouble(0.0)), "mismatch") + check("rad(90)~=pi/2", approx_loose(r_rad.data[1], t.CDouble(1.5707963)), "mismatch") + + a.delete() + b.delete() + r_deg.delete() + r_rad.delete() + section_footer() + + +# ============================================================ +# 10. Additional array operations +# ============================================================ +def test_cumsum_diff(): + section_header("cumsum / diff") + + a: numpy.ndarray | t.CPtr = numpy.zeros(pool, 4) + a.data[0] = t.CDouble(1.0); a.data[1] = t.CDouble(2.0); a.data[2] = t.CDouble(3.0); a.data[3] = t.CDouble(4.0) + + r_cs: numpy.ndarray | t.CPtr = numpy.cumsum(a) + check("cumsum not None", r_cs != None, "cumsum returned None") + check("cumsum[0]==1", r_cs.data[0] == t.CDouble(1.0), "mismatch") + check("cumsum[1]==3", r_cs.data[1] == t.CDouble(3.0), "mismatch") + check("cumsum[2]==6", r_cs.data[2] == t.CDouble(6.0), "mismatch") + check("cumsum[3]==10", r_cs.data[3] == t.CDouble(10.0), "mismatch") + + r_diff: numpy.ndarray | t.CPtr = numpy.diff(a) + check("diff not None", r_diff != None, "diff returned None") + check("diff size==3", r_diff.size == 3, "size mismatch") + check("diff[0]==1", r_diff.data[0] == t.CDouble(1.0), "mismatch") + check("diff[2]==1", r_diff.data[2] == t.CDouble(1.0), "mismatch") + + a.delete() + r_cs.delete() + r_diff.delete() + section_footer() + + +def test_max_min_where(): + section_header("np_maximum / np_minimum / np_where") + + a: numpy.ndarray | t.CPtr = vec3(pool, t.CDouble(1.0), t.CDouble(5.0), t.CDouble(3.0)) + b: numpy.ndarray | t.CPtr = vec3(pool, t.CDouble(4.0), t.CDouble(2.0), t.CDouble(6.0)) + + r_max: numpy.ndarray | t.CPtr = numpy.np_maximum(a, b) + check("maximum[0]==4", r_max.data[0] == t.CDouble(4.0), "mismatch") + check("maximum[1]==5", r_max.data[1] == t.CDouble(5.0), "mismatch") + check("maximum[2]==6", r_max.data[2] == t.CDouble(6.0), "mismatch") + + r_min: numpy.ndarray | t.CPtr = numpy.np_minimum(a, b) + check("minimum[0]==1", r_min.data[0] == t.CDouble(1.0), "mismatch") + check("minimum[1]==2", r_min.data[1] == t.CDouble(2.0), "mismatch") + check("minimum[2]==3", r_min.data[2] == t.CDouble(3.0), "mismatch") + + # where: cond > 0 ? a : b + cond: numpy.ndarray | t.CPtr = vec3(pool, t.CDouble(0.0), t.CDouble(1.0), t.CDouble(0.0)) + r_where: numpy.ndarray | t.CPtr = numpy.np_where(cond, a, b) + check("where[0]==4", r_where.data[0] == t.CDouble(4.0), "mismatch") + check("where[1]==5", r_where.data[1] == t.CDouble(5.0), "mismatch") + check("where[2]==6", r_where.data[2] == t.CDouble(6.0), "mismatch") + + a.delete() + b.delete() + cond.delete() + r_max.delete() + r_min.delete() + r_where.delete() + section_footer() + + +def test_flatten_trace(): + section_header("flatten / trace") + + a: numpy.ndarray | t.CPtr = numpy.empty2d(pool, 2, 3) + a.set2d(0, 0, t.CDouble(1.0)); a.set2d(0, 1, t.CDouble(2.0)); a.set2d(0, 2, t.CDouble(3.0)) + a.set2d(1, 0, t.CDouble(4.0)); a.set2d(1, 1, t.CDouble(5.0)); a.set2d(1, 2, t.CDouble(6.0)) + + r_flat: numpy.ndarray | t.CPtr = numpy.flatten(a) + check("flatten not None", r_flat != None, "flatten returned None") + check("flatten ndim==1", r_flat.ndim == 1, "ndim mismatch") + check("flatten size==6", r_flat.size == 6, "size mismatch") + check("flatten[0]==1", r_flat.data[0] == t.CDouble(1.0), "mismatch") + + # trace of [[1,2],[3,4]] = 1+4 = 5 + b: numpy.ndarray | t.CPtr = numpy.empty2d(pool, 2, 2) + b.set2d(0, 0, t.CDouble(1.0)); b.set2d(0, 1, t.CDouble(2.0)) + b.set2d(1, 0, t.CDouble(3.0)); b.set2d(1, 1, t.CDouble(4.0)) + tr: t.CDouble = numpy.trace(b) + check("trace == 5", tr == t.CDouble(5.0), "mismatch") + + a.delete() + r_flat.delete() + b.delete() + section_footer() + + +def test_outer(): + section_header("outer") + + a: numpy.ndarray | t.CPtr = vec2(pool, t.CDouble(1.0), t.CDouble(2.0)) + b: numpy.ndarray | t.CPtr = vec3(pool, t.CDouble(3.0), t.CDouble(4.0), t.CDouble(5.0)) + + r: numpy.ndarray | t.CPtr = numpy.outer(a, b) + check("outer not None", r != None, "outer returned None") + check("outer ndim==2", r.ndim == 2, "ndim mismatch") + check("outer[0,0]==3", r.at2d(0, 0) == t.CDouble(3.0), "mismatch") + check("outer[0,1]==4", r.at2d(0, 1) == t.CDouble(4.0), "mismatch") + check("outer[1,0]==6", r.at2d(1, 0) == t.CDouble(6.0), "mismatch") + check("outer[1,2]==10", r.at2d(1, 2) == t.CDouble(10.0), "mismatch") + + a.delete() + b.delete() + r.delete() + section_footer() + + +# ============================================================ +# 11. Boolean / comparison +# ============================================================ +def test_bool_comparison(): + section_header("np_all / np_any / np_count_nonzero / np_equal / np_less / np_greater") + + a: numpy.ndarray | t.CPtr = numpy.zeros(pool, 4) + a.data[0] = t.CDouble(1.0); a.data[1] = t.CDouble(0.0); a.data[2] = t.CDouble(3.0); a.data[3] = t.CDouble(0.0) + check("count_nonzero==2", numpy.np_count_nonzero(a) == 2, "mismatch") + check("any==1", numpy.np_any(a) == 1, "mismatch") + + b: numpy.ndarray | t.CPtr = vec3(pool, t.CDouble(1.0), t.CDouble(2.0), t.CDouble(3.0)) + check("all(1,2,3)==1", numpy.np_all(b) == 1, "mismatch") + + c: numpy.ndarray | t.CPtr = numpy.zeros(pool, 3) + check("all(0,0,0)==0", numpy.np_all(c) == 0, "mismatch") + check("any(0,0,0)==0", numpy.np_any(c) == 0, "mismatch") + + d: numpy.ndarray | t.CPtr = vec3(pool, t.CDouble(1.0), t.CDouble(2.0), t.CDouble(3.0)) + e: numpy.ndarray | t.CPtr = vec3(pool, t.CDouble(1.0), t.CDouble(0.0), t.CDouble(4.0)) + + r_eq: numpy.ndarray | t.CPtr = numpy.np_equal(d, e) + check("equal[0]==1", r_eq.data[0] == t.CDouble(1.0), "mismatch") + check("equal[1]==0", r_eq.data[1] == t.CDouble(0.0), "mismatch") + + r_lt: numpy.ndarray | t.CPtr = numpy.np_less(d, e) + check("less[2]==1", r_lt.data[2] == t.CDouble(1.0), "mismatch") + check("less[0]==0", r_lt.data[0] == t.CDouble(0.0), "mismatch") + + r_gt: numpy.ndarray | t.CPtr = numpy.np_greater(d, e) + check("greater[1]==1", r_gt.data[1] == t.CDouble(1.0), "mismatch") + + a.delete() + b.delete() + c.delete() + d.delete() + e.delete() + r_eq.delete() + r_lt.delete() + r_gt.delete() + section_footer() + + +# ============================================================ +# 12. Linear algebra +# ============================================================ +def test_linalg(): + section_header("det2x2 / inv2x2 / cross3 / prod / median / percentile") + + # det2x2: [[1,2],[3,4]] -> 1*4-2*3 = -2 + a: numpy.ndarray | t.CPtr = numpy.empty2d(pool, 2, 2) + a.set2d(0, 0, t.CDouble(1.0)); a.set2d(0, 1, t.CDouble(2.0)) + a.set2d(1, 0, t.CDouble(3.0)); a.set2d(1, 1, t.CDouble(4.0)) + d: t.CDouble = numpy.det2x2(a) + check("det2x2==-2", d == t.CDouble(-2.0), "mismatch") + + # inv2x2 of [[1,2],[3,4]] + inv: numpy.ndarray | t.CPtr = numpy.inv2x2(a) + check("inv2x2 not None", inv != None, "inv2x2 returned None") + check("inv[0,0]==-2", approx_eq(inv.at2d(0, 0), t.CDouble(-2.0)), "mismatch") + check("inv[0,1]==1", approx_eq(inv.at2d(0, 1), t.CDouble(1.0)), "mismatch") + + # cross3: [1,0,0] x [0,1,0] = [0,0,1] + x: numpy.ndarray | t.CPtr = vec3(pool, t.CDouble(1.0), t.CDouble(0.0), t.CDouble(0.0)) + y: numpy.ndarray | t.CPtr = vec3(pool, t.CDouble(0.0), t.CDouble(1.0), t.CDouble(0.0)) + cr: numpy.ndarray | t.CPtr = numpy.cross3(x, y) + check("cross not None", cr != None, "cross returned None") + check("cross[2]==1", cr.data[2] == t.CDouble(1.0), "mismatch") + + # prod + p: numpy.ndarray | t.CPtr = numpy.zeros(pool, 4) + p.data[0] = t.CDouble(1.0); p.data[1] = t.CDouble(2.0); p.data[2] = t.CDouble(3.0); p.data[3] = t.CDouble(4.0) + check("prod==24", numpy.prod(p) == t.CDouble(24.0), "mismatch") + + # median + m: numpy.ndarray | t.CPtr = numpy.zeros(pool, 5) + m.data[0] = t.CDouble(3.0); m.data[1] = t.CDouble(1.0); m.data[2] = t.CDouble(2.0) + m.data[3] = t.CDouble(5.0); m.data[4] = t.CDouble(4.0) + check("median==3", numpy.median(m) == t.CDouble(3.0), "mismatch") + + # percentile + check("p50==3", approx_eq(numpy.percentile(m, t.CDouble(50.0)), t.CDouble(3.0)), "mismatch") + + a.delete() + inv.delete() + x.delete() + y.delete() + cr.delete() + p.delete() + m.delete() + section_footer() + + +# ============================================================ +# 13. Additional creation / constants +# ============================================================ +def test_additional_creation(): + section_header("full2d / zeros_like / ones_like / arange1 / constants") + + f: numpy.ndarray | t.CPtr = numpy.full2d(pool, 2, 3, t.CDouble(7.0)) + check("full2d not None", f != None, "full2d returned None") + check("full2d ndim==2", f.ndim == 2, "ndim mismatch") + check("full2d[0,0]==7", f.at2d(0, 0) == t.CDouble(7.0), "mismatch") + check("full2d[1,2]==7", f.at2d(1, 2) == t.CDouble(7.0), "mismatch") + + a: numpy.ndarray | t.CPtr = vec3(pool, t.CDouble(1.0), t.CDouble(2.0), t.CDouble(3.0)) + zl: numpy.ndarray | t.CPtr = numpy.zeros_like(a) + check("zeros_like not None", zl != None, "returned None") + check("zeros_like size==3", zl.size == 3, "size mismatch") + check("zeros_like[0]==0", zl.data[0] == t.CDouble(0.0), "mismatch") + + ol: numpy.ndarray | t.CPtr = numpy.ones_like(a) + check("ones_like not None", ol != None, "returned None") + check("ones_like[0]==1", ol.data[0] == t.CDouble(1.0), "mismatch") + + ar: numpy.ndarray | t.CPtr = numpy.arange1(pool, t.CDouble(4.0)) + check("arange1 not None", ar != None, "returned None") + check("arange1 size==4", ar.size == 4, "size mismatch") + check("arange1[0]==0", ar.data[0] == t.CDouble(0.0), "mismatch") + check("arange1[3]==3", ar.data[3] == t.CDouble(3.0), "mismatch") + + # Constants + check("pi ~= 3.14", approx_loose(numpy.pi, t.CDouble(3.14159265)), "mismatch") + check("e ~= 2.71", approx_loose(numpy.e, t.CDouble(2.71828182)), "mismatch") + + f.delete() + a.delete() + zl.delete() + ol.delete() + ar.delete() + section_footer() + + +# ============================================================ +# 14. Interpolation +# ============================================================ +def test_interp(): + section_header("np_interp") + + xp: numpy.ndarray | t.CPtr = vec3(pool, t.CDouble(0.0), t.CDouble(1.0), t.CDouble(2.0)) + fp: numpy.ndarray | t.CPtr = vec3(pool, t.CDouble(0.0), t.CDouble(10.0), t.CDouble(20.0)) + + v: t.CDouble = numpy.np_interp(t.CDouble(0.5), xp, fp) + check("interp(0.5)==5", approx_eq(v, t.CDouble(5.0)), "mismatch") + + v2: t.CDouble = numpy.np_interp(t.CDouble(1.5), xp, fp) + check("interp(1.5)==15", approx_eq(v2, t.CDouble(15.0)), "mismatch") + + v3: t.CDouble = numpy.np_interp(t.CDouble(-1.0), xp, fp) + check("interp(-1)==0", approx_eq(v3, t.CDouble(0.0)), "mismatch") + + v4: t.CDouble = numpy.np_interp(t.CDouble(3.0), xp, fp) + check("interp(3)==20", approx_eq(v4, t.CDouble(20.0)), "mismatch") + + xp.delete() + fp.delete() + section_footer() + + +# ============================================================ +# 15. Edge / boundary / exception tests +# ============================================================ +def test_numpy_edge(): + section_header("edge: size=0 / size=1 / non-SIMD-block / negative / div-zero") + + # size=0: pool.alloc(0) returns None, so zeros(0) returns None (expected) + a0: numpy.ndarray | t.CPtr = numpy.zeros(pool, 0) + check("zeros(0) returns None", a0 == None, "expected None for size=0") + + # size=1 + a1: numpy.ndarray | t.CPtr = numpy.zeros(pool, 1) + check("zeros(1) not None", a1 != None, "returned None") + check("zeros(1) size==1", a1.size == 1, "size mismatch") + check("zeros(1) [0]==0", a1.data[0] == t.CDouble(0.0), "mismatch") + a1.delete() + + # non-SIMD-block sizes (1,2,3,5,6,7) + a5: numpy.ndarray | t.CPtr = numpy.arange(pool, t.CDouble(0.0), t.CDouble(5.0), t.CDouble(1.0)) + check("arange(5) size==5", a5.size == 5, "size mismatch") + check("arange(5) sum==10", approx_eq(a5.sum(), t.CDouble(10.0)), "mismatch") + a5.delete() + + a6: numpy.ndarray | t.CPtr = numpy.arange(pool, t.CDouble(0.0), t.CDouble(6.0), t.CDouble(1.0)) + check("arange(6) sum==15", approx_eq(a6.sum(), t.CDouble(15.0)), "mismatch") + a6.delete() + + a7: numpy.ndarray | t.CPtr = numpy.arange(pool, t.CDouble(0.0), t.CDouble(7.0), t.CDouble(1.0)) + check("arange(7) sum==21", approx_eq(a7.sum(), t.CDouble(21.0)), "mismatch") + a7.delete() + + # negative values in sqrt + neg_arr: numpy.ndarray | t.CPtr = vec3(pool, t.CDouble(-1.0), t.CDouble(0.0), t.CDouble(4.0)) + r_sqrt_neg: numpy.ndarray | t.CPtr = numpy.np_sqrt(neg_arr) + check("sqrt(neg) not None", r_sqrt_neg != None, "returned None") + # sqrt(4)=2, sqrt(0)=0; sqrt(-1) is NaN (implementation-defined) + check("sqrt(4)==2", approx_eq(r_sqrt_neg.data[2], t.CDouble(2.0)), "mismatch") + neg_arr.delete() + r_sqrt_neg.delete() + + # div-by-zero: b/a where a has zeros + za: numpy.ndarray | t.CPtr = vec3(pool, t.CDouble(0.0), t.CDouble(2.0), t.CDouble(0.0)) + zb: numpy.ndarray | t.CPtr = vec3(pool, t.CDouble(6.0), t.CDouble(4.0), t.CDouble(8.0)) + r_divz: numpy.ndarray | t.CPtr = za / zb + check("0/6==0", r_divz.data[0] == t.CDouble(0.0), "mismatch") + check("2/4==0.5", r_divz.data[1] == t.CDouble(0.5), "mismatch") + za.delete() + zb.delete() + r_divz.delete() + + # large array (non-aligned, non-SIMD-block) + big: numpy.ndarray | t.CPtr = numpy.zeros(pool, 1000) + check("zeros(1000) not None", big != None, "returned None") + check("zeros(1000) size==1000", big.size == 1000, "size mismatch") + big.delete() + + section_footer() + + +# ============================================================ +# 16. Performance benchmark +# ============================================================ +def bench_numpy_perf(): + section_header("Benchmark: numpy ops") + + N: t.CSizeT = 10000 + ITERS: t.CInt = 5 + + a: numpy.ndarray | t.CPtr = numpy.zeros(pool, N) + b: numpy.ndarray | t.CPtr = numpy.zeros(pool, N) + i: t.CSizeT = 0 + while i < N: + a.data[i] = t.CDouble(1.0) + b.data[i] = t.CDouble(2.0) + i += 1 + + # add benchmark + t0: t.CDouble = c.Timer() + j: t.CInt = 0 + while j < ITERS: + r: numpy.ndarray | t.CPtr = a + b + r.delete() + j += 1 + t1: t.CDouble = c.Timer() + printf(" ADD: %.1f ms\n", (t1 - t0) * t.CDouble(1000.0)) + + # mul benchmark + t0 = c.Timer() + j = 0 + while j < ITERS: + r2: numpy.ndarray | t.CPtr = a * b + r2.delete() + j += 1 + t1 = c.Timer() + printf(" MUL: %.1f ms\n", (t1 - t0) * t.CDouble(1000.0)) + + # sqrt benchmark + t0 = c.Timer() + j = 0 + while j < ITERS: + r3: numpy.ndarray | t.CPtr = numpy.np_sqrt(a) + r3.delete() + j += 1 + t1 = c.Timer() + printf(" SQRT: %.1f ms\n", (t1 - t0) * t.CDouble(1000.0)) + + a.delete() + b.delete() + section_footer() + + +# ============================================================ +# Entry points +# ============================================================ +def test_numpy_correct() -> t.CInt: + global arena, pool, test_passed, test_failed + + arena = calloc(2 * 1024 * 1024, 1) + pool = memhub.MemPool(arena, 2 * 1024 * 1024) + + test_passed = 0 + test_failed = 0 + + printf("==============================================\n") + printf(" numpy Correctness Tests\n") + printf("==============================================\n") + + test_zeros_ones() + test_arange_linspace() + test_eye_diag() + test_sum_mean_min_max() + test_fill_copy() + test_add_sub_mul_div() + test_neg() + test_len() + test_scalar_ops() + test_math_funcs() + test_matmul() + test_dot() + test_transpose() + test_var_std_norm() + test_clip_concatenate() + test_sort_reverse() + test_print_arr() + test_floordiv_mod() + test_additional_math() + test_trig_hyperbolic() + test_degrees_radians() + test_cumsum_diff() + test_max_min_where() + test_flatten_trace() + test_outer() + test_bool_comparison() + test_linalg() + test_additional_creation() + test_interp() + + printf("\n==============================================\n") + printf(" Correctness: %d passed, %d failed\n", test_passed, test_failed) + printf("==============================================\n") + + return test_failed + + +def test_numpy_edge_main() -> t.CInt: + global arena, pool, test_passed, test_failed + + arena = calloc(2 * 1024 * 1024, 1) + pool = memhub.MemPool(arena, 2 * 1024 * 1024) + + test_passed = 0 + test_failed = 0 + + printf("==============================================\n") + printf(" numpy Edge / Boundary Tests\n") + printf("==============================================\n") + + test_numpy_edge() + + printf("\n==============================================\n") + printf(" Edge: %d passed, %d failed\n", test_passed, test_failed) + printf("==============================================\n") + + return test_failed + + +def bench_numpy_main() -> t.CInt: + global arena, pool + + arena = calloc(8 * 1024 * 1024, 1) + pool = memhub.MemPool(arena, 8 * 1024 * 1024) + + printf("==============================================\n") + printf(" numpy Performance Benchmark\n") + printf("==============================================\n") + + bench_numpy_perf() + + printf("==============================================\n") + return 0 + + +# Backward-compatible entry +def test_numpy_main() -> t.CInt: + global arena, pool + + arena = calloc(2 * 1024 * 1024, 1) + pool = memhub.MemPool(arena, 2 * 1024 * 1024) + + failed: t.CInt = test_numpy_correct() + if failed == 0: + failed = test_numpy_edge_main() + if failed == 0: + bench_numpy_main() + return failed diff --git a/Test/NumpyTest/project.json b/Test/NumpyTest/project.json new file mode 100644 index 0000000..b41862c --- /dev/null +++ b/Test/NumpyTest/project.json @@ -0,0 +1,29 @@ +{ + "$schema": "https://raw.githubusercontent.com/TermiNexus/TransPyC/main/schemas/project-schema.json", + "name": "NumpyTest", + "version": "1.0.0", + "source_dir": "./App", + "build_dir": "./.tpv_build", + "compiler": { + "cmd": "llc", + "flags": ["-filetype=obj", "-relocation-model=pic"] + }, + "linker": { + "cmd": "clang++", + "flags": ["-Wl,--allow-multiple-definition", "-Wl,--unresolved-symbols=ignore-in-object-files", "-lmsvcrt", "-lucrt", "-lpthread", "-lmingwex", "-lkernel32", "-luser32", "-latomic"], + "output": "NumpyTest.exe" + }, + "includes": [ + "../../includes" + ], + "target": { + "triple": "x86_64-pc-windows-gnu", + "datalayout": "e-m:w-p270:32:32-p271:32:32-p272:64:64-f80:128-n8:16:32:64-S128" + }, + "options": { + "slice_level": 3, + "sha1_slice_level": 1, + "target": "llvm", + "strict_mode": true + } +} diff --git a/Test/VectorGenericTest/App/main.vp b/Test/VectorGenericTest/App/main.vp new file mode 100644 index 0000000..a056c77 --- /dev/null +++ b/Test/VectorGenericTest/App/main.vp @@ -0,0 +1,11 @@ +import t, c +import testcheck +import vectortest + + +def main() -> t.CInt | t.CExport: + testcheck.begin("VectorGenericTest: Vector 泛型测试") + testcheck.section("Vector 泛型") + vectortest.vector_main() + testcheck.ok("Vector 泛型测试完成") + return testcheck.end() diff --git a/Test/VectorGenericTest/App/vectortest.vp b/Test/VectorGenericTest/App/vectortest.vp new file mode 100644 index 0000000..e39a5f4 --- /dev/null +++ b/Test/VectorGenericTest/App/vectortest.vp @@ -0,0 +1,43 @@ +import t, c +from t import CInt, CPtr, CChar, CFloat64T +import viperlib +import stdlib +import vector +import memhub + +POOL_SIZE: t.CDefine = 4096 + +def vector_main() -> CInt: + buf: str = stdlib.malloc(256) + pool_mem: t.CVoid | t.CPtr = stdlib.malloc(POOL_SIZE) + pool: memhub.MemPool | CPtr = memhub.MemPool(pool_mem, POOL_SIZE) + + vi: vector.Vector | CPtr = vector.Vector(pool, 10, CInt(0)) + vi.push(CInt(10)) + vi.push(CInt(20)) + vi.push(CInt(30)) + viperlib.snprintf(buf, 256, "Vector[int]: len=%d, [0]=%d, [1]=%d, [2]=%d", vi.len(), vi.get(0), vi.get(1), vi.get(2)) + print(buf) + + vi.set(1, CInt(99)) + viperlib.snprintf(buf, 256, "Vector[int]: set[1]=99, [1]=%d", vi.get(1)) + print(buf) + + vi.clear() + viperlib.snprintf(buf, 256, "Vector[int]: cleared, len=%d", vi.len()) + print(buf) + + vi.free() + + vd: vector.Vector | CPtr = vector.Vector(pool, 8, CFloat64T(0.0)) + vd.push(CFloat64T(1.5)) + vd.push(CFloat64T(2.7)) + vd.push(CFloat64T(3.14)) + viperlib.snprintf(buf, 256, "Vector[double]: len=%d, [0]=%.1f, [1]=%.1f, [2]=%.2f", vd.len(), vd.get(0), vd.get(1), vd.get(2)) + print(buf) + + vd.free() + + stdlib.free(pool_mem) + stdlib.free(buf) + return 0 diff --git a/Test/VectorGenericTest/project.json b/Test/VectorGenericTest/project.json new file mode 100644 index 0000000..c3b2619 --- /dev/null +++ b/Test/VectorGenericTest/project.json @@ -0,0 +1,29 @@ +{ + "$schema": "https://raw.githubusercontent.com/TermiNexus/TransPyC/main/schemas/project-schema.json", + "name": "VectorGenericTest", + "version": "1.0.0", + "source_dir": "./App", + "build_dir": "./.tpv_build", + "compiler": { + "cmd": "llc", + "flags": ["-filetype=obj", "-relocation-model=pic"] + }, + "linker": { + "cmd": "clang++", + "flags": ["-Wl,--allow-multiple-definition", "-Wl,--unresolved-symbols=ignore-in-object-files", "-lmsvcrt", "-lucrt", "-lpthread", "-lmingwex", "-lkernel32", "-luser32", "-latomic"], + "output": "VectorGenericTest.exe" + }, + "includes": [ + "../../includes" + ], + "target": { + "triple": "x86_64-pc-windows-gnu", + "datalayout": "e-m:w-p270:32:32-p271:32:32-p272:64:64-f80:128-n8:16:32:64-S128" + }, + "options": { + "slice_level": 3, + "sha1_slice_level": 1, + "target": "llvm", + "strict_mode": true + } +} diff --git a/Test/ZlibTest/App/main.vp b/Test/ZlibTest/App/main.vp index 6575ead..8119514 100644 --- a/Test/ZlibTest/App/main.vp +++ b/Test/ZlibTest/App/main.vp @@ -8,6 +8,7 @@ import __zlib.zchecksum as zchecksum import __zlib.zdef as zdef import __zlib.zhuff as zhuff import __zlib.test_pyzlib as tpz +import zlib.pyzlib as stdzp import w32.win32memory import c import testcheck @@ -16,4 +17,10 @@ def main() -> t.CInt: testcheck.begin("ZlibTest: Zlib 压缩库测试") tpz.main123456() testcheck.ok("zlib test_pyzlib completed") + + # 标准 zlib 库(includes/zlib)与 __zlib 并存验证 + testcheck.section("标准 zlib 库 (zlib.pyzlib)") + print(stdzp.runtime_version()) + testcheck.ok("zlib runtime version printed") + return testcheck.end()