From d88d11b646e6eedee3d0d67d9f5e1f2a54e88404 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Thu, 25 Jun 2026 14:49:46 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=BA=86=E5=A4=A7=E9=87=8F?= =?UTF-8?q?=E5=AD=98=E5=9C=A8=E7=9A=84=E9=97=AE=E9=A2=98=EF=BC=8C=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E4=BA=86=E5=81=87=E9=B8=AD=E5=AD=90=E7=B1=BB=E5=9E=8B?= =?UTF-8?q?=E7=AD=89=E7=AD=89=E6=9C=BA=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TODO | 20 +- Test/BuddyTest/App/main.py | 12 + Test/BuddyTest/App/mbuddytest.py | 535 +++ .../output/067c78e9f121dce3.deps.json | 1 + .../output/271ea3decb810db2.deps.json | 1 + .../output/29813d57621099a9.deps.json | 1 + .../output/5a6a2137958c28c5.deps.json | 1 + .../output/5e430ae5bf7af3a2.deps.json | 1 + .../output/70b580331b822117.deps.json | 1 + .../output/72e2d5ccb7cedcf1.deps.json | 1 + .../output/9dbecd0942a39782.deps.json | 1 + .../output/abf9ce3160c9279e.deps.json | 1 + .../output/b5f1dc665c52a1bd.deps.json | 1 + .../output/bbdf3bbd4c3bc28c.deps.json | 1 + .../output/c53a157505aa8081.deps.json | 1 + .../output/c9f4be41ca1cc2b4.deps.json | 1 + .../output/e1937873ebfba8c3.deps.json | 1 + .../output/fa3691e66b426950.deps.json | 1 + Test/BuddyTest/project.json | 29 + .../temp/067c78e9f121dce3.pyi | 0 Test/BuddyTest/temp/271ea3decb810db2.pyi | 26 + .../temp/29813d57621099a9.pyi | 0 .../temp/49bd8cba55979f76.pyi} | 10 +- .../temp/5a6a2137958c28c5.pyi | 0 Test/BuddyTest/temp/5e430ae5bf7af3a2.pyi | 13 + .../temp/6c2029b306556c00.pyi | 0 .../temp/70b580331b822117.pyi} | 0 Test/BuddyTest/temp/71e0a3ffcb3ebfad.pyi | 20 + .../temp/72e2d5ccb7cedcf1.pyi | 0 Test/BuddyTest/temp/73edbcf76e32d00b.pyi | 28 + Test/BuddyTest/temp/9dbecd0942a39782.pyi | 25 + Test/BuddyTest/temp/_sha1_map.txt | 16 + Test/BuddyTest/temp/_shared_sym.json | 0 .../temp/abf9ce3160c9279e.pyi | 0 .../temp/b5f1dc665c52a1bd.pyi} | 2 +- .../temp/bbdf3bbd4c3bc28c.pyi | 0 Test/BuddyTest/temp/c53a157505aa8081.pyi | 21 + .../temp/c9f4be41ca1cc2b4.pyi | 0 Test/BuddyTest/temp/e1937873ebfba8c3.pyi | 48 + .../temp/fa3691e66b426950.pyi | 0 Test/BuiltinDecoratorTest/App/main.py | 98 +- .../output/9dbecd0942a39782.deps.json | 1 + .../output/b6069b01d8c9cc04.deps.json | 1 - .../output/e3ac223bdaf94a0c.deps.json | 1 + ...dd754a8a09347.pyi => 49bd8cba55979f76.pyi} | 10 +- .../temp/9dbecd0942a39782.pyi | 25 + Test/BuiltinDecoratorTest/temp/_sha1_map.txt | 5 +- ...69b01d8c9cc04.pyi => e3ac223bdaf94a0c.pyi} | 7 +- Test/CPythonTest/App/main.py | 149 +- .../output/0cd580d62a3de4f8.deps.json | 1 - .../output/7c5d5ec59c5fb0a8.deps.json | 2 +- ...580d62a3de4f8.pyi => 3c8ecda6b848f011.pyi} | 6 +- Test/CPythonTest/temp/9dbecd0942a39782.pyi | 25 + Test/CPythonTest/temp/_sha1_map.txt | 3 +- Test/CPythonTest/temp/_shared_sym.json | 0 Test/CPythonTest/temp/_shared_sym.pkl | Bin 609888 -> 0 bytes Test/ClosureTest/App/main.py | 78 +- .../output/52e6b51da061882f.deps.json | 1 + .../output/7dbf085f7e3e8944.deps.json | 1 - .../output/9dbecd0942a39782.deps.json | 1 + ...f085f7e3e8944.pyi => 52e6b51da061882f.pyi} | 3 +- Test/ClosureTest/temp/9dbecd0942a39782.pyi | 25 + Test/ClosureTest/temp/_sha1_map.txt | 3 +- Test/ClosureTest2/App/main.py | 92 +- .../output/052c7f96b9eefa2c.deps.json | 1 - .../output/440f18f9dce85a95.deps.json | 1 + .../output/9dbecd0942a39782.deps.json | 1 + ...c7f96b9eefa2c.pyi => 440f18f9dce85a95.pyi} | 1 + Test/ClosureTest2/temp/9dbecd0942a39782.pyi | 25 + Test/ClosureTest2/temp/_sha1_map.txt | 3 +- Test/DecoratorMarkerTest/App/main.py | 77 + .../output/9dbecd0942a39782.deps.json | 1 + .../output/b1122357fee8fd68.deps.json | 1 + Test/DecoratorMarkerTest/project.json | 29 + .../temp/73edbcf76e32d00b.pyi | 28 + .../temp/9dbecd0942a39782.pyi | 25 + Test/DecoratorMarkerTest/temp/_sha1_map.txt | 3 + .../temp/b1122357fee8fd68.pyi | 36 + Test/DecoratorTest/App/main.py | 58 +- .../output/577f9e1aa32b17f8.deps.json | 1 - .../output/814e6b31adfc6256.deps.json | 1 + .../output/9dbecd0942a39782.deps.json | 1 + ...f9e1aa32b17f8.pyi => 814e6b31adfc6256.pyi} | 1 + Test/DecoratorTest/temp/9dbecd0942a39782.pyi | 25 + Test/DecoratorTest/temp/_sha1_map.txt | 3 +- Test/DictTest/App/main.py | 230 ++ .../output/067c78e9f121dce3.deps.json | 1 + .../output/06f53cc594b4ac6c.deps.json | 1 + .../output/0991af0d22263577.deps.json | 1 + .../output/0eaa586c42dcd931.deps.json | 1 + .../output/271ea3decb810db2.deps.json | 1 + .../output/5a6a2137958c28c5.deps.json | 1 + .../output/72e2d5ccb7cedcf1.deps.json | 1 + .../output/8ee3170049c70333.deps.json | 1 + .../output/9dbecd0942a39782.deps.json | 1 + .../output/abf9ce3160c9279e.deps.json | 1 + .../output/b5f1dc665c52a1bd.deps.json | 1 + .../output/bbdf3bbd4c3bc28c.deps.json | 1 + .../output/bd2e7db1744476fe.deps.json | 1 + .../output/c9f4be41ca1cc2b4.deps.json | 1 + .../output/eaf7a981f0ef5b22.deps.json | 1 + .../output/f1e15ccf054b1e89.deps.json | 1 + .../output/fa3691e66b426950.deps.json | 1 + .../output/fced53b138f67cf5.deps.json | 1 + Test/DictTest/project.json | 29 + .../temp/067c78e9f121dce3.pyi | 0 Test/DictTest/temp/06f53cc594b4ac6c.pyi | 109 + .../temp/0991af0d22263577.pyi} | 2 +- Test/DictTest/temp/0eaa586c42dcd931.pyi | 49 + Test/DictTest/temp/271ea3decb810db2.pyi | 26 + .../temp/49bd8cba55979f76.pyi} | 10 +- Test/DictTest/temp/5a6a2137958c28c5.pyi | 98 + Test/DictTest/temp/6c2029b306556c00.pyi | 18 + Test/DictTest/temp/72e2d5ccb7cedcf1.pyi | 91 + Test/DictTest/temp/73edbcf76e32d00b.pyi | 28 + Test/DictTest/temp/8ee3170049c70333.pyi | 71 + Test/DictTest/temp/9dbecd0942a39782.pyi | 25 + Test/DictTest/temp/_sha1_map.txt | 16 + .../temp/abf9ce3160c9279e.pyi | 0 .../temp/b5f1dc665c52a1bd.pyi} | 2 +- .../temp/bbdf3bbd4c3bc28c.pyi | 0 Test/DictTest/temp/bd2e7db1744476fe.pyi | 38 + Test/DictTest/temp/c9f4be41ca1cc2b4.pyi | 22 + Test/DictTest/temp/eaf7a981f0ef5b22.pyi | 22 + Test/DictTest/temp/f1e15ccf054b1e89.pyi | 54 + .../temp/fa3691e66b426950.pyi | 0 Test/DictTest/temp/fced53b138f67cf5.pyi | 18 + Test/EdgeCaseTest/App/main.py | 260 ++ .../output/9dbecd0942a39782.deps.json | 1 + .../output/ac0d686cb2cc783b.deps.json | 1 + Test/EdgeCaseTest/project.json | 29 + Test/EdgeCaseTest/temp/73edbcf76e32d00b.pyi | 28 + Test/EdgeCaseTest/temp/9dbecd0942a39782.pyi | 25 + Test/EdgeCaseTest/temp/_sha1_map.txt | 3 + Test/EdgeCaseTest/temp/ac0d686cb2cc783b.pyi | 73 + Test/EqTest/App/main.py | 56 + Test/EqTest/output/067c78e9f121dce3.deps.json | 1 + Test/EqTest/output/06f53cc594b4ac6c.deps.json | 1 + Test/EqTest/output/5a6a2137958c28c5.deps.json | 1 + Test/EqTest/output/72e2d5ccb7cedcf1.deps.json | 1 + Test/EqTest/output/78943d0dbc89a29a.deps.json | 1 + Test/EqTest/output/9dbecd0942a39782.deps.json | 1 + Test/EqTest/output/abf9ce3160c9279e.deps.json | 1 + Test/EqTest/output/b5f1dc665c52a1bd.deps.json | 1 + Test/EqTest/output/bbdf3bbd4c3bc28c.deps.json | 1 + Test/EqTest/output/fa3691e66b426950.deps.json | 1 + Test/EqTest/project.json | 29 + Test/EqTest/temp/067c78e9f121dce3.pyi | 136 + Test/EqTest/temp/06f53cc594b4ac6c.pyi | 109 + .../temp/49bd8cba55979f76.pyi} | 10 +- Test/EqTest/temp/5a6a2137958c28c5.pyi | 98 + Test/EqTest/temp/6c2029b306556c00.pyi | 18 + Test/EqTest/temp/72e2d5ccb7cedcf1.pyi | 91 + Test/EqTest/temp/73edbcf76e32d00b.pyi | 28 + Test/EqTest/temp/78943d0dbc89a29a.pyi | 16 + Test/EqTest/temp/9dbecd0942a39782.pyi | 25 + Test/EqTest/temp/_sha1_map.txt | 8 + Test/EqTest/temp/abf9ce3160c9279e.pyi | 179 + .../temp/b5f1dc665c52a1bd.pyi} | 2 +- Test/EqTest/temp/bbdf3bbd4c3bc28c.pyi | 138 + Test/EqTest/temp/fa3691e66b426950.pyi | 80 + Test/FakeDuckTest/App/main.py | 313 ++ .../output/067c78e9f121dce3.deps.json | 1 + .../output/06f53cc594b4ac6c.deps.json | 1 + .../output/0eaa586c42dcd931.deps.json | 1 + .../output/271ea3decb810db2.deps.json | 1 + .../output/5a6a2137958c28c5.deps.json | 1 + .../output/72e2d5ccb7cedcf1.deps.json | 1 + .../output/9d9d71cf83da7ca4.deps.json | 1 + .../output/9dbecd0942a39782.deps.json | 1 + .../output/abf9ce3160c9279e.deps.json | 1 + .../output/b5f1dc665c52a1bd.deps.json | 1 + .../output/b9b237d0e206d76c.deps.json | 1 + .../output/bbdf3bbd4c3bc28c.deps.json | 1 + .../output/c6206460c42ccf10.deps.json | 1 + .../output/ccd58bf663340b12.deps.json | 1 + .../output/fa3691e66b426950.deps.json | 1 + Test/FakeDuckTest/project.json | 29 + Test/FakeDuckTest/temp/067c78e9f121dce3.pyi | 136 + Test/FakeDuckTest/temp/06f53cc594b4ac6c.pyi | 109 + Test/FakeDuckTest/temp/0eaa586c42dcd931.pyi | 49 + Test/FakeDuckTest/temp/271ea3decb810db2.pyi | 26 + Test/FakeDuckTest/temp/49bd8cba55979f76.pyi | 75 + Test/FakeDuckTest/temp/5a6a2137958c28c5.pyi | 98 + Test/FakeDuckTest/temp/6c2029b306556c00.pyi | 18 + Test/FakeDuckTest/temp/72e2d5ccb7cedcf1.pyi | 91 + Test/FakeDuckTest/temp/73edbcf76e32d00b.pyi | 28 + Test/FakeDuckTest/temp/9d9d71cf83da7ca4.pyi | 29 + Test/FakeDuckTest/temp/9dbecd0942a39782.pyi | 25 + Test/FakeDuckTest/temp/_sha1_map.txt | 14 + Test/FakeDuckTest/temp/abf9ce3160c9279e.pyi | 179 + .../temp/b5f1dc665c52a1bd.pyi} | 2 +- Test/FakeDuckTest/temp/b9b237d0e206d76c.pyi | 33 + Test/FakeDuckTest/temp/bbdf3bbd4c3bc28c.pyi | 138 + Test/FakeDuckTest/temp/c6206460c42ccf10.pyi | 35 + Test/FakeDuckTest/temp/ccd58bf663340b12.pyi | 19 + Test/FakeDuckTest/temp/fa3691e66b426950.pyi | 80 + Test/ForAndLoopTest/App/main.py | 159 + .../output/0eaa586c42dcd931.deps.json | 1 + .../output/271ea3decb810db2.deps.json | 1 + .../output/2e079471575f937d.deps.json | 1 + .../output/9163064cf3eb88f4.deps.json | 1 + .../output/9dbecd0942a39782.deps.json | 1 + .../output/b5f1dc665c52a1bd.deps.json | 1 + Test/ForAndLoopTest/project.json | 29 + Test/ForAndLoopTest/temp/0eaa586c42dcd931.pyi | 49 + Test/ForAndLoopTest/temp/271ea3decb810db2.pyi | 26 + Test/ForAndLoopTest/temp/2e079471575f937d.pyi | 36 + Test/ForAndLoopTest/temp/49bd8cba55979f76.pyi | 75 + Test/ForAndLoopTest/temp/6c2029b306556c00.pyi | 18 + Test/ForAndLoopTest/temp/73edbcf76e32d00b.pyi | 28 + Test/ForAndLoopTest/temp/9163064cf3eb88f4.pyi | 35 + Test/ForAndLoopTest/temp/9dbecd0942a39782.pyi | 25 + Test/ForAndLoopTest/temp/_sha1_map.txt | 9 + Test/ForAndLoopTest/temp/b5f1dc665c52a1bd.pyi | 44 + Test/FormatStringTest/App/main.py | 52 + .../output/9dbecd0942a39782.deps.json | 1 + .../output/cdff0d7b58fc935b.deps.json | 1 + Test/FormatStringTest/project.json | 29 + .../temp/42ced27d9e76aef5.pyi | 11 + .../temp/49bd8cba55979f76.pyi | 75 + .../temp/73edbcf76e32d00b.pyi | 28 + .../temp/9dbecd0942a39782.pyi | 25 + Test/FormatStringTest/temp/_sha1_map.txt | 5 + .../temp/cdff0d7b58fc935b.pyi | 14 + Test/FuncTest/App/main.py | 64 +- .../output/067c78e9f121dce3.deps.json | 2 +- ...6.deps.json => 067f811511854c88.deps.json} | 2 +- .../output/29813d57621099a9.deps.json | 2 +- .../output/5a6a2137958c28c5.deps.json | 2 +- .../output/72e2d5ccb7cedcf1.deps.json | 2 +- .../output/9dbecd0942a39782.deps.json | 1 + .../output/abf9ce3160c9279e.deps.json | 2 +- .../output/bbdf3bbd4c3bc28c.deps.json | 2 +- .../output/fa3691e66b426950.deps.json | 2 +- ...1d57732bde476.pyi => 067f811511854c88.pyi} | 1 + Test/FuncTest/temp/49bd8cba55979f76.pyi | 75 + Test/FuncTest/temp/9dbecd0942a39782.pyi | 25 + Test/FuncTest/temp/_sha1_map.txt | 5 +- Test/GenericTest/App/main.py | 80 +- .../output/16e1f65b154831e8.deps.json | 1 + .../output/47df358e08cc5c0e.deps.json | 1 - .../output/9dbecd0942a39782.deps.json | 1 + ...f358e08cc5c0e.pyi => 16e1f65b154831e8.pyi} | 1 + Test/GenericTest/temp/9dbecd0942a39782.pyi | 25 + Test/GenericTest/temp/_sha1_map.txt | 3 +- Test/GenericTest2/App/main.py | 84 +- .../output/1348b0e29ea228ad.deps.json | 1 - .../output/9dbecd0942a39782.deps.json | 1 + .../output/d2165a80fd5563cc.deps.json | 1 + Test/GenericTest2/temp/9dbecd0942a39782.pyi | 25 + Test/GenericTest2/temp/_sha1_map.txt | 3 +- ...8b0e29ea228ad.pyi => d2165a80fd5563cc.pyi} | 7 +- Test/IterTest/App/main.py | 29 +- .../output/067c78e9f121dce3.deps.json | 2 +- .../output/1452048cbd90ae2f.deps.json | 1 + .../output/29813d57621099a9.deps.json | 2 +- .../output/5a6a2137958c28c5.deps.json | 2 +- .../output/6aee24fdefa3cbc0.deps.json | 1 - .../output/72e2d5ccb7cedcf1.deps.json | 2 +- .../output/9dbecd0942a39782.deps.json | 1 + .../output/abf9ce3160c9279e.deps.json | 2 +- .../output/b5f1dc665c52a1bd.deps.json | 1 + .../output/bbdf3bbd4c3bc28c.deps.json | 2 +- .../output/d044f813487c68b6.deps.json | 1 - .../output/fa3691e66b426950.deps.json | 2 +- ...4f813487c68b6.pyi => 1452048cbd90ae2f.pyi} | 1 + Test/IterTest/temp/49bd8cba55979f76.pyi | 75 + Test/IterTest/temp/9dbecd0942a39782.pyi | 25 + Test/IterTest/temp/_sha1_map.txt | 7 +- Test/IterTest/temp/b5f1dc665c52a1bd.pyi | 44 + Test/JsonTest/App/main.py | 189 +- .../output/067c78e9f121dce3.deps.json | 2 +- .../output/0991af0d22263577.deps.json | 1 + .../output/1dd5985fb89f7ef9.deps.json | 1 - .../output/29813d57621099a9.deps.json | 2 +- .../output/5a6a2137958c28c5.deps.json | 2 +- .../output/68c4fe4b12c908e3.deps.json | 1 - .../output/6aee24fdefa3cbc0.deps.json | 1 - .../output/72e2d5ccb7cedcf1.deps.json | 2 +- .../output/8ee3170049c70333.deps.json | 2 +- .../output/9361526faa30d4d2.deps.json | 1 + .../output/9dbecd0942a39782.deps.json | 1 + .../output/abf9ce3160c9279e.deps.json | 2 +- .../output/b5f1dc665c52a1bd.deps.json | 1 + .../output/bbdf3bbd4c3bc28c.deps.json | 2 +- .../output/bd2e7db1744476fe.deps.json | 2 +- .../output/c9f4be41ca1cc2b4.deps.json | 2 +- .../output/eaf7a981f0ef5b22.deps.json | 2 +- .../output/fa3691e66b426950.deps.json | 2 +- ...4fe4b12c908e3.pyi => 0991af0d22263577.pyi} | 2 +- Test/JsonTest/temp/49bd8cba55979f76.pyi | 75 + ...5985fb89f7ef9.pyi => 9361526faa30d4d2.pyi} | 6 +- Test/JsonTest/temp/9dbecd0942a39782.pyi | 25 + Test/JsonTest/temp/_sha1_map.txt | 9 +- Test/JsonTest/temp/b5f1dc665c52a1bd.pyi | 44 + Test/ListTest/App/main.py | 90 + .../output/d4150579dda5d04a.deps.json | 1 + Test/ListTest/project.json | 29 + Test/ListTest/temp/271ea3decb810db2.pyi | 26 + Test/ListTest/temp/49bd8cba55979f76.pyi | 75 + Test/ListTest/temp/5a6a2137958c28c5.pyi | 98 + Test/ListTest/temp/6af0881381d5e37e.pyi | 16 + Test/ListTest/temp/6c2029b306556c00.pyi | 18 + Test/ListTest/temp/73edbcf76e32d00b.pyi | 28 + Test/ListTest/temp/9dbecd0942a39782.pyi | 25 + Test/ListTest/temp/_sha1_map.txt | 10 + Test/ListTest/temp/b5f1dc665c52a1bd.pyi | 44 + Test/ListTest/temp/bbdf3bbd4c3bc28c.pyi | 138 + Test/ListTest/temp/e1937873ebfba8c3.pyi | 48 + Test/LoopTest/App/main.py | 52 +- .../output/4b6b35e3922a169f.deps.json | 1 - .../output/86e203c56ae4de20.deps.json | 1 + .../output/9dbecd0942a39782.deps.json | 1 + ...b35e3922a169f.pyi => 86e203c56ae4de20.pyi} | 1 + Test/LoopTest/temp/9dbecd0942a39782.pyi | 25 + Test/LoopTest/temp/_sha1_map.txt | 3 +- Test/PointerTest/App/main.py | 97 +- .../output/067c78e9f121dce3.deps.json | 2 +- .../output/29813d57621099a9.deps.json | 2 +- .../output/5a6a2137958c28c5.deps.json | 2 +- .../output/6aee24fdefa3cbc0.deps.json | 1 - .../output/72e2d5ccb7cedcf1.deps.json | 2 +- .../output/9dbecd0942a39782.deps.json | 1 + .../output/abf9ce3160c9279e.deps.json | 2 +- .../output/b436212dcff1be29.deps.json | 1 + .../output/b5f1dc665c52a1bd.deps.json | 1 + .../output/bbdf3bbd4c3bc28c.deps.json | 2 +- .../output/e0c894447ac34ed3.deps.json | 1 - .../output/fa3691e66b426950.deps.json | 2 +- Test/PointerTest/temp/49bd8cba55979f76.pyi | 75 + Test/PointerTest/temp/56cdd754a8a09347.pyi | 67 - Test/PointerTest/temp/9dbecd0942a39782.pyi | 25 + Test/PointerTest/temp/_sha1_map.txt | 7 +- ...894447ac34ed3.pyi => b436212dcff1be29.pyi} | 1 + Test/PointerTest/temp/b5f1dc665c52a1bd.pyi | 44 + Test/ShortCircuitTest/App/main.py | 122 + .../output/067c78e9f121dce3.deps.json | 1 + .../output/06f53cc594b4ac6c.deps.json | 1 + .../output/5a6a2137958c28c5.deps.json | 1 + .../output/72e2d5ccb7cedcf1.deps.json | 1 + .../output/9dbecd0942a39782.deps.json | 1 + .../output/a711c9c66fd7c6ca.deps.json | 1 + .../output/abf9ce3160c9279e.deps.json | 1 + .../output/b5f1dc665c52a1bd.deps.json | 1 + .../output/bbdf3bbd4c3bc28c.deps.json | 1 + .../output/fa3691e66b426950.deps.json | 1 + Test/ShortCircuitTest/project.json | 29 + .../temp/067c78e9f121dce3.pyi | 136 + .../temp/06f53cc594b4ac6c.pyi | 109 + .../temp/49bd8cba55979f76.pyi | 75 + .../temp/5a6a2137958c28c5.pyi | 98 + .../temp/6c2029b306556c00.pyi | 18 + .../temp/72e2d5ccb7cedcf1.pyi | 91 + .../temp/73edbcf76e32d00b.pyi | 28 + .../temp/9dbecd0942a39782.pyi | 25 + Test/ShortCircuitTest/temp/_sha1_map.txt | 8 + .../temp/a711c9c66fd7c6ca.pyi | 20 + .../temp/abf9ce3160c9279e.pyi | 179 + .../temp/b5f1dc665c52a1bd.pyi | 44 + .../temp/bbdf3bbd4c3bc28c.pyi | 138 + .../temp/fa3691e66b426950.pyi | 80 + Test/SimdTest/App/main.py | 179 +- .../output/0991af0d22263577.deps.json | 1 + .../output/1787ce01c2ed0493.deps.json | 1 + .../output/1b666d438f4d301e.deps.json | 1 - .../output/3f7c5e78d8652535.deps.json | 2 +- .../output/68c4fe4b12c908e3.deps.json | 1 - .../output/6aee24fdefa3cbc0.deps.json | 1 - .../output/9dbecd0942a39782.deps.json | 1 + .../output/b44ac2a895a4072d.deps.json | 1 + .../output/b5f1dc665c52a1bd.deps.json | 1 + .../output/c3eb91093118e1e1.deps.json | 1 - .../output/c9f4be41ca1cc2b4.deps.json | 2 +- .../output/fe99c83946298690.deps.json | 2 +- ...4fe4b12c908e3.pyi => 0991af0d22263577.pyi} | 2 +- ...b91093118e1e1.pyi => 1787ce01c2ed0493.pyi} | 4 +- Test/SimdTest/temp/49bd8cba55979f76.pyi | 75 + Test/SimdTest/temp/56cdd754a8a09347.pyi | 67 - Test/SimdTest/temp/9dbecd0942a39782.pyi | 25 + Test/SimdTest/temp/_sha1_map.txt | 11 +- ...66d438f4d301e.pyi => b44ac2a895a4072d.pyi} | 7 +- Test/SimdTest/temp/b5f1dc665c52a1bd.pyi | 44 + Test/StringIterTest/App/inline_test.py | 2 +- Test/StringIterTest/App/main.py | 76 +- .../output/2255fdda7aed5595.deps.json | 1 - .../output/6aee24fdefa3cbc0.deps.json | 1 - .../output/924ed8cd4ea5c4c2.deps.json | 1 + .../output/9dbecd0942a39782.deps.json | 1 + .../output/StringIterTest.exe.tmp0 | Bin 0 -> 135689 bytes .../output/b5f1dc665c52a1bd.deps.json | 1 + Test/StringIterTest/temp/49bd8cba55979f76.pyi | 75 + Test/StringIterTest/temp/56cdd754a8a09347.pyi | 67 - Test/StringIterTest/temp/6aee24fdefa3cbc0.pyi | 44 - ...5fdda7aed5595.pyi => 924ed8cd4ea5c4c2.pyi} | 1 + Test/StringIterTest/temp/9dbecd0942a39782.pyi | 25 + Test/StringIterTest/temp/_sha1_map.txt | 7 +- Test/StringIterTest/temp/b5f1dc665c52a1bd.pyi | 44 + Test/StringTest/App/main.py | 55 +- .../output/067c78e9f121dce3.deps.json | 2 +- .../output/29813d57621099a9.deps.json | 2 +- .../output/39178dc5ba692b92.deps.json | 1 + .../output/5a6a2137958c28c5.deps.json | 2 +- .../output/6aee24fdefa3cbc0.deps.json | 1 - .../output/72e2d5ccb7cedcf1.deps.json | 2 +- .../output/7aa13c104a22528a.deps.json | 1 - .../output/9dbecd0942a39782.deps.json | 1 + .../output/abf9ce3160c9279e.deps.json | 2 +- .../output/b5f1dc665c52a1bd.deps.json | 1 + .../output/bbdf3bbd4c3bc28c.deps.json | 2 +- .../output/fa3691e66b426950.deps.json | 2 +- ...13c104a22528a.pyi => 39178dc5ba692b92.pyi} | 1 + Test/StringTest/temp/49bd8cba55979f76.pyi | 75 + Test/StringTest/temp/56cdd754a8a09347.pyi | 67 - Test/StringTest/temp/6aee24fdefa3cbc0.pyi | 44 - Test/StringTest/temp/9dbecd0942a39782.pyi | 25 + Test/StringTest/temp/_sha1_map.txt | 7 +- Test/StringTest/temp/b5f1dc665c52a1bd.pyi | 44 + Test/StructTest/App/main.py | 41 +- .../output/067c78e9f121dce3.deps.json | 2 +- .../output/24e26a8de1173993.deps.json | 1 + .../output/29813d57621099a9.deps.json | 2 +- .../output/5a6a2137958c28c5.deps.json | 2 +- .../output/6aee24fdefa3cbc0.deps.json | 1 - .../output/6f6ee14c129ac228.deps.json | 1 - .../output/72e2d5ccb7cedcf1.deps.json | 2 +- .../output/9dbecd0942a39782.deps.json | 1 + .../output/abf9ce3160c9279e.deps.json | 2 +- .../output/b5f1dc665c52a1bd.deps.json | 1 + .../output/bbdf3bbd4c3bc28c.deps.json | 2 +- .../output/fa3691e66b426950.deps.json | 2 +- ...ee14c129ac228.pyi => 24e26a8de1173993.pyi} | 1 + Test/StructTest/temp/49bd8cba55979f76.pyi | 75 + Test/StructTest/temp/56cdd754a8a09347.pyi | 67 - Test/StructTest/temp/6aee24fdefa3cbc0.pyi | 44 - Test/StructTest/temp/9dbecd0942a39782.pyi | 25 + Test/StructTest/temp/_sha1_map.txt | 7 +- Test/StructTest/temp/b5f1dc665c52a1bd.pyi | 44 + Test/TestFBProject/App/main.py | 105 +- .../output/067c78e9f121dce3.deps.json | 2 +- .../output/29813d57621099a9.deps.json | 2 +- .../output/3727eb00d15bf59d.deps.json | 1 - .../output/4fb8940ff5ab1022.deps.json | 1 + .../output/5a6a2137958c28c5.deps.json | 2 +- .../output/72e2d5ccb7cedcf1.deps.json | 2 +- .../output/9dbecd0942a39782.deps.json | 1 + .../output/abf9ce3160c9279e.deps.json | 2 +- .../output/bbdf3bbd4c3bc28c.deps.json | 2 +- .../output/fa3691e66b426950.deps.json | 2 +- Test/TestFBProject/temp/49bd8cba55979f76.pyi | 75 + ...7eb00d15bf59d.pyi => 4fb8940ff5ab1022.pyi} | 5 +- Test/TestFBProject/temp/56cdd754a8a09347.pyi | 67 - Test/TestFBProject/temp/73edbcf76e32d00b.pyi | 28 + Test/TestFBProject/temp/9dbecd0942a39782.pyi | 25 + Test/TestFBProject/temp/_sha1_map.txt | 6 +- Test/TestProject/App/BINASCII.py | 2 +- Test/TestProject/App/HASHLIB.py | 12 +- Test/TestProject/App/main.py | 239 +- Test/TestProject/App/test_zlib.py | 18 +- .../output/067c78e9f121dce3.deps.json | 1 - .../output/0c04ab530bb9cfa4.deps.json | 1 - .../output/0d13cde396f4a15f.deps.json | 1 - .../output/0d4517fd5afeb330.deps.json | 1 - .../output/29813d57621099a9.deps.json | 1 - .../output/2d7f623c6e3004ce.deps.json | 1 - .../output/2e756dd336749fc2.deps.json | 1 - .../output/3ee89b588a1da94f.deps.json | 1 - .../output/3f7c5e78d8652535.deps.json | 1 - .../output/4638d411fd53fef0.deps.json | 1 - .../output/4bf3e0150b9e02e9.deps.json | 1 - .../output/58121a0fb0ca7466.deps.json | 1 - .../output/5a6a2137958c28c5.deps.json | 1 - .../output/68c4fe4b12c908e3.deps.json | 1 - .../output/6aee24fdefa3cbc0.deps.json | 1 - .../output/72e2d5ccb7cedcf1.deps.json | 1 - .../output/88e3e48eab9e1653.deps.json | 1 - .../output/8e0d8fdba991b3b4.deps.json | 1 - .../output/8f88a3374d5335cc.deps.json | 1 - .../output/94496ec50b0d13fc.deps.json | 1 - .../output/a9fa0f6200c09e65.deps.json | 1 - .../output/abf9ce3160c9279e.deps.json | 1 - .../output/b0267503e816efc4.deps.json | 1 - .../output/ba2e1c2dfc8e2f85.deps.json | 1 - .../output/bbdf3bbd4c3bc28c.deps.json | 1 - .../output/c3eb91093118e1e1.deps.json | 1 - .../output/c9f4be41ca1cc2b4.deps.json | 1 - .../output/d282a7cb3385ecf0.deps.json | 1 - .../output/f9629b8eb4ebdcc2.deps.json | 1 - .../output/fa3691e66b426950.deps.json | 1 - Test/TestProject/temp/0c04ab530bb9cfa4.pyi | 69 - Test/TestProject/temp/2e756dd336749fc2.pyi | 108 - Test/TestProject/temp/3ee89b588a1da94f.pyi | 13 - Test/TestProject/temp/49bd8cba55979f76.pyi | 75 + Test/TestProject/temp/4bf3e0150b9e02e9.pyi | 14 - Test/TestProject/temp/56cdd754a8a09347.pyi | 67 - Test/TestProject/temp/6aee24fdefa3cbc0.pyi | 44 - .../temp/8304671209f68d6c.pyi} | 1 + Test/TestProject/temp/8e0d8fdba991b3b4.pyi | 25 - Test/TestProject/temp/9dbecd0942a39782.pyi | 25 + Test/TestProject/temp/_sha1_map.txt | 31 +- Test/TestProject/temp/_shared_sym.pkl | Bin 924818 -> 0 bytes Test/TestProject/temp/ba2e1c2dfc8e2f85.pyi | 19 - Test/TestProject/temp/c3eb91093118e1e1.pyi | 234 -- Test/TestProject2/App/main.py | 147 +- Test/TestProject2/App/zc/class_test.py | 14 +- .../output/067c78e9f121dce3.deps.json | 1 + .../output/0991af0d22263577.deps.json | 1 + .../output/09ba6d4617920d26.deps.json | 1 - .../output/257e074b935c33b4.deps.json | 1 + .../output/29813d57621099a9.deps.json | 1 + .../output/541a1ed9b8be53c8.deps.json | 1 + .../output/5a6a2137958c28c5.deps.json | 1 + .../output/6ff26590374ae6fc.deps.json | 1 + .../output/72e2d5ccb7cedcf1.deps.json | 1 + .../output/73fcdc4dd1618580.deps.json | 1 + .../output/75583f20a922ab2e.deps.json | 1 - .../output/9dbecd0942a39782.deps.json | 1 + .../output/a7dab00d979c009c.deps.json | 1 - .../output/abf9ce3160c9279e.deps.json | 1 + .../output/b5f1dc665c52a1bd.deps.json | 1 + .../output/bbdf3bbd4c3bc28c.deps.json | 1 + .../output/c9d54a4158f7f5a8.deps.json | 1 + .../output/c9f4be41ca1cc2b4.deps.json | 1 + .../output/cc436a125bbaf28c.deps.json | 1 + .../output/cfc83b830141b00e.deps.json | 2 +- .../output/fa3691e66b426950.deps.json | 1 + .../output/faec3233d98371da.deps.json | 1 - Test/TestProject2/temp/067c78e9f121dce3.pyi | 136 + .../temp/0991af0d22263577.pyi} | 2 +- .../temp/257e074b935c33b4.pyi} | 18 +- .../temp/29813d57621099a9.pyi | 0 Test/TestProject2/temp/49bd8cba55979f76.pyi | 75 + .../temp/541a1ed9b8be53c8.pyi} | 7 +- Test/TestProject2/temp/56cdd754a8a09347.pyi | 67 - .../temp/59d33b6ab0c70953.pyi} | 0 Test/TestProject2/temp/5a6a2137958c28c5.pyi | 98 + Test/TestProject2/temp/6c2029b306556c00.pyi | 18 + .../temp/6ff26590374ae6fc.pyi} | 12 +- Test/TestProject2/temp/72e2d5ccb7cedcf1.pyi | 91 + .../temp/73c1586b83e9b5c2.pyi} | 6 +- .../temp/73fcdc4dd1618580.pyi} | 6 +- Test/TestProject2/temp/75583f20a922ab2e.pyi | 38 - .../temp/8ebed83a7817fa0c.pyi} | 2 +- .../temp/96837bcc64032444.pyi | 0 Test/TestProject2/temp/9dbecd0942a39782.pyi | 25 + Test/TestProject2/temp/_sha1_map.txt | 26 +- Test/TestProject2/temp/_shared_sym.json | 0 Test/TestProject2/temp/_shared_sym.pkl | Bin 194167 -> 0 bytes Test/TestProject2/temp/a7dab00d979c009c.pyi | 66 - Test/TestProject2/temp/abf9ce3160c9279e.pyi | 179 + Test/TestProject2/temp/b5f1dc665c52a1bd.pyi | 44 + Test/TestProject2/temp/bbdf3bbd4c3bc28c.pyi | 138 + .../temp/c39cbbae4b6e264f.pyi} | 2 +- .../temp/c9d54a4158f7f5a8.pyi} | 8 +- Test/TestProject2/temp/c9f4be41ca1cc2b4.pyi | 22 + .../temp/cc436a125bbaf28c.pyi} | 10 +- .../temp/cd520d14822f3f19.pyi} | 10 +- .../temp/f80740e7bcee16ae.pyi} | 0 Test/TestProject2/temp/fa3691e66b426950.pyi | 80 + Test/TestProject2/temp/faec3233d98371da.pyi | 54 - Test/TestProject3/App/main.py | 1003 +++--- Test/TestProject3/App/mpooltest.py | 2 +- .../output/067c78e9f121dce3.deps.json | 2 +- .../output/0991af0d22263577.deps.json | 1 + .../output/0f4d14c17bf75b10.deps.json | 1 - .../output/1b58766d38d05de3.deps.json | 2 +- .../output/2953a7db4185005b.deps.json | 1 - .../output/29813d57621099a9.deps.json | 2 +- .../output/3fdd11bdd589aa8c.deps.json | 2 +- .../output/5325ec533a59d71b.deps.json | 1 - .../output/5a6a2137958c28c5.deps.json | 2 +- .../output/64ac83614c9bdbc6.deps.json | 2 +- .../output/68c4fe4b12c908e3.deps.json | 1 - .../output/6aee24fdefa3cbc0.deps.json | 1 - .../output/70b580331b822117.deps.json | 1 + .../output/72e2d5ccb7cedcf1.deps.json | 2 +- .../output/9dbecd0942a39782.deps.json | 1 + .../output/abf9ce3160c9279e.deps.json | 2 +- .../output/b235d6477436c524.deps.json | 1 + .../output/b5f1dc665c52a1bd.deps.json | 1 + .../output/bbdf3bbd4c3bc28c.deps.json | 2 +- .../output/c01b27dbcd683245.deps.json | 2 +- .../output/c9f4be41ca1cc2b4.deps.json | 2 +- .../output/f8a7f964e23490fb.deps.json | 1 + .../output/fa3691e66b426950.deps.json | 2 +- .../output/fc49f6314bad25e9.deps.json | 2 +- Test/TestProject3/temp/0991af0d22263577.pyi | 50 + Test/TestProject3/temp/49bd8cba55979f76.pyi | 75 + Test/TestProject3/temp/56cdd754a8a09347.pyi | 67 - Test/TestProject3/temp/64ac83614c9bdbc6.pyi | 8 +- Test/TestProject3/temp/6aee24fdefa3cbc0.pyi | 44 - .../temp/70b580331b822117.pyi} | 0 Test/TestProject3/temp/73edbcf76e32d00b.pyi | 28 + Test/TestProject3/temp/9dbecd0942a39782.pyi | 25 + Test/TestProject3/temp/_sha1_map.txt | 14 +- Test/TestProject3/temp/_shared_sym.json | 0 Test/TestProject3/temp/_shared_sym.pkl | Bin 590089 -> 0 bytes ...d14c17bf75b10.pyi => b235d6477436c524.pyi} | 1 + Test/TestProject3/temp/b5f1dc665c52a1bd.pyi | 44 + ...5ec533a59d71b.pyi => f8a7f964e23490fb.pyi} | 0 Test/TypeCastTest/App/main.py | 100 +- .../output/067c78e9f121dce3.deps.json | 2 +- .../output/29813d57621099a9.deps.json | 2 +- .../output/5a6a2137958c28c5.deps.json | 2 +- .../output/6aee24fdefa3cbc0.deps.json | 1 - .../output/72e2d5ccb7cedcf1.deps.json | 2 +- .../output/78418cf2ee722f0f.deps.json | 1 + .../output/9dbecd0942a39782.deps.json | 1 + .../output/abf9ce3160c9279e.deps.json | 2 +- .../output/b5f1dc665c52a1bd.deps.json | 1 + .../output/bbdf3bbd4c3bc28c.deps.json | 2 +- .../output/bf230611b27080fa.deps.json | 1 - .../output/fa3691e66b426950.deps.json | 2 +- Test/TypeCastTest/temp/49bd8cba55979f76.pyi | 75 + Test/TypeCastTest/temp/56cdd754a8a09347.pyi | 67 - Test/TypeCastTest/temp/6aee24fdefa3cbc0.pyi | 44 - ...30611b27080fa.pyi => 78418cf2ee722f0f.pyi} | 1 + Test/TypeCastTest/temp/9dbecd0942a39782.pyi | 25 + Test/TypeCastTest/temp/_sha1_map.txt | 7 +- Test/TypeCastTest/temp/b5f1dc665c52a1bd.pyi | 44 + Test/VRandomTest/App/main.py | 128 + .../output/3f7c5e78d8652535.deps.json | 1 + .../output/62cc01c2bb770ca3.deps.json | 1 + .../output/9dbecd0942a39782.deps.json | 1 + .../output/e24a7f4a875f4518.deps.json | 1 + Test/VRandomTest/project.json | 29 + .../temp/3f7c5e78d8652535.pyi | 0 Test/VRandomTest/temp/49bd8cba55979f76.pyi | 75 + Test/VRandomTest/temp/62cc01c2bb770ca3.pyi | 77 + Test/VRandomTest/temp/73edbcf76e32d00b.pyi | 28 + Test/VRandomTest/temp/9dbecd0942a39782.pyi | 25 + Test/VRandomTest/temp/_sha1_map.txt | 6 + Test/VRandomTest/temp/e24a7f4a875f4518.pyi | 13 + Test/VariadicTest/App/main.py | 52 +- .../output/067c78e9f121dce3.deps.json | 2 +- .../output/2953a7db4185005b.deps.json | 1 - .../output/29813d57621099a9.deps.json | 2 +- .../output/377ad03e9b90ac39.deps.json | 1 - .../output/5a6a2137958c28c5.deps.json | 2 +- .../output/6aee24fdefa3cbc0.deps.json | 1 - .../output/70b580331b822117.deps.json | 1 + .../output/72e2d5ccb7cedcf1.deps.json | 2 +- .../output/9dbecd0942a39782.deps.json | 1 + .../output/abf9ce3160c9279e.deps.json | 2 +- .../output/b5f1dc665c52a1bd.deps.json | 1 + .../output/bbdf3bbd4c3bc28c.deps.json | 2 +- .../output/c1416dfae155d6e2.deps.json | 1 + .../output/c9f4be41ca1cc2b4.deps.json | 2 +- .../output/fa3691e66b426950.deps.json | 2 +- Test/VariadicTest/temp/49bd8cba55979f76.pyi | 75 + Test/VariadicTest/temp/56cdd754a8a09347.pyi | 67 - Test/VariadicTest/temp/6aee24fdefa3cbc0.pyi | 44 - Test/VariadicTest/temp/70b580331b822117.pyi | 19 + Test/VariadicTest/temp/9dbecd0942a39782.pyi | 25 + Test/VariadicTest/temp/_sha1_map.txt | 9 +- Test/VariadicTest/temp/b5f1dc665c52a1bd.pyi | 44 + ...ad03e9b90ac39.pyi => c1416dfae155d6e2.pyi} | 1 + Test/ZlibTest/App/__zlib/pyzlib.py | 2 +- Test/ZlibTest/App/__zlib/test_pyzlib.py | 16 +- Test/ZlibTest/App/__zlib/zchecksum.py | 2 +- Test/ZlibTest/App/__zlib/zdef.py | 10 +- Test/ZlibTest/App/__zlib/zdeflate.py | 8 +- Test/ZlibTest/App/__zlib/zhuff.py | 30 +- Test/ZlibTest/App/__zlib/zinflate.py | 6 +- Test/ZlibTest/App/main.py | 5 +- .../output/03b24bc1d9327958.deps.json | 1 + .../output/067c78e9f121dce3.deps.json | 1 - .../output/0af305ed4e5f787d.deps.json | 1 - .../output/0f8134f67bdaba8f.deps.json | 1 + .../output/26e23066e8c7208d.deps.json | 1 + .../output/29813d57621099a9.deps.json | 1 - .../output/53fa0c913947021f.deps.json | 1 - .../output/5a6a2137958c28c5.deps.json | 1 - .../output/5d8612e70097f0ba.deps.json | 1 + .../output/6aee24fdefa3cbc0.deps.json | 1 - .../output/72e2d5ccb7cedcf1.deps.json | 1 - .../output/7e9fab9c7b47c4db.deps.json | 1 - .../output/95e27d852b773ae8.deps.json | 1 - .../output/abf9ce3160c9279e.deps.json | 1 - .../output/bbdf3bbd4c3bc28c.deps.json | 1 - .../output/c9349bf1e8390dd5.deps.json | 1 - .../output/dca7ef1d57347738.deps.json | 1 - .../output/e00d9854a0d03f4f.deps.json | 1 - .../output/e445a2bb299d1b7d.deps.json | 1 + .../output/f9cd063200178785.deps.json | 1 - .../output/fa3691e66b426950.deps.json | 1 - ...7ef1d57347738.pyi => 03b24bc1d9327958.pyi} | 1 + ...fab9c7b47c4db.pyi => 0f8134f67bdaba8f.pyi} | 2 +- ...a0c913947021f.pyi => 26e23066e8c7208d.pyi} | 0 Test/ZlibTest/temp/49bd8cba55979f76.pyi | 75 + Test/ZlibTest/temp/56cdd754a8a09347.pyi | 67 - ...d063200178785.pyi => 5d8612e70097f0ba.pyi} | 10 +- Test/ZlibTest/temp/6aee24fdefa3cbc0.pyi | 44 - ...305ed4e5f787d.pyi => 77deeee736684e3e.pyi} | 0 ...49bf1e8390dd5.pyi => 8407b4239b208bdb.pyi} | 6 +- Test/ZlibTest/temp/9dbecd0942a39782.pyi | 25 + Test/ZlibTest/temp/_sha1_map.txt | 21 +- Test/ZlibTest/temp/_shared_sym.json | 0 Test/ZlibTest/temp/_shared_sym.pkl | Bin 407147 -> 0 bytes Test/ZlibTest/temp/b5f1dc665c52a1bd.pyi | 44 + ...27d852b773ae8.pyi => cb151b297f4ea56d.pyi} | 2 +- ...d9854a0d03f4f.pyi => e445a2bb299d1b7d.pyi} | 0 Test/fbnq copy 2.py | 147 - Test/fbnq.py | 405 --- Test/test.py | 133 - Test/test_out.txt | 1 - Test/test_output.txt | 1 - _debug_find.txt | 0 build_log.txt | 321 ++ build_log2.txt | 1 + compile_log.txt | 1 + compile_output.txt | 1 + compile_trace.txt | 1 + includes/__builtin.py | 425 +++ includes/_dict.py | 283 ++ includes/_fakeduck.py | 325 ++ includes/_list.py | 85 + includes/_variant.py | 64 + includes/_withcontent.py | 69 + includes/atom.py | 12 +- includes/base64.py | 4 +- includes/binascii.py | 18 +- includes/condition.py | 53 + includes/ctraits.pyi | 20 + includes/event.py | 36 + includes/hashlib/__md5.py | 12 +- includes/hashlib/__sha1.py | 8 +- includes/hashlib/__sha256.py | 10 +- includes/hashlib/__sha512.py | 14 +- includes/lock.py | 39 + includes/mbuddy.py | 374 ++ includes/mpool.py | 7 +- includes/numpy/__init__.py | 4 +- includes/rwlock.py | 46 + includes/spinlock.py | 2 +- includes/stdint.py | 10 + includes/string.py | 2 +- includes/testcheck.py | 54 + includes/viperlib.py | 2 +- includes/vrandom.py | 379 ++ includes/vthreading.py | 104 + includes/w32/win32sync.py | 20 + includes/zlib/pyzlib.py | 4 +- includes/zlib/zchecksum.py | 2 +- includes/zlib/zdef.py | 10 +- includes/zlib/zdeflate.py | 26 +- includes/zlib/zhuff.py | 34 +- includes/zlib/zinflate.py | 6 +- lib/Projectrans/Config.py | 454 +-- lib/Projectrans/DeclarationGenerator.py | 542 +-- lib/Projectrans/Phase1Generator.py | 295 +- lib/Projectrans/Phase2Translator.py | 886 +++-- lib/Projectrans/Utils.py | 94 +- lib/Shell/Config.py | 9 +- lib/Shell/Serializer.py | 29 +- lib/Shell/TransPyC.py | 259 +- lib/StubGen/Config.py | 85 +- lib/StubGen/Converter.py | 337 +- lib/StubGen/Generator.py | 98 +- lib/constants/config.py | 23 +- lib/core/ConstEvaluator.py | 173 +- lib/core/DecoratorPass.py | 221 +- lib/core/DiagnosticCollector.py | 29 +- lib/core/DifferenceCalculation.py | 58 +- lib/core/Exportable.py | 11 +- lib/core/Handles/HandlesAnnAssign.py | 378 +- lib/core/Handles/HandlesAssert.py | 115 +- lib/core/Handles/HandlesAssign.py | 3146 +++++++++-------- lib/core/Handles/HandlesAugAssign.py | 429 +-- lib/core/Handles/HandlesBase.py | 1510 ++++---- lib/core/Handles/HandlesBody.py | 153 +- lib/core/Handles/HandlesClassDef.py | 793 +++-- lib/core/Handles/HandlesDelete.py | 190 +- lib/core/Handles/HandlesExpr.py | 871 ++--- lib/core/Handles/HandlesExprAsm.py | 310 +- lib/core/Handles/HandlesExprAttr.py | 659 ++-- lib/core/Handles/HandlesExprBuiltin.py | 321 +- lib/core/Handles/HandlesExprCall.py | 1009 ++---- lib/core/Handles/HandlesExprFormat.py | 381 +- lib/core/Handles/HandlesExprLambda.py | 465 +-- lib/core/Handles/HandlesExprOps.py | 833 ++--- lib/core/Handles/HandlesExprUtils.py | 481 +-- lib/core/Handles/HandlesFor.py | 1541 +++++--- lib/core/Handles/HandlesFunctions.py | 613 ++-- lib/core/Handles/HandlesIf.py | 407 +-- lib/core/Handles/HandlesImports.py | 546 +-- lib/core/Handles/HandlesMatch.py | 666 ++-- lib/core/Handles/HandlesRaise.py | 276 +- lib/core/Handles/HandlesReturn.py | 318 +- lib/core/Handles/HandlesSpecialCall.py | 155 +- lib/core/Handles/HandlesTry.py | 423 +-- lib/core/Handles/HandlesTypeMerge.py | 457 +-- lib/core/Handles/HandlesWhile.py | 108 +- lib/core/Handles/HandlesWith.py | 308 +- lib/core/LLVMCG/BaseGen.py | 907 ++--- lib/core/LLVMCG/ExprGen.py | 718 ++-- lib/core/LLVMCG/FuncGen.py | 827 +++-- lib/core/LLVMCG/MemoryOps.py | 617 ++-- lib/core/LLVMCG/StructGen.py | 257 +- lib/core/LLVMCG/TypeConvert.py | 1328 +++---- lib/core/LLVMCG/VaArg.py | 188 +- lib/core/LLVMTypeMapper.py | 80 +- lib/core/LlvmCodeGenerator.py | 3 +- lib/core/SymbolData.py | 26 +- lib/core/SymbolExtractor.py | 120 +- lib/core/SymbolInserter.py | 33 +- lib/core/SymbolNode.py | 40 +- lib/core/SymbolReexporter.py | 43 +- lib/core/SymbolTable.py | 332 +- lib/core/SymbolTypeResolver.py | 91 +- lib/core/SymbolUtils.py | 142 +- lib/core/Translator/AnnotationLoader.py | 153 +- lib/core/Translator/BaseTranslator.py | 61 +- lib/core/Translator/ConstEval.py | 217 +- lib/core/Translator/LlvmGenerator.py | 252 +- lib/core/Translator/PythonParser.py | 168 +- lib/core/TypeAnnotationResolver.py | 249 +- lib/core/TypeSpec.py | 31 +- lib/core/VLogger.py | 113 +- lib/core/stub_generator.py | 408 ++- lib/core/translator.py | 3 +- lib/includes/c.py | 325 +- lib/includes/t.py | 956 +++-- lib/utils/helpers.py | 23 +- stderr.txt | 81 + stdout.txt | 261 ++ temp_build_log.txt | 1 + 827 files changed, 32617 insertions(+), 18316 deletions(-) create mode 100644 Test/BuddyTest/App/main.py create mode 100644 Test/BuddyTest/App/mbuddytest.py create mode 100644 Test/BuddyTest/output/067c78e9f121dce3.deps.json create mode 100644 Test/BuddyTest/output/271ea3decb810db2.deps.json create mode 100644 Test/BuddyTest/output/29813d57621099a9.deps.json create mode 100644 Test/BuddyTest/output/5a6a2137958c28c5.deps.json create mode 100644 Test/BuddyTest/output/5e430ae5bf7af3a2.deps.json create mode 100644 Test/BuddyTest/output/70b580331b822117.deps.json create mode 100644 Test/BuddyTest/output/72e2d5ccb7cedcf1.deps.json create mode 100644 Test/BuddyTest/output/9dbecd0942a39782.deps.json create mode 100644 Test/BuddyTest/output/abf9ce3160c9279e.deps.json create mode 100644 Test/BuddyTest/output/b5f1dc665c52a1bd.deps.json create mode 100644 Test/BuddyTest/output/bbdf3bbd4c3bc28c.deps.json create mode 100644 Test/BuddyTest/output/c53a157505aa8081.deps.json create mode 100644 Test/BuddyTest/output/c9f4be41ca1cc2b4.deps.json create mode 100644 Test/BuddyTest/output/e1937873ebfba8c3.deps.json create mode 100644 Test/BuddyTest/output/fa3691e66b426950.deps.json create mode 100644 Test/BuddyTest/project.json rename Test/{TestProject => BuddyTest}/temp/067c78e9f121dce3.pyi (100%) create mode 100644 Test/BuddyTest/temp/271ea3decb810db2.pyi rename Test/{TestProject => BuddyTest}/temp/29813d57621099a9.pyi (100%) rename Test/{IterTest/temp/56cdd754a8a09347.pyi => BuddyTest/temp/49bd8cba55979f76.pyi} (88%) rename Test/{TestProject => BuddyTest}/temp/5a6a2137958c28c5.pyi (100%) create mode 100644 Test/BuddyTest/temp/5e430ae5bf7af3a2.pyi rename Test/{TestProject => BuddyTest}/temp/6c2029b306556c00.pyi (100%) rename Test/{TestProject3/temp/2953a7db4185005b.pyi => BuddyTest/temp/70b580331b822117.pyi} (100%) create mode 100644 Test/BuddyTest/temp/71e0a3ffcb3ebfad.pyi rename Test/{TestProject => BuddyTest}/temp/72e2d5ccb7cedcf1.pyi (100%) create mode 100644 Test/BuddyTest/temp/73edbcf76e32d00b.pyi create mode 100644 Test/BuddyTest/temp/9dbecd0942a39782.pyi create mode 100644 Test/BuddyTest/temp/_sha1_map.txt create mode 100644 Test/BuddyTest/temp/_shared_sym.json rename Test/{TestProject => BuddyTest}/temp/abf9ce3160c9279e.pyi (100%) rename Test/{JsonTest/temp/6aee24fdefa3cbc0.pyi => BuddyTest/temp/b5f1dc665c52a1bd.pyi} (94%) rename Test/{TestProject => BuddyTest}/temp/bbdf3bbd4c3bc28c.pyi (100%) create mode 100644 Test/BuddyTest/temp/c53a157505aa8081.pyi rename Test/{TestProject => BuddyTest}/temp/c9f4be41ca1cc2b4.pyi (100%) create mode 100644 Test/BuddyTest/temp/e1937873ebfba8c3.pyi rename Test/{TestProject => BuddyTest}/temp/fa3691e66b426950.pyi (100%) create mode 100644 Test/BuiltinDecoratorTest/output/9dbecd0942a39782.deps.json delete mode 100644 Test/BuiltinDecoratorTest/output/b6069b01d8c9cc04.deps.json create mode 100644 Test/BuiltinDecoratorTest/output/e3ac223bdaf94a0c.deps.json rename Test/BuiltinDecoratorTest/temp/{56cdd754a8a09347.pyi => 49bd8cba55979f76.pyi} (88%) create mode 100644 Test/BuiltinDecoratorTest/temp/9dbecd0942a39782.pyi rename Test/BuiltinDecoratorTest/temp/{b6069b01d8c9cc04.pyi => e3ac223bdaf94a0c.pyi} (95%) delete mode 100644 Test/CPythonTest/output/0cd580d62a3de4f8.deps.json rename Test/CPythonTest/temp/{0cd580d62a3de4f8.pyi => 3c8ecda6b848f011.pyi} (81%) create mode 100644 Test/CPythonTest/temp/9dbecd0942a39782.pyi create mode 100644 Test/CPythonTest/temp/_shared_sym.json delete mode 100644 Test/CPythonTest/temp/_shared_sym.pkl create mode 100644 Test/ClosureTest/output/52e6b51da061882f.deps.json delete mode 100644 Test/ClosureTest/output/7dbf085f7e3e8944.deps.json create mode 100644 Test/ClosureTest/output/9dbecd0942a39782.deps.json rename Test/ClosureTest/temp/{7dbf085f7e3e8944.pyi => 52e6b51da061882f.pyi} (92%) create mode 100644 Test/ClosureTest/temp/9dbecd0942a39782.pyi delete mode 100644 Test/ClosureTest2/output/052c7f96b9eefa2c.deps.json create mode 100644 Test/ClosureTest2/output/440f18f9dce85a95.deps.json create mode 100644 Test/ClosureTest2/output/9dbecd0942a39782.deps.json rename Test/ClosureTest2/temp/{052c7f96b9eefa2c.pyi => 440f18f9dce85a95.pyi} (98%) create mode 100644 Test/ClosureTest2/temp/9dbecd0942a39782.pyi create mode 100644 Test/DecoratorMarkerTest/App/main.py create mode 100644 Test/DecoratorMarkerTest/output/9dbecd0942a39782.deps.json create mode 100644 Test/DecoratorMarkerTest/output/b1122357fee8fd68.deps.json create mode 100644 Test/DecoratorMarkerTest/project.json create mode 100644 Test/DecoratorMarkerTest/temp/73edbcf76e32d00b.pyi create mode 100644 Test/DecoratorMarkerTest/temp/9dbecd0942a39782.pyi create mode 100644 Test/DecoratorMarkerTest/temp/_sha1_map.txt create mode 100644 Test/DecoratorMarkerTest/temp/b1122357fee8fd68.pyi delete mode 100644 Test/DecoratorTest/output/577f9e1aa32b17f8.deps.json create mode 100644 Test/DecoratorTest/output/814e6b31adfc6256.deps.json create mode 100644 Test/DecoratorTest/output/9dbecd0942a39782.deps.json rename Test/DecoratorTest/temp/{577f9e1aa32b17f8.pyi => 814e6b31adfc6256.pyi} (99%) create mode 100644 Test/DecoratorTest/temp/9dbecd0942a39782.pyi create mode 100644 Test/DictTest/App/main.py create mode 100644 Test/DictTest/output/067c78e9f121dce3.deps.json create mode 100644 Test/DictTest/output/06f53cc594b4ac6c.deps.json create mode 100644 Test/DictTest/output/0991af0d22263577.deps.json create mode 100644 Test/DictTest/output/0eaa586c42dcd931.deps.json create mode 100644 Test/DictTest/output/271ea3decb810db2.deps.json create mode 100644 Test/DictTest/output/5a6a2137958c28c5.deps.json create mode 100644 Test/DictTest/output/72e2d5ccb7cedcf1.deps.json create mode 100644 Test/DictTest/output/8ee3170049c70333.deps.json create mode 100644 Test/DictTest/output/9dbecd0942a39782.deps.json create mode 100644 Test/DictTest/output/abf9ce3160c9279e.deps.json create mode 100644 Test/DictTest/output/b5f1dc665c52a1bd.deps.json create mode 100644 Test/DictTest/output/bbdf3bbd4c3bc28c.deps.json create mode 100644 Test/DictTest/output/bd2e7db1744476fe.deps.json create mode 100644 Test/DictTest/output/c9f4be41ca1cc2b4.deps.json create mode 100644 Test/DictTest/output/eaf7a981f0ef5b22.deps.json create mode 100644 Test/DictTest/output/f1e15ccf054b1e89.deps.json create mode 100644 Test/DictTest/output/fa3691e66b426950.deps.json create mode 100644 Test/DictTest/output/fced53b138f67cf5.deps.json create mode 100644 Test/DictTest/project.json rename Test/{ZlibTest => DictTest}/temp/067c78e9f121dce3.pyi (100%) create mode 100644 Test/DictTest/temp/06f53cc594b4ac6c.pyi rename Test/{TestProject/temp/68c4fe4b12c908e3.pyi => DictTest/temp/0991af0d22263577.pyi} (98%) create mode 100644 Test/DictTest/temp/0eaa586c42dcd931.pyi create mode 100644 Test/DictTest/temp/271ea3decb810db2.pyi rename Test/{JsonTest/temp/56cdd754a8a09347.pyi => DictTest/temp/49bd8cba55979f76.pyi} (88%) create mode 100644 Test/DictTest/temp/5a6a2137958c28c5.pyi create mode 100644 Test/DictTest/temp/6c2029b306556c00.pyi create mode 100644 Test/DictTest/temp/72e2d5ccb7cedcf1.pyi create mode 100644 Test/DictTest/temp/73edbcf76e32d00b.pyi create mode 100644 Test/DictTest/temp/8ee3170049c70333.pyi create mode 100644 Test/DictTest/temp/9dbecd0942a39782.pyi create mode 100644 Test/DictTest/temp/_sha1_map.txt rename Test/{ZlibTest => DictTest}/temp/abf9ce3160c9279e.pyi (100%) rename Test/{IterTest/temp/6aee24fdefa3cbc0.pyi => DictTest/temp/b5f1dc665c52a1bd.pyi} (94%) rename Test/{ZlibTest => DictTest}/temp/bbdf3bbd4c3bc28c.pyi (100%) create mode 100644 Test/DictTest/temp/bd2e7db1744476fe.pyi create mode 100644 Test/DictTest/temp/c9f4be41ca1cc2b4.pyi create mode 100644 Test/DictTest/temp/eaf7a981f0ef5b22.pyi create mode 100644 Test/DictTest/temp/f1e15ccf054b1e89.pyi rename Test/{ZlibTest => DictTest}/temp/fa3691e66b426950.pyi (100%) create mode 100644 Test/DictTest/temp/fced53b138f67cf5.pyi create mode 100644 Test/EdgeCaseTest/App/main.py create mode 100644 Test/EdgeCaseTest/output/9dbecd0942a39782.deps.json create mode 100644 Test/EdgeCaseTest/output/ac0d686cb2cc783b.deps.json create mode 100644 Test/EdgeCaseTest/project.json create mode 100644 Test/EdgeCaseTest/temp/73edbcf76e32d00b.pyi create mode 100644 Test/EdgeCaseTest/temp/9dbecd0942a39782.pyi create mode 100644 Test/EdgeCaseTest/temp/_sha1_map.txt create mode 100644 Test/EdgeCaseTest/temp/ac0d686cb2cc783b.pyi create mode 100644 Test/EqTest/App/main.py create mode 100644 Test/EqTest/output/067c78e9f121dce3.deps.json create mode 100644 Test/EqTest/output/06f53cc594b4ac6c.deps.json create mode 100644 Test/EqTest/output/5a6a2137958c28c5.deps.json create mode 100644 Test/EqTest/output/72e2d5ccb7cedcf1.deps.json create mode 100644 Test/EqTest/output/78943d0dbc89a29a.deps.json create mode 100644 Test/EqTest/output/9dbecd0942a39782.deps.json create mode 100644 Test/EqTest/output/abf9ce3160c9279e.deps.json create mode 100644 Test/EqTest/output/b5f1dc665c52a1bd.deps.json create mode 100644 Test/EqTest/output/bbdf3bbd4c3bc28c.deps.json create mode 100644 Test/EqTest/output/fa3691e66b426950.deps.json create mode 100644 Test/EqTest/project.json create mode 100644 Test/EqTest/temp/067c78e9f121dce3.pyi create mode 100644 Test/EqTest/temp/06f53cc594b4ac6c.pyi rename Test/{FuncTest/temp/56cdd754a8a09347.pyi => EqTest/temp/49bd8cba55979f76.pyi} (88%) create mode 100644 Test/EqTest/temp/5a6a2137958c28c5.pyi create mode 100644 Test/EqTest/temp/6c2029b306556c00.pyi create mode 100644 Test/EqTest/temp/72e2d5ccb7cedcf1.pyi create mode 100644 Test/EqTest/temp/73edbcf76e32d00b.pyi create mode 100644 Test/EqTest/temp/78943d0dbc89a29a.pyi create mode 100644 Test/EqTest/temp/9dbecd0942a39782.pyi create mode 100644 Test/EqTest/temp/_sha1_map.txt create mode 100644 Test/EqTest/temp/abf9ce3160c9279e.pyi rename Test/{SimdTest/temp/6aee24fdefa3cbc0.pyi => EqTest/temp/b5f1dc665c52a1bd.pyi} (94%) create mode 100644 Test/EqTest/temp/bbdf3bbd4c3bc28c.pyi create mode 100644 Test/EqTest/temp/fa3691e66b426950.pyi create mode 100644 Test/FakeDuckTest/App/main.py create mode 100644 Test/FakeDuckTest/output/067c78e9f121dce3.deps.json create mode 100644 Test/FakeDuckTest/output/06f53cc594b4ac6c.deps.json create mode 100644 Test/FakeDuckTest/output/0eaa586c42dcd931.deps.json create mode 100644 Test/FakeDuckTest/output/271ea3decb810db2.deps.json create mode 100644 Test/FakeDuckTest/output/5a6a2137958c28c5.deps.json create mode 100644 Test/FakeDuckTest/output/72e2d5ccb7cedcf1.deps.json create mode 100644 Test/FakeDuckTest/output/9d9d71cf83da7ca4.deps.json create mode 100644 Test/FakeDuckTest/output/9dbecd0942a39782.deps.json create mode 100644 Test/FakeDuckTest/output/abf9ce3160c9279e.deps.json create mode 100644 Test/FakeDuckTest/output/b5f1dc665c52a1bd.deps.json create mode 100644 Test/FakeDuckTest/output/b9b237d0e206d76c.deps.json create mode 100644 Test/FakeDuckTest/output/bbdf3bbd4c3bc28c.deps.json create mode 100644 Test/FakeDuckTest/output/c6206460c42ccf10.deps.json create mode 100644 Test/FakeDuckTest/output/ccd58bf663340b12.deps.json create mode 100644 Test/FakeDuckTest/output/fa3691e66b426950.deps.json create mode 100644 Test/FakeDuckTest/project.json create mode 100644 Test/FakeDuckTest/temp/067c78e9f121dce3.pyi create mode 100644 Test/FakeDuckTest/temp/06f53cc594b4ac6c.pyi create mode 100644 Test/FakeDuckTest/temp/0eaa586c42dcd931.pyi create mode 100644 Test/FakeDuckTest/temp/271ea3decb810db2.pyi create mode 100644 Test/FakeDuckTest/temp/49bd8cba55979f76.pyi create mode 100644 Test/FakeDuckTest/temp/5a6a2137958c28c5.pyi create mode 100644 Test/FakeDuckTest/temp/6c2029b306556c00.pyi create mode 100644 Test/FakeDuckTest/temp/72e2d5ccb7cedcf1.pyi create mode 100644 Test/FakeDuckTest/temp/73edbcf76e32d00b.pyi create mode 100644 Test/FakeDuckTest/temp/9d9d71cf83da7ca4.pyi create mode 100644 Test/FakeDuckTest/temp/9dbecd0942a39782.pyi create mode 100644 Test/FakeDuckTest/temp/_sha1_map.txt create mode 100644 Test/FakeDuckTest/temp/abf9ce3160c9279e.pyi rename Test/{PointerTest/temp/6aee24fdefa3cbc0.pyi => FakeDuckTest/temp/b5f1dc665c52a1bd.pyi} (94%) create mode 100644 Test/FakeDuckTest/temp/b9b237d0e206d76c.pyi create mode 100644 Test/FakeDuckTest/temp/bbdf3bbd4c3bc28c.pyi create mode 100644 Test/FakeDuckTest/temp/c6206460c42ccf10.pyi create mode 100644 Test/FakeDuckTest/temp/ccd58bf663340b12.pyi create mode 100644 Test/FakeDuckTest/temp/fa3691e66b426950.pyi create mode 100644 Test/ForAndLoopTest/App/main.py create mode 100644 Test/ForAndLoopTest/output/0eaa586c42dcd931.deps.json create mode 100644 Test/ForAndLoopTest/output/271ea3decb810db2.deps.json create mode 100644 Test/ForAndLoopTest/output/2e079471575f937d.deps.json create mode 100644 Test/ForAndLoopTest/output/9163064cf3eb88f4.deps.json create mode 100644 Test/ForAndLoopTest/output/9dbecd0942a39782.deps.json create mode 100644 Test/ForAndLoopTest/output/b5f1dc665c52a1bd.deps.json create mode 100644 Test/ForAndLoopTest/project.json create mode 100644 Test/ForAndLoopTest/temp/0eaa586c42dcd931.pyi create mode 100644 Test/ForAndLoopTest/temp/271ea3decb810db2.pyi create mode 100644 Test/ForAndLoopTest/temp/2e079471575f937d.pyi create mode 100644 Test/ForAndLoopTest/temp/49bd8cba55979f76.pyi create mode 100644 Test/ForAndLoopTest/temp/6c2029b306556c00.pyi create mode 100644 Test/ForAndLoopTest/temp/73edbcf76e32d00b.pyi create mode 100644 Test/ForAndLoopTest/temp/9163064cf3eb88f4.pyi create mode 100644 Test/ForAndLoopTest/temp/9dbecd0942a39782.pyi create mode 100644 Test/ForAndLoopTest/temp/_sha1_map.txt create mode 100644 Test/ForAndLoopTest/temp/b5f1dc665c52a1bd.pyi create mode 100644 Test/FormatStringTest/App/main.py create mode 100644 Test/FormatStringTest/output/9dbecd0942a39782.deps.json create mode 100644 Test/FormatStringTest/output/cdff0d7b58fc935b.deps.json create mode 100644 Test/FormatStringTest/project.json create mode 100644 Test/FormatStringTest/temp/42ced27d9e76aef5.pyi create mode 100644 Test/FormatStringTest/temp/49bd8cba55979f76.pyi create mode 100644 Test/FormatStringTest/temp/73edbcf76e32d00b.pyi create mode 100644 Test/FormatStringTest/temp/9dbecd0942a39782.pyi create mode 100644 Test/FormatStringTest/temp/_sha1_map.txt create mode 100644 Test/FormatStringTest/temp/cdff0d7b58fc935b.pyi rename Test/FuncTest/output/{d6f1d57732bde476.deps.json => 067f811511854c88.deps.json} (54%) create mode 100644 Test/FuncTest/output/9dbecd0942a39782.deps.json rename Test/FuncTest/temp/{d6f1d57732bde476.pyi => 067f811511854c88.pyi} (98%) create mode 100644 Test/FuncTest/temp/49bd8cba55979f76.pyi create mode 100644 Test/FuncTest/temp/9dbecd0942a39782.pyi create mode 100644 Test/GenericTest/output/16e1f65b154831e8.deps.json delete mode 100644 Test/GenericTest/output/47df358e08cc5c0e.deps.json create mode 100644 Test/GenericTest/output/9dbecd0942a39782.deps.json rename Test/GenericTest/temp/{47df358e08cc5c0e.pyi => 16e1f65b154831e8.pyi} (98%) create mode 100644 Test/GenericTest/temp/9dbecd0942a39782.pyi delete mode 100644 Test/GenericTest2/output/1348b0e29ea228ad.deps.json create mode 100644 Test/GenericTest2/output/9dbecd0942a39782.deps.json create mode 100644 Test/GenericTest2/output/d2165a80fd5563cc.deps.json create mode 100644 Test/GenericTest2/temp/9dbecd0942a39782.pyi rename Test/GenericTest2/temp/{1348b0e29ea228ad.pyi => d2165a80fd5563cc.pyi} (92%) create mode 100644 Test/IterTest/output/1452048cbd90ae2f.deps.json delete mode 100644 Test/IterTest/output/6aee24fdefa3cbc0.deps.json create mode 100644 Test/IterTest/output/9dbecd0942a39782.deps.json create mode 100644 Test/IterTest/output/b5f1dc665c52a1bd.deps.json delete mode 100644 Test/IterTest/output/d044f813487c68b6.deps.json rename Test/IterTest/temp/{d044f813487c68b6.pyi => 1452048cbd90ae2f.pyi} (94%) create mode 100644 Test/IterTest/temp/49bd8cba55979f76.pyi create mode 100644 Test/IterTest/temp/9dbecd0942a39782.pyi create mode 100644 Test/IterTest/temp/b5f1dc665c52a1bd.pyi create mode 100644 Test/JsonTest/output/0991af0d22263577.deps.json delete mode 100644 Test/JsonTest/output/1dd5985fb89f7ef9.deps.json delete mode 100644 Test/JsonTest/output/68c4fe4b12c908e3.deps.json delete mode 100644 Test/JsonTest/output/6aee24fdefa3cbc0.deps.json create mode 100644 Test/JsonTest/output/9361526faa30d4d2.deps.json create mode 100644 Test/JsonTest/output/9dbecd0942a39782.deps.json create mode 100644 Test/JsonTest/output/b5f1dc665c52a1bd.deps.json rename Test/JsonTest/temp/{68c4fe4b12c908e3.pyi => 0991af0d22263577.pyi} (98%) create mode 100644 Test/JsonTest/temp/49bd8cba55979f76.pyi rename Test/JsonTest/temp/{1dd5985fb89f7ef9.pyi => 9361526faa30d4d2.pyi} (83%) create mode 100644 Test/JsonTest/temp/9dbecd0942a39782.pyi create mode 100644 Test/JsonTest/temp/b5f1dc665c52a1bd.pyi create mode 100644 Test/ListTest/App/main.py create mode 100644 Test/ListTest/output/d4150579dda5d04a.deps.json create mode 100644 Test/ListTest/project.json create mode 100644 Test/ListTest/temp/271ea3decb810db2.pyi create mode 100644 Test/ListTest/temp/49bd8cba55979f76.pyi create mode 100644 Test/ListTest/temp/5a6a2137958c28c5.pyi create mode 100644 Test/ListTest/temp/6af0881381d5e37e.pyi create mode 100644 Test/ListTest/temp/6c2029b306556c00.pyi create mode 100644 Test/ListTest/temp/73edbcf76e32d00b.pyi create mode 100644 Test/ListTest/temp/9dbecd0942a39782.pyi create mode 100644 Test/ListTest/temp/_sha1_map.txt create mode 100644 Test/ListTest/temp/b5f1dc665c52a1bd.pyi create mode 100644 Test/ListTest/temp/bbdf3bbd4c3bc28c.pyi create mode 100644 Test/ListTest/temp/e1937873ebfba8c3.pyi delete mode 100644 Test/LoopTest/output/4b6b35e3922a169f.deps.json create mode 100644 Test/LoopTest/output/86e203c56ae4de20.deps.json create mode 100644 Test/LoopTest/output/9dbecd0942a39782.deps.json rename Test/LoopTest/temp/{4b6b35e3922a169f.pyi => 86e203c56ae4de20.pyi} (95%) create mode 100644 Test/LoopTest/temp/9dbecd0942a39782.pyi delete mode 100644 Test/PointerTest/output/6aee24fdefa3cbc0.deps.json create mode 100644 Test/PointerTest/output/9dbecd0942a39782.deps.json create mode 100644 Test/PointerTest/output/b436212dcff1be29.deps.json create mode 100644 Test/PointerTest/output/b5f1dc665c52a1bd.deps.json delete mode 100644 Test/PointerTest/output/e0c894447ac34ed3.deps.json create mode 100644 Test/PointerTest/temp/49bd8cba55979f76.pyi delete mode 100644 Test/PointerTest/temp/56cdd754a8a09347.pyi create mode 100644 Test/PointerTest/temp/9dbecd0942a39782.pyi rename Test/PointerTest/temp/{e0c894447ac34ed3.pyi => b436212dcff1be29.pyi} (98%) create mode 100644 Test/PointerTest/temp/b5f1dc665c52a1bd.pyi create mode 100644 Test/ShortCircuitTest/App/main.py create mode 100644 Test/ShortCircuitTest/output/067c78e9f121dce3.deps.json create mode 100644 Test/ShortCircuitTest/output/06f53cc594b4ac6c.deps.json create mode 100644 Test/ShortCircuitTest/output/5a6a2137958c28c5.deps.json create mode 100644 Test/ShortCircuitTest/output/72e2d5ccb7cedcf1.deps.json create mode 100644 Test/ShortCircuitTest/output/9dbecd0942a39782.deps.json create mode 100644 Test/ShortCircuitTest/output/a711c9c66fd7c6ca.deps.json create mode 100644 Test/ShortCircuitTest/output/abf9ce3160c9279e.deps.json create mode 100644 Test/ShortCircuitTest/output/b5f1dc665c52a1bd.deps.json create mode 100644 Test/ShortCircuitTest/output/bbdf3bbd4c3bc28c.deps.json create mode 100644 Test/ShortCircuitTest/output/fa3691e66b426950.deps.json create mode 100644 Test/ShortCircuitTest/project.json create mode 100644 Test/ShortCircuitTest/temp/067c78e9f121dce3.pyi create mode 100644 Test/ShortCircuitTest/temp/06f53cc594b4ac6c.pyi create mode 100644 Test/ShortCircuitTest/temp/49bd8cba55979f76.pyi create mode 100644 Test/ShortCircuitTest/temp/5a6a2137958c28c5.pyi create mode 100644 Test/ShortCircuitTest/temp/6c2029b306556c00.pyi create mode 100644 Test/ShortCircuitTest/temp/72e2d5ccb7cedcf1.pyi create mode 100644 Test/ShortCircuitTest/temp/73edbcf76e32d00b.pyi create mode 100644 Test/ShortCircuitTest/temp/9dbecd0942a39782.pyi create mode 100644 Test/ShortCircuitTest/temp/_sha1_map.txt create mode 100644 Test/ShortCircuitTest/temp/a711c9c66fd7c6ca.pyi create mode 100644 Test/ShortCircuitTest/temp/abf9ce3160c9279e.pyi create mode 100644 Test/ShortCircuitTest/temp/b5f1dc665c52a1bd.pyi create mode 100644 Test/ShortCircuitTest/temp/bbdf3bbd4c3bc28c.pyi create mode 100644 Test/ShortCircuitTest/temp/fa3691e66b426950.pyi create mode 100644 Test/SimdTest/output/0991af0d22263577.deps.json create mode 100644 Test/SimdTest/output/1787ce01c2ed0493.deps.json delete mode 100644 Test/SimdTest/output/1b666d438f4d301e.deps.json delete mode 100644 Test/SimdTest/output/68c4fe4b12c908e3.deps.json delete mode 100644 Test/SimdTest/output/6aee24fdefa3cbc0.deps.json create mode 100644 Test/SimdTest/output/9dbecd0942a39782.deps.json create mode 100644 Test/SimdTest/output/b44ac2a895a4072d.deps.json create mode 100644 Test/SimdTest/output/b5f1dc665c52a1bd.deps.json delete mode 100644 Test/SimdTest/output/c3eb91093118e1e1.deps.json rename Test/SimdTest/temp/{68c4fe4b12c908e3.pyi => 0991af0d22263577.pyi} (98%) rename Test/SimdTest/temp/{c3eb91093118e1e1.pyi => 1787ce01c2ed0493.pyi} (99%) create mode 100644 Test/SimdTest/temp/49bd8cba55979f76.pyi delete mode 100644 Test/SimdTest/temp/56cdd754a8a09347.pyi create mode 100644 Test/SimdTest/temp/9dbecd0942a39782.pyi rename Test/SimdTest/temp/{1b666d438f4d301e.pyi => b44ac2a895a4072d.pyi} (86%) create mode 100644 Test/SimdTest/temp/b5f1dc665c52a1bd.pyi delete mode 100644 Test/StringIterTest/output/2255fdda7aed5595.deps.json delete mode 100644 Test/StringIterTest/output/6aee24fdefa3cbc0.deps.json create mode 100644 Test/StringIterTest/output/924ed8cd4ea5c4c2.deps.json create mode 100644 Test/StringIterTest/output/9dbecd0942a39782.deps.json create mode 100644 Test/StringIterTest/output/StringIterTest.exe.tmp0 create mode 100644 Test/StringIterTest/output/b5f1dc665c52a1bd.deps.json create mode 100644 Test/StringIterTest/temp/49bd8cba55979f76.pyi delete mode 100644 Test/StringIterTest/temp/56cdd754a8a09347.pyi delete mode 100644 Test/StringIterTest/temp/6aee24fdefa3cbc0.pyi rename Test/StringIterTest/temp/{2255fdda7aed5595.pyi => 924ed8cd4ea5c4c2.pyi} (97%) create mode 100644 Test/StringIterTest/temp/9dbecd0942a39782.pyi create mode 100644 Test/StringIterTest/temp/b5f1dc665c52a1bd.pyi create mode 100644 Test/StringTest/output/39178dc5ba692b92.deps.json delete mode 100644 Test/StringTest/output/6aee24fdefa3cbc0.deps.json delete mode 100644 Test/StringTest/output/7aa13c104a22528a.deps.json create mode 100644 Test/StringTest/output/9dbecd0942a39782.deps.json create mode 100644 Test/StringTest/output/b5f1dc665c52a1bd.deps.json rename Test/StringTest/temp/{7aa13c104a22528a.pyi => 39178dc5ba692b92.pyi} (96%) create mode 100644 Test/StringTest/temp/49bd8cba55979f76.pyi delete mode 100644 Test/StringTest/temp/56cdd754a8a09347.pyi delete mode 100644 Test/StringTest/temp/6aee24fdefa3cbc0.pyi create mode 100644 Test/StringTest/temp/9dbecd0942a39782.pyi create mode 100644 Test/StringTest/temp/b5f1dc665c52a1bd.pyi create mode 100644 Test/StructTest/output/24e26a8de1173993.deps.json delete mode 100644 Test/StructTest/output/6aee24fdefa3cbc0.deps.json delete mode 100644 Test/StructTest/output/6f6ee14c129ac228.deps.json create mode 100644 Test/StructTest/output/9dbecd0942a39782.deps.json create mode 100644 Test/StructTest/output/b5f1dc665c52a1bd.deps.json rename Test/StructTest/temp/{6f6ee14c129ac228.pyi => 24e26a8de1173993.pyi} (97%) create mode 100644 Test/StructTest/temp/49bd8cba55979f76.pyi delete mode 100644 Test/StructTest/temp/56cdd754a8a09347.pyi delete mode 100644 Test/StructTest/temp/6aee24fdefa3cbc0.pyi create mode 100644 Test/StructTest/temp/9dbecd0942a39782.pyi create mode 100644 Test/StructTest/temp/b5f1dc665c52a1bd.pyi delete mode 100644 Test/TestFBProject/output/3727eb00d15bf59d.deps.json create mode 100644 Test/TestFBProject/output/4fb8940ff5ab1022.deps.json create mode 100644 Test/TestFBProject/output/9dbecd0942a39782.deps.json create mode 100644 Test/TestFBProject/temp/49bd8cba55979f76.pyi rename Test/TestFBProject/temp/{3727eb00d15bf59d.pyi => 4fb8940ff5ab1022.pyi} (91%) delete mode 100644 Test/TestFBProject/temp/56cdd754a8a09347.pyi create mode 100644 Test/TestFBProject/temp/73edbcf76e32d00b.pyi create mode 100644 Test/TestFBProject/temp/9dbecd0942a39782.pyi delete mode 100644 Test/TestProject/output/067c78e9f121dce3.deps.json delete mode 100644 Test/TestProject/output/0c04ab530bb9cfa4.deps.json delete mode 100644 Test/TestProject/output/0d13cde396f4a15f.deps.json delete mode 100644 Test/TestProject/output/0d4517fd5afeb330.deps.json delete mode 100644 Test/TestProject/output/29813d57621099a9.deps.json delete mode 100644 Test/TestProject/output/2d7f623c6e3004ce.deps.json delete mode 100644 Test/TestProject/output/2e756dd336749fc2.deps.json delete mode 100644 Test/TestProject/output/3ee89b588a1da94f.deps.json delete mode 100644 Test/TestProject/output/3f7c5e78d8652535.deps.json delete mode 100644 Test/TestProject/output/4638d411fd53fef0.deps.json delete mode 100644 Test/TestProject/output/4bf3e0150b9e02e9.deps.json delete mode 100644 Test/TestProject/output/58121a0fb0ca7466.deps.json delete mode 100644 Test/TestProject/output/5a6a2137958c28c5.deps.json delete mode 100644 Test/TestProject/output/68c4fe4b12c908e3.deps.json delete mode 100644 Test/TestProject/output/6aee24fdefa3cbc0.deps.json delete mode 100644 Test/TestProject/output/72e2d5ccb7cedcf1.deps.json delete mode 100644 Test/TestProject/output/88e3e48eab9e1653.deps.json delete mode 100644 Test/TestProject/output/8e0d8fdba991b3b4.deps.json delete mode 100644 Test/TestProject/output/8f88a3374d5335cc.deps.json delete mode 100644 Test/TestProject/output/94496ec50b0d13fc.deps.json delete mode 100644 Test/TestProject/output/a9fa0f6200c09e65.deps.json delete mode 100644 Test/TestProject/output/abf9ce3160c9279e.deps.json delete mode 100644 Test/TestProject/output/b0267503e816efc4.deps.json delete mode 100644 Test/TestProject/output/ba2e1c2dfc8e2f85.deps.json delete mode 100644 Test/TestProject/output/bbdf3bbd4c3bc28c.deps.json delete mode 100644 Test/TestProject/output/c3eb91093118e1e1.deps.json delete mode 100644 Test/TestProject/output/c9f4be41ca1cc2b4.deps.json delete mode 100644 Test/TestProject/output/d282a7cb3385ecf0.deps.json delete mode 100644 Test/TestProject/output/f9629b8eb4ebdcc2.deps.json delete mode 100644 Test/TestProject/output/fa3691e66b426950.deps.json delete mode 100644 Test/TestProject/temp/0c04ab530bb9cfa4.pyi delete mode 100644 Test/TestProject/temp/2e756dd336749fc2.pyi delete mode 100644 Test/TestProject/temp/3ee89b588a1da94f.pyi create mode 100644 Test/TestProject/temp/49bd8cba55979f76.pyi delete mode 100644 Test/TestProject/temp/4bf3e0150b9e02e9.pyi delete mode 100644 Test/TestProject/temp/56cdd754a8a09347.pyi delete mode 100644 Test/TestProject/temp/6aee24fdefa3cbc0.pyi rename Test/{TestProject2/temp/09ba6d4617920d26.pyi => TestProject/temp/8304671209f68d6c.pyi} (93%) delete mode 100644 Test/TestProject/temp/8e0d8fdba991b3b4.pyi create mode 100644 Test/TestProject/temp/9dbecd0942a39782.pyi delete mode 100644 Test/TestProject/temp/_shared_sym.pkl delete mode 100644 Test/TestProject/temp/ba2e1c2dfc8e2f85.pyi delete mode 100644 Test/TestProject/temp/c3eb91093118e1e1.pyi create mode 100644 Test/TestProject2/output/067c78e9f121dce3.deps.json create mode 100644 Test/TestProject2/output/0991af0d22263577.deps.json delete mode 100644 Test/TestProject2/output/09ba6d4617920d26.deps.json create mode 100644 Test/TestProject2/output/257e074b935c33b4.deps.json create mode 100644 Test/TestProject2/output/29813d57621099a9.deps.json create mode 100644 Test/TestProject2/output/541a1ed9b8be53c8.deps.json create mode 100644 Test/TestProject2/output/5a6a2137958c28c5.deps.json create mode 100644 Test/TestProject2/output/6ff26590374ae6fc.deps.json create mode 100644 Test/TestProject2/output/72e2d5ccb7cedcf1.deps.json create mode 100644 Test/TestProject2/output/73fcdc4dd1618580.deps.json delete mode 100644 Test/TestProject2/output/75583f20a922ab2e.deps.json create mode 100644 Test/TestProject2/output/9dbecd0942a39782.deps.json delete mode 100644 Test/TestProject2/output/a7dab00d979c009c.deps.json create mode 100644 Test/TestProject2/output/abf9ce3160c9279e.deps.json create mode 100644 Test/TestProject2/output/b5f1dc665c52a1bd.deps.json create mode 100644 Test/TestProject2/output/bbdf3bbd4c3bc28c.deps.json create mode 100644 Test/TestProject2/output/c9d54a4158f7f5a8.deps.json create mode 100644 Test/TestProject2/output/c9f4be41ca1cc2b4.deps.json create mode 100644 Test/TestProject2/output/cc436a125bbaf28c.deps.json create mode 100644 Test/TestProject2/output/fa3691e66b426950.deps.json delete mode 100644 Test/TestProject2/output/faec3233d98371da.deps.json create mode 100644 Test/TestProject2/temp/067c78e9f121dce3.pyi rename Test/{TestProject3/temp/68c4fe4b12c908e3.pyi => TestProject2/temp/0991af0d22263577.pyi} (98%) rename Test/{TestProject/temp/8f88a3374d5335cc.pyi => TestProject2/temp/257e074b935c33b4.pyi} (69%) rename Test/{ZlibTest => TestProject2}/temp/29813d57621099a9.pyi (100%) create mode 100644 Test/TestProject2/temp/49bd8cba55979f76.pyi rename Test/{TestProject/temp/58121a0fb0ca7466.pyi => TestProject2/temp/541a1ed9b8be53c8.pyi} (72%) delete mode 100644 Test/TestProject2/temp/56cdd754a8a09347.pyi rename Test/{TestProject/temp/f9629b8eb4ebdcc2.pyi => TestProject2/temp/59d33b6ab0c70953.pyi} (100%) create mode 100644 Test/TestProject2/temp/5a6a2137958c28c5.pyi create mode 100644 Test/TestProject2/temp/6c2029b306556c00.pyi rename Test/{TestProject/temp/88e3e48eab9e1653.pyi => TestProject2/temp/6ff26590374ae6fc.pyi} (69%) create mode 100644 Test/TestProject2/temp/72e2d5ccb7cedcf1.pyi rename Test/{TestProject/temp/b0267503e816efc4.pyi => TestProject2/temp/73c1586b83e9b5c2.pyi} (91%) rename Test/{TestProject/temp/0d13cde396f4a15f.pyi => TestProject2/temp/73fcdc4dd1618580.pyi} (80%) delete mode 100644 Test/TestProject2/temp/75583f20a922ab2e.pyi rename Test/{TestProject/temp/4638d411fd53fef0.pyi => TestProject2/temp/8ebed83a7817fa0c.pyi} (85%) rename Test/{TestProject => TestProject2}/temp/96837bcc64032444.pyi (100%) create mode 100644 Test/TestProject2/temp/9dbecd0942a39782.pyi create mode 100644 Test/TestProject2/temp/_shared_sym.json delete mode 100644 Test/TestProject2/temp/_shared_sym.pkl delete mode 100644 Test/TestProject2/temp/a7dab00d979c009c.pyi create mode 100644 Test/TestProject2/temp/abf9ce3160c9279e.pyi create mode 100644 Test/TestProject2/temp/b5f1dc665c52a1bd.pyi create mode 100644 Test/TestProject2/temp/bbdf3bbd4c3bc28c.pyi rename Test/{TestProject/temp/d282a7cb3385ecf0.pyi => TestProject2/temp/c39cbbae4b6e264f.pyi} (98%) rename Test/{TestProject/temp/0d4517fd5afeb330.pyi => TestProject2/temp/c9d54a4158f7f5a8.pyi} (76%) create mode 100644 Test/TestProject2/temp/c9f4be41ca1cc2b4.pyi rename Test/{TestProject/temp/94496ec50b0d13fc.pyi => TestProject2/temp/cc436a125bbaf28c.pyi} (76%) rename Test/{TestProject/temp/a9fa0f6200c09e65.pyi => TestProject2/temp/cd520d14822f3f19.pyi} (89%) rename Test/{TestProject/temp/2d7f623c6e3004ce.pyi => TestProject2/temp/f80740e7bcee16ae.pyi} (100%) create mode 100644 Test/TestProject2/temp/fa3691e66b426950.pyi delete mode 100644 Test/TestProject2/temp/faec3233d98371da.pyi create mode 100644 Test/TestProject3/output/0991af0d22263577.deps.json delete mode 100644 Test/TestProject3/output/0f4d14c17bf75b10.deps.json delete mode 100644 Test/TestProject3/output/2953a7db4185005b.deps.json delete mode 100644 Test/TestProject3/output/5325ec533a59d71b.deps.json delete mode 100644 Test/TestProject3/output/68c4fe4b12c908e3.deps.json delete mode 100644 Test/TestProject3/output/6aee24fdefa3cbc0.deps.json create mode 100644 Test/TestProject3/output/70b580331b822117.deps.json create mode 100644 Test/TestProject3/output/9dbecd0942a39782.deps.json create mode 100644 Test/TestProject3/output/b235d6477436c524.deps.json create mode 100644 Test/TestProject3/output/b5f1dc665c52a1bd.deps.json create mode 100644 Test/TestProject3/output/f8a7f964e23490fb.deps.json create mode 100644 Test/TestProject3/temp/0991af0d22263577.pyi create mode 100644 Test/TestProject3/temp/49bd8cba55979f76.pyi delete mode 100644 Test/TestProject3/temp/56cdd754a8a09347.pyi delete mode 100644 Test/TestProject3/temp/6aee24fdefa3cbc0.pyi rename Test/{VariadicTest/temp/2953a7db4185005b.pyi => TestProject3/temp/70b580331b822117.pyi} (100%) create mode 100644 Test/TestProject3/temp/73edbcf76e32d00b.pyi create mode 100644 Test/TestProject3/temp/9dbecd0942a39782.pyi create mode 100644 Test/TestProject3/temp/_shared_sym.json delete mode 100644 Test/TestProject3/temp/_shared_sym.pkl rename Test/TestProject3/temp/{0f4d14c17bf75b10.pyi => b235d6477436c524.pyi} (99%) create mode 100644 Test/TestProject3/temp/b5f1dc665c52a1bd.pyi rename Test/TestProject3/temp/{5325ec533a59d71b.pyi => f8a7f964e23490fb.pyi} (100%) delete mode 100644 Test/TypeCastTest/output/6aee24fdefa3cbc0.deps.json create mode 100644 Test/TypeCastTest/output/78418cf2ee722f0f.deps.json create mode 100644 Test/TypeCastTest/output/9dbecd0942a39782.deps.json create mode 100644 Test/TypeCastTest/output/b5f1dc665c52a1bd.deps.json delete mode 100644 Test/TypeCastTest/output/bf230611b27080fa.deps.json create mode 100644 Test/TypeCastTest/temp/49bd8cba55979f76.pyi delete mode 100644 Test/TypeCastTest/temp/56cdd754a8a09347.pyi delete mode 100644 Test/TypeCastTest/temp/6aee24fdefa3cbc0.pyi rename Test/TypeCastTest/temp/{bf230611b27080fa.pyi => 78418cf2ee722f0f.pyi} (98%) create mode 100644 Test/TypeCastTest/temp/9dbecd0942a39782.pyi create mode 100644 Test/TypeCastTest/temp/b5f1dc665c52a1bd.pyi create mode 100644 Test/VRandomTest/App/main.py create mode 100644 Test/VRandomTest/output/3f7c5e78d8652535.deps.json create mode 100644 Test/VRandomTest/output/62cc01c2bb770ca3.deps.json create mode 100644 Test/VRandomTest/output/9dbecd0942a39782.deps.json create mode 100644 Test/VRandomTest/output/e24a7f4a875f4518.deps.json create mode 100644 Test/VRandomTest/project.json rename Test/{TestProject => VRandomTest}/temp/3f7c5e78d8652535.pyi (100%) create mode 100644 Test/VRandomTest/temp/49bd8cba55979f76.pyi create mode 100644 Test/VRandomTest/temp/62cc01c2bb770ca3.pyi create mode 100644 Test/VRandomTest/temp/73edbcf76e32d00b.pyi create mode 100644 Test/VRandomTest/temp/9dbecd0942a39782.pyi create mode 100644 Test/VRandomTest/temp/_sha1_map.txt create mode 100644 Test/VRandomTest/temp/e24a7f4a875f4518.pyi delete mode 100644 Test/VariadicTest/output/2953a7db4185005b.deps.json delete mode 100644 Test/VariadicTest/output/377ad03e9b90ac39.deps.json delete mode 100644 Test/VariadicTest/output/6aee24fdefa3cbc0.deps.json create mode 100644 Test/VariadicTest/output/70b580331b822117.deps.json create mode 100644 Test/VariadicTest/output/9dbecd0942a39782.deps.json create mode 100644 Test/VariadicTest/output/b5f1dc665c52a1bd.deps.json create mode 100644 Test/VariadicTest/output/c1416dfae155d6e2.deps.json create mode 100644 Test/VariadicTest/temp/49bd8cba55979f76.pyi delete mode 100644 Test/VariadicTest/temp/56cdd754a8a09347.pyi delete mode 100644 Test/VariadicTest/temp/6aee24fdefa3cbc0.pyi create mode 100644 Test/VariadicTest/temp/70b580331b822117.pyi create mode 100644 Test/VariadicTest/temp/9dbecd0942a39782.pyi create mode 100644 Test/VariadicTest/temp/b5f1dc665c52a1bd.pyi rename Test/VariadicTest/temp/{377ad03e9b90ac39.pyi => c1416dfae155d6e2.pyi} (97%) create mode 100644 Test/ZlibTest/output/03b24bc1d9327958.deps.json delete mode 100644 Test/ZlibTest/output/067c78e9f121dce3.deps.json delete mode 100644 Test/ZlibTest/output/0af305ed4e5f787d.deps.json create mode 100644 Test/ZlibTest/output/0f8134f67bdaba8f.deps.json create mode 100644 Test/ZlibTest/output/26e23066e8c7208d.deps.json delete mode 100644 Test/ZlibTest/output/29813d57621099a9.deps.json delete mode 100644 Test/ZlibTest/output/53fa0c913947021f.deps.json delete mode 100644 Test/ZlibTest/output/5a6a2137958c28c5.deps.json create mode 100644 Test/ZlibTest/output/5d8612e70097f0ba.deps.json delete mode 100644 Test/ZlibTest/output/6aee24fdefa3cbc0.deps.json delete mode 100644 Test/ZlibTest/output/72e2d5ccb7cedcf1.deps.json delete mode 100644 Test/ZlibTest/output/7e9fab9c7b47c4db.deps.json delete mode 100644 Test/ZlibTest/output/95e27d852b773ae8.deps.json delete mode 100644 Test/ZlibTest/output/abf9ce3160c9279e.deps.json delete mode 100644 Test/ZlibTest/output/bbdf3bbd4c3bc28c.deps.json delete mode 100644 Test/ZlibTest/output/c9349bf1e8390dd5.deps.json delete mode 100644 Test/ZlibTest/output/dca7ef1d57347738.deps.json delete mode 100644 Test/ZlibTest/output/e00d9854a0d03f4f.deps.json create mode 100644 Test/ZlibTest/output/e445a2bb299d1b7d.deps.json delete mode 100644 Test/ZlibTest/output/f9cd063200178785.deps.json delete mode 100644 Test/ZlibTest/output/fa3691e66b426950.deps.json rename Test/ZlibTest/temp/{dca7ef1d57347738.pyi => 03b24bc1d9327958.pyi} (95%) rename Test/ZlibTest/temp/{7e9fab9c7b47c4db.pyi => 0f8134f67bdaba8f.pyi} (98%) rename Test/ZlibTest/temp/{53fa0c913947021f.pyi => 26e23066e8c7208d.pyi} (100%) create mode 100644 Test/ZlibTest/temp/49bd8cba55979f76.pyi delete mode 100644 Test/ZlibTest/temp/56cdd754a8a09347.pyi rename Test/ZlibTest/temp/{f9cd063200178785.pyi => 5d8612e70097f0ba.pyi} (89%) delete mode 100644 Test/ZlibTest/temp/6aee24fdefa3cbc0.pyi rename Test/ZlibTest/temp/{0af305ed4e5f787d.pyi => 77deeee736684e3e.pyi} (100%) rename Test/ZlibTest/temp/{c9349bf1e8390dd5.pyi => 8407b4239b208bdb.pyi} (91%) create mode 100644 Test/ZlibTest/temp/9dbecd0942a39782.pyi create mode 100644 Test/ZlibTest/temp/_shared_sym.json delete mode 100644 Test/ZlibTest/temp/_shared_sym.pkl create mode 100644 Test/ZlibTest/temp/b5f1dc665c52a1bd.pyi rename Test/ZlibTest/temp/{95e27d852b773ae8.pyi => cb151b297f4ea56d.pyi} (85%) rename Test/ZlibTest/temp/{e00d9854a0d03f4f.pyi => e445a2bb299d1b7d.pyi} (100%) delete mode 100644 Test/fbnq copy 2.py delete mode 100644 Test/fbnq.py delete mode 100644 Test/test.py delete mode 100644 Test/test_out.txt delete mode 100644 Test/test_output.txt create mode 100644 _debug_find.txt create mode 100644 build_log.txt create mode 100644 build_log2.txt create mode 100644 compile_log.txt create mode 100644 compile_output.txt create mode 100644 compile_trace.txt create mode 100644 includes/__builtin.py create mode 100644 includes/_dict.py create mode 100644 includes/_fakeduck.py create mode 100644 includes/_list.py create mode 100644 includes/_variant.py create mode 100644 includes/_withcontent.py create mode 100644 includes/condition.py create mode 100644 includes/ctraits.pyi create mode 100644 includes/event.py create mode 100644 includes/lock.py create mode 100644 includes/mbuddy.py create mode 100644 includes/rwlock.py create mode 100644 includes/testcheck.py create mode 100644 includes/vrandom.py create mode 100644 includes/vthreading.py create mode 100644 stderr.txt create mode 100644 stdout.txt create mode 100644 temp_build_log.txt diff --git a/TODO b/TODO index a381065..b5f0691 100644 --- a/TODO +++ b/TODO @@ -1,7 +1,23 @@ 更复杂的 泛型 函数装饰器 -main 收集 +main 收集(和 导入模块的自动执行) 元类型 @p.set 函数的描述符用装饰器而不是返回值 -崩溃/返回作用域 回调 \ No newline at end of file +崩溃/返回作用域 回调 +假鸭子 +# f-string 自动 snprintf +__doc__ +自动索引 +testcheck默认中文 + +vdebug 工具和 vsdt 工具 +多态 ops 允许单个函数拥有装饰器(可修改,走函数指针) +协程关键字支持 +with出入多态 +哈希表 +内联快速迭代器 +出栈调用函数 +构造函数隐式参数 +小数组直接栈上创建+ i in [xxx] +字符串索引 diff --git a/Test/BuddyTest/App/main.py b/Test/BuddyTest/App/main.py new file mode 100644 index 0000000..83c21b0 --- /dev/null +++ b/Test/BuddyTest/App/main.py @@ -0,0 +1,12 @@ +from stdint import * +import w32.win32console +import t, c +from t import CInt, CExport +import mbuddytest + + +def main() -> CInt | CExport: + w32.win32console.SetConsoleCP(65001) + w32.win32console.SetConsoleOutputCP(65001) + + return mbuddytest.mbuddy_main() diff --git a/Test/BuddyTest/App/mbuddytest.py b/Test/BuddyTest/App/mbuddytest.py new file mode 100644 index 0000000..39ad9ee --- /dev/null +++ b/Test/BuddyTest/App/mbuddytest.py @@ -0,0 +1,535 @@ +import t, c +from t import CInt, CPtr, CChar, CUInt8T, CUInt32T, CUInt64T, CSizeT +import viperlib +import viperio +import stdlib +import mbuddy +import string +import testcheck +import w32.win32process +import w32.win32sync +import w32.win32base + + +# 线程函数: 在共享 MBuddy 上执行 alloc/free (测试 spinlock 线程安全) +def _thread_alloc_free(param: t.CVoid | t.CPtr) -> t.CUInt32T: + bd: mbuddy.MBuddy | t.CPtr = (mbuddy.MBuddy | t.CPtr)(param) + i: CInt + for i in range(100): + p: bytes = bd.alloc(32) + if p != None: + p_c: CUInt8T | CPtr = CPtr(p) + p_c[0] = CUInt8T(i & 0xFF) + bd.free(p) + return 0 + + +def mbuddy_main() -> CInt: + buf: bytes = stdlib.malloc(256) + + testcheck.begin("BuddyTest: 伙伴系统内存分配器测试") + + # === 基础 alloc/free 测试 === + testcheck.section("基础 alloc/free") + arena: bytes = stdlib.malloc(65536) + bd: mbuddy.MBuddy | CPtr = mbuddy.MBuddy(arena, 65536) + + viperlib.snprintf(buf, 256, "stats=%lu, free_count=%lu", bd.stats(), bd.free_count()) + testcheck.info(buf) + + p1: bytes = bd.alloc(16) + p2: bytes = bd.alloc(64) + p3: bytes = bd.alloc(256) + testcheck.check(p1 != None and p2 != None and p3 != None, + "3 allocs OK", "alloc FAILED") + + # 写入数据验证指针可用 + p_c: CUInt8T | CPtr = CPtr(p1) + p_c[0] = CUInt8T(0xAB) + p_c[1] = CUInt8T(0xCD) + viperlib.snprintf(buf, 256, "p1[0]=0x%x p1[1]=0x%x", p_c[0], p_c[1]) + testcheck.info(buf) + testcheck.check(p_c[0] == CUInt8T(0xAB) and p_c[1] == CUInt8T(0xCD), + "write/read OK", "write/read FAILED") + + bd.free(p1) + bd.free(p2) + bd.free(p3) + testcheck.ok("3 frees OK") + + # 释放后验证合并: free_count 应回到 1 (单个大块) + testcheck.check(bd.free_count() == 1, + "coalesce: free_count=1 OK", "coalesce: free_count != 1") + + # 合并后应能分配大块 + big: bytes = bd.alloc(16000) + testcheck.check(big != None, "big alloc OK", "big alloc FAILED") + bd.free(big) + + stdlib.free(arena) + + # === calloc 测试 (验证清零) === + testcheck.section("calloc 清零") + arena2: bytes = stdlib.malloc(4096) + bd2: mbuddy.MBuddy | CPtr = mbuddy.MBuddy(arena2, 4096) + + dirty: bytes = bd2.alloc(64) + d_c: CUInt8T | CPtr = CPtr(dirty) + i: CInt + for i in range(64): + d_c[i] = CUInt8T(0xFF) + bd2.free(dirty) + + cl: bytes = bd2.calloc(8, 8) + if cl != None: + cl_c: CUInt8T | CPtr = CPtr(cl) + all_zero: CInt = 1 + j: CInt + for j in range(64): + if cl_c[j] != 0: + all_zero = 0 + break + testcheck.check(all_zero == 1, "calloc zeroed OK", "calloc NOT zeroed") + bd2.free(cl) + else: + testcheck.fail("calloc FAILED") + + stdlib.free(arena2) + + # === realloc 扩展测试 === + testcheck.section("realloc 扩展") + arena3: bytes = stdlib.malloc(4096) + bd3: mbuddy.MBuddy | CPtr = mbuddy.MBuddy(arena3, 4096) + + rp: bytes = bd3.alloc(32) + rp_c: CUInt8T | CPtr = CPtr(rp) + k: CInt + for k in range(32): + rp_c[k] = CUInt8T(k + 1) + + rp2: bytes = bd3.realloc(rp, 128) + if rp2 != None: + rp2_c: CUInt8T | CPtr = CPtr(rp2) + ok: CInt = 1 + m: CInt + for m in range(32): + if rp2_c[m] != CUInt8T(m + 1): + ok = 0 + break + testcheck.check(ok == 1, "realloc grow data preserved OK", "realloc grow data LOST") + bd3.free(rp2) + else: + testcheck.fail("realloc grow FAILED") + + stdlib.free(arena3) + + # === 原地收缩测试 (验证无泄漏) === + testcheck.section("原地收缩 (realloc shrink)") + arena_shrink: bytes = stdlib.malloc(4096) + bds: mbuddy.MBuddy | CPtr = mbuddy.MBuddy(arena_shrink, 4096) + + sp: bytes = bds.alloc(256) + testcheck.check(sp != None, "alloc 256 OK", "alloc 256 FAILED") + + fc_before: CSizeT = bds.free_count() + # realloc 到更小尺寸: 256+8=264 -> order 4 (512); 32+8=40 -> order 1 (64) + # new_order(1) <= old_order(4), 应原地返回同一指针 + sp2: bytes = bds.realloc(sp, 32) + fc_after: CSizeT = bds.free_count() + + testcheck.check(sp2 == sp, "shrink same ptr OK", "shrink ptr changed") + testcheck.check(fc_after == fc_before, "shrink no leak OK", "shrink LEAKED blocks") + + # 验证数据仍可读写 + sp_c: CUInt8T | CPtr = CPtr(sp2) + sp_c[0] = CUInt8T(0x42) + testcheck.check(sp_c[0] == CUInt8T(0x42), "shrink data OK", "shrink data FAILED") + + bds.free(sp2) + testcheck.check(bds.free_count() == 1, "shrink+free coalesce OK", "shrink+free coalesce FAILED") + + stdlib.free(arena_shrink) + + # === 边界情况测试 === + testcheck.section("边界情况") + arena4: bytes = stdlib.malloc(4096) + bd4: mbuddy.MBuddy | CPtr = mbuddy.MBuddy(arena4, 4096) + + # alloc(0) 应返回 None + z: bytes = bd4.alloc(0) + testcheck.check(z == None, "alloc(0)=None OK", "alloc(0) should be None") + + # free(None) 应安全 + bd4.free(None) + testcheck.ok("free(None) safe") + + # realloc(None, size) 等价于 alloc + rn: bytes = bd4.realloc(None, 32) + testcheck.check(rn != None, "realloc(None)=alloc OK", "realloc(None) FAILED") + bd4.free(rn) + + # realloc(ptr, 0) 等价于 free + rz: bytes = bd4.alloc(32) + rz2: bytes = bd4.realloc(rz, 0) + testcheck.check(rz2 == None, "realloc(ptr,0)=free OK", "realloc(ptr,0) should be None") + + stdlib.free(arena4) + + # === 非法指针防护测试 === + testcheck.section("非法指针防护") + arena5: bytes = stdlib.malloc(4096) + bd5: mbuddy.MBuddy | CPtr = mbuddy.MBuddy(arena5, 4096) + + valid: bytes = bd5.alloc(32) + testcheck.check(valid != None, "alloc for illegal test OK", "alloc FAILED") + + # 1. free 随机地址 (地址 1) + bd5.free(t.CVoid(t.CUInt64T(1), t.CPtr)) + testcheck.ok("free(addr=1) ignored") + + # 2. free NULL + bd5.free(None) + testcheck.ok("free(NULL) ignored") + + # 3. free 越界指针 (arena 之前) + bd5.free(t.CVoid(t.CUInt64T(arena5), t.CPtr)) + testcheck.ok("free(before arena) ignored") + + # 4. free 越界指针 (arena 之后) + bd5.free(t.CVoid(t.CUInt64T(arena5) + 99999, t.CPtr)) + testcheck.ok("free(after arena) ignored") + + # 5. free 未对齐指针 (arena + 1, 在 mem 区域内但不对齐) + bd5.free(t.CVoid(t.CUInt64T(bd5.mem) + 1, t.CPtr)) + testcheck.ok("free(misaligned) ignored") + + # 6. 验证合法 free 仍正常工作 (释放后应能再次分配) + bd5.free(valid) + retry5: bytes = bd5.alloc(32) + testcheck.check(retry5 != None, "valid free still works OK", "valid free BROKEN") + if retry5 != None: + bd5.free(retry5) + + # 7. realloc 非法指针应返回 None + r_illegal: bytes = bd5.realloc(t.CVoid(t.CUInt64T(1), t.CPtr), 64) + testcheck.check(r_illegal == None, "realloc(illegal)=None OK", "realloc(illegal) should be None") + + stdlib.free(arena5) + + # === OOM 内存耗尽测试 === + testcheck.section("OOM 内存耗尽") + arena6: bytes = stdlib.malloc(4096) + bd6: mbuddy.MBuddy | CPtr = mbuddy.MBuddy(arena6, 4096) + + # 持续分配直到失败 + alloc_count: CInt = 0 + ptrs_arr: bytes = stdlib.malloc(8 * 256) # 存储指针的数组 + ptrs: CUInt64T | CPtr = CPtr(ptrs_arr) + + while alloc_count < 256: + p: bytes = bd6.alloc(32) + if p == None: + break + ptrs[alloc_count] = t.CUInt64T(p) + alloc_count += 1 + + viperlib.snprintf(buf, 256, "allocated %d blocks before OOM", alloc_count) + testcheck.info(buf) + testcheck.check(alloc_count > 0, "OOM: got some allocs OK", "OOM: no allocs at all") + + # 尝试再分配应失败 + oom_p: bytes = bd6.alloc(32) + testcheck.check(oom_p == None, "OOM: alloc fails OK", "OOM: alloc should fail") + + # 释放一个块后应能再次分配 + if alloc_count > 0: + first_ptr: bytes = t.CVoid(ptrs[0], t.CPtr) + bd6.free(first_ptr) + retry: bytes = bd6.alloc(32) + testcheck.check(retry != None, "OOM: free+alloc OK", "OOM: free+alloc FAILED") + if retry != None: + bd6.free(retry) + + # 释放所有块 + idx: CInt = 1 + while idx < alloc_count: + cur_p: bytes = t.CVoid(ptrs[idx], t.CPtr) + bd6.free(cur_p) + idx += 1 + + # 全部释放后应能合并回单个大块 + testcheck.check(bd6.free_count() == 1, + "OOM: full coalesce OK", "OOM: free_count != 1 after full free") + + stdlib.free(ptrs_arr) + stdlib.free(arena6) + + # === 空闲链表状态测试 === + testcheck.section("空闲链表状态") + arena7: bytes = stdlib.malloc(4096) + bd7: mbuddy.MBuddy | CPtr = mbuddy.MBuddy(arena7, 4096) + + # 初始: 1 个大块 + testcheck.check(bd7.free_count() == 1, "init: 1 free block OK", "init: free_count != 1") + + # 分配后: 空闲块数应增加 (分裂产生多个小块) + a1: bytes = bd7.alloc(32) + fc1: CSizeT = bd7.free_count() + viperlib.snprintf(buf, 256, "after alloc(32): free_count=%lu", fc1) + testcheck.info(buf) + testcheck.check(fc1 > 1, "after alloc: split OK", "after alloc: no split") + + # 再分配 + a2: bytes = bd7.alloc(32) + fc2: CSizeT = bd7.free_count() + testcheck.check(fc2 >= 1, "after 2nd alloc: free >= 1 OK", "after 2nd alloc: free < 1") + + # 释放 a1: 空闲块数应增加 + bd7.free(a1) + fc3: CSizeT = bd7.free_count() + testcheck.check(fc3 > fc2, "after free a1: free increased OK", "after free a1: free not increased") + + # 释放 a2: 应合并, 空闲块数回到 1 + bd7.free(a2) + testcheck.check(bd7.free_count() == 1, + "after free all: coalesced to 1 OK", "after free all: free_count != 1") + + stdlib.free(arena7) + + # === with 上下文管理器测试 === + testcheck.section("with 上下文管理器") + arena8: bytes = stdlib.malloc(4096) + with mbuddy.MBuddy(arena8, 4096) as wbd: + wp1: bytes = wbd.alloc(32) + wp2: bytes = wbd.alloc(64) + testcheck.check(wp1 != None and wp2 != None, + "with: allocs OK", "with: allocs FAILED") + # 退出 with 块时 __exit__ 自动 reset + + # 退出后重新进入,验证 reset 生效 + with mbuddy.MBuddy(arena8, 4096) as wbd2: + wp3: bytes = wbd2.alloc(1024) + testcheck.check(wp3 != None, "with: reset+realloc OK", "with: reset+realloc FAILED") + + stdlib.free(arena8) + + # === 双重 free 检测测试 === + testcheck.section("双重 free 检测") + arena_df: bytes = stdlib.malloc(4096) + bd_df: mbuddy.MBuddy | CPtr = mbuddy.MBuddy(arena_df, 4096) + + df: bytes = bd_df.alloc(64) + testcheck.check(df != None, "df: alloc OK", "df: alloc FAILED") + + # 第一次 free + bd_df.free(df) + fc_df1: CSizeT = bd_df.free_count() + testcheck.ok("first free OK") + + # 第二次 free (双重 free) — 应被静默拒绝 + bd_df.free(df) + fc_df2: CSizeT = bd_df.free_count() + testcheck.check(fc_df2 == fc_df1, "double free rejected OK", "double free CORRUPTED state") + + # 验证分配器仍正常工作 + df2: bytes = bd_df.alloc(64) + testcheck.check(df2 != None, "df: alloc after double-free OK", "df: alloc after double-free FAILED") + if df2 != None: + bd_df.free(df2) + + stdlib.free(arena_df) + + # === 自检功能测试 === + testcheck.section("自检功能") + arena_sc: bytes = stdlib.malloc(4096) + bd_sc: mbuddy.MBuddy | CPtr = mbuddy.MBuddy(arena_sc, 4096) + + # 初始状态自检 + testcheck.check(bd_sc.self_check() == 0, "self_check init OK", "self_check init FAILED") + + # 分配后自检 + sc_p1: bytes = bd_sc.alloc(32) + sc_p2: bytes = bd_sc.alloc(128) + testcheck.check(bd_sc.self_check() == 0, "self_check after alloc OK", "self_check after alloc FAILED") + + # 部分释放后自检 + bd_sc.free(sc_p1) + testcheck.check(bd_sc.self_check() == 0, "self_check after partial free OK", "self_check after partial free FAILED") + + # 全部释放后自检 (应合并回单个大块) + bd_sc.free(sc_p2) + testcheck.check(bd_sc.self_check() == 0, "self_check after full free OK", "self_check after full free FAILED") + + # 双重 free 后自检 (验证状态未损坏) + sc_p3: bytes = bd_sc.alloc(64) + bd_sc.free(sc_p3) + bd_sc.free(sc_p3) # 双重 free,应被拒绝 + testcheck.check(bd_sc.self_check() == 0, "self_check after double-free OK", "self_check after double-free CORRUPTED") + + stdlib.free(arena_sc) + + # === 并发多线程测试 (spinlock) === + testcheck.section("并发多线程 (spinlock)") + arena_mt: bytes = stdlib.malloc(65536) + bd_mt: mbuddy.MBuddy | CPtr = mbuddy.MBuddy(arena_mt, 65536) + + NUM_THREADS: CInt = 4 + handles_arr: bytes = stdlib.malloc(8 * 4) + handles: CUInt64T | CPtr = CPtr(handles_arr) + tid: CUInt32T = 0 + + # 创建 4 个线程并发 alloc/free + t_idx: CInt + for t_idx in range(NUM_THREADS): + h: bytes = w32.win32process.CreateThread(None, 0, _thread_alloc_free, t.CVoid(t.CUInt64T(bd_mt), t.CPtr), 0, c.Addr(tid)) + handles[t_idx] = CUInt64T(h) + + # 等待所有线程完成 + for t_idx in range(NUM_THREADS): + h: bytes = t.CVoid(handles[t_idx], t.CPtr) + w32.win32sync.WaitForSingleObject(h, w32.win32base.INFINITE) + w32.win32base.CloseHandle(h) + + # 验证分配器状态: 自检通过,所有块已合并 + testcheck.check(bd_mt.self_check() == 0, "mt: self_check OK", "mt: self_check FAILED") + testcheck.check(bd_mt.free_count() == 1, "mt: free_count=1 OK", "mt: free_count != 1 (leaked)") + + viperlib.snprintf(buf, 256, "mt: free_count=%lu", bd_mt.free_count()) + testcheck.info(buf) + + stdlib.free(handles_arr) + stdlib.free(arena_mt) + + # === 极端边界测试 === + testcheck.section("极端边界") + + # 1. 分配尺寸恰巧是块边界 + arena_ex: bytes = stdlib.malloc(4096) + bd_ex: mbuddy.MBuddy | CPtr = mbuddy.MBuddy(arena_ex, 4096) + + # 24 + 8 = 32 = MIN_BLOCK, 恰好填满 order 0 块 + exact_fit: bytes = bd_ex.alloc(24) + testcheck.check(exact_fit != None, "exact fit order 0 OK", "exact fit order 0 FAILED") + + # 25 + 8 = 33 > 32, 需要 order 1 (64 字节) + over_fit: bytes = bd_ex.alloc(25) + testcheck.check(over_fit != None, "over by 1 byte OK", "over by 1 byte FAILED") + + bd_ex.free(exact_fit) + bd_ex.free(over_fit) + testcheck.check(bd_ex.free_count() == 1, "boundary: coalesce OK", "boundary: coalesce FAILED") + + # 2. 单次分配接近 arena 上限 + max_usable: CSizeT = bd_ex.mem_size - 8 + viperlib.snprintf(buf, 256, "mem_size=%lu, max_usable=%lu", bd_ex.mem_size, max_usable) + testcheck.info(buf) + + # 恰好用完整个 arena + exact_max: bytes = bd_ex.alloc(max_usable) + testcheck.check(exact_max != None, "exact max alloc OK", "exact max alloc FAILED") + testcheck.check(bd_ex.free_count() == 0, "max alloc: arena full OK", "max alloc: arena not full") + + bd_ex.free(exact_max) + testcheck.check(bd_ex.free_count() == 1, "max free: coalesce OK", "max free: coalesce FAILED") + + # 再次分配同样大小 — 验证合并后可再次使用 + exact_max2: bytes = bd_ex.alloc(max_usable) + testcheck.check(exact_max2 != None, "exact max re-alloc OK", "exact max re-alloc FAILED") + bd_ex.free(exact_max2) + + # 3. 分配超过 arena 上限 — 应失败 + over_max: bytes = bd_ex.alloc(bd_ex.mem_size) + testcheck.check(over_max == None, "over max: fails OK", "over max: should fail") + + over_max2: bytes = bd_ex.alloc(max_usable + 1) + testcheck.check(over_max2 == None, "max+1: fails OK", "max+1: should fail") + + stdlib.free(arena_ex) + + # 4. Arena 太小 (仅够 free_lists 开销, 264 字节) + arena_tiny: bytes = stdlib.malloc(264) + bd_tiny: mbuddy.MBuddy | CPtr = mbuddy.MBuddy(arena_tiny, 264) + testcheck.check(bd_tiny.stats() == 0, "tiny arena: stats=0 OK", "tiny arena: stats != 0") + tiny_p: bytes = bd_tiny.alloc(32) + testcheck.check(tiny_p == None, "tiny arena: alloc fails OK", "tiny arena: should fail") + stdlib.free(arena_tiny) + + # 5. Arena 刚好够一个最小块 (264 + 32 = 296) + arena_one: bytes = stdlib.malloc(296) + bd_one: mbuddy.MBuddy | CPtr = mbuddy.MBuddy(arena_one, 296) + testcheck.check(bd_one.stats() == 32, "one block: stats=32 OK", "one block: stats != 32") + + one_p: bytes = bd_one.alloc(24) + testcheck.check(one_p != None, "one block: alloc OK", "one block: alloc FAILED") + + one_p2: bytes = bd_one.alloc(24) + testcheck.check(one_p2 == None, "one block: OOM OK", "one block: should be OOM") + + bd_one.free(one_p) + testcheck.check(bd_one.free_count() == 1, "one block: free OK", "one block: free FAILED") + stdlib.free(arena_one) + + # 6. 2 的幂 arena vs 非 2 的幂 arena + arena_pow2: bytes = stdlib.malloc(512) + bd_pow2: mbuddy.MBuddy | CPtr = mbuddy.MBuddy(arena_pow2, 512) + # 512 - 264 = 248, largest_pow2(248) = 128 + testcheck.check(bd_pow2.stats() == 128, "pow2 arena: stats=128 OK", "pow2 arena: stats != 128") + stdlib.free(arena_pow2) + + arena_non2: bytes = stdlib.malloc(500) + bd_non2: mbuddy.MBuddy | CPtr = mbuddy.MBuddy(arena_non2, 500) + # 500 - 264 = 236, largest_pow2(236) = 128 + testcheck.check(bd_non2.stats() == 128, "non-pow2 arena: stats=128 OK", "non-pow2 arena: stats != 128") + stdlib.free(arena_non2) + + # 7. 压力测试: 反复 alloc/free 同一尺寸 1000 次 + arena_stress: bytes = stdlib.malloc(4096) + bd_stress: mbuddy.MBuddy | CPtr = mbuddy.MBuddy(arena_stress, 4096) + + s: CInt + for s in range(1000): + sp: bytes = bd_stress.alloc(64) + if sp != None: + sp_c: CUInt8T | CPtr = CPtr(sp) + sp_c[0] = CUInt8T(s & 0xFF) + bd_stress.free(sp) + + testcheck.check(bd_stress.self_check() == 0, "stress: self_check OK", "stress: self_check FAILED") + testcheck.check(bd_stress.free_count() == 1, "stress: free_count=1 OK", "stress: leaked") + stdlib.free(arena_stress) + + # 8. 分配全部最小块然后全部释放 + arena_fill: bytes = stdlib.malloc(4096) + bd_fill: mbuddy.MBuddy | CPtr = mbuddy.MBuddy(arena_fill, 4096) + + fill_count: CInt = 0 + fill_ptrs_arr: bytes = stdlib.malloc(8 * 256) + fill_ptrs: CUInt64T | CPtr = CPtr(fill_ptrs_arr) + + fc: CInt + for fc in range(256): + fp: bytes = bd_fill.alloc(24) + if fp == None: + break + fill_ptrs[fill_count] = t.CUInt64T(fp) + fill_count += 1 + + viperlib.snprintf(buf, 256, "fill: %d min blocks allocated", fill_count) + testcheck.info(buf) + testcheck.check(fill_count > 0, "fill: got blocks OK", "fill: no blocks") + testcheck.check(bd_fill.self_check() == 0, "fill: self_check OK", "fill: self_check FAILED") + + # 全部释放 + fi: CInt + for fi in range(fill_count): + fp2: bytes = t.CVoid(fill_ptrs[fi], t.CPtr) + bd_fill.free(fp2) + + testcheck.check(bd_fill.free_count() == 1, "fill: all freed OK", "fill: leaked after free all") + testcheck.check(bd_fill.self_check() == 0, "fill: self_check after free OK", "fill: self_check FAILED") + + stdlib.free(fill_ptrs_arr) + stdlib.free(arena_fill) + + stdlib.free(buf) + return testcheck.end() diff --git a/Test/BuddyTest/output/067c78e9f121dce3.deps.json b/Test/BuddyTest/output/067c78e9f121dce3.deps.json new file mode 100644 index 0000000..df6cb25 --- /dev/null +++ b/Test/BuddyTest/output/067c78e9f121dce3.deps.json @@ -0,0 +1 @@ +{"w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "atom": "271ea3decb810db2", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "main": "5e430ae5bf7af3a2", "stdlib": "6c2029b306556c00", "viperlib": "70b580331b822117", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "mbuddytest": "c53a157505aa8081", "viperio": "c9f4be41ca1cc2b4", "mbuddy": "e1937873ebfba8c3", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1"} \ No newline at end of file diff --git a/Test/BuddyTest/output/271ea3decb810db2.deps.json b/Test/BuddyTest/output/271ea3decb810db2.deps.json new file mode 100644 index 0000000..c9395e8 --- /dev/null +++ b/Test/BuddyTest/output/271ea3decb810db2.deps.json @@ -0,0 +1 @@ +{"w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "atom": "271ea3decb810db2", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "main": "5e430ae5bf7af3a2", "stdlib": "6c2029b306556c00", "viperlib": "70b580331b822117", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "mbuddytest": "c53a157505aa8081", "viperio": "c9f4be41ca1cc2b4", "mbuddy": "e1937873ebfba8c3"} \ No newline at end of file diff --git a/Test/BuddyTest/output/29813d57621099a9.deps.json b/Test/BuddyTest/output/29813d57621099a9.deps.json new file mode 100644 index 0000000..df6cb25 --- /dev/null +++ b/Test/BuddyTest/output/29813d57621099a9.deps.json @@ -0,0 +1 @@ +{"w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "atom": "271ea3decb810db2", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "main": "5e430ae5bf7af3a2", "stdlib": "6c2029b306556c00", "viperlib": "70b580331b822117", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "mbuddytest": "c53a157505aa8081", "viperio": "c9f4be41ca1cc2b4", "mbuddy": "e1937873ebfba8c3", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1"} \ No newline at end of file diff --git a/Test/BuddyTest/output/5a6a2137958c28c5.deps.json b/Test/BuddyTest/output/5a6a2137958c28c5.deps.json new file mode 100644 index 0000000..c9395e8 --- /dev/null +++ b/Test/BuddyTest/output/5a6a2137958c28c5.deps.json @@ -0,0 +1 @@ +{"w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "atom": "271ea3decb810db2", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "main": "5e430ae5bf7af3a2", "stdlib": "6c2029b306556c00", "viperlib": "70b580331b822117", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "mbuddytest": "c53a157505aa8081", "viperio": "c9f4be41ca1cc2b4", "mbuddy": "e1937873ebfba8c3"} \ No newline at end of file diff --git a/Test/BuddyTest/output/5e430ae5bf7af3a2.deps.json b/Test/BuddyTest/output/5e430ae5bf7af3a2.deps.json new file mode 100644 index 0000000..ba25294 --- /dev/null +++ b/Test/BuddyTest/output/5e430ae5bf7af3a2.deps.json @@ -0,0 +1 @@ +{"w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "atom": "271ea3decb810db2", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "viperlib": "70b580331b822117", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "mbuddytest": "c53a157505aa8081", "viperio": "c9f4be41ca1cc2b4", "mbuddy": "e1937873ebfba8c3"} \ No newline at end of file diff --git a/Test/BuddyTest/output/70b580331b822117.deps.json b/Test/BuddyTest/output/70b580331b822117.deps.json new file mode 100644 index 0000000..c9395e8 --- /dev/null +++ b/Test/BuddyTest/output/70b580331b822117.deps.json @@ -0,0 +1 @@ +{"w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "atom": "271ea3decb810db2", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "main": "5e430ae5bf7af3a2", "stdlib": "6c2029b306556c00", "viperlib": "70b580331b822117", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "mbuddytest": "c53a157505aa8081", "viperio": "c9f4be41ca1cc2b4", "mbuddy": "e1937873ebfba8c3"} \ No newline at end of file diff --git a/Test/BuddyTest/output/72e2d5ccb7cedcf1.deps.json b/Test/BuddyTest/output/72e2d5ccb7cedcf1.deps.json new file mode 100644 index 0000000..df6cb25 --- /dev/null +++ b/Test/BuddyTest/output/72e2d5ccb7cedcf1.deps.json @@ -0,0 +1 @@ +{"w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "atom": "271ea3decb810db2", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "main": "5e430ae5bf7af3a2", "stdlib": "6c2029b306556c00", "viperlib": "70b580331b822117", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "mbuddytest": "c53a157505aa8081", "viperio": "c9f4be41ca1cc2b4", "mbuddy": "e1937873ebfba8c3", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1"} \ No newline at end of file diff --git a/Test/BuddyTest/output/9dbecd0942a39782.deps.json b/Test/BuddyTest/output/9dbecd0942a39782.deps.json new file mode 100644 index 0000000..c9395e8 --- /dev/null +++ b/Test/BuddyTest/output/9dbecd0942a39782.deps.json @@ -0,0 +1 @@ +{"w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "atom": "271ea3decb810db2", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "main": "5e430ae5bf7af3a2", "stdlib": "6c2029b306556c00", "viperlib": "70b580331b822117", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "mbuddytest": "c53a157505aa8081", "viperio": "c9f4be41ca1cc2b4", "mbuddy": "e1937873ebfba8c3"} \ No newline at end of file diff --git a/Test/BuddyTest/output/abf9ce3160c9279e.deps.json b/Test/BuddyTest/output/abf9ce3160c9279e.deps.json new file mode 100644 index 0000000..07af4b4 --- /dev/null +++ b/Test/BuddyTest/output/abf9ce3160c9279e.deps.json @@ -0,0 +1 @@ +{"w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "atom": "271ea3decb810db2", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "main": "5e430ae5bf7af3a2", "stdlib": "6c2029b306556c00", "viperlib": "70b580331b822117", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "mbuddytest": "c53a157505aa8081", "viperio": "c9f4be41ca1cc2b4", "mbuddy": "e1937873ebfba8c3", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e"} \ No newline at end of file diff --git a/Test/BuddyTest/output/b5f1dc665c52a1bd.deps.json b/Test/BuddyTest/output/b5f1dc665c52a1bd.deps.json new file mode 100644 index 0000000..c9395e8 --- /dev/null +++ b/Test/BuddyTest/output/b5f1dc665c52a1bd.deps.json @@ -0,0 +1 @@ +{"w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "atom": "271ea3decb810db2", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "main": "5e430ae5bf7af3a2", "stdlib": "6c2029b306556c00", "viperlib": "70b580331b822117", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "mbuddytest": "c53a157505aa8081", "viperio": "c9f4be41ca1cc2b4", "mbuddy": "e1937873ebfba8c3"} \ No newline at end of file diff --git a/Test/BuddyTest/output/bbdf3bbd4c3bc28c.deps.json b/Test/BuddyTest/output/bbdf3bbd4c3bc28c.deps.json new file mode 100644 index 0000000..c9395e8 --- /dev/null +++ b/Test/BuddyTest/output/bbdf3bbd4c3bc28c.deps.json @@ -0,0 +1 @@ +{"w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "atom": "271ea3decb810db2", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "main": "5e430ae5bf7af3a2", "stdlib": "6c2029b306556c00", "viperlib": "70b580331b822117", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "mbuddytest": "c53a157505aa8081", "viperio": "c9f4be41ca1cc2b4", "mbuddy": "e1937873ebfba8c3"} \ No newline at end of file diff --git a/Test/BuddyTest/output/c53a157505aa8081.deps.json b/Test/BuddyTest/output/c53a157505aa8081.deps.json new file mode 100644 index 0000000..df11c14 --- /dev/null +++ b/Test/BuddyTest/output/c53a157505aa8081.deps.json @@ -0,0 +1 @@ +{"w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "atom": "271ea3decb810db2", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "main": "5e430ae5bf7af3a2", "stdlib": "6c2029b306556c00", "viperlib": "70b580331b822117", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "viperio": "c9f4be41ca1cc2b4", "mbuddy": "e1937873ebfba8c3"} \ No newline at end of file diff --git a/Test/BuddyTest/output/c9f4be41ca1cc2b4.deps.json b/Test/BuddyTest/output/c9f4be41ca1cc2b4.deps.json new file mode 100644 index 0000000..c9395e8 --- /dev/null +++ b/Test/BuddyTest/output/c9f4be41ca1cc2b4.deps.json @@ -0,0 +1 @@ +{"w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "atom": "271ea3decb810db2", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "main": "5e430ae5bf7af3a2", "stdlib": "6c2029b306556c00", "viperlib": "70b580331b822117", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "mbuddytest": "c53a157505aa8081", "viperio": "c9f4be41ca1cc2b4", "mbuddy": "e1937873ebfba8c3"} \ No newline at end of file diff --git a/Test/BuddyTest/output/e1937873ebfba8c3.deps.json b/Test/BuddyTest/output/e1937873ebfba8c3.deps.json new file mode 100644 index 0000000..c9395e8 --- /dev/null +++ b/Test/BuddyTest/output/e1937873ebfba8c3.deps.json @@ -0,0 +1 @@ +{"w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "atom": "271ea3decb810db2", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "main": "5e430ae5bf7af3a2", "stdlib": "6c2029b306556c00", "viperlib": "70b580331b822117", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "mbuddytest": "c53a157505aa8081", "viperio": "c9f4be41ca1cc2b4", "mbuddy": "e1937873ebfba8c3"} \ No newline at end of file diff --git a/Test/BuddyTest/output/fa3691e66b426950.deps.json b/Test/BuddyTest/output/fa3691e66b426950.deps.json new file mode 100644 index 0000000..7c13893 --- /dev/null +++ b/Test/BuddyTest/output/fa3691e66b426950.deps.json @@ -0,0 +1 @@ +{"w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "atom": "271ea3decb810db2", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "main": "5e430ae5bf7af3a2", "stdlib": "6c2029b306556c00", "viperlib": "70b580331b822117", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "mbuddytest": "c53a157505aa8081", "viperio": "c9f4be41ca1cc2b4", "mbuddy": "e1937873ebfba8c3", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file diff --git a/Test/BuddyTest/project.json b/Test/BuddyTest/project.json new file mode 100644 index 0000000..8b76992 --- /dev/null +++ b/Test/BuddyTest/project.json @@ -0,0 +1,29 @@ +{ + "$schema": "https://raw.githubusercontent.com/TermiNexus/TransPyC/main/schemas/project-schema.json", + "name": "BuddyTest", + "version": "1.0.0", + "source_dir": "./App", + "temp_dir": "./temp", + "output_dir": "./output", + "compiler": { + "cmd": "llc", + "flags": ["-filetype=obj", "-relocation-model=pic"] + }, + "linker": { + "cmd": "clang++", + "flags": ["-lmsvcrt", "-lucrt", "-lpthread", "-lmingwex", "-lkernel32", "-Wl,--allow-multiple-definition"], + "output": "BuddyTest.exe" + }, + "includes": [ + "./includes" + ], + "target": { + "triple": "x86_64-pc-windows-gnu", + "datalayout": "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" + }, + "options": { + "slice_level": 3, + "target": "llvm", + "strict_mode": true + } +} diff --git a/Test/TestProject/temp/067c78e9f121dce3.pyi b/Test/BuddyTest/temp/067c78e9f121dce3.pyi similarity index 100% rename from Test/TestProject/temp/067c78e9f121dce3.pyi rename to Test/BuddyTest/temp/067c78e9f121dce3.pyi diff --git a/Test/BuddyTest/temp/271ea3decb810db2.pyi b/Test/BuddyTest/temp/271ea3decb810db2.pyi new file mode 100644 index 0000000..3d637bf --- /dev/null +++ b/Test/BuddyTest/temp/271ea3decb810db2.pyi @@ -0,0 +1,26 @@ +""" +Auto-generated Python stub file from atom.py +Module: atom +""" + + +import t, c + +ATOMIC_RELAXED: t.CDefine = 0 +ATOMIC_CONSUME: t.CDefine = 1 +ATOMIC_ACQUIRE: t.CDefine = 2 +ATOMIC_RELEASE: t.CDefine = 3 +ATOMIC_ACQ_REL: t.CDefine = 4 +ATOMIC_SEQ_CST: t.CDefine = 5 + +def __atomic_test_and_set(ptr: t.CUInt64T | t.CPtr, order: t.CInt) -> t.CBool: pass + +def __atomic_clear(ptr: t.CUInt64T | t.CPtr, order: t.CInt) -> t.CVoid: pass + +def __atomic_thread_fence(order: t.CInt) -> t.CVoid: pass + +def __atomic_signal_fence(order: t.CInt) -> t.CVoid: pass + +def __atomic_always_lock_free(size: t.CSizeT, ptr: t.CVoid | t.CPtr) -> t.CBool: pass + +def __atomic_is_lock_free(size: t.CSizeT, ptr: t.CVoid | t.CPtr) -> t.CBool: pass diff --git a/Test/TestProject/temp/29813d57621099a9.pyi b/Test/BuddyTest/temp/29813d57621099a9.pyi similarity index 100% rename from Test/TestProject/temp/29813d57621099a9.pyi rename to Test/BuddyTest/temp/29813d57621099a9.pyi diff --git a/Test/IterTest/temp/56cdd754a8a09347.pyi b/Test/BuddyTest/temp/49bd8cba55979f76.pyi similarity index 88% rename from Test/IterTest/temp/56cdd754a8a09347.pyi rename to Test/BuddyTest/temp/49bd8cba55979f76.pyi index 007ccb8..f1d844a 100644 --- a/Test/IterTest/temp/56cdd754a8a09347.pyi +++ b/Test/BuddyTest/temp/49bd8cba55979f76.pyi @@ -64,4 +64,12 @@ CHAR16: t.CTypedef = t.CChar16T CHAR32: t.CTypedef = t.CChar32T CHAR8PTR: t.CTypedef = t.CChar8T | t.CPtr CHAR16PTR: t.CTypedef = t.CChar16T | t.CPtr -CHAR32PTR: t.CTypedef = t.CChar32T | t.CPtr \ No newline at end of file +CHAR32PTR: t.CTypedef = t.CChar32T | t.CPtr +i8: t.CTypedef = t.CInt8T +i16: t.CTypedef = t.CInt16T +i32: t.CTypedef = t.CInt32T +i64: t.CTypedef = t.CInt64T +u8: t.CTypedef = t.CUInt8T +u16: t.CTypedef = t.CUInt16T +u32: t.CTypedef = t.CUInt32T +u64: t.CTypedef = t.CUInt64T \ No newline at end of file diff --git a/Test/TestProject/temp/5a6a2137958c28c5.pyi b/Test/BuddyTest/temp/5a6a2137958c28c5.pyi similarity index 100% rename from Test/TestProject/temp/5a6a2137958c28c5.pyi rename to Test/BuddyTest/temp/5a6a2137958c28c5.pyi diff --git a/Test/BuddyTest/temp/5e430ae5bf7af3a2.pyi b/Test/BuddyTest/temp/5e430ae5bf7af3a2.pyi new file mode 100644 index 0000000..bbe03a4 --- /dev/null +++ b/Test/BuddyTest/temp/5e430ae5bf7af3a2.pyi @@ -0,0 +1,13 @@ +""" +Auto-generated Python stub file from main.py +Module: main +""" + + +from stdint import * +import w32.win32console +import t, c +from t import CInt, CExport +import mbuddytest + +def main() -> CInt | CExport: pass diff --git a/Test/TestProject/temp/6c2029b306556c00.pyi b/Test/BuddyTest/temp/6c2029b306556c00.pyi similarity index 100% rename from Test/TestProject/temp/6c2029b306556c00.pyi rename to Test/BuddyTest/temp/6c2029b306556c00.pyi diff --git a/Test/TestProject3/temp/2953a7db4185005b.pyi b/Test/BuddyTest/temp/70b580331b822117.pyi similarity index 100% rename from Test/TestProject3/temp/2953a7db4185005b.pyi rename to Test/BuddyTest/temp/70b580331b822117.pyi diff --git a/Test/BuddyTest/temp/71e0a3ffcb3ebfad.pyi b/Test/BuddyTest/temp/71e0a3ffcb3ebfad.pyi new file mode 100644 index 0000000..574b20e --- /dev/null +++ b/Test/BuddyTest/temp/71e0a3ffcb3ebfad.pyi @@ -0,0 +1,20 @@ +""" +Auto-generated Python stub file from stdarg.py +Module: stdarg +""" + +import c + + +import t + +def va_start(args: t.CPtr, last_arg: t.CPtr) -> t.State: pass + +def va_arg(args: t.CPtr, type: t.CPtr) -> t.CPtr | t.State: pass + +def va_end(args: t.CPtr) -> t.State | t.State: pass + + +va_list: t.CTypedef = t.CUnsignedChar | t.CPtr + +def arg(type: t.CType) -> t.State: pass diff --git a/Test/TestProject/temp/72e2d5ccb7cedcf1.pyi b/Test/BuddyTest/temp/72e2d5ccb7cedcf1.pyi similarity index 100% rename from Test/TestProject/temp/72e2d5ccb7cedcf1.pyi rename to Test/BuddyTest/temp/72e2d5ccb7cedcf1.pyi diff --git a/Test/BuddyTest/temp/73edbcf76e32d00b.pyi b/Test/BuddyTest/temp/73edbcf76e32d00b.pyi new file mode 100644 index 0000000..ef712e3 --- /dev/null +++ b/Test/BuddyTest/temp/73edbcf76e32d00b.pyi @@ -0,0 +1,28 @@ +""" +Auto-generated Python stub file from stdio.py +Module: stdio +""" + + +import t, c + +def printf(fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass + +def fprintf(stream: t.CVoid | t.CPtr, fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass + +def sprintf(buf: t.CChar | t.CPtr, fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass + +def snprintf(buf: t.CChar | t.CPtr, size: t.CSizeT, fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass + +def puts(s: t.CChar | t.CConst | t.CPtr) -> t.CInt | t.CExtern | t.CExport: pass + +def fputs(s: t.CChar | t.CConst | t.CPtr, stream: t.CVoid | t.CPtr) -> t.CInt | t.CExtern | t.CExport: pass + +def fgets(buf: t.CChar | t.CPtr, size: t.CInt, stream: t.CVoid | t.CPtr) -> t.CChar | t.CPtr | t.CExtern | t.CExport: pass + +def fflush(stream: t.CVoid | t.CPtr) -> t.CInt | t.CExtern | t.CExport: pass + + +stdin: t.CExtern | t.CVoid | t.CPtr +stdout: t.CExtern | t.CVoid | t.CPtr +stderr: t.CExtern | t.CVoid | t.CPtr \ No newline at end of file diff --git a/Test/BuddyTest/temp/9dbecd0942a39782.pyi b/Test/BuddyTest/temp/9dbecd0942a39782.pyi new file mode 100644 index 0000000..41648c1 --- /dev/null +++ b/Test/BuddyTest/temp/9dbecd0942a39782.pyi @@ -0,0 +1,25 @@ +""" +Auto-generated Python stub file from testcheck.py +Module: testcheck +""" + + +import t, c +import stdio + +_pass_count: t.CExtern | t.CInt +_fail_count: t.CExtern | t.CInt + +def begin(name: str) -> t.CInt: pass + +def section(name: str) -> t.CInt: pass + +def ok(msg: str) -> t.CInt: pass + +def fail(msg: str) -> t.CInt: pass + +def check(cond: t.CInt, ok_msg: str, fail_msg: str) -> t.CInt: pass + +def info(msg: str) -> t.CInt: pass + +def end() -> t.CInt: pass diff --git a/Test/BuddyTest/temp/_sha1_map.txt b/Test/BuddyTest/temp/_sha1_map.txt new file mode 100644 index 0000000..172c0bf --- /dev/null +++ b/Test/BuddyTest/temp/_sha1_map.txt @@ -0,0 +1,16 @@ +067c78e9f121dce3:includes/w32\win32process.py +271ea3decb810db2:includes/atom.py +29813d57621099a9:includes/w32\win32sync.py +49bd8cba55979f76:includes/stdint.py +5a6a2137958c28c5:includes/w32\win32base.py +5e430ae5bf7af3a2:main.py +6c2029b306556c00:includes/stdlib.py +70b580331b822117:includes/viperlib.py +71e0a3ffcb3ebfad:includes/stdarg.py +73edbcf76e32d00b:includes/stdio.py +9dbecd0942a39782:includes/testcheck.py +b5f1dc665c52a1bd:includes/string.py +bbdf3bbd4c3bc28c:includes/w32\win32console.py +c53a157505aa8081:mbuddytest.py +c9f4be41ca1cc2b4:includes/viperio.py +e1937873ebfba8c3:includes/mbuddy.py diff --git a/Test/BuddyTest/temp/_shared_sym.json b/Test/BuddyTest/temp/_shared_sym.json new file mode 100644 index 0000000..e69de29 diff --git a/Test/TestProject/temp/abf9ce3160c9279e.pyi b/Test/BuddyTest/temp/abf9ce3160c9279e.pyi similarity index 100% rename from Test/TestProject/temp/abf9ce3160c9279e.pyi rename to Test/BuddyTest/temp/abf9ce3160c9279e.pyi diff --git a/Test/JsonTest/temp/6aee24fdefa3cbc0.pyi b/Test/BuddyTest/temp/b5f1dc665c52a1bd.pyi similarity index 94% rename from Test/JsonTest/temp/6aee24fdefa3cbc0.pyi rename to Test/BuddyTest/temp/b5f1dc665c52a1bd.pyi index c17475f..8b6959e 100644 --- a/Test/JsonTest/temp/6aee24fdefa3cbc0.pyi +++ b/Test/BuddyTest/temp/b5f1dc665c52a1bd.pyi @@ -41,4 +41,4 @@ def atoll(src: str) -> t.CInt64T: pass def atof(src: str) -> t.CDouble: pass -def split(s: str, delim: str, result: list[str]) -> int: pass +def split(s: str, delim: str, result: t.CArray[str]) -> int: pass diff --git a/Test/TestProject/temp/bbdf3bbd4c3bc28c.pyi b/Test/BuddyTest/temp/bbdf3bbd4c3bc28c.pyi similarity index 100% rename from Test/TestProject/temp/bbdf3bbd4c3bc28c.pyi rename to Test/BuddyTest/temp/bbdf3bbd4c3bc28c.pyi diff --git a/Test/BuddyTest/temp/c53a157505aa8081.pyi b/Test/BuddyTest/temp/c53a157505aa8081.pyi new file mode 100644 index 0000000..268a742 --- /dev/null +++ b/Test/BuddyTest/temp/c53a157505aa8081.pyi @@ -0,0 +1,21 @@ +""" +Auto-generated Python stub file from mbuddytest.py +Module: mbuddytest +""" + + +import t, c +from t import CInt, CPtr, CChar, CUInt8T, CUInt32T, CUInt64T, CSizeT +import viperlib +import viperio +import stdlib +import mbuddy +import string +import testcheck +import w32.win32process +import w32.win32sync +import w32.win32base + +def _thread_alloc_free(param: t.CVoid | t.CPtr) -> t.CUInt32T: pass + +def mbuddy_main() -> CInt: pass diff --git a/Test/TestProject/temp/c9f4be41ca1cc2b4.pyi b/Test/BuddyTest/temp/c9f4be41ca1cc2b4.pyi similarity index 100% rename from Test/TestProject/temp/c9f4be41ca1cc2b4.pyi rename to Test/BuddyTest/temp/c9f4be41ca1cc2b4.pyi diff --git a/Test/BuddyTest/temp/e1937873ebfba8c3.pyi b/Test/BuddyTest/temp/e1937873ebfba8c3.pyi new file mode 100644 index 0000000..851a008 --- /dev/null +++ b/Test/BuddyTest/temp/e1937873ebfba8c3.pyi @@ -0,0 +1,48 @@ +""" +Auto-generated Python stub file from mbuddy.py +Module: mbuddy +""" + + +import t, c +from stdint import * +import string +import atom + +MBUDDY_MIN_BLOCK: t.CDefine = 32 # 最小块大小 (字节),需 >= 16 以容纳链表指针 +MBUDDY_MAX_ORDERS: t.CDefine = 32 # 最大阶数数量 +MBUDDY_HEADER_SIZE: t.CDefine = 8 # 块头大小 (存储阶数) + +def _largest_pow2_le(val: t.CSizeT) -> t.CSizeT: pass + +def _block_size_at_order(order: t.CInt) -> t.CSizeT: pass + + +class MBuddy: + mem: t.CVoid | t.CPtr + mem_size: t.CSizeT + max_order: t.CInt + free_lists: t.CUInt64T | t.CPtr + lock_val: t.CVolatile | t.CInt + def __init__(self: MBuddy, arena: t.CVoid | t.CPtr, arena_size: t.CSizeT) -> t.CInt: pass + def __enter__(self: MBuddy) -> 'MBuddy' | t.CPtr: pass + def __exit__(self: MBuddy) -> t.CInt: pass + def reset(self: MBuddy) -> t.CInt: pass + def _fl_push(self: MBuddy, order: t.CInt, block: t.CVoid | t.CPtr) -> t.CInt: pass + def _fl_pop(self: MBuddy, order: t.CInt) -> t.CVoid | t.CPtr: pass + def _fl_find_and_remove(self: MBuddy, order: t.CInt, target: t.CVoid | t.CPtr) -> t.CInt: pass + def _buddy_of(self: MBuddy, block: t.CVoid | t.CPtr, order: t.CInt) -> t.CVoid | t.CPtr: pass + def _order_for_size(self: MBuddy, size: t.CSizeT) -> t.CInt: pass + def _split_to_order(self: MBuddy, to_order: t.CInt) -> t.CVoid | t.CPtr: pass + def _coalesce(self: MBuddy, block: t.CVoid | t.CPtr, order: t.CInt) -> t.CInt: pass + def _is_valid_ptr(self: MBuddy, ptr: t.CVoid | t.CPtr) -> t.CInt: pass + def _fl_count(self: MBuddy, order: t.CInt) -> t.CSizeT: pass + def _lock(self: MBuddy) -> t.CInt: pass + def _unlock(self: MBuddy) -> t.CInt: pass + def alloc(self: MBuddy, size: t.CSizeT) -> t.CVoid | t.CPtr: pass + def free(self: MBuddy, ptr: t.CVoid | t.CPtr) -> t.CInt: pass + def calloc(self: MBuddy, count: t.CSizeT, size: t.CSizeT) -> t.CVoid | t.CPtr: pass + def realloc(self: MBuddy, ptr: t.CVoid | t.CPtr, new_size: t.CSizeT) -> t.CVoid | t.CPtr: pass + def stats(self: MBuddy) -> t.CSizeT: pass + def free_count(self: MBuddy) -> t.CSizeT: pass + def self_check(self: MBuddy) -> t.CInt: pass \ No newline at end of file diff --git a/Test/TestProject/temp/fa3691e66b426950.pyi b/Test/BuddyTest/temp/fa3691e66b426950.pyi similarity index 100% rename from Test/TestProject/temp/fa3691e66b426950.pyi rename to Test/BuddyTest/temp/fa3691e66b426950.pyi diff --git a/Test/BuiltinDecoratorTest/App/main.py b/Test/BuiltinDecoratorTest/App/main.py index 17d9da4..56566d9 100644 --- a/Test/BuiltinDecoratorTest/App/main.py +++ b/Test/BuiltinDecoratorTest/App/main.py @@ -2,21 +2,7 @@ import t from stdint import * from stdio import printf from stdlib import malloc - -# ============================================================ -# 测试计数器 -# ============================================================ -_pass_count: t.CInt = 0 -_fail_count: t.CInt = 0 - -def check(name: t.CChar | t.CPtr, condition: bool): - global _pass_count, _fail_count - if condition: - _pass_count += 1 - printf(" [PASS] %s\n", name) - else: - _fail_count += 1 - printf(" [FAIL] %s\n", name) +import testcheck # ============================================================ @@ -43,14 +29,13 @@ class Rect: def test_property_getter(): - printf("\n+-- @property getter --+\n") + testcheck.section("@property getter") r1: Rect = Rect(3, 4) - check("area == 12", r1.area == 12) - check("not square", not r1.is_square) + testcheck.check(r1.area == 12, "area == 12", "area expect 12") + testcheck.check(not r1.is_square, "not square", "should not be square") r2: Rect = Rect(5, 5) - check("square area == 25", r2.area == 25) - check("is_square", r2.is_square) - printf("+--------------------------------------------+\n") + testcheck.check(r2.area == 25, "square area == 25", "square area expect 25") + testcheck.check(r2.is_square, "is_square", "should be square") # ============================================================ @@ -79,13 +64,12 @@ class Temperature: def test_property_setter(): - printf("\n+-- @property.setter --+\n") + testcheck.section("@property.setter") tmp1: Temperature = Temperature(0.0) - check("0C == 32F", tmp1.fahrenheit > 31.9 and tmp1.fahrenheit < 32.1) + testcheck.check(tmp1.fahrenheit > 31.9 and tmp1.fahrenheit < 32.1, "0C == 32F", "0C expect 32F") tmp1.celsius = 100.0 - check("100C == 212F", tmp1.fahrenheit > 211.9 and tmp1.fahrenheit < 212.1) - check("celsius == 100", tmp1.celsius > 99.9 and tmp1.celsius < 100.1) - printf("+--------------------------------------------+\n") + testcheck.check(tmp1.fahrenheit > 211.9 and tmp1.fahrenheit < 212.1, "100C == 212F", "100C expect 212F") + testcheck.check(tmp1.celsius > 99.9 and tmp1.celsius < 100.1, "celsius == 100", "celsius expect 100") # ============================================================ @@ -110,12 +94,11 @@ class Counter: def test_property_getter_redef(): - printf("\n+-- @property.getter redef --+\n") + testcheck.section("@property.getter redef") cnt: Counter = Counter() - check("init == 0", cnt.value == 0) + testcheck.check(cnt.value == 0, "init == 0", "init expect 0") cnt.value = 42 - check("set == 42", cnt.value == 42) - printf("+--------------------------------------------+\n") + testcheck.check(cnt.value == 42, "set == 42", "set expect 42") # ============================================================ @@ -150,14 +133,13 @@ class Config: def test_property_deleter(): - printf("\n+-- @property.deleter --+\n") + testcheck.section("@property.deleter") cfg: Config = Config(99) - check("init == 99", cfg.value == 99) - check("not deleted", not cfg.is_deleted()) + testcheck.check(cfg.value == 99, "init == 99", "init expect 99") + testcheck.check(not cfg.is_deleted(), "not deleted", "should not be deleted") del cfg.value - check("after del == 0", cfg.value == 0) - check("is_deleted", cfg.is_deleted()) - printf("+--------------------------------------------+\n") + testcheck.check(cfg.value == 0, "after del == 0", "after del expect 0") + testcheck.check(cfg.is_deleted(), "is_deleted", "should be deleted") # ============================================================ @@ -174,11 +156,10 @@ class MathUtils: def test_staticmethod(): - printf("\n+-- @staticmethod --+\n") + testcheck.section("@staticmethod") # 通过类名调用 - check("MathUtils.add(3,4)==7", MathUtils.add(3, 4) == 7) - check("MathUtils.max(5,10)==10", MathUtils.max_val(5, 10) == 10) - printf("+--------------------------------------------+\n") + testcheck.check(MathUtils.add(3, 4) == 7, "MathUtils.add(3,4)==7", "MathUtils.add(3,4) expect 7") + testcheck.check(MathUtils.max_val(5, 10) == 10, "MathUtils.max(5,10)==10", "MathUtils.max(5,10) expect 10") # ============================================================ @@ -208,18 +189,17 @@ class Point: def test_classmethod(): - printf("\n+-- @classmethod --+\n") + testcheck.section("@classmethod") # 通过类名调用 p1: Point = Point.origin() - check("origin.x ~= 0", p1.x > -0.01 and p1.x < 0.01) - check("origin.y ~= 0", p1.y > -0.01 and p1.y < 0.01) - check("origin.dist ~= 0", p1.dist_sq() < 0.01) + testcheck.check(p1.x > -0.01 and p1.x < 0.01, "origin.x ~= 0", "origin.x expect ~0") + testcheck.check(p1.y > -0.01 and p1.y < 0.01, "origin.y ~= 0", "origin.y expect ~0") + testcheck.check(p1.dist_sq() < 0.01, "origin.dist ~= 0", "origin.dist expect ~0") p2: Point = Point.from_int(3, 4) - check("from_int(3,4).x ~= 3", p2.x > 2.99 and p2.x < 3.01) - check("from_int(3,4).y ~= 4", p2.y > 3.99 and p2.y < 4.01) - check("dist_sq ~= 25", p2.dist_sq() > 24.99 and p2.dist_sq() < 25.01) - printf("+--------------------------------------------+\n") + testcheck.check(p2.x > 2.99 and p2.x < 3.01, "from_int(3,4).x ~= 3", "from_int(3,4).x expect ~3") + testcheck.check(p2.y > 3.99 and p2.y < 4.01, "from_int(3,4).y ~= 4", "from_int(3,4).y expect ~4") + testcheck.check(p2.dist_sq() > 24.99 and p2.dist_sq() < 25.01, "dist_sq ~= 25", "dist_sq expect ~25") # ============================================================ @@ -256,27 +236,26 @@ class Circle: def test_combined(): - printf("\n+-- Combined @property + @staticmethod + @classmethod --+\n") + testcheck.section("Combined @property + @staticmethod + @classmethod") # 先测试直接构造 cr0: Circle = Circle(1.0) - check("direct radius ~= 1", cr0.radius > 0.99 and cr0.radius < 1.01) - check("direct area ~= pi", cr0.area > 3.14 and cr0.area < 3.15) + testcheck.check(cr0.radius > 0.99 and cr0.radius < 1.01, "direct radius ~= 1", "direct radius expect ~1") + testcheck.check(cr0.area > 3.14 and cr0.area < 3.15, "direct area ~= pi", "direct area expect ~pi") cr0.radius = 2.0 - check("direct radius 2.0", cr0.radius > 1.99 and cr0.radius < 2.01) - check("direct area ~= 4pi", cr0.area > 12.56 and cr0.area < 12.58) + testcheck.check(cr0.radius > 1.99 and cr0.radius < 2.01, "direct radius 2.0", "direct radius expect 2.0") + testcheck.check(cr0.area > 12.56 and cr0.area < 12.58, "direct area ~= 4pi", "direct area expect ~4pi") # 测试 classmethod cr1: Circle = Circle.unit() - check("unit radius ~= 1", cr1.radius > 0.99 and cr1.radius < 1.01) - check("is_unit(1.0)", Circle.is_unit(1.0)) - check("not is_unit(2.0)", not Circle.is_unit(2.0)) - printf("+--------------------------------------------+\n") + testcheck.check(cr1.radius > 0.99 and cr1.radius < 1.01, "unit radius ~= 1", "unit radius expect ~1") + testcheck.check(Circle.is_unit(1.0), "is_unit(1.0)", "is_unit(1.0) should be true") + testcheck.check(not Circle.is_unit(2.0), "not is_unit(2.0)", "is_unit(2.0) should be false") # ============================================================ # 主函数 # ============================================================ def main() -> t.CInt | t.CExport: - printf("=== Builtin Decorator Test ===\n") + testcheck.begin("Builtin Decorator Test") test_property_getter() test_property_setter() @@ -286,5 +265,4 @@ def main() -> t.CInt | t.CExport: test_classmethod() test_combined() - printf("\n=== Results: %d passed, %d failed ===\n", _pass_count, _fail_count) - return 0 + return testcheck.end() diff --git a/Test/BuiltinDecoratorTest/output/9dbecd0942a39782.deps.json b/Test/BuiltinDecoratorTest/output/9dbecd0942a39782.deps.json new file mode 100644 index 0000000..264baa2 --- /dev/null +++ b/Test/BuiltinDecoratorTest/output/9dbecd0942a39782.deps.json @@ -0,0 +1 @@ +{"stdint": "49bd8cba55979f76", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "main": "e3ac223bdaf94a0c"} \ No newline at end of file diff --git a/Test/BuiltinDecoratorTest/output/b6069b01d8c9cc04.deps.json b/Test/BuiltinDecoratorTest/output/b6069b01d8c9cc04.deps.json deleted file mode 100644 index b9a8517..0000000 --- a/Test/BuiltinDecoratorTest/output/b6069b01d8c9cc04.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"stdint": "56cdd754a8a09347", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b"} \ No newline at end of file diff --git a/Test/BuiltinDecoratorTest/output/e3ac223bdaf94a0c.deps.json b/Test/BuiltinDecoratorTest/output/e3ac223bdaf94a0c.deps.json new file mode 100644 index 0000000..8596d97 --- /dev/null +++ b/Test/BuiltinDecoratorTest/output/e3ac223bdaf94a0c.deps.json @@ -0,0 +1 @@ +{"stdint": "49bd8cba55979f76", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782"} \ No newline at end of file diff --git a/Test/BuiltinDecoratorTest/temp/56cdd754a8a09347.pyi b/Test/BuiltinDecoratorTest/temp/49bd8cba55979f76.pyi similarity index 88% rename from Test/BuiltinDecoratorTest/temp/56cdd754a8a09347.pyi rename to Test/BuiltinDecoratorTest/temp/49bd8cba55979f76.pyi index 007ccb8..f1d844a 100644 --- a/Test/BuiltinDecoratorTest/temp/56cdd754a8a09347.pyi +++ b/Test/BuiltinDecoratorTest/temp/49bd8cba55979f76.pyi @@ -64,4 +64,12 @@ CHAR16: t.CTypedef = t.CChar16T CHAR32: t.CTypedef = t.CChar32T CHAR8PTR: t.CTypedef = t.CChar8T | t.CPtr CHAR16PTR: t.CTypedef = t.CChar16T | t.CPtr -CHAR32PTR: t.CTypedef = t.CChar32T | t.CPtr \ No newline at end of file +CHAR32PTR: t.CTypedef = t.CChar32T | t.CPtr +i8: t.CTypedef = t.CInt8T +i16: t.CTypedef = t.CInt16T +i32: t.CTypedef = t.CInt32T +i64: t.CTypedef = t.CInt64T +u8: t.CTypedef = t.CUInt8T +u16: t.CTypedef = t.CUInt16T +u32: t.CTypedef = t.CUInt32T +u64: t.CTypedef = t.CUInt64T \ No newline at end of file diff --git a/Test/BuiltinDecoratorTest/temp/9dbecd0942a39782.pyi b/Test/BuiltinDecoratorTest/temp/9dbecd0942a39782.pyi new file mode 100644 index 0000000..41648c1 --- /dev/null +++ b/Test/BuiltinDecoratorTest/temp/9dbecd0942a39782.pyi @@ -0,0 +1,25 @@ +""" +Auto-generated Python stub file from testcheck.py +Module: testcheck +""" + + +import t, c +import stdio + +_pass_count: t.CExtern | t.CInt +_fail_count: t.CExtern | t.CInt + +def begin(name: str) -> t.CInt: pass + +def section(name: str) -> t.CInt: pass + +def ok(msg: str) -> t.CInt: pass + +def fail(msg: str) -> t.CInt: pass + +def check(cond: t.CInt, ok_msg: str, fail_msg: str) -> t.CInt: pass + +def info(msg: str) -> t.CInt: pass + +def end() -> t.CInt: pass diff --git a/Test/BuiltinDecoratorTest/temp/_sha1_map.txt b/Test/BuiltinDecoratorTest/temp/_sha1_map.txt index 5f7f065..895d278 100644 --- a/Test/BuiltinDecoratorTest/temp/_sha1_map.txt +++ b/Test/BuiltinDecoratorTest/temp/_sha1_map.txt @@ -1,4 +1,5 @@ -56cdd754a8a09347:includes/stdint.py +49bd8cba55979f76:includes/stdint.py 6c2029b306556c00:includes/stdlib.py 73edbcf76e32d00b:includes/stdio.py -b6069b01d8c9cc04:main.py +9dbecd0942a39782:includes/testcheck.py +e3ac223bdaf94a0c:main.py diff --git a/Test/BuiltinDecoratorTest/temp/b6069b01d8c9cc04.pyi b/Test/BuiltinDecoratorTest/temp/e3ac223bdaf94a0c.pyi similarity index 95% rename from Test/BuiltinDecoratorTest/temp/b6069b01d8c9cc04.pyi rename to Test/BuiltinDecoratorTest/temp/e3ac223bdaf94a0c.pyi index be4ff19..10d5c52 100644 --- a/Test/BuiltinDecoratorTest/temp/b6069b01d8c9cc04.pyi +++ b/Test/BuiltinDecoratorTest/temp/e3ac223bdaf94a0c.pyi @@ -10,12 +10,7 @@ import t from stdint import * from stdio import printf from stdlib import malloc - -_pass_count: t.CExtern | t.CInt -_fail_count: t.CExtern | t.CInt - -def check(name: t.CChar | t.CPtr, condition: bool) -> t.CInt: pass - +import testcheck class Rect: width: t.CInt diff --git a/Test/CPythonTest/App/main.py b/Test/CPythonTest/App/main.py index 8e66d08..6db84ea 100644 --- a/Test/CPythonTest/App/main.py +++ b/Test/CPythonTest/App/main.py @@ -2,61 +2,48 @@ import t, c from t import CInt, CLong, CDouble, CPtr, CSizeT from stdio import printf import cpython - - -_pass_count: CInt = 0 -_fail_count: CInt = 0 - -def check(name: t.CChar | CPtr, condition: bool): - global _pass_count, _fail_count - if condition: - _pass_count += 1 - printf(" [PASS] %s\n", name) - else: - _fail_count += 1 - printf(" [FAIL] %s\n", name) +import testcheck def test_init_finalize(): - printf("\n+-- Py_Initialize / Py_Finalize --+\n") + testcheck.section("Py_Initialize / Py_Finalize") cpython.Py_Initialize() - check("Py_Initialize succeeded", cpython.Py_IsInitialized() != 0) + testcheck.check(cpython.Py_IsInitialized() != 0, "Py_Initialize succeeded", "Py_Initialize succeeded") cpython.Py_Finalize() - check("Py_Finalize succeeded", cpython.Py_IsInitialized() == 0) - printf("+--------------------------------------------+\n") + testcheck.check(cpython.Py_IsInitialized() == 0, "Py_Finalize succeeded", "Py_Finalize succeeded") def test_long_operations(): - printf("\n+-- PyLong operations --+\n") + testcheck.section("PyLong operations") cpython.Py_Initialize() # 创建整数 py_num: cpython.PyObject | CPtr = cpython.PyLong_FromLong(12345) - check("PyLong_FromLong != NULL", py_num != 0) + testcheck.check(py_num != 0, "PyLong_FromLong != NULL", "PyLong_FromLong != NULL") # 整数转字符串 - py_str: cpython.PyObject | CPtr = cpython.PyObject_Str(py_num) - check("PyObject_Str != NULL", py_str != 0) + py_str: cpython.PyObject | CPtr = cpython.PyObject_str(py_num) + testcheck.check(py_str != 0, "PyObject_Str != NULL", "PyObject_Str != NULL") # 获取 C 字符串 c_str: t.CChar | CPtr = cpython.PyUnicode_AsUTF8(py_str) - check("PyUnicode_AsUTF8 != NULL", c_str != 0) + testcheck.check(c_str != 0, "PyUnicode_AsUTF8 != NULL", "PyUnicode_AsUTF8 != NULL") printf(" PyLong_FromLong(12345) -> str = %s\n", c_str) # 读取回来 val: CLong = cpython.PyLong_AsLong(py_num) - check("PyLong_AsLong == 12345", val == 12345) + testcheck.check(val == 12345, "PyLong_AsLong == 12345", "PyLong_AsLong == 12345") # 负数 py_neg: cpython.PyObject | CPtr = cpython.PyLong_FromLong(-999) neg_val: CLong = cpython.PyLong_AsLong(py_neg) - check("PyLong_FromLong(-999) == -999", neg_val == -999) + testcheck.check(neg_val == -999, "PyLong_FromLong(-999) == -999", "PyLong_FromLong(-999) == -999") # 浮点数转整数 py_dbl: cpython.PyObject | CPtr = cpython.PyFloat_FromDouble(3.14159) - check("PyFloat_FromDouble != NULL", py_dbl != 0) + testcheck.check(py_dbl != 0, "PyFloat_FromDouble != NULL", "PyFloat_FromDouble != NULL") dbl_val: CDouble = cpython.PyFloat_AsDouble(py_dbl) - check("PyFloat_AsDouble ~= 3.14", dbl_val > 3.14 and dbl_val < 3.15) + testcheck.check(dbl_val > 3.14 and dbl_val < 3.15, "PyFloat_AsDouble ~= 3.14", "PyFloat_AsDouble ~= 3.14") # 清理 cpython.Py_DecRef(py_dbl) @@ -65,31 +52,30 @@ def test_long_operations(): cpython.Py_DecRef(py_num) cpython.Py_Finalize() - printf("+--------------------------------------------+\n") def test_string_operations(): - printf("\n+-- PyUnicode operations --+\n") + testcheck.section("PyUnicode operations") cpython.Py_Initialize() # 从 C 字符串创建 py_s1: cpython.PyObject | CPtr = cpython.PyUnicode_FromString("Hello, Viper!") - check("PyUnicode_FromString != NULL", py_s1 != 0) + testcheck.check(py_s1 != 0, "PyUnicode_FromString != NULL", "PyUnicode_FromString != NULL") # 获取 UTF8 utf8: t.CChar | CPtr = cpython.PyUnicode_AsUTF8(py_s1) - check("AsUTF8 != NULL", utf8 != 0) + testcheck.check(utf8 != 0, "AsUTF8 != NULL", "AsUTF8 != NULL") printf(" PyUnicode_FromString -> %s\n", utf8) # 字符串长度 length: CLong = cpython.PyUnicode_GetLength(py_s1) - check("GetLength == 13", length == 13) + testcheck.check(length == 13, "GetLength == 13", "GetLength == 13") # 字符串拼接 py_s2: cpython.PyObject | CPtr = cpython.PyUnicode_FromString(" World") py_concat: cpython.PyObject | CPtr = cpython.PyUnicode_Concat(py_s1, py_s2) concat_utf8: t.CChar | CPtr = cpython.PyUnicode_AsUTF8(py_concat) - check("Concat != NULL", py_concat != 0) + testcheck.check(py_concat != 0, "Concat != NULL", "Concat != NULL") printf(" Concat -> %s\n", concat_utf8) # 清理 @@ -98,16 +84,15 @@ def test_string_operations(): cpython.Py_DecRef(py_s1) cpython.Py_Finalize() - printf("+--------------------------------------------+\n") def test_list_operations(): - printf("\n+-- PyList operations --+\n") + testcheck.section("PyList operations") cpython.Py_Initialize() # 创建列表 py_list: cpython.PyObject | CPtr = cpython.PyList_New(0) - check("PyList_New != NULL", py_list != 0) + testcheck.check(py_list != 0, "PyList_New != NULL", "PyList_New != NULL") # Append 元素 py_i1: cpython.PyObject | CPtr = cpython.PyLong_FromLong(10) @@ -119,16 +104,16 @@ def test_list_operations(): # 检查大小 list_size: CSizeT = cpython.PyList_Size(py_list) - check("PyList_Size == 3", list_size == 3) + testcheck.check(list_size == 3, "PyList_Size == 3", "PyList_Size == 3") # 获取元素 item0: cpython.PyObject | CPtr = cpython.PyList_GetItem(py_list, 0) val0: CLong = cpython.PyLong_AsLong(item0) - check("list[0] == 10", val0 == 10) + testcheck.check(val0 == 10, "list[0] == 10", "list[0] == 10") item2: cpython.PyObject | CPtr = cpython.PyList_GetItem(py_list, 2) val2: CLong = cpython.PyLong_AsLong(item2) - check("list[2] == 30", val2 == 30) + testcheck.check(val2 == 30, "list[2] == 30", "list[2] == 30") # 清理 cpython.Py_DecRef(py_i3) @@ -137,16 +122,15 @@ def test_list_operations(): cpython.Py_DecRef(py_list) cpython.Py_Finalize() - printf("+--------------------------------------------+\n") def test_dict_operations(): - printf("\n+-- PyDict operations --+\n") + testcheck.section("PyDict operations") cpython.Py_Initialize() # 创建字典 py_dict: cpython.PyObject | CPtr = cpython.PyDict_New() - check("PyDict_New != NULL", py_dict != 0) + testcheck.check(py_dict != 0, "PyDict_New != NULL", "PyDict_New != NULL") # 设置键值对 py_key1: cpython.PyObject | CPtr = cpython.PyUnicode_FromString("name") @@ -159,20 +143,20 @@ def test_dict_operations(): # 检查大小 dict_size: CSizeT = cpython.PyDict_Size(py_dict) - check("PyDict_Size == 2", dict_size == 2) + testcheck.check(dict_size == 2, "PyDict_Size == 2", "PyDict_Size == 2") # 获取值 got_val: cpython.PyObject | CPtr = cpython.PyDict_GetItem(py_dict, py_key1) - check("GetItem(name) != NULL", got_val != 0) + testcheck.check(got_val != 0, "GetItem(name) != NULL", "GetItem(name) != NULL") got_str: t.CChar | CPtr = cpython.PyUnicode_AsUTF8(got_val) - check("name == Viper", got_str != 0) + testcheck.check(got_str != 0, "name == Viper", "name == Viper") printf(" dict['name'] = %s\n", got_str) # 使用 GetItemString got_ver: cpython.PyObject | CPtr = cpython.PyDict_GetItemString(py_dict, "version") - check("GetItemString(version) != NULL", got_ver != 0) + testcheck.check(got_ver != 0, "GetItemString(version) != NULL", "GetItemString(version) != NULL") ver_val: CLong = cpython.PyLong_AsLong(got_ver) - check("version == 1", ver_val == 1) + testcheck.check(ver_val == 1, "version == 1", "version == 1") # 清理 cpython.Py_DecRef(py_val2) @@ -182,79 +166,76 @@ def test_dict_operations(): cpython.Py_DecRef(py_dict) cpython.Py_Finalize() - printf("+--------------------------------------------+\n") def test_pyrun_string(): - printf("\n+-- PyRun_SimpleString --+\n") + testcheck.section("PyRun_SimpleString") cpython.Py_Initialize() # 执行简单 Python 代码 rc: CInt = cpython.PyRun_SimpleString("print('Hello from embedded Python!')") - check("PyRun_SimpleString == 0", rc == 0) + testcheck.check(rc == 0, "PyRun_SimpleString == 0", "PyRun_SimpleString == 0") # 执行赋值 rc2: CInt = cpython.PyRun_SimpleString("x = 6 * 7") - check("PyRun_SimpleString(assign) == 0", rc2 == 0) + testcheck.check(rc2 == 0, "PyRun_SimpleString(assign) == 0", "PyRun_SimpleString(assign) == 0") # 读取结果 rc3: CInt = cpython.PyRun_SimpleString("print(f'The answer is {x}')") - check("PyRun_SimpleString(print) == 0", rc3 == 0) + testcheck.check(rc3 == 0, "PyRun_SimpleString(print) == 0", "PyRun_SimpleString(print) == 0") cpython.Py_Finalize() - printf("+--------------------------------------------+\n") def test_import_module(): - printf("\n+-- PyImport_ImportModule --+\n") + testcheck.section("PyImport_ImportModule") cpython.Py_Initialize() # 导入 math 模块 math_mod: cpython.PyObject | CPtr = cpython.PyImport_ImportModule("math") - check("import math != NULL", math_mod != 0) + testcheck.check(math_mod != 0, "import math != NULL", "import math != NULL") if math_mod != 0: # 获取 math.pi pi_val: cpython.PyObject | CPtr = cpython.PyObject_GetAttrString(math_mod, "pi") - check("math.pi != NULL", pi_val != 0) + testcheck.check(pi_val != 0, "math.pi != NULL", "math.pi != NULL") if pi_val != 0: pi_dbl: CDouble = cpython.PyFloat_AsDouble(pi_val) - check("math.pi ~= 3.14", pi_dbl > 3.14 and pi_dbl < 3.15) + testcheck.check(pi_dbl > 3.14 and pi_dbl < 3.15, "math.pi ~= 3.14", "math.pi ~= 3.14") printf(" math.pi = %f\n", pi_dbl) cpython.Py_DecRef(pi_val) # 获取 math.sqrt 函数 sqrt_func: cpython.PyObject | CPtr = cpython.PyObject_GetAttrString(math_mod, "sqrt") - check("math.sqrt != NULL", sqrt_func != 0) + testcheck.check(sqrt_func != 0, "math.sqrt != NULL", "math.sqrt != NULL") if sqrt_func != 0: cpython.Py_DecRef(sqrt_func) cpython.Py_DecRef(math_mod) cpython.Py_Finalize() - printf("+--------------------------------------------+\n") def test_operator_overload(): - printf("\n+-- Operator Overload (PyLongObj / PyFloatObj / PyUnicodeObj / PyListObj / PyDictObj) --+\n") + testcheck.section("Operator Overload (PyLongObj / PyFloatObj / PyUnicodeObj / PyListObj / PyDictObj)") cpython.Py_Initialize() # --- PyLongObj: from_long, to_long, +, -, *, - (neg) --- a: cpython.PyLongObj | CPtr = cpython.PyLongObj.from_long(10) b: cpython.PyLongObj | CPtr = cpython.PyLongObj.from_long(3) - check("PyLongObj.from_long != NULL", a != 0 and b != 0) + testcheck.check(a != 0 and b != 0, "PyLongObj.from_long != NULL", "PyLongObj.from_long != NULL") add_r: cpython.PyLongObj | CPtr = a + b - check("PyLongObj 10 + 3 == 13", add_r.to_long() == 13) + testcheck.check(add_r.to_long() == 13, "PyLongObj 10 + 3 == 13", "PyLongObj 10 + 3 == 13") sub_r: cpython.PyLongObj | CPtr = a - b - check("PyLongObj 10 - 3 == 7", sub_r.to_long() == 7) + testcheck.check(sub_r.to_long() == 7, "PyLongObj 10 - 3 == 7", "PyLongObj 10 - 3 == 7") mul_r: cpython.PyLongObj | CPtr = a * b - check("PyLongObj 10 * 3 == 30", mul_r.to_long() == 30) + testcheck.check(mul_r.to_long() == 30, "PyLongObj 10 * 3 == 30", "PyLongObj 10 * 3 == 30") neg_r: cpython.PyLongObj | CPtr = -b - check("PyLongObj -3 == -3", neg_r.to_long() == -3) + testcheck.check(neg_r.to_long() == -3, "PyLongObj -3 == -3", "PyLongObj -3 == -3") mul_r.dec_ref() sub_r.dec_ref() @@ -266,22 +247,22 @@ def test_operator_overload(): # --- PyFloatObj: from_double, to_double, +, -, *, /, - (neg) --- fa: cpython.PyFloatObj | CPtr = cpython.PyFloatObj.from_double(10.0) fb: cpython.PyFloatObj | CPtr = cpython.PyFloatObj.from_double(4.0) - check("PyFloatObj.from_double != NULL", fa != 0 and fb != 0) + testcheck.check(fa != 0 and fb != 0, "PyFloatObj.from_double != NULL", "PyFloatObj.from_double != NULL") fadd: cpython.PyFloatObj | CPtr = fa + fb - check("PyFloatObj 10.0 + 4.0 == 14.0", fadd.to_double() == 14.0) + testcheck.check(fadd.to_double() == 14.0, "PyFloatObj 10.0 + 4.0 == 14.0", "PyFloatObj 10.0 + 4.0 == 14.0") fsub: cpython.PyFloatObj | CPtr = fa - fb - check("PyFloatObj 10.0 - 4.0 == 6.0", fsub.to_double() == 6.0) + testcheck.check(fsub.to_double() == 6.0, "PyFloatObj 10.0 - 4.0 == 6.0", "PyFloatObj 10.0 - 4.0 == 6.0") fmul: cpython.PyFloatObj | CPtr = fa * fb - check("PyFloatObj 10.0 * 4.0 == 40.0", fmul.to_double() == 40.0) + testcheck.check(fmul.to_double() == 40.0, "PyFloatObj 10.0 * 4.0 == 40.0", "PyFloatObj 10.0 * 4.0 == 40.0") fdiv: cpython.PyFloatObj | CPtr = fa / fb - check("PyFloatObj 10.0 / 4.0 == 2.5", fdiv.to_double() == 2.5) + testcheck.check(fdiv.to_double() == 2.5, "PyFloatObj 10.0 / 4.0 == 2.5", "PyFloatObj 10.0 / 4.0 == 2.5") fneg: cpython.PyFloatObj | CPtr = -fb - check("PyFloatObj -4.0 == -4.0", fneg.to_double() == -4.0) + testcheck.check(fneg.to_double() == -4.0, "PyFloatObj -4.0 == -4.0", "PyFloatObj -4.0 == -4.0") fadd.dec_ref() fsub.dec_ref() @@ -294,16 +275,16 @@ def test_operator_overload(): # --- PyUnicodeObj: from_string, as_utf8, len, + (concat) --- sa: cpython.PyUnicodeObj | CPtr = cpython.PyUnicodeObj.from_string("Hello") sb: cpython.PyUnicodeObj | CPtr = cpython.PyUnicodeObj.from_string(" World") - check("PyUnicodeObj.from_string != NULL", sa != 0 and sb != 0) + testcheck.check(sa != 0 and sb != 0, "PyUnicodeObj.from_string != NULL", "PyUnicodeObj.from_string != NULL") sc: cpython.PyUnicodeObj | CPtr = sa + sb sc_utf8: t.CChar | CPtr = sc.as_utf8() - check("PyUnicodeObj concat != NULL", sc_utf8 != 0) + testcheck.check(sc_utf8 != 0, "PyUnicodeObj concat != NULL", "PyUnicodeObj concat != NULL") if sc_utf8 != 0: printf(" PyUnicodeObj 'Hello' + ' World' = %s\n", sc_utf8) sa_len: t.CPtrDiffT = len(sa) - check("PyUnicodeObj len('Hello') == 5", sa_len == 5) + testcheck.check(sa_len == 5, "PyUnicodeObj len('Hello') == 5", "PyUnicodeObj len('Hello') == 5") sc.dec_ref() sb.dec_ref() @@ -311,7 +292,7 @@ def test_operator_overload(): # --- PyListObj: new, append, len, [], []= --- lst: cpython.PyListObj | CPtr = cpython.PyListObj.new() - check("PyListObj.new != NULL", lst != 0) + testcheck.check(lst != 0, "PyListObj.new != NULL", "PyListObj.new != NULL") if lst != 0: e1: cpython.PyObject | CPtr = cpython.PyLong_FromLong(100) e2: cpython.PyObject | CPtr = cpython.PyLong_FromLong(200) @@ -319,16 +300,16 @@ def test_operator_overload(): lst.append(e1) lst.append(e2) lst.append(e3) - check("PyListObj len == 3", len(lst) == 3) + testcheck.check(len(lst) == 3, "PyListObj len == 3", "PyListObj len == 3") item0: cpython.PyObject | CPtr = lst[t.CSizeT(0)] - check("PyListObj lst[0] == 100", cpython.PyLong_AsLong(item0) == 100) + testcheck.check(cpython.PyLong_AsLong(item0) == 100, "PyListObj lst[0] == 100", "PyListObj lst[0] == 100") # __setitem__ e4: cpython.PyObject | CPtr = cpython.PyLong_FromLong(999) lst[t.CSizeT(1)] = e4 item1: cpython.PyObject | CPtr = lst[t.CSizeT(1)] - check("PyListObj lst[1] = 999", cpython.PyLong_AsLong(item1) == 999) + testcheck.check(cpython.PyLong_AsLong(item1) == 999, "PyListObj lst[1] = 999", "PyListObj lst[1] = 999") cpython.Py_DecRef(e4) cpython.Py_DecRef(e3) @@ -338,34 +319,33 @@ def test_operator_overload(): # --- PyDictObj: new, [], []=, len, set_string, get_string --- dct: cpython.PyDictObj | CPtr = cpython.PyDictObj.new() - check("PyDictObj.new != NULL", dct != 0) + testcheck.check(dct != 0, "PyDictObj.new != NULL", "PyDictObj.new != NULL") if dct != 0: dk1: cpython.PyObject | CPtr = cpython.PyUnicode_FromString("lang") dv1: cpython.PyObject | CPtr = cpython.PyUnicode_FromString("Viper") dct[dk1] = dv1 - check("PyDictObj len == 1", len(dct) == 1) + testcheck.check(len(dct) == 1, "PyDictObj len == 1", "PyDictObj len == 1") got_lang: cpython.PyObject | CPtr = dct[dk1] got_str: t.CChar | CPtr = cpython.PyUnicode_AsUTF8(got_lang) - check("PyDictObj dct['lang'] == Viper", got_str != 0) + testcheck.check(got_str != 0, "PyDictObj dct['lang'] == Viper", "PyDictObj dct['lang'] == Viper") if got_str != 0: printf(" PyDictObj dct['lang'] = %s\n", got_str) # get_string / set_string dct.set_string("ver", cpython.PyLong_FromLong(3)) got_ver: cpython.PyObject | CPtr = dct.get_string("ver") - check("PyDictObj get_string('ver') == 3", got_ver != 0 and cpython.PyLong_AsLong(got_ver) == 3) + testcheck.check(got_ver != 0 and cpython.PyLong_AsLong(got_ver) == 3, "PyDictObj get_string('ver') == 3", "PyDictObj get_string('ver') == 3") cpython.Py_DecRef(dv1) cpython.Py_DecRef(dk1) dct.dec_ref() cpython.Py_Finalize() - printf("+--------------------------------------------+\n") def main() -> CInt | t.CExport: - printf("=== CPython Integration Test ===\n") + testcheck.begin("CPython Integration Test") test_init_finalize() test_long_operations() @@ -376,5 +356,4 @@ def main() -> CInt | t.CExport: test_import_module() test_operator_overload() - printf("\n=== Results: %d passed, %d failed ===\n", _pass_count, _fail_count) - return 0 + return testcheck.end() diff --git a/Test/CPythonTest/output/0cd580d62a3de4f8.deps.json b/Test/CPythonTest/output/0cd580d62a3de4f8.deps.json deleted file mode 100644 index f813be8..0000000 --- a/Test/CPythonTest/output/0cd580d62a3de4f8.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"stdio": "73edbcf76e32d00b", "cpython": "7c5d5ec59c5fb0a8"} \ No newline at end of file diff --git a/Test/CPythonTest/output/7c5d5ec59c5fb0a8.deps.json b/Test/CPythonTest/output/7c5d5ec59c5fb0a8.deps.json index 7d8bc7a..01f7286 100644 --- a/Test/CPythonTest/output/7c5d5ec59c5fb0a8.deps.json +++ b/Test/CPythonTest/output/7c5d5ec59c5fb0a8.deps.json @@ -1 +1 @@ -{"main": "0cd580d62a3de4f8", "stdio": "73edbcf76e32d00b"} \ No newline at end of file +{"main": "3c8ecda6b848f011", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782"} \ No newline at end of file diff --git a/Test/CPythonTest/temp/0cd580d62a3de4f8.pyi b/Test/CPythonTest/temp/3c8ecda6b848f011.pyi similarity index 81% rename from Test/CPythonTest/temp/0cd580d62a3de4f8.pyi rename to Test/CPythonTest/temp/3c8ecda6b848f011.pyi index 60b905d..12b9442 100644 --- a/Test/CPythonTest/temp/0cd580d62a3de4f8.pyi +++ b/Test/CPythonTest/temp/3c8ecda6b848f011.pyi @@ -8,11 +8,7 @@ import t, c from t import CInt, CLong, CDouble, CPtr, CSizeT from stdio import printf import cpython - -_pass_count: t.CExtern | CInt -_fail_count: t.CExtern | CInt - -def check(name: t.CChar | CPtr, condition: bool) -> t.CInt: pass +import testcheck def test_init_finalize() -> t.CInt: pass diff --git a/Test/CPythonTest/temp/9dbecd0942a39782.pyi b/Test/CPythonTest/temp/9dbecd0942a39782.pyi new file mode 100644 index 0000000..41648c1 --- /dev/null +++ b/Test/CPythonTest/temp/9dbecd0942a39782.pyi @@ -0,0 +1,25 @@ +""" +Auto-generated Python stub file from testcheck.py +Module: testcheck +""" + + +import t, c +import stdio + +_pass_count: t.CExtern | t.CInt +_fail_count: t.CExtern | t.CInt + +def begin(name: str) -> t.CInt: pass + +def section(name: str) -> t.CInt: pass + +def ok(msg: str) -> t.CInt: pass + +def fail(msg: str) -> t.CInt: pass + +def check(cond: t.CInt, ok_msg: str, fail_msg: str) -> t.CInt: pass + +def info(msg: str) -> t.CInt: pass + +def end() -> t.CInt: pass diff --git a/Test/CPythonTest/temp/_sha1_map.txt b/Test/CPythonTest/temp/_sha1_map.txt index 8ac6cdb..1c8fb08 100644 --- a/Test/CPythonTest/temp/_sha1_map.txt +++ b/Test/CPythonTest/temp/_sha1_map.txt @@ -1,3 +1,4 @@ -0cd580d62a3de4f8:main.py +3c8ecda6b848f011:main.py 73edbcf76e32d00b:includes/stdio.py 7c5d5ec59c5fb0a8:cpython.py +9dbecd0942a39782:includes/testcheck.py diff --git a/Test/CPythonTest/temp/_shared_sym.json b/Test/CPythonTest/temp/_shared_sym.json new file mode 100644 index 0000000..e69de29 diff --git a/Test/CPythonTest/temp/_shared_sym.pkl b/Test/CPythonTest/temp/_shared_sym.pkl deleted file mode 100644 index b3960e202a2981b57ff536319693b2270212b974..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 609888 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 faqQKSLSPV3mSA t.CInt: nonlocal x x = x * 2 return x r: t.CInt = double_x() - if r == 10 and x == 10: - stdio.printf("PASS: nested return (r=%d x=%d)\n", r, x) - else: - stdio.printf("FAIL: nested return (r=%d x=%d, expect 10 10)\n", r, x) + testcheck.check(r == 10 and x == 10, "nested return (r==10 x==10)", "nested return (expect r=10 x=10)") # ============================================================ # Test 7: nonlocal 与循环变量 # ============================================================ def test_nonlocal_loop(): - stdio.printf("--- Test 7: nonlocal with loop ---\n") + testcheck.section("Test 7: nonlocal with loop") total: t.CInt = 0 def accumulate(n: t.CInt): nonlocal total @@ -124,34 +107,28 @@ def test_nonlocal_loop(): accumulate(5) accumulate(5) # 0+1+2+3+4 = 10, twice = 20 - if total == 20: - stdio.printf("PASS: nonlocal loop (total=%d)\n", total) - else: - stdio.printf("FAIL: nonlocal loop (total=%d, expect 20)\n", total) + testcheck.check(total == 20, "nonlocal loop (total == 20)", "nonlocal loop (expect 20)") # ============================================================ # Test 8: global 数组操作 # ============================================================ -g_arr: list[t.CInt, 4] = [0] +g_arr: t.CArray[t.CInt, 4] = [0] def test_global_array(): - stdio.printf("--- Test 8: global array ---\n") + testcheck.section("Test 8: global array") global g_arr g_arr[0] = 10 g_arr[1] = 20 g_arr[2] = 30 g_arr[3] = 40 total: t.CInt = g_arr[0] + g_arr[1] + g_arr[2] + g_arr[3] - if total == 100: - stdio.printf("PASS: global array (total=%d)\n", total) - else: - stdio.printf("FAIL: global array (total=%d, expect 100)\n", total) + testcheck.check(total == 100, "global array (total == 100)", "global array (expect 100)") # ============================================================ # Test 9: 嵌套函数条件调用 # ============================================================ def test_nested_conditional(): - stdio.printf("--- Test 9: nested conditional call ---\n") + testcheck.section("Test 9: nested conditional call") result: t.CInt = 0 def set_result(val: t.CInt): nonlocal result @@ -160,26 +137,20 @@ def test_nested_conditional(): set_result(42) else: set_result(99) - if result == 42: - stdio.printf("PASS: nested conditional (result=%d)\n", result) - else: - stdio.printf("FAIL: nested conditional (result=%d, expect 42)\n", result) + testcheck.check(result == 42, "nested conditional (result == 42)", "nested conditional (expect 42)") # ============================================================ # Test 10: lambda 链式调用 # ============================================================ def test_lambda_chain(): - stdio.printf("--- Test 10: lambda chain ---\n") + testcheck.section("Test 10: lambda chain") f1 = lambda: 10 f2 = lambda: 20 r: t.CInt = f1() + f2() - if r == 30: - stdio.printf("PASS: lambda chain (10+20=%d)\n", r) - else: - stdio.printf("FAIL: lambda chain (result=%d, expect 30)\n", r) + testcheck.check(r == 30, "lambda chain (10+20 == 30)", "lambda chain (expect 30)") def main() -> t.CInt: - stdio.printf("=== ClosureAdvancedTest: 高级闭包测试 ===\n\n") + testcheck.begin("ClosureAdvancedTest: 高级闭包测试") test_global_in_nested() test_nonlocal_multi_level() test_global_nonlocal_mixed() @@ -190,5 +161,4 @@ def main() -> t.CInt: test_global_array() test_nested_conditional() test_lambda_chain() - stdio.printf("\n=== ClosureAdvancedTest Complete ===\n") - return 0 + return testcheck.end() diff --git a/Test/ClosureTest/output/52e6b51da061882f.deps.json b/Test/ClosureTest/output/52e6b51da061882f.deps.json new file mode 100644 index 0000000..94ebae9 --- /dev/null +++ b/Test/ClosureTest/output/52e6b51da061882f.deps.json @@ -0,0 +1 @@ +{"stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782"} \ No newline at end of file diff --git a/Test/ClosureTest/output/7dbf085f7e3e8944.deps.json b/Test/ClosureTest/output/7dbf085f7e3e8944.deps.json deleted file mode 100644 index 073d6e7..0000000 --- a/Test/ClosureTest/output/7dbf085f7e3e8944.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"stdio": "73edbcf76e32d00b"} \ No newline at end of file diff --git a/Test/ClosureTest/output/9dbecd0942a39782.deps.json b/Test/ClosureTest/output/9dbecd0942a39782.deps.json new file mode 100644 index 0000000..1920dae --- /dev/null +++ b/Test/ClosureTest/output/9dbecd0942a39782.deps.json @@ -0,0 +1 @@ +{"main": "52e6b51da061882f", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782"} \ No newline at end of file diff --git a/Test/ClosureTest/temp/7dbf085f7e3e8944.pyi b/Test/ClosureTest/temp/52e6b51da061882f.pyi similarity index 92% rename from Test/ClosureTest/temp/7dbf085f7e3e8944.pyi rename to Test/ClosureTest/temp/52e6b51da061882f.pyi index 481b94b..edc39b5 100644 --- a/Test/ClosureTest/temp/7dbf085f7e3e8944.pyi +++ b/Test/ClosureTest/temp/52e6b51da061882f.pyi @@ -8,6 +8,7 @@ import c import t import stdio +import testcheck g_val: t.CExtern | t.CInt @@ -31,7 +32,7 @@ def test_nested_return() -> t.CInt: pass def test_nonlocal_loop() -> t.CInt: pass -g_arr: t.CExtern | list[t.CInt, 4] +g_arr: t.CExtern | t.CArray[t.CInt, 4] def test_global_array() -> t.CInt: pass diff --git a/Test/ClosureTest/temp/9dbecd0942a39782.pyi b/Test/ClosureTest/temp/9dbecd0942a39782.pyi new file mode 100644 index 0000000..41648c1 --- /dev/null +++ b/Test/ClosureTest/temp/9dbecd0942a39782.pyi @@ -0,0 +1,25 @@ +""" +Auto-generated Python stub file from testcheck.py +Module: testcheck +""" + + +import t, c +import stdio + +_pass_count: t.CExtern | t.CInt +_fail_count: t.CExtern | t.CInt + +def begin(name: str) -> t.CInt: pass + +def section(name: str) -> t.CInt: pass + +def ok(msg: str) -> t.CInt: pass + +def fail(msg: str) -> t.CInt: pass + +def check(cond: t.CInt, ok_msg: str, fail_msg: str) -> t.CInt: pass + +def info(msg: str) -> t.CInt: pass + +def end() -> t.CInt: pass diff --git a/Test/ClosureTest/temp/_sha1_map.txt b/Test/ClosureTest/temp/_sha1_map.txt index 3346d98..11d918b 100644 --- a/Test/ClosureTest/temp/_sha1_map.txt +++ b/Test/ClosureTest/temp/_sha1_map.txt @@ -1,2 +1,3 @@ +52e6b51da061882f:main.py 73edbcf76e32d00b:includes/stdio.py -7dbf085f7e3e8944:main.py +9dbecd0942a39782:includes/testcheck.py diff --git a/Test/ClosureTest2/App/main.py b/Test/ClosureTest2/App/main.py index 6151355..24e8bfb 100644 --- a/Test/ClosureTest2/App/main.py +++ b/Test/ClosureTest2/App/main.py @@ -1,11 +1,12 @@ import t import stdio +import testcheck # ============================================================ # Test 1: nonlocal 在条件分支中修改 # ============================================================ def test_nonlocal_conditional(): - stdio.printf("--- Test 1: nonlocal in conditional branches ---\n") + testcheck.section("Test 1: nonlocal in conditional branches") x: t.CInt = 0 def modify(flag: t.CInt): nonlocal x @@ -16,16 +17,13 @@ def test_nonlocal_conditional(): modify(1) modify(0) modify(1) - if x == 120: - stdio.printf("PASS: nonlocal conditional (x=%d)\n", x) - else: - stdio.printf("FAIL: nonlocal conditional (x=%d, expect 120)\n", x) + testcheck.check(x == 120, "nonlocal conditional (x == 120)", "nonlocal conditional (expect 120)") # ============================================================ # Test 2: 多个nonlocal变量同时修改 # ============================================================ def test_nonlocal_multi_var(): - stdio.printf("--- Test 2: multiple nonlocal variables ---\n") + testcheck.section("Test 2: multiple nonlocal variables") a: t.CInt = 1 b: t.CInt = 2 c_val: t.CInt = 3 @@ -36,10 +34,7 @@ def test_nonlocal_multi_var(): b = c_val c_val = tmp swap_add() - if a == 2 and b == 3 and c_val == 1: - stdio.printf("PASS: multi nonlocal (a=%d b=%d c=%d)\n", a, b, c_val) - else: - stdio.printf("FAIL: multi nonlocal (a=%d b=%d c=%d, expect 2 3 1)\n", a, b, c_val) + testcheck.check(a == 2 and b == 3 and c_val == 1, "multi nonlocal (a==2 b==3 c==1)", "multi nonlocal (expect 2 3 1)") # ============================================================ # Test 3: global 在多个函数中交叉修改 @@ -55,55 +50,46 @@ def add_global(n: t.CInt): g_counter += n def test_global_cross_functions(): - stdio.printf("--- Test 3: global cross-function modification ---\n") + testcheck.section("Test 3: global cross-function modification") global g_counter g_counter = 0 inc_global() inc_global() add_global(10) inc_global() - if g_counter == 13: - stdio.printf("PASS: global cross (g_counter=%d)\n", g_counter) - else: - stdio.printf("FAIL: global cross (g_counter=%d, expect 13)\n", g_counter) + testcheck.check(g_counter == 13, "global cross (g_counter == 13)", "global cross (expect 13)") # ============================================================ # Test 4: 嵌套函数修改外层局部变量(引用捕获) # ============================================================ def test_nested_ref_capture(): - stdio.printf("--- Test 4: nested function ref capture ---\n") - arr: list[t.CInt, 4] = [0] + testcheck.section("Test 4: nested function ref capture") + arr: t.CArray[t.CInt, 4] = [0] def fill(): nonlocal arr for i in range(4): arr[i] = (i + 1) * 10 fill() total: t.CInt = arr[0] + arr[1] + arr[2] + arr[3] - if total == 100: - stdio.printf("PASS: ref capture (total=%d)\n", total) - else: - stdio.printf("FAIL: ref capture (total=%d, expect 100)\n", total) + testcheck.check(total == 100, "ref capture (total == 100)", "ref capture (expect 100)") # ============================================================ # Test 5: lambda捕获后修改原变量 # ============================================================ def test_lambda_capture_then_modify(): - stdio.printf("--- Test 5: lambda capture then modify ---\n") + testcheck.section("Test 5: lambda capture then modify") x: t.CInt = 10 f = lambda: x r1: t.CInt = f() x = 20 r2: t.CInt = f() - if r1 == 10 and r2 == 10: - stdio.printf("PASS: lambda value capture (before=%d after=%d)\n", r1, r2) - else: - stdio.printf("FAIL: lambda value capture (before=%d after=%d, expect 10 10)\n", r1, r2) + testcheck.check(r1 == 10 and r2 == 10, "lambda value capture (before==10 after==10)", "lambda value capture (expect 10 10)") # ============================================================ # Test 6: 嵌套函数中nonlocal与循环结合 # ============================================================ def test_nonlocal_loop_accumulate(): - stdio.printf("--- Test 6: nonlocal with loop accumulate ---\n") + testcheck.section("Test 6: nonlocal with loop accumulate") sum_val: t.CInt = 0 count: t.CInt = 0 def add_numbers(n: t.CInt): @@ -113,16 +99,13 @@ def test_nonlocal_loop_accumulate(): count += 1 add_numbers(5) # 1+2+3+4+5=15 add_numbers(3) # 1+2+3=6 - if sum_val == 21 and count == 8: - stdio.printf("PASS: loop accumulate (sum=%d count=%d)\n", sum_val, count) - else: - stdio.printf("FAIL: loop accumulate (sum=%d count=%d, expect 21 8)\n", sum_val, count) + testcheck.check(sum_val == 21 and count == 8, "loop accumulate (sum==21 count==8)", "loop accumulate (expect 21 8)") # ============================================================ # Test 7: 三层嵌套中每层修改不同变量 # ============================================================ def test_deep_nested_vars(): - stdio.printf("--- Test 7: deep nested different vars ---\n") + testcheck.section("Test 7: deep nested different vars") a: t.CInt = 0 b: t.CInt = 0 c_val: t.CInt = 0 @@ -139,10 +122,7 @@ def test_deep_nested_vars(): level2() level1() level1() - if a == 2 and b == 20 and c_val == 200: - stdio.printf("PASS: deep nested (a=%d b=%d c=%d)\n", a, b, c_val) - else: - stdio.printf("FAIL: deep nested (a=%d b=%d c=%d, expect 2 20 200)\n", a, b, c_val) + testcheck.check(a == 2 and b == 20 and c_val == 200, "deep nested (a==2 b==20 c==200)", "deep nested (expect 2 20 200)") # ============================================================ # Test 8: global + nonlocal 在同一嵌套函数中 @@ -150,7 +130,7 @@ def test_deep_nested_vars(): g_state: t.CInt = 0 def test_global_nonlocal_same_func(): - stdio.printf("--- Test 8: global+nonlocal in same nested func ---\n") + testcheck.section("Test 8: global+nonlocal in same nested func") global g_state g_state = 0 local_state: t.CInt = 0 @@ -161,30 +141,24 @@ def test_global_nonlocal_same_func(): g_state += 1 local_state += 2 worker(5) - if g_state == 5 and local_state == 10: - stdio.printf("PASS: global+nonlocal same (g=%d l=%d)\n", g_state, local_state) - else: - stdio.printf("FAIL: global+nonlocal same (g=%d l=%d, expect 5 10)\n", g_state, local_state) + testcheck.check(g_state == 5 and local_state == 10, "global+nonlocal same (g==5 l==10)", "global+nonlocal same (expect 5 10)") # ============================================================ # Test 9: lambda带默认参数与捕获 # ============================================================ def test_lambda_default_and_capture(): - stdio.printf("--- Test 9: lambda with arg and capture ---\n") + testcheck.section("Test 9: lambda with arg and capture") base: t.CInt = 100 multiply = lambda x: base * x r1: t.CInt = multiply(3) r2: t.CInt = multiply(5) - if r1 == 300 and r2 == 500: - stdio.printf("PASS: lambda arg+capture (100*3=%d 100*5=%d)\n", r1, r2) - else: - stdio.printf("FAIL: lambda arg+capture (100*3=%d 100*5=%d, expect 300 500)\n", r1, r2) + testcheck.check(r1 == 300 and r2 == 500, "lambda arg+capture (100*3==300 100*5==500)", "lambda arg+capture (expect 300 500)") # ============================================================ # Test 10: 嵌套函数多次调用累积 # ============================================================ def test_nested_accumulate(): - stdio.printf("--- Test 10: nested function accumulate ---\n") + testcheck.section("Test 10: nested function accumulate") total: t.CInt = 0 def add_val(n: t.CInt): nonlocal total @@ -192,16 +166,13 @@ def test_nested_accumulate(): add_val(10) add_val(20) add_val(30) - if total == 60: - stdio.printf("PASS: nested accumulate (total=%d)\n", total) - else: - stdio.printf("FAIL: nested accumulate (total=%d, expect 60)\n", total) + testcheck.check(total == 60, "nested accumulate (total == 60)", "nested accumulate (expect 60)") # ============================================================ # Test 11: nonlocal在while循环中 # ============================================================ def test_nonlocal_while(): - stdio.printf("--- Test 11: nonlocal in while loop ---\n") + testcheck.section("Test 11: nonlocal in while loop") result: t.CInt = 0 def countdown(n: t.CInt): nonlocal result @@ -210,10 +181,7 @@ def test_nonlocal_while(): result += i i -= 1 countdown(5) # 5+4+3+2+1=15 - if result == 15: - stdio.printf("PASS: nonlocal while (result=%d)\n", result) - else: - stdio.printf("FAIL: nonlocal while (result=%d, expect 15)\n", result) + testcheck.check(result == 15, "nonlocal while (result == 15)", "nonlocal while (expect 15)") # ============================================================ # Test 12: 嵌套函数修改结构体字段 @@ -223,7 +191,7 @@ class Point: y: t.CInt def test_nested_modify_struct(): - stdio.printf("--- Test 12: nested modify struct ---\n") + testcheck.section("Test 12: nested modify struct") p: Point = Point() p.x = 0 p.y = 0 @@ -233,13 +201,10 @@ def test_nested_modify_struct(): p.y += dy translate(10, 20) translate(5, 15) - if p.x == 15 and p.y == 35: - stdio.printf("PASS: nested struct (x=%d y=%d)\n", p.x, p.y) - else: - stdio.printf("FAIL: nested struct (x=%d y=%d, expect 15 35)\n", p.x, p.y) + testcheck.check(p.x == 15 and p.y == 35, "nested struct (x==15 y==35)", "nested struct (expect 15 35)") def main() -> t.CInt: - stdio.printf("=== ClosureTest2: Advanced Closure/Lambda/Global/Nonlocal ===\n\n") + testcheck.begin("ClosureTest2: Advanced Closure/Lambda/Global/Nonlocal") test_nonlocal_conditional() test_nonlocal_multi_var() test_global_cross_functions() @@ -252,5 +217,4 @@ def main() -> t.CInt: test_nested_accumulate() test_nonlocal_while() test_nested_modify_struct() - stdio.printf("\n=== ClosureTest2 Complete ===\n") - return 0 + return testcheck.end() diff --git a/Test/ClosureTest2/output/052c7f96b9eefa2c.deps.json b/Test/ClosureTest2/output/052c7f96b9eefa2c.deps.json deleted file mode 100644 index 073d6e7..0000000 --- a/Test/ClosureTest2/output/052c7f96b9eefa2c.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"stdio": "73edbcf76e32d00b"} \ No newline at end of file diff --git a/Test/ClosureTest2/output/440f18f9dce85a95.deps.json b/Test/ClosureTest2/output/440f18f9dce85a95.deps.json new file mode 100644 index 0000000..94ebae9 --- /dev/null +++ b/Test/ClosureTest2/output/440f18f9dce85a95.deps.json @@ -0,0 +1 @@ +{"stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782"} \ No newline at end of file diff --git a/Test/ClosureTest2/output/9dbecd0942a39782.deps.json b/Test/ClosureTest2/output/9dbecd0942a39782.deps.json new file mode 100644 index 0000000..b6bcb24 --- /dev/null +++ b/Test/ClosureTest2/output/9dbecd0942a39782.deps.json @@ -0,0 +1 @@ +{"main": "440f18f9dce85a95", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782"} \ No newline at end of file diff --git a/Test/ClosureTest2/temp/052c7f96b9eefa2c.pyi b/Test/ClosureTest2/temp/440f18f9dce85a95.pyi similarity index 98% rename from Test/ClosureTest2/temp/052c7f96b9eefa2c.pyi rename to Test/ClosureTest2/temp/440f18f9dce85a95.pyi index b371ecf..0b2c4a4 100644 --- a/Test/ClosureTest2/temp/052c7f96b9eefa2c.pyi +++ b/Test/ClosureTest2/temp/440f18f9dce85a95.pyi @@ -8,6 +8,7 @@ import c import t import stdio +import testcheck def test_nonlocal_conditional() -> t.CInt: pass diff --git a/Test/ClosureTest2/temp/9dbecd0942a39782.pyi b/Test/ClosureTest2/temp/9dbecd0942a39782.pyi new file mode 100644 index 0000000..41648c1 --- /dev/null +++ b/Test/ClosureTest2/temp/9dbecd0942a39782.pyi @@ -0,0 +1,25 @@ +""" +Auto-generated Python stub file from testcheck.py +Module: testcheck +""" + + +import t, c +import stdio + +_pass_count: t.CExtern | t.CInt +_fail_count: t.CExtern | t.CInt + +def begin(name: str) -> t.CInt: pass + +def section(name: str) -> t.CInt: pass + +def ok(msg: str) -> t.CInt: pass + +def fail(msg: str) -> t.CInt: pass + +def check(cond: t.CInt, ok_msg: str, fail_msg: str) -> t.CInt: pass + +def info(msg: str) -> t.CInt: pass + +def end() -> t.CInt: pass diff --git a/Test/ClosureTest2/temp/_sha1_map.txt b/Test/ClosureTest2/temp/_sha1_map.txt index 8f2ff70..21991d5 100644 --- a/Test/ClosureTest2/temp/_sha1_map.txt +++ b/Test/ClosureTest2/temp/_sha1_map.txt @@ -1,2 +1,3 @@ -052c7f96b9eefa2c:main.py +440f18f9dce85a95:main.py 73edbcf76e32d00b:includes/stdio.py +9dbecd0942a39782:includes/testcheck.py diff --git a/Test/DecoratorMarkerTest/App/main.py b/Test/DecoratorMarkerTest/App/main.py new file mode 100644 index 0000000..09d4eac --- /dev/null +++ b/Test/DecoratorMarkerTest/App/main.py @@ -0,0 +1,77 @@ +import t +from stdio import printf +import testcheck + + +# 装饰器形式:@t.CStruct 等同于 class Point(t.CStruct): +@t.CStruct +class Point: + x: t.CInt + y: t.CInt + + +# 装饰器形式:@t.CEnum 等同于 class Color(t.CEnum): +@t.CEnum +class Color: + RED = 1 + GREEN = 2 + BLUE = 3 + + +# 装饰器形式:@t.CUnion 等同于 class Data(t.CUnion): +@t.CUnion +class Data: + i: t.CInt + f: t.CFloat + + +# 装饰器形式:@t.CExport 等同于 def test() -> t.CInt | t.CExport: +@t.CExport +def test() -> t.CInt: + printf("test_export called\n") + return 42 + + +# 装饰器形式:@t.CStatic 等同于 def static_func() -> t.CInt | t.CStatic: +@t.CStatic +def static_func() -> t.CInt: + return 100 + + +# 混合形式:装饰器 + 注解 +@t.CStatic +def mixed_func() -> t.CInt | t.CExport: + return 200 + + +def main() -> t.CInt: + testcheck.begin("DecoratorMarkerTest: 装饰器标记测试") + + p: Point = Point() + p.x = 10 + p.y = 20 + printf("Point: (%d, %d)\n", p.x, p.y) + testcheck.check(p.x == 10 and p.y == 20, "Point (10, 20)", "Point expect (10, 20)") + + c: t.CInt = Color.GREEN + printf("Color: %d\n", c) + testcheck.check(c == 2, "Color.GREEN == 2", "Color.GREEN expect 2") + + d: Data = Data() + d.i = 65 + printf("Data.i: %d\n", d.i) + testcheck.check(d.i == 65, "Data.i == 65", "Data.i expect 65") + + ret: t.CInt = test() + printf("test() returned: %d\n", ret) + testcheck.check(ret == 42, "test() returned 42", "test() expect 42") + + s: t.CInt = static_func() + printf("static_func() returned: %d\n", s) + testcheck.check(s == 100, "static_func() returned 100", "static_func() expect 100") + + m: t.CInt = mixed_func() + printf("mixed_func() returned: %d\n", m) + testcheck.check(m == 200, "mixed_func() returned 200", "mixed_func() expect 200") + + return testcheck.end() diff --git a/Test/DecoratorMarkerTest/output/9dbecd0942a39782.deps.json b/Test/DecoratorMarkerTest/output/9dbecd0942a39782.deps.json new file mode 100644 index 0000000..d9f1ce5 --- /dev/null +++ b/Test/DecoratorMarkerTest/output/9dbecd0942a39782.deps.json @@ -0,0 +1 @@ +{"stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "main": "b1122357fee8fd68"} \ No newline at end of file diff --git a/Test/DecoratorMarkerTest/output/b1122357fee8fd68.deps.json b/Test/DecoratorMarkerTest/output/b1122357fee8fd68.deps.json new file mode 100644 index 0000000..94ebae9 --- /dev/null +++ b/Test/DecoratorMarkerTest/output/b1122357fee8fd68.deps.json @@ -0,0 +1 @@ +{"stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782"} \ No newline at end of file diff --git a/Test/DecoratorMarkerTest/project.json b/Test/DecoratorMarkerTest/project.json new file mode 100644 index 0000000..c25d371 --- /dev/null +++ b/Test/DecoratorMarkerTest/project.json @@ -0,0 +1,29 @@ +{ + "$schema": "https://raw.githubusercontent.com/TermiNexus/TransPyC/main/schemas/project-schema.json", + "name": "DecoratorMarkerTest", + "version": "1.0.0", + "source_dir": "./App", + "temp_dir": "./temp", + "output_dir": "./output", + "compiler": { + "cmd": "llc", + "flags": ["-filetype=obj", "-relocation-model=pic"] + }, + "linker": { + "cmd": "clang++", + "flags": ["-lmsvcrt", "-lucrt", "-lpthread", "-lmingwex", "-lkernel32", "-Wl,--allow-multiple-definition"], + "output": "DecoratorMarkerTest.exe" + }, + "includes": [ + "../../includes" + ], + "target": { + "triple": "x86_64-pc-windows-gnu", + "datalayout": "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" + }, + "options": { + "slice_level": 3, + "target": "llvm", + "strict_mode": true + } +} diff --git a/Test/DecoratorMarkerTest/temp/73edbcf76e32d00b.pyi b/Test/DecoratorMarkerTest/temp/73edbcf76e32d00b.pyi new file mode 100644 index 0000000..ef712e3 --- /dev/null +++ b/Test/DecoratorMarkerTest/temp/73edbcf76e32d00b.pyi @@ -0,0 +1,28 @@ +""" +Auto-generated Python stub file from stdio.py +Module: stdio +""" + + +import t, c + +def printf(fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass + +def fprintf(stream: t.CVoid | t.CPtr, fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass + +def sprintf(buf: t.CChar | t.CPtr, fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass + +def snprintf(buf: t.CChar | t.CPtr, size: t.CSizeT, fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass + +def puts(s: t.CChar | t.CConst | t.CPtr) -> t.CInt | t.CExtern | t.CExport: pass + +def fputs(s: t.CChar | t.CConst | t.CPtr, stream: t.CVoid | t.CPtr) -> t.CInt | t.CExtern | t.CExport: pass + +def fgets(buf: t.CChar | t.CPtr, size: t.CInt, stream: t.CVoid | t.CPtr) -> t.CChar | t.CPtr | t.CExtern | t.CExport: pass + +def fflush(stream: t.CVoid | t.CPtr) -> t.CInt | t.CExtern | t.CExport: pass + + +stdin: t.CExtern | t.CVoid | t.CPtr +stdout: t.CExtern | t.CVoid | t.CPtr +stderr: t.CExtern | t.CVoid | t.CPtr \ No newline at end of file diff --git a/Test/DecoratorMarkerTest/temp/9dbecd0942a39782.pyi b/Test/DecoratorMarkerTest/temp/9dbecd0942a39782.pyi new file mode 100644 index 0000000..41648c1 --- /dev/null +++ b/Test/DecoratorMarkerTest/temp/9dbecd0942a39782.pyi @@ -0,0 +1,25 @@ +""" +Auto-generated Python stub file from testcheck.py +Module: testcheck +""" + + +import t, c +import stdio + +_pass_count: t.CExtern | t.CInt +_fail_count: t.CExtern | t.CInt + +def begin(name: str) -> t.CInt: pass + +def section(name: str) -> t.CInt: pass + +def ok(msg: str) -> t.CInt: pass + +def fail(msg: str) -> t.CInt: pass + +def check(cond: t.CInt, ok_msg: str, fail_msg: str) -> t.CInt: pass + +def info(msg: str) -> t.CInt: pass + +def end() -> t.CInt: pass diff --git a/Test/DecoratorMarkerTest/temp/_sha1_map.txt b/Test/DecoratorMarkerTest/temp/_sha1_map.txt new file mode 100644 index 0000000..6d5594a --- /dev/null +++ b/Test/DecoratorMarkerTest/temp/_sha1_map.txt @@ -0,0 +1,3 @@ +73edbcf76e32d00b:includes/stdio.py +9dbecd0942a39782:includes/testcheck.py +b1122357fee8fd68:main.py diff --git a/Test/DecoratorMarkerTest/temp/b1122357fee8fd68.pyi b/Test/DecoratorMarkerTest/temp/b1122357fee8fd68.pyi new file mode 100644 index 0000000..97850c4 --- /dev/null +++ b/Test/DecoratorMarkerTest/temp/b1122357fee8fd68.pyi @@ -0,0 +1,36 @@ +""" +Auto-generated Python stub file from main.py +Module: main +""" + +import c + + +import t +from stdio import printf +import testcheck + +@t.CStruct +class Point: + x: t.CInt + y: t.CInt +@t.CEnum +class Color: + RED = 1 + GREEN = 2 + BLUE = 3 +@t.CUnion +class Data: + i: t.CInt + f: t.CFloat + +@t.CExport +def test() -> t.CInt: pass + +@t.CStatic +def static_func() -> t.CInt: pass + +@t.CStatic +def mixed_func() -> t.CInt | t.CExport: pass + +def main() -> t.CInt: pass diff --git a/Test/DecoratorTest/App/main.py b/Test/DecoratorTest/App/main.py index 21cf473..97553c5 100644 --- a/Test/DecoratorTest/App/main.py +++ b/Test/DecoratorTest/App/main.py @@ -1,5 +1,6 @@ import t from stdio import printf +import testcheck # ============================================================ # 自定义装饰器处理函数 @@ -226,65 +227,72 @@ def fib(n: t.CInt) -> t.CInt | t.CExport: # ============================================================ def main() -> t.CInt | t.CExport: - printf("=== Decorator Test v4 ===\n\n") + testcheck.begin("Decorator Test v4") # 测试 1:单个 @log - printf("--- Test 1: single @log ---\n") + testcheck.section("Test 1: single @log") r1: t.CInt = add(3, 4) - printf("add(3,4) = %d\n\n", r1) + printf("add(3,4) = %d\n", r1) + testcheck.check(r1 == 7, "add(3,4) = 7", "add(3,4) expect 7") # 测试 2:链式 @log @trace - printf("--- Test 2: chained @log @trace ---\n") + testcheck.section("Test 2: chained @log @trace") r2: t.CInt = multiply(5, 6) - printf("multiply(5,6) = %d\n\n", r2) + printf("multiply(5,6) = %d\n", r2) + testcheck.check(r2 == 30, "multiply(5,6) = 30", "multiply(5,6) expect 30") # 测试 3:void 返回 - printf("--- Test 3: @log on void function ---\n") + testcheck.section("Test 3: @log on void function") greet("Viper") - printf("\n") + testcheck.ok("@log on void function greet") # 测试 4:无参数 - printf("--- Test 4: @log on no-arg function ---\n") + testcheck.section("Test 4: @log on no-arg function") r4: t.CInt = get_value() - printf("get_value() = %d\n\n", r4) + printf("get_value() = %d\n", r4) + testcheck.check(r4 == 42, "get_value() = 42", "get_value() expect 42") # 测试 5:@timing - printf("--- Test 5: @timing ---\n") + testcheck.section("Test 5: @timing") r5: t.CInt = compute(7) - printf("compute(7) = %d\n\n", r5) + printf("compute(7) = %d\n", r5) + testcheck.check(r5 == 50, "compute(7) = 50", "compute(7) expect 50") # 测试 6:@repeat(3) — 流程劫持,循环 3 次 - printf("--- Test 6: @repeat(3) flow hijack ---\n") + testcheck.section("Test 6: @repeat(3) flow hijack") echo("hello") - printf("\n") + testcheck.ok("@repeat(3) flow hijack echo") # 测试 7:链式 @timing @log - printf("--- Test 7: chained @timing @log ---\n") + testcheck.section("Test 7: chained @timing @log") r7: t.CInt = power(2, 10) - printf("power(2,10) = %d\n\n", r7) + printf("power(2,10) = %d\n", r7) + testcheck.check(r7 == 1024, "power(2,10) = 1024", "power(2,10) expect 1024") # 测试 8:@skip — 跳过原函数调用 - printf("--- Test 8: @skip flow hijack ---\n") + testcheck.section("Test 8: @skip flow hijack") r8: t.CInt = dangerous() - printf("dangerous() = %d (should be 0, skipped)\n\n", r8) + printf("dangerous() = %d (should be 0, skipped)\n", r8) + testcheck.check(r8 == 0, "dangerous() skipped = 0", "dangerous() expect 0") # 测试 9:@repeat(3) 有返回值 - printf("--- Test 9: @repeat(3) with return value ---\n") + testcheck.section("Test 9: @repeat(3) with return value") r9: t.CInt = accumulate(5) - printf("accumulate(5) = %d (last iteration result)\n\n", r9) + printf("accumulate(5) = %d (last iteration result)\n", r9) + testcheck.check(r9 == 50, "accumulate(5) = 50", "accumulate(5) expect 50") # 测试 10:递归装饰保护 — @count_calls - printf("--- Test 10: recursive decoration protection ---\n") + testcheck.section("Test 10: recursive decoration protection") _call_count = 0 r10: t.CInt = factorial(5) printf("factorial(5) = %d (should be 120)\n", r10) - printf(" decorator call count = %d (should be 1, not 5)\n\n", _call_count) + printf(" decorator call count = %d (should be 1, not 5)\n", _call_count) + testcheck.check(r10 == 120 and _call_count == 1, "factorial(5)=120, calls=1", "factorial(5) expect 120, calls=1") # 测试 11:@log 递归保护 — fib - printf("--- Test 11: @log on recursive fib ---\n") + testcheck.section("Test 11: @log on recursive fib") r11: t.CInt = fib(6) printf("fib(6) = %d (should be 8)\n", r11) - printf(" (should see only 1 LOG enter/exit pair)\n\n") + testcheck.check(r11 == 8, "fib(6) = 8", "fib(6) expect 8") - printf("=== All decorator tests done ===\n") - return 0 + return testcheck.end() diff --git a/Test/DecoratorTest/output/577f9e1aa32b17f8.deps.json b/Test/DecoratorTest/output/577f9e1aa32b17f8.deps.json deleted file mode 100644 index 073d6e7..0000000 --- a/Test/DecoratorTest/output/577f9e1aa32b17f8.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"stdio": "73edbcf76e32d00b"} \ No newline at end of file diff --git a/Test/DecoratorTest/output/814e6b31adfc6256.deps.json b/Test/DecoratorTest/output/814e6b31adfc6256.deps.json new file mode 100644 index 0000000..94ebae9 --- /dev/null +++ b/Test/DecoratorTest/output/814e6b31adfc6256.deps.json @@ -0,0 +1 @@ +{"stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782"} \ No newline at end of file diff --git a/Test/DecoratorTest/output/9dbecd0942a39782.deps.json b/Test/DecoratorTest/output/9dbecd0942a39782.deps.json new file mode 100644 index 0000000..d0eeac8 --- /dev/null +++ b/Test/DecoratorTest/output/9dbecd0942a39782.deps.json @@ -0,0 +1 @@ +{"stdio": "73edbcf76e32d00b", "main": "814e6b31adfc6256", "testcheck": "9dbecd0942a39782"} \ No newline at end of file diff --git a/Test/DecoratorTest/temp/577f9e1aa32b17f8.pyi b/Test/DecoratorTest/temp/814e6b31adfc6256.pyi similarity index 99% rename from Test/DecoratorTest/temp/577f9e1aa32b17f8.pyi rename to Test/DecoratorTest/temp/814e6b31adfc6256.pyi index fa3ba61..0a0bccf 100644 --- a/Test/DecoratorTest/temp/577f9e1aa32b17f8.pyi +++ b/Test/DecoratorTest/temp/814e6b31adfc6256.pyi @@ -8,6 +8,7 @@ import c import t from stdio import printf +import testcheck def log(ctx: t.CVoid | t.CPtr, func_name: str, phase: t.CInt, args_ptr: t.CVoid | t.CPtr, ret_ptr: t.CVoid | t.CPtr, decor_args_ptr: t.CVoid | t.CPtr) -> t.CInt | t.CExport: pass diff --git a/Test/DecoratorTest/temp/9dbecd0942a39782.pyi b/Test/DecoratorTest/temp/9dbecd0942a39782.pyi new file mode 100644 index 0000000..41648c1 --- /dev/null +++ b/Test/DecoratorTest/temp/9dbecd0942a39782.pyi @@ -0,0 +1,25 @@ +""" +Auto-generated Python stub file from testcheck.py +Module: testcheck +""" + + +import t, c +import stdio + +_pass_count: t.CExtern | t.CInt +_fail_count: t.CExtern | t.CInt + +def begin(name: str) -> t.CInt: pass + +def section(name: str) -> t.CInt: pass + +def ok(msg: str) -> t.CInt: pass + +def fail(msg: str) -> t.CInt: pass + +def check(cond: t.CInt, ok_msg: str, fail_msg: str) -> t.CInt: pass + +def info(msg: str) -> t.CInt: pass + +def end() -> t.CInt: pass diff --git a/Test/DecoratorTest/temp/_sha1_map.txt b/Test/DecoratorTest/temp/_sha1_map.txt index 8a3a6d8..09f38fe 100644 --- a/Test/DecoratorTest/temp/_sha1_map.txt +++ b/Test/DecoratorTest/temp/_sha1_map.txt @@ -1,2 +1,3 @@ -577f9e1aa32b17f8:main.py 73edbcf76e32d00b:includes/stdio.py +814e6b31adfc6256:main.py +9dbecd0942a39782:includes/testcheck.py diff --git a/Test/DictTest/App/main.py b/Test/DictTest/App/main.py new file mode 100644 index 0000000..8ba172e --- /dev/null +++ b/Test/DictTest/App/main.py @@ -0,0 +1,230 @@ +from stdint import * +import w32.win32console +import t, c +from t import CInt, CExport +import stdio +import stdlib +import string +import mbuddy +import mpool +import testcheck + + +def main() -> CInt | CExport: + w32.win32console.SetConsoleCP(65001) + w32.win32console.SetConsoleOutputCP(65001) + + testcheck.begin("DictTest: 万能 dict (Variant 存储) 测试") + + # 分配内存竞技场 + arena: bytes = stdlib.malloc(65536) + bd: mbuddy.MBuddy | t.CPtr = mbuddy.MBuddy(arena, 65536) + + # === Test 1: dict set_int / c.Deref 基本操作 === + testcheck.section("Test 1: dict set_int / c.Deref 基本操作") + d: dict = dict(bd) + d.set_int("alpha", 10) + d.set_int("beta", 20) + d.set_int("gamma", 30) + n: t.CSizeT = len(d) + stdio.printf("len=%lu\n", n) + testcheck.check(n == 3, "dict len OK (3)", "dict len FAILED") + + p1: t.CPtr = d["alpha"] + stdio.printf("p1=%p\n", p1) + p2: t.CPtr = d["beta"] + stdio.printf("p2=%p\n", p2) + p3: t.CPtr = d["gamma"] + stdio.printf("p3=%p\n", p3) + v1: int = c.Deref(p1) + stdio.printf("v1=%d\n", v1) + v2: int = c.Deref(p2) + v3: int = c.Deref(p3) + stdio.printf("alpha=%d beta=%d gamma=%d\n", v1, v2, v3) + testcheck.check(v1 == 10, "dict[alpha]==10 OK", "dict[alpha] FAILED") + testcheck.check(v2 == 20, "dict[beta]==20 OK", "dict[beta] FAILED") + testcheck.check(v3 == 30, "dict[gamma]==30 OK", "dict[gamma] FAILED") + + # === Test 2: 更新已有键 === + testcheck.section("Test 2: 更新已有键") + d.set_int("beta", 99) + p2b: t.CPtr = d["beta"] + v2b: int = c.Deref(p2b) + stdio.printf("beta(updated)=%d\n", v2b) + testcheck.check(v2b == 99, "dict update OK", "dict update FAILED") + testcheck.check(len(d) == 3, "dict len still 3 OK", "dict len changed FAILED") + + # === Test 3: get with default === + testcheck.section("Test 3: get with default") + gv: t.CPtr = d.get("missing", None) + testcheck.check(gv == None, "dict get missing OK (None)", "dict get missing FAILED") + + gp: t.CPtr = d.get("alpha", None) + ga: int = c.Deref(gp) + stdio.printf("get(alpha)=%d\n", ga) + testcheck.check(ga == 10, "dict get existing OK", "dict get existing FAILED") + + # === Test 4: contains === + testcheck.section("Test 4: contains") + has_alpha: t.CInt = d.contains("alpha") + has_missing: t.CInt = d.contains("missing") + stdio.printf("contains(alpha)=%d contains(missing)=%d\n", has_alpha, has_missing) + testcheck.check(has_alpha == 1, "contains alpha OK", "contains alpha FAILED") + testcheck.check(has_missing == 0, "not contains missing OK", "contains missing FAILED") + + # === Test 5: 迭代器 === + testcheck.section("Test 5: 迭代器 for key in dict") + iter_count: int = 0 + for key in d: + kp: t.CPtr = d[key] + val: int = c.Deref(kp) + stdio.printf("dict[%s]=%d\n", key, val) + iter_count += 1 + testcheck.check(iter_count == 3, "dict iter OK (3)", "dict iter FAILED") + + # === Test 6: dict set_str 字符串值 === + testcheck.section("Test 6: dict set_str 字符串值") + d2: dict = dict(bd) + d2.set_str("name", "Alice") + d2.set_str("city", "Beijing") + d2.set_str("lang", "TransPyC") + n2: t.CSizeT = len(d2) + stdio.printf("d2 len=%lu\n", n2) + testcheck.check(n2 == 3, "dict set_str len OK (3)", "dict set_str len FAILED") + + name_p: t.CPtr = d2["name"] + city_p: t.CPtr = d2["city"] + lang_p: t.CPtr = d2["lang"] + name: str = name_p + city: str = city_p + lang: str = lang_p + stdio.printf("name=%s city=%s lang=%s\n", name, city, lang) + testcheck.check(string.strcmp(name, "Alice") == 0, "dict str name OK", "dict str name FAILED") + testcheck.check(string.strcmp(city, "Beijing") == 0, "dict str city OK", "dict str city FAILED") + testcheck.check(string.strcmp(lang, "TransPyC") == 0, "dict str lang OK", "dict str lang FAILED") + + # === Test 7: dict[str] 迭代 === + testcheck.section("Test 7: dict 迭代 (str values)") + str_iter_count: int = 0 + for k in d2: + svp: t.CPtr = d2[k] + sv: str = svp + stdio.printf("d2[%s]=%s\n", k, sv) + str_iter_count += 1 + testcheck.check(str_iter_count == 3, "dict str iter OK (3)", "dict str iter FAILED") + + # === Test 8: 扩容测试 === + testcheck.section("Test 8: 扩容测试 (>8 个元素)") + d3: dict = dict(bd) + i: int = 0 + while i < 20: + key_buf: str = stdlib.malloc(16) + stdio.sprintf(key_buf, "key%d", i) + d3.set_int(key_buf, i * 100) + i += 1 + n3: t.CSizeT = len(d3) + stdio.printf("d3 len=%lu (after 20 inserts)\n", n3) + testcheck.check(n3 == 20, "dict expand OK (20)", "dict expand FAILED") + + # 验证几个值 + k5: str = stdlib.malloc(16) + stdio.sprintf(k5, "key5") + p5: t.CPtr = d3[k5] + v5: int = c.Deref(p5) + stdio.printf("d3[key5]=%d\n", v5) + testcheck.check(v5 == 500, "dict expand key5 OK", "dict expand key5 FAILED") + + k15: str = stdlib.malloc(16) + stdio.sprintf(k15, "key15") + p15: t.CPtr = d3[k15] + v15: int = c.Deref(p15) + stdio.printf("d3[key15]=%d\n", v15) + testcheck.check(v15 == 1500, "dict expand key15 OK", "dict expand key15 FAILED") + + # === Test 9: JSON dumps === + testcheck.section("Test 9: JSON dumps") + pool_mem: bytes = stdlib.malloc(65536) + pool: mpool.MPool = mpool.MPool(pool_mem, 65536, 0) + + jd: dict = dict(bd) + jd.set_int("x", 100) + jd.set_int("y", 200) + jd.set_int("z", 300) + + json_str: str = jd.dumps(pool) + stdio.printf("JSON dumps: %s\n", json_str) + testcheck.check(json_str != None, "dumps OK", "dumps FAILED (null)") + + # === Test 10: JSON loads === + testcheck.section("Test 10: JSON loads") + jd2: dict = dict(bd) + jd2.loads(pool, "{\"x\":1,\"y\":2,\"z\":3}") + xp: t.CPtr = jd2["x"] + yp: t.CPtr = jd2["y"] + zp: t.CPtr = jd2["z"] + xv: int = c.Deref(xp) + yv: int = c.Deref(yp) + zv: int = c.Deref(zp) + stdio.printf("loads: x=%d y=%d z=%d\n", xv, yv, zv) + testcheck.check(xv == 1, "loads x OK", "loads x FAILED") + testcheck.check(yv == 2, "loads y OK", "loads y FAILED") + testcheck.check(zv == 3, "loads z OK", "loads z FAILED") + + # === Test 11: JSON dumps (str values) === + testcheck.section("Test 11: JSON dumps (str values)") + jd3: dict = dict(bd) + jd3.set_str("name", "Alice") + jd3.set_str("city", "Beijing") + + json_str2: str = jd3.dumps(pool) + stdio.printf("JSON dumps (str): %s\n", json_str2) + testcheck.check(json_str2 != None, "dumps str OK", "dumps str FAILED (null)") + + # === Test 12: JSON round-trip === + testcheck.section("Test 12: JSON round-trip") + rt: dict = dict(bd) + rt.set_int("a", 1) + rt.set_int("b", 2) + rt_str: str = rt.dumps(pool) + stdio.printf("round-trip dump: %s\n", rt_str) + rt2: dict = dict(bd) + rt2.loads(pool, rt_str) + rta_p: t.CPtr = rt2["a"] + rtb_p: t.CPtr = rt2["b"] + rta: int = c.Deref(rta_p) + rtb: int = c.Deref(rtb_p) + stdio.printf("round-trip: a=%d b=%d\n", rta, rtb) + testcheck.check(rta == 1, "round-trip a OK", "round-trip a FAILED") + testcheck.check(rtb == 2, "round-trip b OK", "round-trip b FAILED") + + # === Test 13: 嵌套 dict === + testcheck.section("Test 13: 嵌套 dict") + outer: dict = dict(bd) + inner: dict = dict(bd) + inner.set_int("a", 1) + inner.set_int("b", 2) + outer.set_dict("sub", inner) + + sub_p: t.CPtr = outer["sub"] + sub: dict = sub_p + sa_p: t.CPtr = sub["a"] + sb_p: t.CPtr = sub["b"] + sa: int = c.Deref(sa_p) + sb: int = c.Deref(sb_p) + stdio.printf("nested: sub.a=%d sub.b=%d\n", sa, sb) + testcheck.check(sa == 1, "nested sub.a OK", "nested sub.a FAILED") + testcheck.check(sb == 2, "nested sub.b OK", "nested sub.b FAILED") + + # === Test 14: get_vtype 类型标签 === + testcheck.section("Test 14: get_vtype 类型标签") + vt1: t.CInt = d.get_vtype("alpha") + vt2: t.CInt = d2.get_vtype("name") + vt3: t.CInt = outer.get_vtype("sub") + stdio.printf("vtype(alpha)=%d vtype(name)=%d vtype(sub)=%d\n", vt1, vt2, vt3) + testcheck.check(vt1 == 1, "vtype int OK", "vtype int FAILED") + testcheck.check(vt2 == 4, "vtype str OK", "vtype str FAILED") + testcheck.check(vt3 == 5, "vtype dict OK", "vtype dict FAILED") + + stdlib.free(pool_mem) + stdlib.free(arena) + return testcheck.end() diff --git a/Test/DictTest/output/067c78e9f121dce3.deps.json b/Test/DictTest/output/067c78e9f121dce3.deps.json new file mode 100644 index 0000000..e62bd88 --- /dev/null +++ b/Test/DictTest/output/067c78e9f121dce3.deps.json @@ -0,0 +1 @@ +{"mpool": "0991af0d22263577", "mbuddy": "0eaa586c42dcd931", "atom": "271ea3decb810db2", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "json.__init__": "8ee3170049c70333", "__init__": "8ee3170049c70333", "json": "8ee3170049c70333", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "json.__parser": "bd2e7db1744476fe", "__parser": "bd2e7db1744476fe", "viperio": "c9f4be41ca1cc2b4", "json.__writer": "eaf7a981f0ef5b22", "__writer": "eaf7a981f0ef5b22", "_dict": "f1e15ccf054b1e89", "main": "fced53b138f67cf5", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3"} \ No newline at end of file diff --git a/Test/DictTest/output/06f53cc594b4ac6c.deps.json b/Test/DictTest/output/06f53cc594b4ac6c.deps.json new file mode 100644 index 0000000..9d051f1 --- /dev/null +++ b/Test/DictTest/output/06f53cc594b4ac6c.deps.json @@ -0,0 +1 @@ +{"mpool": "0991af0d22263577", "mbuddy": "0eaa586c42dcd931", "atom": "271ea3decb810db2", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "json.__init__": "8ee3170049c70333", "__init__": "8ee3170049c70333", "json": "8ee3170049c70333", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "json.__parser": "bd2e7db1744476fe", "__parser": "bd2e7db1744476fe", "viperio": "c9f4be41ca1cc2b4", "json.__writer": "eaf7a981f0ef5b22", "__writer": "eaf7a981f0ef5b22", "_dict": "f1e15ccf054b1e89", "main": "fced53b138f67cf5", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "06f53cc594b4ac6c", "win32sync": "06f53cc594b4ac6c"} \ No newline at end of file diff --git a/Test/DictTest/output/0991af0d22263577.deps.json b/Test/DictTest/output/0991af0d22263577.deps.json new file mode 100644 index 0000000..5f003b1 --- /dev/null +++ b/Test/DictTest/output/0991af0d22263577.deps.json @@ -0,0 +1 @@ +{"mpool": "0991af0d22263577", "mbuddy": "0eaa586c42dcd931", "atom": "271ea3decb810db2", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "json.__init__": "8ee3170049c70333", "__init__": "8ee3170049c70333", "json": "8ee3170049c70333", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "json.__parser": "bd2e7db1744476fe", "__parser": "bd2e7db1744476fe", "viperio": "c9f4be41ca1cc2b4", "json.__writer": "eaf7a981f0ef5b22", "__writer": "eaf7a981f0ef5b22", "_dict": "f1e15ccf054b1e89", "main": "fced53b138f67cf5"} \ No newline at end of file diff --git a/Test/DictTest/output/0eaa586c42dcd931.deps.json b/Test/DictTest/output/0eaa586c42dcd931.deps.json new file mode 100644 index 0000000..5f003b1 --- /dev/null +++ b/Test/DictTest/output/0eaa586c42dcd931.deps.json @@ -0,0 +1 @@ +{"mpool": "0991af0d22263577", "mbuddy": "0eaa586c42dcd931", "atom": "271ea3decb810db2", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "json.__init__": "8ee3170049c70333", "__init__": "8ee3170049c70333", "json": "8ee3170049c70333", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "json.__parser": "bd2e7db1744476fe", "__parser": "bd2e7db1744476fe", "viperio": "c9f4be41ca1cc2b4", "json.__writer": "eaf7a981f0ef5b22", "__writer": "eaf7a981f0ef5b22", "_dict": "f1e15ccf054b1e89", "main": "fced53b138f67cf5"} \ No newline at end of file diff --git a/Test/DictTest/output/271ea3decb810db2.deps.json b/Test/DictTest/output/271ea3decb810db2.deps.json new file mode 100644 index 0000000..5f003b1 --- /dev/null +++ b/Test/DictTest/output/271ea3decb810db2.deps.json @@ -0,0 +1 @@ +{"mpool": "0991af0d22263577", "mbuddy": "0eaa586c42dcd931", "atom": "271ea3decb810db2", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "json.__init__": "8ee3170049c70333", "__init__": "8ee3170049c70333", "json": "8ee3170049c70333", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "json.__parser": "bd2e7db1744476fe", "__parser": "bd2e7db1744476fe", "viperio": "c9f4be41ca1cc2b4", "json.__writer": "eaf7a981f0ef5b22", "__writer": "eaf7a981f0ef5b22", "_dict": "f1e15ccf054b1e89", "main": "fced53b138f67cf5"} \ No newline at end of file diff --git a/Test/DictTest/output/5a6a2137958c28c5.deps.json b/Test/DictTest/output/5a6a2137958c28c5.deps.json new file mode 100644 index 0000000..5f003b1 --- /dev/null +++ b/Test/DictTest/output/5a6a2137958c28c5.deps.json @@ -0,0 +1 @@ +{"mpool": "0991af0d22263577", "mbuddy": "0eaa586c42dcd931", "atom": "271ea3decb810db2", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "json.__init__": "8ee3170049c70333", "__init__": "8ee3170049c70333", "json": "8ee3170049c70333", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "json.__parser": "bd2e7db1744476fe", "__parser": "bd2e7db1744476fe", "viperio": "c9f4be41ca1cc2b4", "json.__writer": "eaf7a981f0ef5b22", "__writer": "eaf7a981f0ef5b22", "_dict": "f1e15ccf054b1e89", "main": "fced53b138f67cf5"} \ No newline at end of file diff --git a/Test/DictTest/output/72e2d5ccb7cedcf1.deps.json b/Test/DictTest/output/72e2d5ccb7cedcf1.deps.json new file mode 100644 index 0000000..a066bf6 --- /dev/null +++ b/Test/DictTest/output/72e2d5ccb7cedcf1.deps.json @@ -0,0 +1 @@ +{"mpool": "0991af0d22263577", "mbuddy": "0eaa586c42dcd931", "atom": "271ea3decb810db2", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "json.__init__": "8ee3170049c70333", "__init__": "8ee3170049c70333", "json": "8ee3170049c70333", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "json.__parser": "bd2e7db1744476fe", "__parser": "bd2e7db1744476fe", "viperio": "c9f4be41ca1cc2b4", "json.__writer": "eaf7a981f0ef5b22", "__writer": "eaf7a981f0ef5b22", "_dict": "f1e15ccf054b1e89", "main": "fced53b138f67cf5", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1"} \ No newline at end of file diff --git a/Test/DictTest/output/8ee3170049c70333.deps.json b/Test/DictTest/output/8ee3170049c70333.deps.json new file mode 100644 index 0000000..5f003b1 --- /dev/null +++ b/Test/DictTest/output/8ee3170049c70333.deps.json @@ -0,0 +1 @@ +{"mpool": "0991af0d22263577", "mbuddy": "0eaa586c42dcd931", "atom": "271ea3decb810db2", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "json.__init__": "8ee3170049c70333", "__init__": "8ee3170049c70333", "json": "8ee3170049c70333", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "json.__parser": "bd2e7db1744476fe", "__parser": "bd2e7db1744476fe", "viperio": "c9f4be41ca1cc2b4", "json.__writer": "eaf7a981f0ef5b22", "__writer": "eaf7a981f0ef5b22", "_dict": "f1e15ccf054b1e89", "main": "fced53b138f67cf5"} \ No newline at end of file diff --git a/Test/DictTest/output/9dbecd0942a39782.deps.json b/Test/DictTest/output/9dbecd0942a39782.deps.json new file mode 100644 index 0000000..5f003b1 --- /dev/null +++ b/Test/DictTest/output/9dbecd0942a39782.deps.json @@ -0,0 +1 @@ +{"mpool": "0991af0d22263577", "mbuddy": "0eaa586c42dcd931", "atom": "271ea3decb810db2", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "json.__init__": "8ee3170049c70333", "__init__": "8ee3170049c70333", "json": "8ee3170049c70333", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "json.__parser": "bd2e7db1744476fe", "__parser": "bd2e7db1744476fe", "viperio": "c9f4be41ca1cc2b4", "json.__writer": "eaf7a981f0ef5b22", "__writer": "eaf7a981f0ef5b22", "_dict": "f1e15ccf054b1e89", "main": "fced53b138f67cf5"} \ No newline at end of file diff --git a/Test/DictTest/output/abf9ce3160c9279e.deps.json b/Test/DictTest/output/abf9ce3160c9279e.deps.json new file mode 100644 index 0000000..49ca6dc --- /dev/null +++ b/Test/DictTest/output/abf9ce3160c9279e.deps.json @@ -0,0 +1 @@ +{"mpool": "0991af0d22263577", "mbuddy": "0eaa586c42dcd931", "atom": "271ea3decb810db2", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "json.__init__": "8ee3170049c70333", "__init__": "8ee3170049c70333", "json": "8ee3170049c70333", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "json.__parser": "bd2e7db1744476fe", "__parser": "bd2e7db1744476fe", "viperio": "c9f4be41ca1cc2b4", "json.__writer": "eaf7a981f0ef5b22", "__writer": "eaf7a981f0ef5b22", "_dict": "f1e15ccf054b1e89", "main": "fced53b138f67cf5", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e"} \ No newline at end of file diff --git a/Test/DictTest/output/b5f1dc665c52a1bd.deps.json b/Test/DictTest/output/b5f1dc665c52a1bd.deps.json new file mode 100644 index 0000000..5f003b1 --- /dev/null +++ b/Test/DictTest/output/b5f1dc665c52a1bd.deps.json @@ -0,0 +1 @@ +{"mpool": "0991af0d22263577", "mbuddy": "0eaa586c42dcd931", "atom": "271ea3decb810db2", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "json.__init__": "8ee3170049c70333", "__init__": "8ee3170049c70333", "json": "8ee3170049c70333", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "json.__parser": "bd2e7db1744476fe", "__parser": "bd2e7db1744476fe", "viperio": "c9f4be41ca1cc2b4", "json.__writer": "eaf7a981f0ef5b22", "__writer": "eaf7a981f0ef5b22", "_dict": "f1e15ccf054b1e89", "main": "fced53b138f67cf5"} \ No newline at end of file diff --git a/Test/DictTest/output/bbdf3bbd4c3bc28c.deps.json b/Test/DictTest/output/bbdf3bbd4c3bc28c.deps.json new file mode 100644 index 0000000..5f003b1 --- /dev/null +++ b/Test/DictTest/output/bbdf3bbd4c3bc28c.deps.json @@ -0,0 +1 @@ +{"mpool": "0991af0d22263577", "mbuddy": "0eaa586c42dcd931", "atom": "271ea3decb810db2", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "json.__init__": "8ee3170049c70333", "__init__": "8ee3170049c70333", "json": "8ee3170049c70333", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "json.__parser": "bd2e7db1744476fe", "__parser": "bd2e7db1744476fe", "viperio": "c9f4be41ca1cc2b4", "json.__writer": "eaf7a981f0ef5b22", "__writer": "eaf7a981f0ef5b22", "_dict": "f1e15ccf054b1e89", "main": "fced53b138f67cf5"} \ No newline at end of file diff --git a/Test/DictTest/output/bd2e7db1744476fe.deps.json b/Test/DictTest/output/bd2e7db1744476fe.deps.json new file mode 100644 index 0000000..5f003b1 --- /dev/null +++ b/Test/DictTest/output/bd2e7db1744476fe.deps.json @@ -0,0 +1 @@ +{"mpool": "0991af0d22263577", "mbuddy": "0eaa586c42dcd931", "atom": "271ea3decb810db2", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "json.__init__": "8ee3170049c70333", "__init__": "8ee3170049c70333", "json": "8ee3170049c70333", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "json.__parser": "bd2e7db1744476fe", "__parser": "bd2e7db1744476fe", "viperio": "c9f4be41ca1cc2b4", "json.__writer": "eaf7a981f0ef5b22", "__writer": "eaf7a981f0ef5b22", "_dict": "f1e15ccf054b1e89", "main": "fced53b138f67cf5"} \ No newline at end of file diff --git a/Test/DictTest/output/c9f4be41ca1cc2b4.deps.json b/Test/DictTest/output/c9f4be41ca1cc2b4.deps.json new file mode 100644 index 0000000..5f003b1 --- /dev/null +++ b/Test/DictTest/output/c9f4be41ca1cc2b4.deps.json @@ -0,0 +1 @@ +{"mpool": "0991af0d22263577", "mbuddy": "0eaa586c42dcd931", "atom": "271ea3decb810db2", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "json.__init__": "8ee3170049c70333", "__init__": "8ee3170049c70333", "json": "8ee3170049c70333", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "json.__parser": "bd2e7db1744476fe", "__parser": "bd2e7db1744476fe", "viperio": "c9f4be41ca1cc2b4", "json.__writer": "eaf7a981f0ef5b22", "__writer": "eaf7a981f0ef5b22", "_dict": "f1e15ccf054b1e89", "main": "fced53b138f67cf5"} \ No newline at end of file diff --git a/Test/DictTest/output/eaf7a981f0ef5b22.deps.json b/Test/DictTest/output/eaf7a981f0ef5b22.deps.json new file mode 100644 index 0000000..5f003b1 --- /dev/null +++ b/Test/DictTest/output/eaf7a981f0ef5b22.deps.json @@ -0,0 +1 @@ +{"mpool": "0991af0d22263577", "mbuddy": "0eaa586c42dcd931", "atom": "271ea3decb810db2", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "json.__init__": "8ee3170049c70333", "__init__": "8ee3170049c70333", "json": "8ee3170049c70333", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "json.__parser": "bd2e7db1744476fe", "__parser": "bd2e7db1744476fe", "viperio": "c9f4be41ca1cc2b4", "json.__writer": "eaf7a981f0ef5b22", "__writer": "eaf7a981f0ef5b22", "_dict": "f1e15ccf054b1e89", "main": "fced53b138f67cf5"} \ No newline at end of file diff --git a/Test/DictTest/output/f1e15ccf054b1e89.deps.json b/Test/DictTest/output/f1e15ccf054b1e89.deps.json new file mode 100644 index 0000000..5f003b1 --- /dev/null +++ b/Test/DictTest/output/f1e15ccf054b1e89.deps.json @@ -0,0 +1 @@ +{"mpool": "0991af0d22263577", "mbuddy": "0eaa586c42dcd931", "atom": "271ea3decb810db2", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "json.__init__": "8ee3170049c70333", "__init__": "8ee3170049c70333", "json": "8ee3170049c70333", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "json.__parser": "bd2e7db1744476fe", "__parser": "bd2e7db1744476fe", "viperio": "c9f4be41ca1cc2b4", "json.__writer": "eaf7a981f0ef5b22", "__writer": "eaf7a981f0ef5b22", "_dict": "f1e15ccf054b1e89", "main": "fced53b138f67cf5"} \ No newline at end of file diff --git a/Test/DictTest/output/fa3691e66b426950.deps.json b/Test/DictTest/output/fa3691e66b426950.deps.json new file mode 100644 index 0000000..451f31f --- /dev/null +++ b/Test/DictTest/output/fa3691e66b426950.deps.json @@ -0,0 +1 @@ +{"mpool": "0991af0d22263577", "mbuddy": "0eaa586c42dcd931", "atom": "271ea3decb810db2", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "json.__init__": "8ee3170049c70333", "__init__": "8ee3170049c70333", "json": "8ee3170049c70333", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "json.__parser": "bd2e7db1744476fe", "__parser": "bd2e7db1744476fe", "viperio": "c9f4be41ca1cc2b4", "json.__writer": "eaf7a981f0ef5b22", "__writer": "eaf7a981f0ef5b22", "_dict": "f1e15ccf054b1e89", "main": "fced53b138f67cf5", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file diff --git a/Test/DictTest/output/fced53b138f67cf5.deps.json b/Test/DictTest/output/fced53b138f67cf5.deps.json new file mode 100644 index 0000000..7444bd6 --- /dev/null +++ b/Test/DictTest/output/fced53b138f67cf5.deps.json @@ -0,0 +1 @@ +{"mpool": "0991af0d22263577", "mbuddy": "0eaa586c42dcd931", "atom": "271ea3decb810db2", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "json.__init__": "8ee3170049c70333", "__init__": "8ee3170049c70333", "json": "8ee3170049c70333", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "json.__parser": "bd2e7db1744476fe", "__parser": "bd2e7db1744476fe", "viperio": "c9f4be41ca1cc2b4", "json.__writer": "eaf7a981f0ef5b22", "__writer": "eaf7a981f0ef5b22", "_dict": "f1e15ccf054b1e89"} \ No newline at end of file diff --git a/Test/DictTest/project.json b/Test/DictTest/project.json new file mode 100644 index 0000000..3d3fb5f --- /dev/null +++ b/Test/DictTest/project.json @@ -0,0 +1,29 @@ +{ + "$schema": "https://raw.githubusercontent.com/TermiNexus/TransPyC/main/schemas/project-schema.json", + "name": "DictTest", + "version": "1.0.0", + "source_dir": "./App", + "temp_dir": "./temp", + "output_dir": "./output", + "compiler": { + "cmd": "llc", + "flags": ["-filetype=obj", "-relocation-model=pic"] + }, + "linker": { + "cmd": "clang++", + "flags": ["-Wl,--allow-multiple-definition", "-lmsvcrt", "-lucrt", "-lpthread", "-lmingwex", "-lkernel32"], + "output": "DictTest.exe" + }, + "includes": [ + "../../includes" + ], + "target": { + "triple": "x86_64-pc-windows-gnu", + "datalayout": "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" + }, + "options": { + "slice_level": 3, + "target": "llvm", + "strict_mode": true + } +} diff --git a/Test/ZlibTest/temp/067c78e9f121dce3.pyi b/Test/DictTest/temp/067c78e9f121dce3.pyi similarity index 100% rename from Test/ZlibTest/temp/067c78e9f121dce3.pyi rename to Test/DictTest/temp/067c78e9f121dce3.pyi diff --git a/Test/DictTest/temp/06f53cc594b4ac6c.pyi b/Test/DictTest/temp/06f53cc594b4ac6c.pyi new file mode 100644 index 0000000..8b5a8cf --- /dev/null +++ b/Test/DictTest/temp/06f53cc594b4ac6c.pyi @@ -0,0 +1,109 @@ +""" +Auto-generated Python stub file from w32.win32sync.py +Module: w32.win32sync +""" + +import c + + +import t +from stdint import * +from w32.win32base import * + +class CRITICAL_SECTION: + DebugInfo: VOIDPTR + LockCount: LONG + RecursionCount: LONG + OwningThread: HANDLE + LockSemaphore: HANDLE + SpinCount: QWORD + +def InitializeCriticalSection(lpCriticalSection: CRITICAL_SECTION | t.CPtr) -> VOID | t.State: pass + +def EnterCriticalSection(lpCriticalSection: CRITICAL_SECTION | t.CPtr) -> VOID | t.State: pass + +def LeaveCriticalSection(lpCriticalSection: CRITICAL_SECTION | t.CPtr) -> VOID | t.State: pass + +def DeleteCriticalSection(lpCriticalSection: CRITICAL_SECTION | t.CPtr) -> VOID | t.State: pass + +def TryEnterCriticalSection(lpCriticalSection: CRITICAL_SECTION | t.CPtr) -> BOOL | t.State: pass + +def SetCriticalSectionSpinCount(lpCriticalSection: CRITICAL_SECTION | t.CPtr, dwSpinCount: ULONG) -> ULONG | t.State: pass + +def InitializeCriticalSectionAndSpinCount(lpCriticalSection: CRITICAL_SECTION | t.CPtr, dwSpinCount: ULONG) -> BOOL | t.State: pass + +def CreateMutexA(lpMutexAttributes: SECURITY_ATTRIBUTES | t.CPtr, bInitialOwner: BOOL, lpName: LPCSTR) -> HANDLE | t.State: pass + +def CreateMutexW(lpMutexAttributes: SECURITY_ATTRIBUTES | t.CPtr, bInitialOwner: BOOL, lpName: LPCWSTR) -> HANDLE | t.State: pass + +def OpenMutexA(dwDesiredAccess: ULONG, bInheritHandle: BOOL, lpName: LPCSTR) -> HANDLE | t.State: pass + +def OpenMutexW(dwDesiredAccess: ULONG, bInheritHandle: BOOL, lpName: LPCWSTR) -> HANDLE | t.State: pass + +def ReleaseMutex(hMutex: HANDLE) -> BOOL | t.State: pass + +def CreateEventA(lpEventAttributes: SECURITY_ATTRIBUTES | t.CPtr, bManualReset: BOOL, bInitialState: BOOL, lpName: LPCSTR) -> HANDLE | t.State: pass + +def CreateEventW(lpEventAttributes: SECURITY_ATTRIBUTES | t.CPtr, bManualReset: BOOL, bInitialState: BOOL, lpName: LPCWSTR) -> HANDLE | t.State: pass + +def OpenEventA(dwDesiredAccess: ULONG, bInheritHandle: BOOL, lpName: LPCSTR) -> HANDLE | t.State: pass + +def OpenEventW(dwDesiredAccess: ULONG, bInheritHandle: BOOL, lpName: LPCWSTR) -> HANDLE | t.State: pass + +def SetEvent(hEvent: HANDLE) -> BOOL | t.State: pass + +def ResetEvent(hEvent: HANDLE) -> BOOL | t.State: pass + +def PulseEvent(hEvent: HANDLE) -> BOOL | t.State: pass + +def CreateSemaphoreA(lpSemaphoreAttributes: SECURITY_ATTRIBUTES | t.CPtr, lInitialCount: LONG, lMaximumCount: LONG, lpName: LPCSTR) -> HANDLE | t.State: pass + +def CreateSemaphoreW(lpSemaphoreAttributes: SECURITY_ATTRIBUTES | t.CPtr, lInitialCount: LONG, lMaximumCount: LONG, lpName: LPCWSTR) -> HANDLE | t.State: pass + +def OpenSemaphoreA(dwDesiredAccess: ULONG, bInheritHandle: BOOL, lpName: LPCSTR) -> HANDLE | t.State: pass + +def OpenSemaphoreW(dwDesiredAccess: ULONG, bInheritHandle: BOOL, lpName: LPCWSTR) -> HANDLE | t.State: pass + +def ReleaseSemaphore(hSemaphore: HANDLE, lReleaseCount: LONG, lpPreviousCount: LONG | t.CPtr) -> BOOL | t.State: pass + +def WaitForSingleObject(hHandle: HANDLE, dwMilliseconds: ULONG) -> ULONG | t.State: pass + +def WaitForSingleObjectEx(hHandle: HANDLE, dwMilliseconds: ULONG, bAlertable: BOOL) -> ULONG | t.State: pass + +def WaitForMultipleObjects(nCount: ULONG, lpHandles: VOIDPTR, bWaitAll: BOOL, dwMilliseconds: ULONG) -> ULONG | t.State: pass + +def WaitForMultipleObjectsEx(nCount: ULONG, lpHandles: VOIDPTR, bWaitAll: BOOL, dwMilliseconds: ULONG, bAlertable: BOOL) -> ULONG | t.State: pass + +def InitializeSRWLock(SRWLock: VOIDPTR) -> VOID | t.State: pass + +def AcquireSRWLockExclusive(SRWLock: VOIDPTR) -> VOID | t.State: pass + +def AcquireSRWLockShared(SRWLock: VOIDPTR) -> VOID | t.State: pass + +def ReleaseSRWLockExclusive(SRWLock: VOIDPTR) -> VOID | t.State: pass + +def ReleaseSRWLockShared(SRWLock: VOIDPTR) -> VOID | t.State: pass + + +CONDITION_VARIABLE_LOCKMODE_SHARED: t.CDefine = 0x1 + +def InitializeConditionVariable(ConditionVariable: VOIDPTR) -> VOID | t.State: pass + +def SleepConditionVariableCS(ConditionVariable: VOIDPTR, CriticalSection: CRITICAL_SECTION | t.CPtr, dwMilliseconds: ULONG) -> BOOL | t.State: pass + +def SleepConditionVariableSRW(ConditionVariable: VOIDPTR, SRWLock: VOIDPTR, dwMilliseconds: ULONG, Flags: ULONG) -> BOOL | t.State: pass + +def WakeConditionVariable(ConditionVariable: VOIDPTR) -> VOID | t.State: pass + +def WakeAllConditionVariable(ConditionVariable: VOIDPTR) -> VOID | t.State: pass + + +INIT_ONCE_STATIC_INIT: t.CDefine = 0x00000001 +INIT_ONCE_CHECK_ONLY: t.CDefine = 0x00000002 +INIT_ONCE_ASYNC: t.CDefine = 0x00000004 +INIT_ONCE_INIT_FAILED: t.CDefine = 0x00000008 + +class INIT_ONCE: + Ptr: t.CPtr + +def InitOnceExecuteOnce(InitOnce: INIT_ONCE | t.CPtr, InitFn: VOIDPTR, Parameter: VOIDPTR, Context: VOIDPTR | t.CPtr) -> BOOL | t.State: pass diff --git a/Test/TestProject/temp/68c4fe4b12c908e3.pyi b/Test/DictTest/temp/0991af0d22263577.pyi similarity index 98% rename from Test/TestProject/temp/68c4fe4b12c908e3.pyi rename to Test/DictTest/temp/0991af0d22263577.pyi index fc2010b..f001c8a 100644 --- a/Test/TestProject/temp/68c4fe4b12c908e3.pyi +++ b/Test/DictTest/temp/0991af0d22263577.pyi @@ -11,7 +11,7 @@ import string MPOOL_ALIGN: t.CDefine = 8 MPOOL_TYPE_SLAB: t.CDefine = 0 -MPOOL_TYPE_BUMP: t.CDefine = 2 +MPOOL_TYPE_BUMP: t.CDefine = 1 def _align_up(val: t.CSizeT, align: t.CSizeT) -> t.CSizeT: pass diff --git a/Test/DictTest/temp/0eaa586c42dcd931.pyi b/Test/DictTest/temp/0eaa586c42dcd931.pyi new file mode 100644 index 0000000..7ce46eb --- /dev/null +++ b/Test/DictTest/temp/0eaa586c42dcd931.pyi @@ -0,0 +1,49 @@ +""" +Auto-generated Python stub file from mbuddy.py +Module: mbuddy +""" + + +import t, c +from stdint import * +import string +import atom + +MBUDDY_MIN_BLOCK: t.CDefine = 32 # 最小块大小 (字节),需 >= 16 以容纳链表指针 +MBUDDY_MAX_ORDERS: t.CDefine = 32 # 最大阶数数量 +MBUDDY_HEADER_SIZE: t.CDefine = 8 # 块头大小 (存储阶数) + +def _largest_pow2_le(val: t.CSizeT) -> t.CSizeT: pass + +def _block_size_at_order(order: t.CInt) -> t.CSizeT: pass + + +class MBuddy: + __provides__: list[str] = ['__mbuddy__'] + mem: t.CVoid | t.CPtr + mem_size: t.CSizeT + max_order: t.CInt + free_lists: t.CUInt64T | t.CPtr + lock_val: t.CVolatile | t.CInt + def __init__(self: MBuddy, arena: t.CVoid | t.CPtr, arena_size: t.CSizeT) -> t.CInt: pass + def __enter__(self: MBuddy) -> 'MBuddy' | t.CPtr: pass + def __exit__(self: MBuddy) -> t.CInt: pass + def reset(self: MBuddy) -> t.CInt: pass + def _fl_push(self: MBuddy, order: t.CInt, block: t.CVoid | t.CPtr) -> t.CInt: pass + def _fl_pop(self: MBuddy, order: t.CInt) -> t.CVoid | t.CPtr: pass + def _fl_find_and_remove(self: MBuddy, order: t.CInt, target: t.CVoid | t.CPtr) -> t.CInt: pass + def _buddy_of(self: MBuddy, block: t.CVoid | t.CPtr, order: t.CInt) -> t.CVoid | t.CPtr: pass + def _order_for_size(self: MBuddy, size: t.CSizeT) -> t.CInt: pass + def _split_to_order(self: MBuddy, to_order: t.CInt) -> t.CVoid | t.CPtr: pass + def _coalesce(self: MBuddy, block: t.CVoid | t.CPtr, order: t.CInt) -> t.CInt: pass + def _is_valid_ptr(self: MBuddy, ptr: t.CVoid | t.CPtr) -> t.CInt: pass + def _fl_count(self: MBuddy, order: t.CInt) -> t.CSizeT: pass + def _lock(self: MBuddy) -> t.CInt: pass + def _unlock(self: MBuddy) -> t.CInt: pass + def alloc(self: MBuddy, size: t.CSizeT) -> t.CVoid | t.CPtr: pass + def free(self: MBuddy, ptr: t.CVoid | t.CPtr) -> t.CInt: pass + def calloc(self: MBuddy, count: t.CSizeT, size: t.CSizeT) -> t.CVoid | t.CPtr: pass + def realloc(self: MBuddy, ptr: t.CVoid | t.CPtr, new_size: t.CSizeT) -> t.CVoid | t.CPtr: pass + def stats(self: MBuddy) -> t.CSizeT: pass + def free_count(self: MBuddy) -> t.CSizeT: pass + def self_check(self: MBuddy) -> t.CInt: pass \ No newline at end of file diff --git a/Test/DictTest/temp/271ea3decb810db2.pyi b/Test/DictTest/temp/271ea3decb810db2.pyi new file mode 100644 index 0000000..3d637bf --- /dev/null +++ b/Test/DictTest/temp/271ea3decb810db2.pyi @@ -0,0 +1,26 @@ +""" +Auto-generated Python stub file from atom.py +Module: atom +""" + + +import t, c + +ATOMIC_RELAXED: t.CDefine = 0 +ATOMIC_CONSUME: t.CDefine = 1 +ATOMIC_ACQUIRE: t.CDefine = 2 +ATOMIC_RELEASE: t.CDefine = 3 +ATOMIC_ACQ_REL: t.CDefine = 4 +ATOMIC_SEQ_CST: t.CDefine = 5 + +def __atomic_test_and_set(ptr: t.CUInt64T | t.CPtr, order: t.CInt) -> t.CBool: pass + +def __atomic_clear(ptr: t.CUInt64T | t.CPtr, order: t.CInt) -> t.CVoid: pass + +def __atomic_thread_fence(order: t.CInt) -> t.CVoid: pass + +def __atomic_signal_fence(order: t.CInt) -> t.CVoid: pass + +def __atomic_always_lock_free(size: t.CSizeT, ptr: t.CVoid | t.CPtr) -> t.CBool: pass + +def __atomic_is_lock_free(size: t.CSizeT, ptr: t.CVoid | t.CPtr) -> t.CBool: pass diff --git a/Test/JsonTest/temp/56cdd754a8a09347.pyi b/Test/DictTest/temp/49bd8cba55979f76.pyi similarity index 88% rename from Test/JsonTest/temp/56cdd754a8a09347.pyi rename to Test/DictTest/temp/49bd8cba55979f76.pyi index 007ccb8..f1d844a 100644 --- a/Test/JsonTest/temp/56cdd754a8a09347.pyi +++ b/Test/DictTest/temp/49bd8cba55979f76.pyi @@ -64,4 +64,12 @@ CHAR16: t.CTypedef = t.CChar16T CHAR32: t.CTypedef = t.CChar32T CHAR8PTR: t.CTypedef = t.CChar8T | t.CPtr CHAR16PTR: t.CTypedef = t.CChar16T | t.CPtr -CHAR32PTR: t.CTypedef = t.CChar32T | t.CPtr \ No newline at end of file +CHAR32PTR: t.CTypedef = t.CChar32T | t.CPtr +i8: t.CTypedef = t.CInt8T +i16: t.CTypedef = t.CInt16T +i32: t.CTypedef = t.CInt32T +i64: t.CTypedef = t.CInt64T +u8: t.CTypedef = t.CUInt8T +u16: t.CTypedef = t.CUInt16T +u32: t.CTypedef = t.CUInt32T +u64: t.CTypedef = t.CUInt64T \ No newline at end of file diff --git a/Test/DictTest/temp/5a6a2137958c28c5.pyi b/Test/DictTest/temp/5a6a2137958c28c5.pyi new file mode 100644 index 0000000..a137977 --- /dev/null +++ b/Test/DictTest/temp/5a6a2137958c28c5.pyi @@ -0,0 +1,98 @@ +""" +Auto-generated Python stub file from w32.win32base.py +Module: w32.win32base +""" + +import c + + +import t +from stdint import * + +HANDLE: t.CTypedef = VOIDPTR +LPCSTR: t.CTypedef = t.CConst | t.CChar | t.CPtr +LPCWSTR: t.CTypedef = t.CConst | t.CUnsignedShort | t.CPtr +INVALID_HANDLE_VALUE: t.CDefine = t.CVoid(-1) +NULL: t.CDefine = 0 +TRUE: t.CDefine = 1 +FALSE: t.CDefine = 0 +INFINITE: t.CDefine = 0xFFFFFFFF +WAIT_FAILED: t.CDefine = 0xFFFFFFFF +WAIT_OBJECT_0: t.CDefine = 0 +WAIT_TIMEOUT: t.CDefine = 258 +WAIT_ABANDONED: t.CDefine = 0x80 +MAX_PATH: t.CDefine = 260 +ERROR_SUCCESS: t.CDefine = 0 +ERROR_FILE_NOT_FOUND: t.CDefine = 2 +ERROR_ACCESS_DENIED: t.CDefine = 5 +ERROR_INSUFFICIENT_BUFFER: t.CDefine = 122 + +class SECURITY_ATTRIBUTES: + nLength: ULONG + lpSecurityDescriptor: VOIDPTR + bInheritHandle: BOOL +class OVERLAPPED: + Internal: ULONGLONG + InternalHigh: ULONGLONG + Offset: ULONG + OffsetHigh: ULONG + hEvent: HANDLE +class FILETIME: + dwLowDateTime: DWORD + dwHighDateTime: DWORD +class SYSTEMTIME: + wYear: WORD + wMonth: WORD + wDayOfWeek: WORD + wDay: WORD + wHour: WORD + wMinute: WORD + wSecond: WORD + wMilliseconds: WORD +class GUID: + Data1: DWORD + Data2: WORD + Data3: WORD + Data4: BYTEPTR +class LARGE_INTEGER: + QuadPart: LONGLONG +class ULARGE_INTEGER: + QuadPart: ULONGLONG + +def GetLastError() -> ULONG | t.State: pass + +def SetLastError(dwErrCode: ULONG) -> t.State: pass + +def CloseHandle(hObject: HANDLE) -> BOOL | t.State: pass + +def GetProcAddress(hModule: HANDLE, lpProcName: LPCSTR) -> VOIDPTR | t.State: pass + +def GetModuleHandleA(lpModuleName: LPCSTR) -> HANDLE | t.State: pass + +def GetModuleHandleW(lpModuleName: LPCWSTR) -> HANDLE | t.State: pass + +def LoadLibraryA(lpLibFileName: LPCSTR) -> HANDLE | t.State: pass + +def LoadLibraryW(lpLibFileName: LPCWSTR) -> HANDLE | t.State: pass + +def FreeLibrary(hLibModule: HANDLE) -> BOOL | t.State: pass + +def GetSystemTime(lpSystemTime: SYSTEMTIME | t.CPtr) -> t.State: pass + +def GetLocalTime(lpSystemTime: SYSTEMTIME | t.CPtr) -> t.State: pass + +def FileTimeToSystemTime(lpFileTime: FILETIME | t.CPtr, lpSystemTime: SYSTEMTIME | t.CPtr) -> BOOL | t.State: pass + +def SystemTimeToFileTime(lpSystemTime: SYSTEMTIME | t.CPtr, lpFileTime: FILETIME | t.CPtr) -> BOOL | t.State: pass + +def QueryPerformanceCounter(lpPerformanceCount: LARGE_INTEGER | t.CPtr) -> BOOL | t.State: pass + +def QueryPerformanceFrequency(lpFrequency: LARGE_INTEGER | t.CPtr) -> BOOL | t.State: pass + +def Sleep(dwMilliseconds: ULONG) -> t.State: pass + +def SleepEx(dwMilliseconds: ULONG, bAlertable: BOOL) -> ULONG | t.State: pass + +def GetTickCount() -> ULONG | t.State: pass + +def GetTickCount64() -> ULONGLONG | t.State: pass diff --git a/Test/DictTest/temp/6c2029b306556c00.pyi b/Test/DictTest/temp/6c2029b306556c00.pyi new file mode 100644 index 0000000..98da680 --- /dev/null +++ b/Test/DictTest/temp/6c2029b306556c00.pyi @@ -0,0 +1,18 @@ +""" +Auto-generated Python stub file from stdlib.py +Module: stdlib +""" + +import c + + +from stdint import * +import t + +def malloc(size: t.CSizeT) -> t.CVoid | t.CPtr | t.State | t.CExtern | t.CExport: pass + +def calloc(nmemb: t.CSizeT, size: t.CSizeT) -> t.CVoid | t.CPtr | t.State | t.CExtern | t.CExport: pass + +def realloc(p: t.CVoid | t.CPtr, size: t.CSizeT) -> t.CVoid | t.CPtr | t.State | t.CExtern | t.CExport: pass + +def free(p: t.CVoid | t.CPtr) -> None | t.State | t.CExtern | t.CExport: pass diff --git a/Test/DictTest/temp/72e2d5ccb7cedcf1.pyi b/Test/DictTest/temp/72e2d5ccb7cedcf1.pyi new file mode 100644 index 0000000..5fceb08 --- /dev/null +++ b/Test/DictTest/temp/72e2d5ccb7cedcf1.pyi @@ -0,0 +1,91 @@ +""" +Auto-generated Python stub file from w32.win32memory.py +Module: w32.win32memory +""" + +import c + + +import t +from stdint import * +from w32.win32base import * + +MEM_COMMIT: t.CDefine = 0x00001000 +MEM_RESERVE: t.CDefine = 0x00002000 +MEM_DECOMMIT: t.CDefine = 0x00004000 +MEM_RELEASE: t.CDefine = 0x00008000 +MEM_FREE: t.CDefine = 0x00010000 +MEM_RESET: t.CDefine = 0x00080000 +MEM_TOP_DOWN: t.CDefine = 0x00100000 +MEM_WRITE_WATCH: t.CDefine = 0x00200000 +MEM_PHYSICAL: t.CDefine = 0x00400000 +MEM_LARGE_PAGES: t.CDefine = 0x20000000 +PAGE_NOACCESS: t.CDefine = 0x01 +PAGE_READONLY: t.CDefine = 0x02 +PAGE_READWRITE: t.CDefine = 0x04 +PAGE_WRITECOPY: t.CDefine = 0x08 +PAGE_EXECUTE: t.CDefine = 0x10 +PAGE_EXECUTE_READ: t.CDefine = 0x20 +PAGE_EXECUTE_READWRITE: t.CDefine = 0x40 +PAGE_EXECUTE_WRITECOPY: t.CDefine = 0x80 +PAGE_GUARD: t.CDefine = 0x100 +PAGE_NOCACHE: t.CDefine = 0x200 +PAGE_WRITECOMBINE: t.CDefine = 0x400 +HEAP_NO_SERIALIZE: t.CDefine = 0x00000001 +HEAP_GROWABLE: t.CDefine = 0x00000002 +HEAP_GENERATE_EXCEPTIONS: t.CDefine = 0x00000004 +HEAP_ZERO_MEMORY: t.CDefine = 0x00000008 +HEAP_REALLOC_IN_PLACE_ONLY: t.CDefine = 0x00000010 + +class MEMORY_BASIC_INFORMATION: + BaseAddress: VOIDPTR + AllocationBase: VOIDPTR + AllocationProtect: ULONG + RegionSize: t.CSizeT + State: ULONG + Protect: ULONG + Type: ULONG + +def VirtualAlloc(lpAddress: VOIDPTR, dwSize: t.CSizeT, flAllocationType: ULONG, flProtect: ULONG) -> VOIDPTR | t.State: pass + +def VirtualFree(lpAddress: VOIDPTR, dwSize: t.CSizeT, dwFreeType: ULONG) -> BOOL | t.State: pass + +def VirtualProtect(lpAddress: VOIDPTR, dwSize: t.CSizeT, flNewProtect: ULONG, lpflOldProtect: ULONG | t.CPtr) -> BOOL | t.State: pass + +def VirtualQuery(lpAddress: t.CConst | VOIDPTR, lpBuffer: MEMORY_BASIC_INFORMATION | t.CPtr, dwLength: t.CSizeT) -> t.CSizeT | t.State: pass + +def VirtualLock(lpAddress: VOIDPTR, dwSize: t.CSizeT) -> BOOL | t.State: pass + +def VirtualUnlock(lpAddress: VOIDPTR, dwSize: t.CSizeT) -> BOOL | t.State: pass + +def GetProcessHeap() -> HANDLE | t.State: pass + +def HeapCreate(flOptions: ULONG, dwInitialSize: t.CSizeT, dwMaximumSize: t.CSizeT) -> HANDLE | t.State: pass + +def HeapDestroy(hHeap: HANDLE) -> BOOL | t.State: pass + +def HeapAlloc(hHeap: HANDLE, dwFlags: ULONG, dwBytes: t.CSizeT) -> VOIDPTR | t.State: pass + +def HeapReAlloc(hHeap: HANDLE, dwFlags: ULONG, lpMem: VOIDPTR, dwBytes: t.CSizeT) -> VOIDPTR | t.State: pass + +def HeapFree(hHeap: HANDLE, dwFlags: ULONG, lpMem: VOIDPTR) -> BOOL | t.State: pass + +def HeapSize(hHeap: HANDLE, dwFlags: ULONG, lpMem: t.CConst | VOIDPTR) -> t.CSizeT | t.State: pass + +def HeapValidate(hHeap: HANDLE, dwFlags: ULONG, lpMem: t.CConst | VOIDPTR) -> BOOL | t.State: pass + +def HeapCompact(hHeap: HANDLE, dwFlags: ULONG) -> t.CSizeT | t.State: pass + +def GlobalAlloc(uFlags: UINT, dwBytes: t.CSizeT) -> VOIDPTR | t.State: pass + +def GlobalFree(hMem: VOIDPTR) -> VOIDPTR | t.State: pass + +def GlobalLock(hMem: VOIDPTR) -> VOIDPTR | t.State: pass + +def GlobalUnlock(hMem: VOIDPTR) -> BOOL | t.State: pass + +def GlobalSize(hMem: VOIDPTR) -> t.CSizeT | t.State: pass + +def LocalAlloc(uFlags: UINT, dwBytes: t.CSizeT) -> VOIDPTR | t.State: pass + +def LocalFree(hMem: VOIDPTR) -> VOIDPTR | t.State: pass diff --git a/Test/DictTest/temp/73edbcf76e32d00b.pyi b/Test/DictTest/temp/73edbcf76e32d00b.pyi new file mode 100644 index 0000000..ef712e3 --- /dev/null +++ b/Test/DictTest/temp/73edbcf76e32d00b.pyi @@ -0,0 +1,28 @@ +""" +Auto-generated Python stub file from stdio.py +Module: stdio +""" + + +import t, c + +def printf(fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass + +def fprintf(stream: t.CVoid | t.CPtr, fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass + +def sprintf(buf: t.CChar | t.CPtr, fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass + +def snprintf(buf: t.CChar | t.CPtr, size: t.CSizeT, fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass + +def puts(s: t.CChar | t.CConst | t.CPtr) -> t.CInt | t.CExtern | t.CExport: pass + +def fputs(s: t.CChar | t.CConst | t.CPtr, stream: t.CVoid | t.CPtr) -> t.CInt | t.CExtern | t.CExport: pass + +def fgets(buf: t.CChar | t.CPtr, size: t.CInt, stream: t.CVoid | t.CPtr) -> t.CChar | t.CPtr | t.CExtern | t.CExport: pass + +def fflush(stream: t.CVoid | t.CPtr) -> t.CInt | t.CExtern | t.CExport: pass + + +stdin: t.CExtern | t.CVoid | t.CPtr +stdout: t.CExtern | t.CVoid | t.CPtr +stderr: t.CExtern | t.CVoid | t.CPtr \ No newline at end of file diff --git a/Test/DictTest/temp/8ee3170049c70333.pyi b/Test/DictTest/temp/8ee3170049c70333.pyi new file mode 100644 index 0000000..8e3fa45 --- /dev/null +++ b/Test/DictTest/temp/8ee3170049c70333.pyi @@ -0,0 +1,71 @@ +""" +Auto-generated Python stub file from json.__init__.py +Module: json.__init__ +""" + + +import t, c +from stdint import * +import mpool +import string +import viperio + +JSON_NULL: t.CDefine = 0 +JSON_BOOL: t.CDefine = 1 +JSON_INT: t.CDefine = 2 +JSON_FLOAT: t.CDefine = 3 +JSON_STRING: t.CDefine = 4 +JSON_ARRAY: t.CDefine = 5 +JSON_OBJECT: t.CDefine = 6 + +class JsonValue: + vtype: t.CInt + bool_val: t.CInt + int_val: t.CInt64T + float_val: t.CDouble + str_val: t.CChar | t.CPtr + next: JsonValue | t.CPtr + key: t.CChar | t.CPtr + child: JsonValue | t.CPtr + child_count: t.CSizeT + def __new__(self: JsonValue, pool: mpool.MPool | t.CPtr) -> t.CInt: pass + def type(self: JsonValue) -> t.CInt: pass + def is_null(self: JsonValue) -> bool: pass + def is_bool(self: JsonValue) -> bool: pass + def is_int(self: JsonValue) -> bool: pass + def is_float(self: JsonValue) -> bool: pass + def is_string(self: JsonValue) -> bool: pass + def is_array(self: JsonValue) -> bool: pass + def is_object(self: JsonValue) -> bool: pass + def as_bool(self: JsonValue) -> bool: pass + def as_int(self: JsonValue) -> t.CInt64T: pass + def as_float(self: JsonValue) -> t.CDouble: pass + def as_string(self: JsonValue) -> t.CChar | t.CPtr: pass + def __len__(self: JsonValue) -> t.CSizeT: pass + def __getitem__(self: JsonValue, key: t.CChar | t.CPtr) -> JsonValue | t.CPtr: pass + def __setitem__(self: JsonValue, key: t.CChar | t.CPtr, val: JsonValue | t.CPtr) -> t.CInt: pass + def get_item(self: JsonValue, index: t.CSizeT) -> JsonValue | t.CPtr: pass + def _pool_alloc(self: JsonValue, size: t.CSizeT) -> t.CChar | t.CPtr: pass + def _append_child(self: JsonValue, child: JsonValue | t.CPtr) -> t.CInt: pass + +def null(pool: mpool.MPool | t.CPtr) -> JsonValue | t.CPtr: pass + +def bool_val(pool: mpool.MPool | t.CPtr, val: bool) -> JsonValue | t.CPtr: pass + +def int_val(pool: mpool.MPool | t.CPtr, val: t.CInt64T) -> JsonValue | t.CPtr: pass + +def float_val(pool: mpool.MPool | t.CPtr, val: t.CDouble) -> JsonValue | t.CPtr: pass + +def string_val(pool: mpool.MPool | t.CPtr, val: t.CChar | t.CPtr) -> JsonValue | t.CPtr: pass + +def array(pool: mpool.MPool | t.CPtr) -> JsonValue | t.CPtr: pass + +def object(pool: mpool.MPool | t.CPtr) -> JsonValue | t.CPtr: pass + +def array_append(pool: mpool.MPool | t.CPtr, arr: JsonValue | t.CPtr, item: JsonValue | t.CPtr) -> t.CInt: pass + +def object_set(pool: mpool.MPool | t.CPtr, obj: JsonValue | t.CPtr, key: t.CChar | t.CPtr, val: JsonValue | t.CPtr) -> t.CInt: pass + + +from .__parser import parse +from .__writer import write \ No newline at end of file diff --git a/Test/DictTest/temp/9dbecd0942a39782.pyi b/Test/DictTest/temp/9dbecd0942a39782.pyi new file mode 100644 index 0000000..41648c1 --- /dev/null +++ b/Test/DictTest/temp/9dbecd0942a39782.pyi @@ -0,0 +1,25 @@ +""" +Auto-generated Python stub file from testcheck.py +Module: testcheck +""" + + +import t, c +import stdio + +_pass_count: t.CExtern | t.CInt +_fail_count: t.CExtern | t.CInt + +def begin(name: str) -> t.CInt: pass + +def section(name: str) -> t.CInt: pass + +def ok(msg: str) -> t.CInt: pass + +def fail(msg: str) -> t.CInt: pass + +def check(cond: t.CInt, ok_msg: str, fail_msg: str) -> t.CInt: pass + +def info(msg: str) -> t.CInt: pass + +def end() -> t.CInt: pass diff --git a/Test/DictTest/temp/_sha1_map.txt b/Test/DictTest/temp/_sha1_map.txt new file mode 100644 index 0000000..d27027f --- /dev/null +++ b/Test/DictTest/temp/_sha1_map.txt @@ -0,0 +1,16 @@ +0991af0d22263577:includes/mpool.py +0eaa586c42dcd931:includes/mbuddy.py +271ea3decb810db2:includes/atom.py +49bd8cba55979f76:includes/stdint.py +5a6a2137958c28c5:includes/w32\win32base.py +6c2029b306556c00:includes/stdlib.py +73edbcf76e32d00b:includes/stdio.py +8ee3170049c70333:includes/json\__init__.py +9dbecd0942a39782:includes/testcheck.py +b5f1dc665c52a1bd:includes/string.py +bbdf3bbd4c3bc28c:includes/w32\win32console.py +bd2e7db1744476fe:includes/json\__parser.py +c9f4be41ca1cc2b4:includes/viperio.py +eaf7a981f0ef5b22:includes/json\__writer.py +f1e15ccf054b1e89:includes/_dict.py +fced53b138f67cf5:main.py diff --git a/Test/ZlibTest/temp/abf9ce3160c9279e.pyi b/Test/DictTest/temp/abf9ce3160c9279e.pyi similarity index 100% rename from Test/ZlibTest/temp/abf9ce3160c9279e.pyi rename to Test/DictTest/temp/abf9ce3160c9279e.pyi diff --git a/Test/IterTest/temp/6aee24fdefa3cbc0.pyi b/Test/DictTest/temp/b5f1dc665c52a1bd.pyi similarity index 94% rename from Test/IterTest/temp/6aee24fdefa3cbc0.pyi rename to Test/DictTest/temp/b5f1dc665c52a1bd.pyi index c17475f..8b6959e 100644 --- a/Test/IterTest/temp/6aee24fdefa3cbc0.pyi +++ b/Test/DictTest/temp/b5f1dc665c52a1bd.pyi @@ -41,4 +41,4 @@ def atoll(src: str) -> t.CInt64T: pass def atof(src: str) -> t.CDouble: pass -def split(s: str, delim: str, result: list[str]) -> int: pass +def split(s: str, delim: str, result: t.CArray[str]) -> int: pass diff --git a/Test/ZlibTest/temp/bbdf3bbd4c3bc28c.pyi b/Test/DictTest/temp/bbdf3bbd4c3bc28c.pyi similarity index 100% rename from Test/ZlibTest/temp/bbdf3bbd4c3bc28c.pyi rename to Test/DictTest/temp/bbdf3bbd4c3bc28c.pyi diff --git a/Test/DictTest/temp/bd2e7db1744476fe.pyi b/Test/DictTest/temp/bd2e7db1744476fe.pyi new file mode 100644 index 0000000..c332a45 --- /dev/null +++ b/Test/DictTest/temp/bd2e7db1744476fe.pyi @@ -0,0 +1,38 @@ +""" +Auto-generated Python stub file from json.__parser.py +Module: json.__parser +""" + + +import t, c +from stdint import * +import mpool +import string +from . import JsonValue, JSON_NULL, JSON_BOOL, JSON_INT, JSON_FLOAT, JSON_STRING, JSON_ARRAY, JSON_OBJECT, null, bool_val, int_val, float_val, string_val, array, object + +class ParseState: + src: t.CChar | t.CPtr + pos: t.CSizeT + len: t.CSizeT + pool: mpool.MPool | t.CPtr + def __init__(self: ParseState, src: t.CChar | t.CPtr, pool: mpool.MPool | t.CPtr) -> t.CInt: pass + +def _peek(s: ParseState | t.CPtr) -> t.CChar: pass + +def _advance(s: ParseState | t.CPtr) -> t.CChar: pass + +def _skip_whitespace(s: ParseState | t.CPtr) -> t.CInt: pass + +def _expect(s: ParseState | t.CPtr, ch: t.CChar) -> bool: pass + +def _parse_string(s: ParseState | t.CPtr) -> t.CChar | t.CPtr: pass + +def _parse_number(s: ParseState | t.CPtr) -> JsonValue | t.CPtr: pass + +def _parse_value(s: ParseState | t.CPtr) -> JsonValue | t.CPtr: pass + +def _parse_array(s: ParseState | t.CPtr) -> JsonValue | t.CPtr: pass + +def _parse_object(s: ParseState | t.CPtr) -> JsonValue | t.CPtr: pass + +def parse(pool: mpool.MPool | t.CPtr, src: t.CChar | t.CPtr) -> JsonValue | t.CPtr: pass diff --git a/Test/DictTest/temp/c9f4be41ca1cc2b4.pyi b/Test/DictTest/temp/c9f4be41ca1cc2b4.pyi new file mode 100644 index 0000000..fdbd7ec --- /dev/null +++ b/Test/DictTest/temp/c9f4be41ca1cc2b4.pyi @@ -0,0 +1,22 @@ +""" +Auto-generated Python stub file from viperio.py +Module: viperio +""" + + +import t, c +from stdint import * + +class Buf: + data: t.CChar | t.CPtr + length: t.CSizeT + capacity: t.CSizeT + owned: bool + def __init__(self: Buf, data: t.CChar | t.CPtr, capacity: t.CSizeT, length: t.CSizeT, owned: bool) -> t.CInt: pass + def clear(self: Buf) -> t.CInt: pass + def write(self: Buf, src: t.CChar | t.CPtr, count: t.CSizeT) -> t.CSizeT: pass + def cstr(self: Buf) -> t.CChar | t.CPtr: pass + def reset(self: Buf) -> t.CInt: pass + def __enter__(self: Buf) -> 'Buf' | t.CPtr: pass + def __exit__(self: Buf) -> t.CInt: pass + def free(self: Buf) -> t.CInt: pass \ No newline at end of file diff --git a/Test/DictTest/temp/eaf7a981f0ef5b22.pyi b/Test/DictTest/temp/eaf7a981f0ef5b22.pyi new file mode 100644 index 0000000..5f9da84 --- /dev/null +++ b/Test/DictTest/temp/eaf7a981f0ef5b22.pyi @@ -0,0 +1,22 @@ +""" +Auto-generated Python stub file from json.__writer.py +Module: json.__writer +""" + + +import t, c +from stdint import * +import mpool +import string +from stdio import snprintf +from . import JsonValue, JSON_NULL, JSON_BOOL, JSON_INT, JSON_FLOAT, JSON_STRING, JSON_ARRAY, JSON_OBJECT + +def _write_char(buf: t.CChar | t.CPtr, pos: t.CSizeT, ch: t.CChar) -> t.CSizeT: pass + +def _write_str(buf: t.CChar | t.CPtr, pos: t.CSizeT, s: t.CChar | t.CPtr) -> t.CSizeT: pass + +def _write_string_escaped(buf: t.CChar | t.CPtr, pos: t.CSizeT, s: t.CChar | t.CPtr) -> t.CSizeT: pass + +def _write_value(buf: t.CChar | t.CPtr, pos: t.CSizeT, val: JsonValue | t.CPtr, pool: mpool.MPool | t.CPtr) -> t.CSizeT: pass + +def write(pool: mpool.MPool | t.CPtr, val: JsonValue | t.CPtr, pretty: bool) -> t.CChar | t.CPtr: pass diff --git a/Test/DictTest/temp/f1e15ccf054b1e89.pyi b/Test/DictTest/temp/f1e15ccf054b1e89.pyi new file mode 100644 index 0000000..4951b53 --- /dev/null +++ b/Test/DictTest/temp/f1e15ccf054b1e89.pyi @@ -0,0 +1,54 @@ +""" +Auto-generated Python stub file from _dict.py +Module: _dict +""" + + +import t, c +import mbuddy +import string +import json +import mpool +from stdint import * + +VARIANT_NONE: t.CDefine = 0 # 无类型/空值 +VARIANT_INT: t.CDefine = 1 # int (i64) +VARIANT_FLOAT: t.CDefine = 2 # float (f32) +VARIANT_DOUBLE: t.CDefine = 3 # double (f64) +VARIANT_STR: t.CDefine = 4 # str (i8*) +VARIANT_DICT: t.CDefine = 5 # dict* +VARIANT_LIST: t.CDefine = 6 # list* +VARIANT_BOOL: t.CDefine = 7 # bool (i1/i32) +VARIANT_PTR: t.CDefine = 8 # 自定义指针类型 +_VARIANT_SIZE: t.CDefine = 16 + +class dict: + __keys__: t.CVoid | t.CPtr + __values__: t.CVoid | t.CPtr + __count__: t.CSizeT + __capacity__: t.CSizeT + __mbuddy__: mbuddy.MBuddy | t.CPtr + __iter_index__: t.CSizeT + def __new__(self: dict, mb: mbuddy.MBuddy | t.CPtr) -> t.CPtr: pass + def __init__(self: dict, mb: mbuddy.MBuddy | t.CPtr) -> t.CInt: pass + def __len__(self: dict) -> t.CSizeT: pass + def _find(self: dict, key: str) -> t.CSizeT: pass + def __getitem__(self: dict, key: str) -> t.CPtr: pass + def __setitem__(self: dict, key: str, val: t.CNeedPtr) -> t.CInt: pass + def _set_variant_raw(self: dict, key: str, vtype: t.CInt, ptr: t.CPtr) -> t.CInt: pass + def set_int(self: dict, key: str, val: int) -> t.CInt: pass + def set_str(self: dict, key: str, val: str) -> t.CInt: pass + def set_float(self: dict, key: str, val: float) -> t.CInt: pass + def set_double(self: dict, key: str, val: t.CDouble) -> t.CInt: pass + def set_dict(self: dict, key: str, val: dict | t.CPtr) -> t.CInt: pass + def set_list(self: dict, key: str, val: t.CPtr) -> t.CInt: pass + def set_bool(self: dict, key: str, val: t.CInt) -> t.CInt: pass + def get_vtype(self: dict, key: str) -> t.CInt: pass + def get(self: dict, key: str, default: t.CPtr) -> t.CPtr: pass + def contains(self: dict, key: str) -> t.CInt: pass + def __iter__(self: dict) -> dict | t.CPtr: pass + def __next__(self: dict) -> str: pass + def to_json(self: dict, pool: mpool.MPool | t.CPtr) -> json.JsonValue | t.CPtr: pass + def from_json(self: dict, pool: mpool.MPool | t.CPtr, root: json.JsonValue | t.CPtr) -> t.CInt: pass + def dumps(self: dict, pool: mpool.MPool | t.CPtr) -> str: pass + def loads(self: dict, pool: mpool.MPool | t.CPtr, json_str: str) -> t.CInt: pass \ No newline at end of file diff --git a/Test/ZlibTest/temp/fa3691e66b426950.pyi b/Test/DictTest/temp/fa3691e66b426950.pyi similarity index 100% rename from Test/ZlibTest/temp/fa3691e66b426950.pyi rename to Test/DictTest/temp/fa3691e66b426950.pyi diff --git a/Test/DictTest/temp/fced53b138f67cf5.pyi b/Test/DictTest/temp/fced53b138f67cf5.pyi new file mode 100644 index 0000000..8bd78b0 --- /dev/null +++ b/Test/DictTest/temp/fced53b138f67cf5.pyi @@ -0,0 +1,18 @@ +""" +Auto-generated Python stub file from main.py +Module: main +""" + + +from stdint import * +import w32.win32console +import t, c +from t import CInt, CExport +import stdio +import stdlib +import string +import mbuddy +import mpool +import testcheck + +def main() -> CInt | CExport: pass diff --git a/Test/EdgeCaseTest/App/main.py b/Test/EdgeCaseTest/App/main.py new file mode 100644 index 0000000..125e21a --- /dev/null +++ b/Test/EdgeCaseTest/App/main.py @@ -0,0 +1,260 @@ +import t +import t as tt +import stdio +import testcheck + +from t import CEnum as en +from t import CUnion as un +from t import REnum as ren +from t import CStruct as cs +from t import CInt as myint +from t import CChar, CPtr + + +# ============================================================ +# Test 1: from t import CEnum as en; class X(en) +# ============================================================ +class Color(en): + Red = 0 + Green = 1 + Blue = 2 + + +# ============================================================ +# Test 2: import t as tt; class X(tt.CEnum) +# ============================================================ +class Status(tt.CEnum): + Ok = 0 + Error = 1 + + +# ============================================================ +# Test 3: from t import CUnion as un; class X(un) +# ============================================================ +class Data(un): + i_val: t.CInt + f_val: t.CFloat + + +# ============================================================ +# Test 4: from t import REnum as ren; class X(ren) +# ============================================================ +class Opt(ren): + class Some: + val: myint + None_ = 0 + + +# ============================================================ +# Test 5: 前向引用检测 — _class_graph 正确识别父类 +# (注:检测已修复,但成员继承仍需父类先处理) +# ============================================================ +class Parent: + a: t.CInt + + def get_a(self) -> t.CInt: + return self.a + + +class Child(Parent): + b: t.CInt + + def get_sum(self) -> t.CInt: + return self.a + self.b + + +# ============================================================ +# Test 6: 多层继承 A -> B -> C,CVTable 向上传播 +# ============================================================ +class Base: + x: t.CInt + + def base_val(self) -> t.CInt: + return self.x + + +class Mid(Base): + y: t.CInt + + def mid_val(self) -> t.CInt: + return self.y + + +class Leaf(Mid): + z: t.CInt + + def leaf_val(self) -> t.CInt: + return self.z + + +# ============================================================ +# Test 7: 类型别名用于注解 +# ============================================================ +val: myint = 42 + + +# ============================================================ +# Test 8: BigEndian 字节序 +# ============================================================ +class NetHeader: + magic: t.CInt | t.BigEndian + length: t.CShort | t.BigEndian + normal: t.CInt + + +# ============================================================ +# Test 9: import t as tt; tt.CInt 作为类型注解 +# ============================================================ +# class TtStruct: +# x: tt.CInt +# y: tt.CFloat + + +# ============================================================ +# Test 10: import t as tt; class X(tt.CStruct) +# ============================================================ +class TtPoint(tt.CStruct): + x: t.CInt + y: t.CInt + + +# ============================================================ +# Test 11: import t as tt; @tt.Object 装饰器 +# ============================================================ +@tt.Object +class TtObject: + val: t.CInt + + def get_val(self) -> t.CInt: + return self.val + + +# ============================================================ +# Test 12: from t import CStruct as cs; class X(cs) +# ============================================================ +class CsPoint(cs): + x: t.CInt + y: t.CInt + + +# ============================================================ +# Test 13: import t as tt; class X(tt.CUnion) +# ============================================================ +class TtUnion(tt.CUnion): + a: t.CInt + b: t.CFloat + + +# ============================================================ +# Test 14: @tt.Object on class without methods (should fail?) +# ============================================================ +@tt.Object +class TtEmptyObject: + val: t.CInt + + +def main() -> t.CInt: + testcheck.begin("EdgeCaseTest: 类型别名与边界情况测试") + + # Test 1: CEnum alias + testcheck.section("Test 1: CEnum alias") + c: t.CInt = Color.Green + stdio.printf("Test1 CEnum alias: %d\n", c) + testcheck.ok("CEnum alias (Color.Green=1)") + + # Test 2: module alias + CEnum + testcheck.section("Test 2: module alias + CEnum") + s: t.CInt = Status.Error + stdio.printf("Test2 t as tt.CEnum: %d\n", s) + testcheck.ok("t as tt.CEnum (Status.Error=1)") + + # Test 3: CUnion alias + testcheck.section("Test 3: CUnion alias") + d: Data = Data() + d.i_val = 10 + d.f_val = 3.14 + stdio.printf("Test3 CUnion alias: i=%d f=%f\n", d.i_val, d.f_val) + testcheck.ok("CUnion alias (i=10 f=3.14)") + + # Test 4: REnum alias + testcheck.section("Test 4: REnum alias") + o: Opt = Opt.Some(99) + match o: + case Opt.Some(v): + stdio.printf("Test4 REnum alias: val=%d\n", v) + case Opt.None_(): + stdio.printf("Test4 REnum alias: None\n") + testcheck.ok("REnum alias (Opt.Some(99))") + + # Test 5: forward reference + testcheck.section("Test 5: forward reference") + ch: Child = Child() + ch.a = 100 + ch.b = 200 + stdio.printf("Test5 forward ref: a=%d b=%d sum=%d\n", ch.a, ch.b, ch.get_sum()) + stdio.printf("Test5 parent method: %d\n", ch.get_a()) + testcheck.ok("forward ref (a=100 b=200 sum=300)") + + # Test 6: multi-level inheritance + testcheck.section("Test 6: multi-level inheritance") + lf: Leaf = Leaf() + lf.x = 1 + lf.y = 2 + lf.z = 3 + stdio.printf("Test6 multi-inherit: base=%d mid=%d leaf=%d\n", + lf.base_val(), lf.mid_val(), lf.leaf_val()) + testcheck.ok("multi-inherit (base=1 mid=2 leaf=3)") + + # Test 7: type alias in annotation + testcheck.section("Test 7: type alias in annotation") + stdio.printf("Test7 type alias: val=%d\n", val) + testcheck.ok("type alias (val=42)") + + # Test 8: BigEndian + testcheck.section("Test 8: BigEndian") + nh: NetHeader = NetHeader() + nh.magic = 0x12345678 + nh.length = 256 + nh.normal = 42 + stdio.printf("Test8 BigEndian: magic=0x%X length=%d normal=%d\n", + nh.magic, nh.length, nh.normal) + testcheck.ok("BigEndian (magic=0x12345678 length=256 normal=42)") + + # Test 10: tt.CStruct as base class + testcheck.section("Test 10: tt.CStruct as base class") + tp: TtPoint = TtPoint() + tp.x = 100 + tp.y = 200 + stdio.printf("Test10 tt.CStruct: x=%d y=%d\n", tp.x, tp.y) + testcheck.ok("tt.CStruct (x=100 y=200)") + + # Test 11: @tt.Object decorator + testcheck.section("Test 11: @tt.Object decorator") + to: TtObject = TtObject() + to.val = 999 + stdio.printf("Test11 @tt.Object: val=%d\n", to.get_val()) + testcheck.ok("@tt.Object (val=999)") + + # Test 12: from t import CStruct as cs + testcheck.section("Test 12: from t import CStruct as cs") + cp: CsPoint = CsPoint() + cp.x = 11 + cp.y = 22 + stdio.printf("Test12 cs alias: x=%d y=%d\n", cp.x, cp.y) + testcheck.ok("cs alias (x=11 y=22)") + + # Test 13: tt.CUnion + testcheck.section("Test 13: tt.CUnion") + tu: TtUnion = TtUnion() + tu.a = 77 + stdio.printf("Test13 tt.CUnion: a=%d\n", tu.a) + testcheck.ok("tt.CUnion (a=77)") + + # Test 14: @tt.Object on empty class + testcheck.section("Test 14: @tt.Object on empty class") + teo: TtEmptyObject = TtEmptyObject() + teo.val = 555 + stdio.printf("Test14 @tt.Object empty: val=%d\n", teo.val) + testcheck.ok("@tt.Object empty (val=555)") + + return testcheck.end() diff --git a/Test/EdgeCaseTest/output/9dbecd0942a39782.deps.json b/Test/EdgeCaseTest/output/9dbecd0942a39782.deps.json new file mode 100644 index 0000000..8f985e2 --- /dev/null +++ b/Test/EdgeCaseTest/output/9dbecd0942a39782.deps.json @@ -0,0 +1 @@ +{"stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "main": "ac0d686cb2cc783b"} \ No newline at end of file diff --git a/Test/EdgeCaseTest/output/ac0d686cb2cc783b.deps.json b/Test/EdgeCaseTest/output/ac0d686cb2cc783b.deps.json new file mode 100644 index 0000000..94ebae9 --- /dev/null +++ b/Test/EdgeCaseTest/output/ac0d686cb2cc783b.deps.json @@ -0,0 +1 @@ +{"stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782"} \ No newline at end of file diff --git a/Test/EdgeCaseTest/project.json b/Test/EdgeCaseTest/project.json new file mode 100644 index 0000000..c54b6f3 --- /dev/null +++ b/Test/EdgeCaseTest/project.json @@ -0,0 +1,29 @@ +{ + "$schema": "https://raw.githubusercontent.com/TermiNexus/TransPyC/main/schemas/project-schema.json", + "name": "EdgeCaseTest", + "version": "1.0.0", + "source_dir": "./App", + "temp_dir": "./temp", + "output_dir": "./output", + "compiler": { + "cmd": "llc", + "flags": ["-filetype=obj", "-relocation-model=pic"] + }, + "linker": { + "cmd": "clang++", + "flags": ["-lmsvcrt", "-lucrt", "-lpthread", "-lmingwex", "-lkernel32", "-Wl,--allow-multiple-definition"], + "output": "EdgeCaseTest.exe" + }, + "includes": [ + "../../includes" + ], + "target": { + "triple": "x86_64-pc-windows-gnu", + "datalayout": "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" + }, + "options": { + "slice_level": 3, + "target": "llvm", + "strict_mode": true + } +} diff --git a/Test/EdgeCaseTest/temp/73edbcf76e32d00b.pyi b/Test/EdgeCaseTest/temp/73edbcf76e32d00b.pyi new file mode 100644 index 0000000..ef712e3 --- /dev/null +++ b/Test/EdgeCaseTest/temp/73edbcf76e32d00b.pyi @@ -0,0 +1,28 @@ +""" +Auto-generated Python stub file from stdio.py +Module: stdio +""" + + +import t, c + +def printf(fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass + +def fprintf(stream: t.CVoid | t.CPtr, fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass + +def sprintf(buf: t.CChar | t.CPtr, fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass + +def snprintf(buf: t.CChar | t.CPtr, size: t.CSizeT, fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass + +def puts(s: t.CChar | t.CConst | t.CPtr) -> t.CInt | t.CExtern | t.CExport: pass + +def fputs(s: t.CChar | t.CConst | t.CPtr, stream: t.CVoid | t.CPtr) -> t.CInt | t.CExtern | t.CExport: pass + +def fgets(buf: t.CChar | t.CPtr, size: t.CInt, stream: t.CVoid | t.CPtr) -> t.CChar | t.CPtr | t.CExtern | t.CExport: pass + +def fflush(stream: t.CVoid | t.CPtr) -> t.CInt | t.CExtern | t.CExport: pass + + +stdin: t.CExtern | t.CVoid | t.CPtr +stdout: t.CExtern | t.CVoid | t.CPtr +stderr: t.CExtern | t.CVoid | t.CPtr \ No newline at end of file diff --git a/Test/EdgeCaseTest/temp/9dbecd0942a39782.pyi b/Test/EdgeCaseTest/temp/9dbecd0942a39782.pyi new file mode 100644 index 0000000..41648c1 --- /dev/null +++ b/Test/EdgeCaseTest/temp/9dbecd0942a39782.pyi @@ -0,0 +1,25 @@ +""" +Auto-generated Python stub file from testcheck.py +Module: testcheck +""" + + +import t, c +import stdio + +_pass_count: t.CExtern | t.CInt +_fail_count: t.CExtern | t.CInt + +def begin(name: str) -> t.CInt: pass + +def section(name: str) -> t.CInt: pass + +def ok(msg: str) -> t.CInt: pass + +def fail(msg: str) -> t.CInt: pass + +def check(cond: t.CInt, ok_msg: str, fail_msg: str) -> t.CInt: pass + +def info(msg: str) -> t.CInt: pass + +def end() -> t.CInt: pass diff --git a/Test/EdgeCaseTest/temp/_sha1_map.txt b/Test/EdgeCaseTest/temp/_sha1_map.txt new file mode 100644 index 0000000..ec00880 --- /dev/null +++ b/Test/EdgeCaseTest/temp/_sha1_map.txt @@ -0,0 +1,3 @@ +73edbcf76e32d00b:includes/stdio.py +9dbecd0942a39782:includes/testcheck.py +ac0d686cb2cc783b:main.py diff --git a/Test/EdgeCaseTest/temp/ac0d686cb2cc783b.pyi b/Test/EdgeCaseTest/temp/ac0d686cb2cc783b.pyi new file mode 100644 index 0000000..7b2670f --- /dev/null +++ b/Test/EdgeCaseTest/temp/ac0d686cb2cc783b.pyi @@ -0,0 +1,73 @@ +""" +Auto-generated Python stub file from main.py +Module: main +""" + +import c + + +import t +import t as tt +import stdio +import testcheck +from t import CEnum as en +from t import CUnion as un +from t import REnum as ren +from t import CStruct as cs +from t import CInt as myint +from t import CChar, CPtr + +class Color(en): + Red = 0 + Green = 1 + Blue = 2 +class Status(tt.CEnum): + Ok = 0 + Error = 1 +class Data(un): + i_val: t.CInt + f_val: t.CFloat +class Opt(ren): + class Some: + val: myint + None_ = 0 +class Parent: + a: t.CInt + def get_a(self: Parent) -> t.CInt: pass +class Child(Parent): + b: t.CInt + def get_sum(self: Child) -> t.CInt: pass +class Base: + x: t.CInt + def base_val(self: Base) -> t.CInt: pass +class Mid(Base): + y: t.CInt + def mid_val(self: Mid) -> t.CInt: pass +class Leaf(Mid): + z: t.CInt + def leaf_val(self: Leaf) -> t.CInt: pass + +val: t.CExtern | myint + +class NetHeader: + magic: t.CInt | t.BigEndian + length: t.CShort | t.BigEndian + normal: t.CInt +class TtPoint(tt.CStruct): + x: t.CInt + y: t.CInt +@tt.Object +class TtObject: + val: t.CInt + def get_val(self: TtObject) -> t.CInt: pass +class CsPoint(cs): + x: t.CInt + y: t.CInt +class TtUnion(tt.CUnion): + a: t.CInt + b: t.CFloat +@tt.Object +class TtEmptyObject: + val: t.CInt + +def main() -> t.CInt: pass diff --git a/Test/EqTest/App/main.py b/Test/EqTest/App/main.py new file mode 100644 index 0000000..ba3db77 --- /dev/null +++ b/Test/EqTest/App/main.py @@ -0,0 +1,56 @@ +from stdint import * +import w32.win32console +import t, c +from t import CInt, CExport +import stdio +import stdlib +import string +import testcheck + + +def main() -> CInt | CExport: + w32.win32console.SetConsoleCP(65001) + w32.win32console.SetConsoleOutputCP(65001) + + testcheck.begin("== 重载和 is 地址比较测试") + + # === Test 1: str == str 值比较 === + testcheck.section("Test 1: str == str 值比较") + s1: str = "hello" + s2: str = "hello" + s3: str = "world" + testcheck.check(s1 == s2, "str == str (same value) OK", "str == str (same value) FAILED") + testcheck.check(not (s1 == s3), "str != str (diff value) OK", "str != str (diff value) FAILED") + + # === Test 2: str != str === + testcheck.section("Test 2: str != str") + testcheck.check(s1 != s3, "str != str (diff) OK", "str != str (diff) FAILED") + testcheck.check(not (s1 != s2), "str == str (same) via != OK", "str == str (same) via != FAILED") + + # === Test 3: str == 字面量 === + testcheck.section("Test 3: str == literal") + testcheck.check(s1 == "hello", "str == literal OK", "str == literal FAILED") + testcheck.check(not (s1 == "world"), "str != literal OK", "str != literal FAILED") + + # === Test 4: str is str 地址比较 === + testcheck.section("Test 4: str is str address compare") + # s1 和 s2 是不同的字符串变量,地址不同 + testcheck.check(not (s1 is s2), "str is str (diff addr) OK", "str is str (diff addr) FAILED") + # s1 is s1 应该为 True(同一变量) + testcheck.check(s1 is s1, "str is self OK", "str is self FAILED") + + # === Test 5: int == int === + testcheck.section("Test 5: int == int") + i1: int = 42 + i2: int = 42 + i3: int = 99 + testcheck.check(i1 == i2, "int == int (same) OK", "int == int (same) FAILED") + testcheck.check(not (i1 == i3), "int != int (diff) OK", "int != int (diff) FAILED") + + # === Test 6: None 比较 === + testcheck.section("Test 6: None compare") + null_ptr: str = None + testcheck.check(null_ptr == None, "ptr == None OK", "ptr == None FAILED") + testcheck.check(not (s1 == None), "str != None OK", "str != None FAILED") + + return testcheck.end() diff --git a/Test/EqTest/output/067c78e9f121dce3.deps.json b/Test/EqTest/output/067c78e9f121dce3.deps.json new file mode 100644 index 0000000..093174c --- /dev/null +++ b/Test/EqTest/output/067c78e9f121dce3.deps.json @@ -0,0 +1 @@ +{"stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "main": "78943d0dbc89a29a", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3"} \ No newline at end of file diff --git a/Test/EqTest/output/06f53cc594b4ac6c.deps.json b/Test/EqTest/output/06f53cc594b4ac6c.deps.json new file mode 100644 index 0000000..112bbca --- /dev/null +++ b/Test/EqTest/output/06f53cc594b4ac6c.deps.json @@ -0,0 +1 @@ +{"stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "main": "78943d0dbc89a29a", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "06f53cc594b4ac6c", "win32sync": "06f53cc594b4ac6c"} \ No newline at end of file diff --git a/Test/EqTest/output/5a6a2137958c28c5.deps.json b/Test/EqTest/output/5a6a2137958c28c5.deps.json new file mode 100644 index 0000000..156396d --- /dev/null +++ b/Test/EqTest/output/5a6a2137958c28c5.deps.json @@ -0,0 +1 @@ +{"stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "main": "78943d0dbc89a29a", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c"} \ No newline at end of file diff --git a/Test/EqTest/output/72e2d5ccb7cedcf1.deps.json b/Test/EqTest/output/72e2d5ccb7cedcf1.deps.json new file mode 100644 index 0000000..bdf4c43 --- /dev/null +++ b/Test/EqTest/output/72e2d5ccb7cedcf1.deps.json @@ -0,0 +1 @@ +{"stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "main": "78943d0dbc89a29a", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1"} \ No newline at end of file diff --git a/Test/EqTest/output/78943d0dbc89a29a.deps.json b/Test/EqTest/output/78943d0dbc89a29a.deps.json new file mode 100644 index 0000000..1406042 --- /dev/null +++ b/Test/EqTest/output/78943d0dbc89a29a.deps.json @@ -0,0 +1 @@ +{"stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c"} \ No newline at end of file diff --git a/Test/EqTest/output/9dbecd0942a39782.deps.json b/Test/EqTest/output/9dbecd0942a39782.deps.json new file mode 100644 index 0000000..156396d --- /dev/null +++ b/Test/EqTest/output/9dbecd0942a39782.deps.json @@ -0,0 +1 @@ +{"stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "main": "78943d0dbc89a29a", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c"} \ No newline at end of file diff --git a/Test/EqTest/output/abf9ce3160c9279e.deps.json b/Test/EqTest/output/abf9ce3160c9279e.deps.json new file mode 100644 index 0000000..e834f2c --- /dev/null +++ b/Test/EqTest/output/abf9ce3160c9279e.deps.json @@ -0,0 +1 @@ +{"stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "main": "78943d0dbc89a29a", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e"} \ No newline at end of file diff --git a/Test/EqTest/output/b5f1dc665c52a1bd.deps.json b/Test/EqTest/output/b5f1dc665c52a1bd.deps.json new file mode 100644 index 0000000..156396d --- /dev/null +++ b/Test/EqTest/output/b5f1dc665c52a1bd.deps.json @@ -0,0 +1 @@ +{"stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "main": "78943d0dbc89a29a", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c"} \ No newline at end of file diff --git a/Test/EqTest/output/bbdf3bbd4c3bc28c.deps.json b/Test/EqTest/output/bbdf3bbd4c3bc28c.deps.json new file mode 100644 index 0000000..156396d --- /dev/null +++ b/Test/EqTest/output/bbdf3bbd4c3bc28c.deps.json @@ -0,0 +1 @@ +{"stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "main": "78943d0dbc89a29a", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c"} \ No newline at end of file diff --git a/Test/EqTest/output/fa3691e66b426950.deps.json b/Test/EqTest/output/fa3691e66b426950.deps.json new file mode 100644 index 0000000..16a6961 --- /dev/null +++ b/Test/EqTest/output/fa3691e66b426950.deps.json @@ -0,0 +1 @@ +{"stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "main": "78943d0dbc89a29a", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file diff --git a/Test/EqTest/project.json b/Test/EqTest/project.json new file mode 100644 index 0000000..9a71251 --- /dev/null +++ b/Test/EqTest/project.json @@ -0,0 +1,29 @@ +{ + "$schema": "https://raw.githubusercontent.com/TermiNexus/TransPyC/main/schemas/project-schema.json", + "name": "EqTest", + "version": "1.0.0", + "source_dir": "./App", + "temp_dir": "./temp", + "output_dir": "./output", + "compiler": { + "cmd": "llc", + "flags": ["-filetype=obj", "-relocation-model=pic"] + }, + "linker": { + "cmd": "clang++", + "flags": ["-lmsvcrt", "-lucrt", "-lpthread", "-lmingwex", "-lkernel32", "-Wl,--allow-multiple-definition"], + "output": "EqTest.exe" + }, + "includes": [ + "./includes" + ], + "target": { + "triple": "x86_64-pc-windows-gnu", + "datalayout": "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" + }, + "options": { + "slice_level": 3, + "target": "llvm", + "strict_mode": true + } +} diff --git a/Test/EqTest/temp/067c78e9f121dce3.pyi b/Test/EqTest/temp/067c78e9f121dce3.pyi new file mode 100644 index 0000000..f4f767c --- /dev/null +++ b/Test/EqTest/temp/067c78e9f121dce3.pyi @@ -0,0 +1,136 @@ +""" +Auto-generated Python stub file from w32.win32process.py +Module: w32.win32process +""" + +import c + + +import t +from stdint import * +from w32.win32base import * + +PROCESS_TERMINATE: t.CDefine = 0x0001 +PROCESS_CREATE_THREAD: t.CDefine = 0x0002 +PROCESS_VM_OPERATION: t.CDefine = 0x0008 +PROCESS_VM_READ: t.CDefine = 0x0010 +PROCESS_VM_WRITE: t.CDefine = 0x0020 +PROCESS_QUERY_INFORMATION: t.CDefine = 0x0400 +PROCESS_ALL_ACCESS: t.CDefine = 0x001FFFFF +THREAD_TERMINATE: t.CDefine = 0x0001 +THREAD_SUSPEND_RESUME: t.CDefine = 0x0002 +THREAD_GET_CONTEXT: t.CDefine = 0x0008 +THREAD_SET_CONTEXT: t.CDefine = 0x0010 +THREAD_QUERY_INFORMATION: t.CDefine = 0x0040 +THREAD_ALL_ACCESS: t.CDefine = 0x001FFFFF +CREATE_SUSPENDED: t.CDefine = 0x00000004 +CREATE_NEW_CONSOLE: t.CDefine = 0x00000010 +CREATE_NEW_PROCESS_GROUP: t.CDefine = 0x00000200 +CREATE_NO_WINDOW: t.CDefine = 0x08000000 +DETACHED_PROCESS: t.CDefine = 0x00000008 +STARTF_USESHOWWINDOW: t.CDefine = 0x00000001 +STARTF_USESTDHANDLES: t.CDefine = 0x00000100 +SW_HIDE: t.CDefine = 0 +SW_SHOW: t.CDefine = 5 +SW_MINIMIZE: t.CDefine = 6 +NORMAL_PRIORITY_CLASS: t.CDefine = 0x00000020 +IDLE_PRIORITY_CLASS: t.CDefine = 0x00000040 +HIGH_PRIORITY_CLASS: t.CDefine = 0x00000080 +REALTIME_PRIORITY_CLASS: t.CDefine = 0x00000100 +BELOW_NORMAL_PRIORITY_CLASS: t.CDefine = 0x00004000 +ABOVE_NORMAL_PRIORITY_CLASS: t.CDefine = 0x00008000 +STILL_ACTIVE: t.CDefine = 259 + +class STARTUPINFOA: + cb: ULONG + lpReserved: CHARPTR + lpDesktop: CHARPTR + lpTitle: CHARPTR + dwX: ULONG + dwY: ULONG + dwXSize: ULONG + dwYSize: ULONG + dwXCountChars: ULONG + dwYCountChars: ULONG + dwFillAttribute: ULONG + dwFlags: ULONG + wShowWindow: WORD + cbReserved2: WORD + lpReserved2: VOIDPTR + hStdInput: HANDLE + hStdOutput: HANDLE + hStdError: HANDLE +class STARTUPINFOW: + cb: ULONG + lpReserved: WCHARPTR + lpDesktop: WCHARPTR + lpTitle: WCHARPTR + dwX: ULONG + dwY: ULONG + dwXSize: ULONG + dwYSize: ULONG + dwXCountChars: ULONG + dwYCountChars: ULONG + dwFillAttribute: ULONG + dwFlags: ULONG + wShowWindow: WORD + cbReserved2: WORD + lpReserved2: VOIDPTR + hStdInput: HANDLE + hStdOutput: HANDLE + hStdError: HANDLE +class PROCESS_INFORMATION: + hProcess: HANDLE + hThread: HANDLE + dwProcessId: ULONG + dwThreadId: ULONG + +def CreateProcessA(lpApplicationName: LPCSTR, lpCommandLine: CHARPTR, lpProcessAttributes: SECURITY_ATTRIBUTES | t.CPtr, lpThreadAttributes: SECURITY_ATTRIBUTES | t.CPtr, bInheritHandles: BOOL, dwCreationFlags: ULONG, lpEnvironment: VOIDPTR, lpCurrentDirectory: LPCSTR, lpStartupInfo: STARTUPINFOA | t.CPtr, lpProcessInformation: PROCESS_INFORMATION | t.CPtr) -> BOOL | t.State: pass + +def CreateProcessW(lpApplicationName: LPCWSTR, lpCommandLine: WCHARPTR, lpProcessAttributes: SECURITY_ATTRIBUTES | t.CPtr, lpThreadAttributes: SECURITY_ATTRIBUTES | t.CPtr, bInheritHandles: BOOL, dwCreationFlags: ULONG, lpEnvironment: VOIDPTR, lpCurrentDirectory: LPCWSTR, lpStartupInfo: STARTUPINFOW | t.CPtr, lpProcessInformation: PROCESS_INFORMATION | t.CPtr) -> BOOL | t.State: pass + +def TerminateProcess(hProcess: HANDLE, uExitCode: UINT) -> BOOL | t.State: pass + +def GetExitCodeProcess(hProcess: HANDLE, lpExitCode: ULONG | t.CPtr) -> BOOL | t.State: pass + +def GetExitCodeThread(hThread: HANDLE, lpExitCode: ULONG | t.CPtr) -> BOOL | t.State: pass + +def OpenProcess(dwDesiredAccess: ULONG, bInheritHandle: BOOL, dwProcessId: ULONG) -> HANDLE | t.State: pass + +def GetCurrentProcess() -> HANDLE | t.State: pass + +def GetCurrentProcessId() -> ULONG | t.State: pass + +def CreateThread(lpThreadAttributes: SECURITY_ATTRIBUTES | t.CPtr, dwStackSize: t.CSizeT, lpStartAddress: VOIDPTR, lpParameter: VOIDPTR, dwCreationFlags: ULONG, lpThreadId: ULONG | t.CPtr) -> HANDLE | t.State: pass + +def OpenThread(dwDesiredAccess: ULONG, bInheritHandle: BOOL, dwThreadId: ULONG) -> HANDLE | t.State: pass + +def SuspendThread(hThread: HANDLE) -> ULONG | t.State: pass + +def ResumeThread(hThread: HANDLE) -> ULONG | t.State: pass + +def TerminateThread(hThread: HANDLE, dwExitCode: ULONG) -> BOOL | t.State: pass + +def GetCurrentThread() -> HANDLE | t.State: pass + +def GetCurrentThreadId() -> ULONG | t.State: pass + +def GetThreadId(hThread: HANDLE) -> ULONG | t.State: pass + +def GetProcessId(hProcess: HANDLE) -> ULONG | t.State: pass + +def SetThreadPriority(hThread: HANDLE, nPriority: INT) -> BOOL | t.State: pass + +def GetThreadPriority(hThread: HANDLE) -> INT | t.State: pass + +def ExitProcess(uExitCode: UINT) -> VOID | t.State: pass + +def ExitThread(dwExitCode: ULONG) -> VOID | t.State: pass + +def TlsAlloc() -> ULONG | t.State: pass + +def TlsFree(dwTlsIndex: ULONG) -> BOOL | t.State: pass + +def TlsGetValue(dwTlsIndex: ULONG) -> VOIDPTR | t.State: pass + +def TlsSetValue(dwTlsIndex: ULONG, lpTlsValue: VOIDPTR) -> BOOL | t.State: pass diff --git a/Test/EqTest/temp/06f53cc594b4ac6c.pyi b/Test/EqTest/temp/06f53cc594b4ac6c.pyi new file mode 100644 index 0000000..8b5a8cf --- /dev/null +++ b/Test/EqTest/temp/06f53cc594b4ac6c.pyi @@ -0,0 +1,109 @@ +""" +Auto-generated Python stub file from w32.win32sync.py +Module: w32.win32sync +""" + +import c + + +import t +from stdint import * +from w32.win32base import * + +class CRITICAL_SECTION: + DebugInfo: VOIDPTR + LockCount: LONG + RecursionCount: LONG + OwningThread: HANDLE + LockSemaphore: HANDLE + SpinCount: QWORD + +def InitializeCriticalSection(lpCriticalSection: CRITICAL_SECTION | t.CPtr) -> VOID | t.State: pass + +def EnterCriticalSection(lpCriticalSection: CRITICAL_SECTION | t.CPtr) -> VOID | t.State: pass + +def LeaveCriticalSection(lpCriticalSection: CRITICAL_SECTION | t.CPtr) -> VOID | t.State: pass + +def DeleteCriticalSection(lpCriticalSection: CRITICAL_SECTION | t.CPtr) -> VOID | t.State: pass + +def TryEnterCriticalSection(lpCriticalSection: CRITICAL_SECTION | t.CPtr) -> BOOL | t.State: pass + +def SetCriticalSectionSpinCount(lpCriticalSection: CRITICAL_SECTION | t.CPtr, dwSpinCount: ULONG) -> ULONG | t.State: pass + +def InitializeCriticalSectionAndSpinCount(lpCriticalSection: CRITICAL_SECTION | t.CPtr, dwSpinCount: ULONG) -> BOOL | t.State: pass + +def CreateMutexA(lpMutexAttributes: SECURITY_ATTRIBUTES | t.CPtr, bInitialOwner: BOOL, lpName: LPCSTR) -> HANDLE | t.State: pass + +def CreateMutexW(lpMutexAttributes: SECURITY_ATTRIBUTES | t.CPtr, bInitialOwner: BOOL, lpName: LPCWSTR) -> HANDLE | t.State: pass + +def OpenMutexA(dwDesiredAccess: ULONG, bInheritHandle: BOOL, lpName: LPCSTR) -> HANDLE | t.State: pass + +def OpenMutexW(dwDesiredAccess: ULONG, bInheritHandle: BOOL, lpName: LPCWSTR) -> HANDLE | t.State: pass + +def ReleaseMutex(hMutex: HANDLE) -> BOOL | t.State: pass + +def CreateEventA(lpEventAttributes: SECURITY_ATTRIBUTES | t.CPtr, bManualReset: BOOL, bInitialState: BOOL, lpName: LPCSTR) -> HANDLE | t.State: pass + +def CreateEventW(lpEventAttributes: SECURITY_ATTRIBUTES | t.CPtr, bManualReset: BOOL, bInitialState: BOOL, lpName: LPCWSTR) -> HANDLE | t.State: pass + +def OpenEventA(dwDesiredAccess: ULONG, bInheritHandle: BOOL, lpName: LPCSTR) -> HANDLE | t.State: pass + +def OpenEventW(dwDesiredAccess: ULONG, bInheritHandle: BOOL, lpName: LPCWSTR) -> HANDLE | t.State: pass + +def SetEvent(hEvent: HANDLE) -> BOOL | t.State: pass + +def ResetEvent(hEvent: HANDLE) -> BOOL | t.State: pass + +def PulseEvent(hEvent: HANDLE) -> BOOL | t.State: pass + +def CreateSemaphoreA(lpSemaphoreAttributes: SECURITY_ATTRIBUTES | t.CPtr, lInitialCount: LONG, lMaximumCount: LONG, lpName: LPCSTR) -> HANDLE | t.State: pass + +def CreateSemaphoreW(lpSemaphoreAttributes: SECURITY_ATTRIBUTES | t.CPtr, lInitialCount: LONG, lMaximumCount: LONG, lpName: LPCWSTR) -> HANDLE | t.State: pass + +def OpenSemaphoreA(dwDesiredAccess: ULONG, bInheritHandle: BOOL, lpName: LPCSTR) -> HANDLE | t.State: pass + +def OpenSemaphoreW(dwDesiredAccess: ULONG, bInheritHandle: BOOL, lpName: LPCWSTR) -> HANDLE | t.State: pass + +def ReleaseSemaphore(hSemaphore: HANDLE, lReleaseCount: LONG, lpPreviousCount: LONG | t.CPtr) -> BOOL | t.State: pass + +def WaitForSingleObject(hHandle: HANDLE, dwMilliseconds: ULONG) -> ULONG | t.State: pass + +def WaitForSingleObjectEx(hHandle: HANDLE, dwMilliseconds: ULONG, bAlertable: BOOL) -> ULONG | t.State: pass + +def WaitForMultipleObjects(nCount: ULONG, lpHandles: VOIDPTR, bWaitAll: BOOL, dwMilliseconds: ULONG) -> ULONG | t.State: pass + +def WaitForMultipleObjectsEx(nCount: ULONG, lpHandles: VOIDPTR, bWaitAll: BOOL, dwMilliseconds: ULONG, bAlertable: BOOL) -> ULONG | t.State: pass + +def InitializeSRWLock(SRWLock: VOIDPTR) -> VOID | t.State: pass + +def AcquireSRWLockExclusive(SRWLock: VOIDPTR) -> VOID | t.State: pass + +def AcquireSRWLockShared(SRWLock: VOIDPTR) -> VOID | t.State: pass + +def ReleaseSRWLockExclusive(SRWLock: VOIDPTR) -> VOID | t.State: pass + +def ReleaseSRWLockShared(SRWLock: VOIDPTR) -> VOID | t.State: pass + + +CONDITION_VARIABLE_LOCKMODE_SHARED: t.CDefine = 0x1 + +def InitializeConditionVariable(ConditionVariable: VOIDPTR) -> VOID | t.State: pass + +def SleepConditionVariableCS(ConditionVariable: VOIDPTR, CriticalSection: CRITICAL_SECTION | t.CPtr, dwMilliseconds: ULONG) -> BOOL | t.State: pass + +def SleepConditionVariableSRW(ConditionVariable: VOIDPTR, SRWLock: VOIDPTR, dwMilliseconds: ULONG, Flags: ULONG) -> BOOL | t.State: pass + +def WakeConditionVariable(ConditionVariable: VOIDPTR) -> VOID | t.State: pass + +def WakeAllConditionVariable(ConditionVariable: VOIDPTR) -> VOID | t.State: pass + + +INIT_ONCE_STATIC_INIT: t.CDefine = 0x00000001 +INIT_ONCE_CHECK_ONLY: t.CDefine = 0x00000002 +INIT_ONCE_ASYNC: t.CDefine = 0x00000004 +INIT_ONCE_INIT_FAILED: t.CDefine = 0x00000008 + +class INIT_ONCE: + Ptr: t.CPtr + +def InitOnceExecuteOnce(InitOnce: INIT_ONCE | t.CPtr, InitFn: VOIDPTR, Parameter: VOIDPTR, Context: VOIDPTR | t.CPtr) -> BOOL | t.State: pass diff --git a/Test/FuncTest/temp/56cdd754a8a09347.pyi b/Test/EqTest/temp/49bd8cba55979f76.pyi similarity index 88% rename from Test/FuncTest/temp/56cdd754a8a09347.pyi rename to Test/EqTest/temp/49bd8cba55979f76.pyi index 007ccb8..f1d844a 100644 --- a/Test/FuncTest/temp/56cdd754a8a09347.pyi +++ b/Test/EqTest/temp/49bd8cba55979f76.pyi @@ -64,4 +64,12 @@ CHAR16: t.CTypedef = t.CChar16T CHAR32: t.CTypedef = t.CChar32T CHAR8PTR: t.CTypedef = t.CChar8T | t.CPtr CHAR16PTR: t.CTypedef = t.CChar16T | t.CPtr -CHAR32PTR: t.CTypedef = t.CChar32T | t.CPtr \ No newline at end of file +CHAR32PTR: t.CTypedef = t.CChar32T | t.CPtr +i8: t.CTypedef = t.CInt8T +i16: t.CTypedef = t.CInt16T +i32: t.CTypedef = t.CInt32T +i64: t.CTypedef = t.CInt64T +u8: t.CTypedef = t.CUInt8T +u16: t.CTypedef = t.CUInt16T +u32: t.CTypedef = t.CUInt32T +u64: t.CTypedef = t.CUInt64T \ No newline at end of file diff --git a/Test/EqTest/temp/5a6a2137958c28c5.pyi b/Test/EqTest/temp/5a6a2137958c28c5.pyi new file mode 100644 index 0000000..a137977 --- /dev/null +++ b/Test/EqTest/temp/5a6a2137958c28c5.pyi @@ -0,0 +1,98 @@ +""" +Auto-generated Python stub file from w32.win32base.py +Module: w32.win32base +""" + +import c + + +import t +from stdint import * + +HANDLE: t.CTypedef = VOIDPTR +LPCSTR: t.CTypedef = t.CConst | t.CChar | t.CPtr +LPCWSTR: t.CTypedef = t.CConst | t.CUnsignedShort | t.CPtr +INVALID_HANDLE_VALUE: t.CDefine = t.CVoid(-1) +NULL: t.CDefine = 0 +TRUE: t.CDefine = 1 +FALSE: t.CDefine = 0 +INFINITE: t.CDefine = 0xFFFFFFFF +WAIT_FAILED: t.CDefine = 0xFFFFFFFF +WAIT_OBJECT_0: t.CDefine = 0 +WAIT_TIMEOUT: t.CDefine = 258 +WAIT_ABANDONED: t.CDefine = 0x80 +MAX_PATH: t.CDefine = 260 +ERROR_SUCCESS: t.CDefine = 0 +ERROR_FILE_NOT_FOUND: t.CDefine = 2 +ERROR_ACCESS_DENIED: t.CDefine = 5 +ERROR_INSUFFICIENT_BUFFER: t.CDefine = 122 + +class SECURITY_ATTRIBUTES: + nLength: ULONG + lpSecurityDescriptor: VOIDPTR + bInheritHandle: BOOL +class OVERLAPPED: + Internal: ULONGLONG + InternalHigh: ULONGLONG + Offset: ULONG + OffsetHigh: ULONG + hEvent: HANDLE +class FILETIME: + dwLowDateTime: DWORD + dwHighDateTime: DWORD +class SYSTEMTIME: + wYear: WORD + wMonth: WORD + wDayOfWeek: WORD + wDay: WORD + wHour: WORD + wMinute: WORD + wSecond: WORD + wMilliseconds: WORD +class GUID: + Data1: DWORD + Data2: WORD + Data3: WORD + Data4: BYTEPTR +class LARGE_INTEGER: + QuadPart: LONGLONG +class ULARGE_INTEGER: + QuadPart: ULONGLONG + +def GetLastError() -> ULONG | t.State: pass + +def SetLastError(dwErrCode: ULONG) -> t.State: pass + +def CloseHandle(hObject: HANDLE) -> BOOL | t.State: pass + +def GetProcAddress(hModule: HANDLE, lpProcName: LPCSTR) -> VOIDPTR | t.State: pass + +def GetModuleHandleA(lpModuleName: LPCSTR) -> HANDLE | t.State: pass + +def GetModuleHandleW(lpModuleName: LPCWSTR) -> HANDLE | t.State: pass + +def LoadLibraryA(lpLibFileName: LPCSTR) -> HANDLE | t.State: pass + +def LoadLibraryW(lpLibFileName: LPCWSTR) -> HANDLE | t.State: pass + +def FreeLibrary(hLibModule: HANDLE) -> BOOL | t.State: pass + +def GetSystemTime(lpSystemTime: SYSTEMTIME | t.CPtr) -> t.State: pass + +def GetLocalTime(lpSystemTime: SYSTEMTIME | t.CPtr) -> t.State: pass + +def FileTimeToSystemTime(lpFileTime: FILETIME | t.CPtr, lpSystemTime: SYSTEMTIME | t.CPtr) -> BOOL | t.State: pass + +def SystemTimeToFileTime(lpSystemTime: SYSTEMTIME | t.CPtr, lpFileTime: FILETIME | t.CPtr) -> BOOL | t.State: pass + +def QueryPerformanceCounter(lpPerformanceCount: LARGE_INTEGER | t.CPtr) -> BOOL | t.State: pass + +def QueryPerformanceFrequency(lpFrequency: LARGE_INTEGER | t.CPtr) -> BOOL | t.State: pass + +def Sleep(dwMilliseconds: ULONG) -> t.State: pass + +def SleepEx(dwMilliseconds: ULONG, bAlertable: BOOL) -> ULONG | t.State: pass + +def GetTickCount() -> ULONG | t.State: pass + +def GetTickCount64() -> ULONGLONG | t.State: pass diff --git a/Test/EqTest/temp/6c2029b306556c00.pyi b/Test/EqTest/temp/6c2029b306556c00.pyi new file mode 100644 index 0000000..98da680 --- /dev/null +++ b/Test/EqTest/temp/6c2029b306556c00.pyi @@ -0,0 +1,18 @@ +""" +Auto-generated Python stub file from stdlib.py +Module: stdlib +""" + +import c + + +from stdint import * +import t + +def malloc(size: t.CSizeT) -> t.CVoid | t.CPtr | t.State | t.CExtern | t.CExport: pass + +def calloc(nmemb: t.CSizeT, size: t.CSizeT) -> t.CVoid | t.CPtr | t.State | t.CExtern | t.CExport: pass + +def realloc(p: t.CVoid | t.CPtr, size: t.CSizeT) -> t.CVoid | t.CPtr | t.State | t.CExtern | t.CExport: pass + +def free(p: t.CVoid | t.CPtr) -> None | t.State | t.CExtern | t.CExport: pass diff --git a/Test/EqTest/temp/72e2d5ccb7cedcf1.pyi b/Test/EqTest/temp/72e2d5ccb7cedcf1.pyi new file mode 100644 index 0000000..5fceb08 --- /dev/null +++ b/Test/EqTest/temp/72e2d5ccb7cedcf1.pyi @@ -0,0 +1,91 @@ +""" +Auto-generated Python stub file from w32.win32memory.py +Module: w32.win32memory +""" + +import c + + +import t +from stdint import * +from w32.win32base import * + +MEM_COMMIT: t.CDefine = 0x00001000 +MEM_RESERVE: t.CDefine = 0x00002000 +MEM_DECOMMIT: t.CDefine = 0x00004000 +MEM_RELEASE: t.CDefine = 0x00008000 +MEM_FREE: t.CDefine = 0x00010000 +MEM_RESET: t.CDefine = 0x00080000 +MEM_TOP_DOWN: t.CDefine = 0x00100000 +MEM_WRITE_WATCH: t.CDefine = 0x00200000 +MEM_PHYSICAL: t.CDefine = 0x00400000 +MEM_LARGE_PAGES: t.CDefine = 0x20000000 +PAGE_NOACCESS: t.CDefine = 0x01 +PAGE_READONLY: t.CDefine = 0x02 +PAGE_READWRITE: t.CDefine = 0x04 +PAGE_WRITECOPY: t.CDefine = 0x08 +PAGE_EXECUTE: t.CDefine = 0x10 +PAGE_EXECUTE_READ: t.CDefine = 0x20 +PAGE_EXECUTE_READWRITE: t.CDefine = 0x40 +PAGE_EXECUTE_WRITECOPY: t.CDefine = 0x80 +PAGE_GUARD: t.CDefine = 0x100 +PAGE_NOCACHE: t.CDefine = 0x200 +PAGE_WRITECOMBINE: t.CDefine = 0x400 +HEAP_NO_SERIALIZE: t.CDefine = 0x00000001 +HEAP_GROWABLE: t.CDefine = 0x00000002 +HEAP_GENERATE_EXCEPTIONS: t.CDefine = 0x00000004 +HEAP_ZERO_MEMORY: t.CDefine = 0x00000008 +HEAP_REALLOC_IN_PLACE_ONLY: t.CDefine = 0x00000010 + +class MEMORY_BASIC_INFORMATION: + BaseAddress: VOIDPTR + AllocationBase: VOIDPTR + AllocationProtect: ULONG + RegionSize: t.CSizeT + State: ULONG + Protect: ULONG + Type: ULONG + +def VirtualAlloc(lpAddress: VOIDPTR, dwSize: t.CSizeT, flAllocationType: ULONG, flProtect: ULONG) -> VOIDPTR | t.State: pass + +def VirtualFree(lpAddress: VOIDPTR, dwSize: t.CSizeT, dwFreeType: ULONG) -> BOOL | t.State: pass + +def VirtualProtect(lpAddress: VOIDPTR, dwSize: t.CSizeT, flNewProtect: ULONG, lpflOldProtect: ULONG | t.CPtr) -> BOOL | t.State: pass + +def VirtualQuery(lpAddress: t.CConst | VOIDPTR, lpBuffer: MEMORY_BASIC_INFORMATION | t.CPtr, dwLength: t.CSizeT) -> t.CSizeT | t.State: pass + +def VirtualLock(lpAddress: VOIDPTR, dwSize: t.CSizeT) -> BOOL | t.State: pass + +def VirtualUnlock(lpAddress: VOIDPTR, dwSize: t.CSizeT) -> BOOL | t.State: pass + +def GetProcessHeap() -> HANDLE | t.State: pass + +def HeapCreate(flOptions: ULONG, dwInitialSize: t.CSizeT, dwMaximumSize: t.CSizeT) -> HANDLE | t.State: pass + +def HeapDestroy(hHeap: HANDLE) -> BOOL | t.State: pass + +def HeapAlloc(hHeap: HANDLE, dwFlags: ULONG, dwBytes: t.CSizeT) -> VOIDPTR | t.State: pass + +def HeapReAlloc(hHeap: HANDLE, dwFlags: ULONG, lpMem: VOIDPTR, dwBytes: t.CSizeT) -> VOIDPTR | t.State: pass + +def HeapFree(hHeap: HANDLE, dwFlags: ULONG, lpMem: VOIDPTR) -> BOOL | t.State: pass + +def HeapSize(hHeap: HANDLE, dwFlags: ULONG, lpMem: t.CConst | VOIDPTR) -> t.CSizeT | t.State: pass + +def HeapValidate(hHeap: HANDLE, dwFlags: ULONG, lpMem: t.CConst | VOIDPTR) -> BOOL | t.State: pass + +def HeapCompact(hHeap: HANDLE, dwFlags: ULONG) -> t.CSizeT | t.State: pass + +def GlobalAlloc(uFlags: UINT, dwBytes: t.CSizeT) -> VOIDPTR | t.State: pass + +def GlobalFree(hMem: VOIDPTR) -> VOIDPTR | t.State: pass + +def GlobalLock(hMem: VOIDPTR) -> VOIDPTR | t.State: pass + +def GlobalUnlock(hMem: VOIDPTR) -> BOOL | t.State: pass + +def GlobalSize(hMem: VOIDPTR) -> t.CSizeT | t.State: pass + +def LocalAlloc(uFlags: UINT, dwBytes: t.CSizeT) -> VOIDPTR | t.State: pass + +def LocalFree(hMem: VOIDPTR) -> VOIDPTR | t.State: pass diff --git a/Test/EqTest/temp/73edbcf76e32d00b.pyi b/Test/EqTest/temp/73edbcf76e32d00b.pyi new file mode 100644 index 0000000..ef712e3 --- /dev/null +++ b/Test/EqTest/temp/73edbcf76e32d00b.pyi @@ -0,0 +1,28 @@ +""" +Auto-generated Python stub file from stdio.py +Module: stdio +""" + + +import t, c + +def printf(fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass + +def fprintf(stream: t.CVoid | t.CPtr, fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass + +def sprintf(buf: t.CChar | t.CPtr, fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass + +def snprintf(buf: t.CChar | t.CPtr, size: t.CSizeT, fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass + +def puts(s: t.CChar | t.CConst | t.CPtr) -> t.CInt | t.CExtern | t.CExport: pass + +def fputs(s: t.CChar | t.CConst | t.CPtr, stream: t.CVoid | t.CPtr) -> t.CInt | t.CExtern | t.CExport: pass + +def fgets(buf: t.CChar | t.CPtr, size: t.CInt, stream: t.CVoid | t.CPtr) -> t.CChar | t.CPtr | t.CExtern | t.CExport: pass + +def fflush(stream: t.CVoid | t.CPtr) -> t.CInt | t.CExtern | t.CExport: pass + + +stdin: t.CExtern | t.CVoid | t.CPtr +stdout: t.CExtern | t.CVoid | t.CPtr +stderr: t.CExtern | t.CVoid | t.CPtr \ No newline at end of file diff --git a/Test/EqTest/temp/78943d0dbc89a29a.pyi b/Test/EqTest/temp/78943d0dbc89a29a.pyi new file mode 100644 index 0000000..ce1d065 --- /dev/null +++ b/Test/EqTest/temp/78943d0dbc89a29a.pyi @@ -0,0 +1,16 @@ +""" +Auto-generated Python stub file from main.py +Module: main +""" + + +from stdint import * +import w32.win32console +import t, c +from t import CInt, CExport +import stdio +import stdlib +import string +import testcheck + +def main() -> CInt | CExport: pass diff --git a/Test/EqTest/temp/9dbecd0942a39782.pyi b/Test/EqTest/temp/9dbecd0942a39782.pyi new file mode 100644 index 0000000..41648c1 --- /dev/null +++ b/Test/EqTest/temp/9dbecd0942a39782.pyi @@ -0,0 +1,25 @@ +""" +Auto-generated Python stub file from testcheck.py +Module: testcheck +""" + + +import t, c +import stdio + +_pass_count: t.CExtern | t.CInt +_fail_count: t.CExtern | t.CInt + +def begin(name: str) -> t.CInt: pass + +def section(name: str) -> t.CInt: pass + +def ok(msg: str) -> t.CInt: pass + +def fail(msg: str) -> t.CInt: pass + +def check(cond: t.CInt, ok_msg: str, fail_msg: str) -> t.CInt: pass + +def info(msg: str) -> t.CInt: pass + +def end() -> t.CInt: pass diff --git a/Test/EqTest/temp/_sha1_map.txt b/Test/EqTest/temp/_sha1_map.txt new file mode 100644 index 0000000..593f764 --- /dev/null +++ b/Test/EqTest/temp/_sha1_map.txt @@ -0,0 +1,8 @@ +49bd8cba55979f76:includes/stdint.py +5a6a2137958c28c5:includes/w32\win32base.py +6c2029b306556c00:includes/stdlib.py +73edbcf76e32d00b:includes/stdio.py +78943d0dbc89a29a:main.py +9dbecd0942a39782:includes/testcheck.py +b5f1dc665c52a1bd:includes/string.py +bbdf3bbd4c3bc28c:includes/w32\win32console.py diff --git a/Test/EqTest/temp/abf9ce3160c9279e.pyi b/Test/EqTest/temp/abf9ce3160c9279e.pyi new file mode 100644 index 0000000..4249b58 --- /dev/null +++ b/Test/EqTest/temp/abf9ce3160c9279e.pyi @@ -0,0 +1,179 @@ +""" +Auto-generated Python stub file from w32.win32file.py +Module: w32.win32file +""" + +import c + + +import t +from stdint import * +from w32.win32base import * + +GENERIC_READ: t.CDefine = 0x80000000 +GENERIC_WRITE: t.CDefine = 0x40000000 +GENERIC_EXECUTE: t.CDefine = 0x20000000 +GENERIC_ALL: t.CDefine = 0x10000000 +FILE_SHARE_READ: t.CDefine = 0x00000001 +FILE_SHARE_WRITE: t.CDefine = 0x00000002 +FILE_SHARE_DELETE: t.CDefine = 0x00000004 +CREATE_NEW: t.CDefine = 1 +CREATE_ALWAYS: t.CDefine = 2 +OPEN_EXISTING: t.CDefine = 3 +OPEN_ALWAYS: t.CDefine = 4 +TRUNCATE_EXISTING: t.CDefine = 5 +FILE_ATTRIBUTE_READONLY: t.CDefine = 0x00000001 +FILE_ATTRIBUTE_HIDDEN: t.CDefine = 0x00000002 +FILE_ATTRIBUTE_SYSTEM: t.CDefine = 0x00000004 +FILE_ATTRIBUTE_DIRECTORY: t.CDefine = 0x00000010 +FILE_ATTRIBUTE_ARCHIVE: t.CDefine = 0x00000020 +FILE_ATTRIBUTE_NORMAL: t.CDefine = 0x00000080 +FILE_ATTRIBUTE_TEMPORARY: t.CDefine = 0x00000100 +FILE_ATTRIBUTE_COMPRESSED: t.CDefine = 0x00000800 +FILE_ATTRIBUTE_OFFLINE: t.CDefine = 0x00001000 +FILE_ATTRIBUTE_ENCRYPTED: t.CDefine = 0x00004000 +FILE_FLAG_WRITE_THROUGH: t.CDefine = 0x80000000 +FILE_FLAG_OVERLAPPED: t.CDefine = 0x40000000 +FILE_FLAG_NO_BUFFERING: t.CDefine = 0x20000000 +FILE_FLAG_RANDOM_ACCESS: t.CDefine = 0x10000000 +FILE_FLAG_SEQUENTIAL_SCAN: t.CDefine = 0x08000000 +FILE_FLAG_DELETE_ON_CLOSE: t.CDefine = 0x04000000 +FILE_FLAG_BACKUP_SEMANTICS: t.CDefine = 0x02000000 +FILE_FLAG_POSIX_SEMANTICS: t.CDefine = 0x01000000 +FILE_BEGIN: t.CDefine = 0 +FILE_CURRENT: t.CDefine = 1 +FILE_END: t.CDefine = 2 +STD_INPUT_HANDLE: t.CDefine = t.CUnsignedLong(-10) +STD_OUTPUT_HANDLE: t.CDefine = t.CUnsignedLong(-11) +STD_ERROR_HANDLE: t.CDefine = t.CUnsignedLong(-12) +MOVEFILE_REPLACE_EXISTING: t.CDefine = 0x00000001 +MOVEFILE_COPY_ALLOWED: t.CDefine = 0x00000002 +MOVEFILE_WRITE_THROUGH: t.CDefine = 0x00000008 + +class BY_HANDLE_FILE_INFORMATION: + dwFileAttributes: ULONG + ftCreationTime: FILETIME + ftLastAccessTime: FILETIME + ftLastWriteTime: FILETIME + dwVolumeSerialNumber: ULONG + nFileSizeHigh: ULONG + nFileSizeLow: ULONG + nNumberOfLinks: ULONG + nFileIndexHigh: ULONG + nFileIndexLow: ULONG +class WIN32_FIND_DATAA: + dwFileAttributes: ULONG + ftCreationTime: FILETIME + ftLastAccessTime: FILETIME + ftLastWriteTime: FILETIME + nFileSizeHigh: ULONG + nFileSizeLow: ULONG + dwReserved0: ULONG + dwReserved1: ULONG + cFileName: CHARPTR + cAlternateFileName: CHARPTR +class WIN32_FIND_DATAW: + dwFileAttributes: ULONG + ftCreationTime: FILETIME + ftLastAccessTime: FILETIME + ftLastWriteTime: FILETIME + nFileSizeHigh: ULONG + nFileSizeLow: ULONG + dwReserved0: ULONG + dwReserved1: ULONG + cFileName: WCHARPTR + cAlternateFileName: WCHARPTR + +def CreateFileA(lpFileName: LPCSTR, dwDesiredAccess: ULONG, dwShareMode: ULONG, lpSecurityAttributes: SECURITY_ATTRIBUTES | t.CPtr, dwCreationDisposition: ULONG, dwFlagsAndAttributes: ULONG, hTemplateFile: HANDLE) -> HANDLE | t.State: pass + +def CreateFileW(lpFileName: LPCWSTR, dwDesiredAccess: ULONG, dwShareMode: ULONG, lpSecurityAttributes: SECURITY_ATTRIBUTES | t.CPtr, dwCreationDisposition: ULONG, dwFlagsAndAttributes: ULONG, hTemplateFile: HANDLE) -> HANDLE | t.State: pass + +def ReadFile(hFile: HANDLE, lpBuffer: VOIDPTR, nNumberOfBytesToRead: ULONG, lpNumberOfBytesRead: ULONG | t.CPtr, lpOverlapped: OVERLAPPED | t.CPtr) -> BOOL | t.State: pass + +def WriteFile(hFile: HANDLE, lpBuffer: t.CConst | VOIDPTR, nNumberOfBytesToWrite: ULONG, lpNumberOfBytesWritten: ULONG | t.CPtr, lpOverlapped: OVERLAPPED | t.CPtr) -> BOOL | t.State: pass + +def SetFilePointer(hFile: HANDLE, lDistanceToMove: LONG, lpDistanceToMoveHigh: LONG | t.CPtr, dwMoveMethod: ULONG) -> LONG | t.State: pass + +def SetFilePointerEx(hFile: HANDLE, liDistanceToMove: LARGE_INTEGER | t.CPtr, lpNewFilePointer: LARGE_INTEGER | t.CPtr, dwMoveMethod: ULONG) -> BOOL | t.State: pass + +def GetFileSize(hFile: HANDLE, lpFileSizeHigh: ULONG | t.CPtr) -> ULONG | t.State: pass + +def GetFileSizeEx(hFile: HANDLE, lpFileSize: LARGE_INTEGER | t.CPtr) -> BOOL | t.State: pass + +def SetEndOfFile(hFile: HANDLE) -> BOOL | t.State: pass + +def FlushFileBuffers(hFile: HANDLE) -> BOOL | t.State: pass + +def GetFileType(hFile: HANDLE) -> ULONG | t.State: pass + +def GetFileAttributesA(lpFileName: LPCSTR) -> ULONG | t.State: pass + +def GetFileAttributesW(lpFileName: LPCWSTR) -> ULONG | t.State: pass + +def SetFileAttributesA(lpFileName: LPCSTR, dwFileAttributes: ULONG) -> BOOL | t.State: pass + +def SetFileAttributesW(lpFileName: LPCWSTR, dwFileAttributes: ULONG) -> BOOL | t.State: pass + +def DeleteFileA(lpFileName: LPCSTR) -> BOOL | t.State: pass + +def DeleteFileW(lpFileName: LPCWSTR) -> BOOL | t.State: pass + +def MoveFileA(lpExistingFileName: LPCSTR, lpNewFileName: LPCSTR) -> BOOL | t.State: pass + +def MoveFileW(lpExistingFileName: LPCWSTR, lpNewFileName: LPCWSTR) -> BOOL | t.State: pass + +def MoveFileExA(lpExistingFileName: LPCSTR, lpNewFileName: LPCSTR, dwFlags: ULONG) -> BOOL | t.State: pass + +def MoveFileExW(lpExistingFileName: LPCWSTR, lpNewFileName: LPCWSTR, dwFlags: ULONG) -> BOOL | t.State: pass + +def CopyFileA(lpExistingFileName: LPCSTR, lpNewFileName: LPCSTR, bFailIfExists: BOOL) -> BOOL | t.State: pass + +def CopyFileW(lpExistingFileName: LPCWSTR, lpNewFileName: LPCWSTR, bFailIfExists: BOOL) -> BOOL | t.State: pass + +def CreateDirectoryA(lpPathName: LPCSTR, lpSecurityAttributes: SECURITY_ATTRIBUTES | t.CPtr) -> BOOL | t.State: pass + +def CreateDirectoryW(lpPathName: LPCWSTR, lpSecurityAttributes: SECURITY_ATTRIBUTES | t.CPtr) -> BOOL | t.State: pass + +def RemoveDirectoryA(lpPathName: LPCSTR) -> BOOL | t.State: pass + +def RemoveDirectoryW(lpPathName: LPCWSTR) -> BOOL | t.State: pass + +def FindFirstFileA(lpFileName: LPCSTR, lpFindFileData: WIN32_FIND_DATAA | t.CPtr) -> HANDLE | t.State: pass + +def FindFirstFileW(lpFileName: LPCWSTR, lpFindFileData: WIN32_FIND_DATAW | t.CPtr) -> HANDLE | t.State: pass + +def FindNextFileA(hFindFile: HANDLE, lpFindFileData: WIN32_FIND_DATAA | t.CPtr) -> BOOL | t.State: pass + +def FindNextFileW(hFindFile: HANDLE, lpFindFileData: WIN32_FIND_DATAW | t.CPtr) -> BOOL | t.State: pass + +def FindClose(hFindFile: HANDLE) -> BOOL | t.State: pass + +def GetStdHandle(nStdHandle: ULONG) -> HANDLE | t.State: pass + +def SetStdHandle(nStdHandle: ULONG, hHandle: HANDLE) -> BOOL | t.State: pass + +def GetFileInformationByHandle(hFile: HANDLE, lpFileInformation: BY_HANDLE_FILE_INFORMATION | t.CPtr) -> BOOL | t.State: pass + +def LockFile(hFile: HANDLE, dwFileOffsetLow: ULONG, dwFileOffsetHigh: ULONG, nNumberOfBytesToLockLow: ULONG, nNumberOfBytesToLockHigh: ULONG) -> BOOL | t.State: pass + +def UnlockFile(hFile: HANDLE, dwFileOffsetLow: ULONG, dwFileOffsetHigh: ULONG, nNumberOfBytesToUnlockLow: ULONG, nNumberOfBytesToUnlockHigh: ULONG) -> BOOL | t.State: pass + +def GetTempPathA(nBufferLength: ULONG, lpBuffer: CHARPTR) -> ULONG | t.State: pass + +def GetTempPathW(nBufferLength: ULONG, lpBuffer: WCHARPTR) -> ULONG | t.State: pass + +def GetTempFileNameA(lpPathName: LPCSTR, lpPrefixString: LPCSTR, uUnique: UINT, lpTempFileName: CHARPTR) -> UINT | t.State: pass + +def GetTempFileNameW(lpPathName: LPCWSTR, lpPrefixString: LPCWSTR, uUnique: UINT, lpTempFileName: WCHARPTR) -> UINT | t.State: pass + +def GetCurrentDirectoryA(nBufferLength: ULONG, lpBuffer: CHARPTR) -> ULONG | t.State: pass + +def GetCurrentDirectoryW(nBufferLength: ULONG, lpBuffer: WCHARPTR) -> ULONG | t.State: pass + +def SetCurrentDirectoryA(lpPathName: LPCSTR) -> BOOL | t.State: pass + +def SetCurrentDirectoryW(lpPathName: LPCWSTR) -> BOOL | t.State: pass + +def GetModuleFileNameA(hModule: HANDLE, lpFilename: CHARPTR, nSize: ULONG) -> ULONG | t.State: pass + +def GetModuleFileNameW(hModule: HANDLE, lpFilename: WCHARPTR, nSize: ULONG) -> ULONG | t.State: pass diff --git a/Test/SimdTest/temp/6aee24fdefa3cbc0.pyi b/Test/EqTest/temp/b5f1dc665c52a1bd.pyi similarity index 94% rename from Test/SimdTest/temp/6aee24fdefa3cbc0.pyi rename to Test/EqTest/temp/b5f1dc665c52a1bd.pyi index c17475f..8b6959e 100644 --- a/Test/SimdTest/temp/6aee24fdefa3cbc0.pyi +++ b/Test/EqTest/temp/b5f1dc665c52a1bd.pyi @@ -41,4 +41,4 @@ def atoll(src: str) -> t.CInt64T: pass def atof(src: str) -> t.CDouble: pass -def split(s: str, delim: str, result: list[str]) -> int: pass +def split(s: str, delim: str, result: t.CArray[str]) -> int: pass diff --git a/Test/EqTest/temp/bbdf3bbd4c3bc28c.pyi b/Test/EqTest/temp/bbdf3bbd4c3bc28c.pyi new file mode 100644 index 0000000..70dcdbc --- /dev/null +++ b/Test/EqTest/temp/bbdf3bbd4c3bc28c.pyi @@ -0,0 +1,138 @@ +""" +Auto-generated Python stub file from w32.win32console.py +Module: w32.win32console +""" + +import c + + +import t +from stdint import * +from w32.win32base import * + +ENABLE_PROCESSED_INPUT: t.CDefine = 0x0001 +ENABLE_LINE_INPUT: t.CDefine = 0x0002 +ENABLE_ECHO_INPUT: t.CDefine = 0x0004 +ENABLE_WINDOW_INPUT: t.CDefine = 0x0008 +ENABLE_MOUSE_INPUT: t.CDefine = 0x0010 +ENABLE_INSERT_MODE: t.CDefine = 0x0020 +ENABLE_QUICK_EDIT_MODE: t.CDefine = 0x0040 +ENABLE_EXTENDED_FLAGS: t.CDefine = 0x0080 +ENABLE_PROCESSED_OUTPUT: t.CDefine = 0x0001 +ENABLE_WRAP_AT_EOL_OUTPUT: t.CDefine = 0x0002 +ENABLE_VIRTUAL_TERMINAL_PROCESSING: t.CDefine = 0x0004 +DISABLE_NEWLINE_AUTO_RETURN: t.CDefine = 0x0008 +ENABLE_LVB_GRID_WORLDWIDE: t.CDefine = 0x0010 +FOREGROUND_BLUE: t.CDefine = 0x0001 +FOREGROUND_GREEN: t.CDefine = 0x0002 +FOREGROUND_RED: t.CDefine = 0x0004 +FOREGROUND_INTENSITY: t.CDefine = 0x0008 +BACKGROUND_BLUE: t.CDefine = 0x0010 +BACKGROUND_GREEN: t.CDefine = 0x0020 +BACKGROUND_RED: t.CDefine = 0x0040 +BACKGROUND_INTENSITY: t.CDefine = 0x0080 +KEY_EVENT: t.CDefine = 0x0001 +MOUSE_EVENT: t.CDefine = 0x0002 +WINDOW_BUFFER_SIZE_EVENT: t.CDefine = 0x0004 +MENU_EVENT: t.CDefine = 0x0008 +FOCUS_EVENT: t.CDefine = 0x0010 + +class COORD: + X: SHORT + Y: SHORT +class SMALL_RECT: + Left: SHORT + Top: SHORT + Right: SHORT + Bottom: SHORT +class CONSOLE_SCREEN_BUFFER_INFO: + dwSize: COORD + dwCursorPosition: COORD + wAttributes: WORD + srWindow: SMALL_RECT + dwMaximumWindowSize: COORD +class CONSOLE_CURSOR_INFO: + dwSize: ULONG + bVisible: BOOL +class CHAR_INFO: + UnicodeChar: WCHAR + Attributes: WORD +class KEY_EVENT_RECORD: + bKeyDown: BOOL + wRepeatCount: WORD + wVirtualKeyCode: WORD + wVirtualScanCode: WORD + uChar: WCHAR + dwControlKeyState: ULONG +class MOUSE_EVENT_RECORD: + dwMousePosition: COORD + dwButtonState: ULONG + dwControlKeyState: ULONG + dwEventFlags: ULONG +class WINDOW_BUFFER_SIZE_RECORD: + dwSize: COORD +class INPUT_RECORD: + EventType: WORD + Event: KEY_EVENT_RECORD + +def SetConsoleOutputCP(codepage: UINT) -> BOOL | t.State: pass + +def SetConsoleCP(codepage: UINT) -> BOOL | t.State: pass + +def GetConsoleCP() -> UINT | t.State: pass + +def GetConsoleOutputCP() -> UINT | t.State: pass + +def GetConsoleScreenBufferInfo(hConsoleOutput: HANDLE, lpConsoleScreenBufferInfo: CONSOLE_SCREEN_BUFFER_INFO | t.CPtr) -> BOOL | t.State: pass + +def SetConsoleScreenBufferSize(hConsoleOutput: HANDLE, dwSize: COORD) -> BOOL | t.State: pass + +def SetConsoleCursorPosition(hConsoleOutput: HANDLE, dwCursorPosition: COORD) -> BOOL | t.State: pass + +def GetConsoleCursorInfo(hConsoleOutput: HANDLE, lpConsoleCursorInfo: CONSOLE_CURSOR_INFO | t.CPtr) -> BOOL | t.State: pass + +def SetConsoleCursorInfo(hConsoleOutput: HANDLE, lpConsoleCursorInfo: CONSOLE_CURSOR_INFO | t.CPtr) -> BOOL | t.State: pass + +def SetConsoleTextAttribute(hConsoleOutput: HANDLE, wAttributes: WORD) -> BOOL | t.State: pass + +def FillConsoleOutputCharacterA(hConsoleOutput: HANDLE, cCharacter: t.CChar, nLength: ULONG, dwWriteCoord: COORD, lpNumberOfCharsWritten: ULONG | t.CPtr) -> BOOL | t.State: pass + +def FillConsoleOutputCharacterW(hConsoleOutput: HANDLE, cCharacter: WCHAR, nLength: ULONG, dwWriteCoord: COORD, lpNumberOfCharsWritten: ULONG | t.CPtr) -> BOOL | t.State: pass + +def FillConsoleOutputAttribute(hConsoleOutput: HANDLE, wAttribute: WORD, nLength: ULONG, dwWriteCoord: COORD, lpNumberOfAttrsWritten: ULONG | t.CPtr) -> BOOL | t.State: pass + +def WriteConsoleA(hConsoleOutput: HANDLE, lpBuffer: t.CConst | VOIDPTR, nNumberOfCharsToWrite: ULONG, lpNumberOfCharsWritten: ULONG | t.CPtr, lpReserved: VOIDPTR) -> BOOL | t.State: pass + +def WriteConsoleW(hConsoleOutput: HANDLE, lpBuffer: t.CConst | VOIDPTR, nNumberOfCharsToWrite: ULONG, lpNumberOfCharsWritten: ULONG | t.CPtr, lpReserved: VOIDPTR) -> BOOL | t.State: pass + +def ReadConsoleA(hConsoleInput: HANDLE, lpBuffer: VOIDPTR, nNumberOfCharsToRead: ULONG, lpNumberOfCharsRead: ULONG | t.CPtr, pInputControl: VOIDPTR) -> BOOL | t.State: pass + +def ReadConsoleW(hConsoleInput: HANDLE, lpBuffer: VOIDPTR, nNumberOfCharsToRead: ULONG, lpNumberOfCharsRead: ULONG | t.CPtr, pInputControl: VOIDPTR) -> BOOL | t.State: pass + +def GetConsoleMode(hConsoleHandle: HANDLE, lpMode: ULONG | t.CPtr) -> BOOL | t.State: pass + +def SetConsoleMode(hConsoleHandle: HANDLE, dwMode: ULONG) -> BOOL | t.State: pass + +def ReadConsoleInputA(hConsoleInput: HANDLE, lpBuffer: INPUT_RECORD | t.CPtr, nLength: ULONG, lpNumberOfEventsRead: ULONG | t.CPtr) -> BOOL | t.State: pass + +def ReadConsoleInputW(hConsoleInput: HANDLE, lpBuffer: INPUT_RECORD | t.CPtr, nLength: ULONG, lpNumberOfEventsRead: ULONG | t.CPtr) -> BOOL | t.State: pass + +def GetNumberOfConsoleInputEvents(hConsoleInput: HANDLE, lpNumberOfEvents: ULONG | t.CPtr) -> BOOL | t.State: pass + +def FlushConsoleInputBuffer(hConsoleInput: HANDLE) -> BOOL | t.State: pass + +def SetConsoleTitleA(lpConsoleTitle: LPCSTR) -> BOOL | t.State: pass + +def SetConsoleTitleW(lpConsoleTitle: LPCWSTR) -> BOOL | t.State: pass + +def GetConsoleTitleA(lpConsoleTitle: CHARPTR, nSize: ULONG) -> ULONG | t.State: pass + +def GetConsoleTitleW(lpConsoleTitle: WCHARPTR, nSize: ULONG) -> ULONG | t.State: pass + +def AllocConsole() -> BOOL | t.State: pass + +def FreeConsole() -> BOOL | t.State: pass + +def SetConsoleWindowInfo(hConsoleOutput: HANDLE, bAbsolute: BOOL, lpConsoleWindow: SMALL_RECT | t.CPtr) -> BOOL | t.State: pass + +def ScrollConsoleScreenBufferA(hConsoleOutput: HANDLE, lpScrollRectangle: SMALL_RECT | t.CPtr, lpClipRectangle: SMALL_RECT | t.CPtr, dwDestinationOrigin: COORD, lpFill: CHAR_INFO | t.CPtr) -> BOOL | t.State: pass diff --git a/Test/EqTest/temp/fa3691e66b426950.pyi b/Test/EqTest/temp/fa3691e66b426950.pyi new file mode 100644 index 0000000..48fd36c --- /dev/null +++ b/Test/EqTest/temp/fa3691e66b426950.pyi @@ -0,0 +1,80 @@ +""" +Auto-generated Python stub file from w32.fileio.py +Module: w32.fileio +""" + + +import t, c +from stdint import * +import w32.win32base +import w32.win32file + +class MODE(t.CEnum): + R = 0 + W = 1 + A = 2 + RP = 3 + WP = 4 + AP = 5 + X = 6 + XP = 7 +class FRESULT(t.CEnum): + OK = 0 + ERR = -1 + ERR_CLOSED = -2 + ERR_PERM = -3 + ERR_IO = -4 + ERR_NOTFOUND = -5 + +SEEK_SET: t.CDefine = 0 +SEEK_CUR: t.CDefine = 1 +SEEK_END: t.CDefine = 2 +INVALID_SET_FILE_POINTER: t.CDefine = -1 +SHARE_READ: t.CDefine = 0x00000001 +SHARE_WRITE: t.CDefine = 0x00000002 +SHARE_DELETE: t.CDefine = 0x00000004 + +class File: + handle: w32.win32base.HANDLE + closed: bool + can_read: bool + can_write: bool + is_append: bool + _share_mode: ULONG + def __init__(self: File, filename: str, mode: ULONG, share: ULONG) -> t.CInt: pass + def __enter__(self: File) -> 'File' | t.CPtr: pass + def __exit__(self: File) -> t.CInt: pass + def read(self: File, buf: bytes, count: ULONG) -> LONG: pass + def write(self: File, buf: bytes, count: ULONG) -> LONG: pass + def write_str(self: File, s: str) -> LONG: pass + def seek(self: File, offset: LONG, origin: ULONG) -> LONG: pass + def tell(self: File) -> LONG: pass + def close(self: File) -> LONG: pass + def flush(self: File) -> LONG: pass + def size(self: File) -> LONGLONG: pass + def readline(self: File, buf: bytes, max_count: ULONG) -> LONG: pass + def read_all(self: File, buf: bytes, max_count: ULONG) -> LONG: pass +class FileW: + handle: HANDLE + closed: bool + can_read: bool + can_write: bool + is_append: bool + _share_mode: ULONG + def __init__(self: FileW, filename: LPCWSTR, mode: ULONG, share: ULONG) -> t.CInt: pass + def __enter__(self: FileW) -> 'FileW' | t.CPtr: pass + def __exit__(self: FileW) -> t.CInt: pass + def read(self: FileW, buf: bytes, count: ULONG) -> LONG: pass + def write(self: FileW, buf: bytes, count: ULONG) -> LONG: pass + def write_str(self: FileW, s: str) -> LONG: pass + def seek(self: FileW, offset: LONG, origin: ULONG) -> LONG: pass + def tell(self: FileW) -> LONG: pass + def close(self: FileW) -> LONG: pass + def flush(self: FileW) -> LONG: pass + def size(self: FileW) -> LONGLONG: pass + def readline(self: FileW, buf: bytes, max_count: ULONG) -> LONG: pass + def read_all(self: FileW, buf: bytes, max_count: ULONG) -> LONG: pass + +def open(filename: str, mode: ULONG, share: ULONG) -> File | t.CPtr: pass + +def openw(filename: LPCWSTR, mode: ULONG, share: ULONG) -> FileW | t.CPtr: pass diff --git a/Test/FakeDuckTest/App/main.py b/Test/FakeDuckTest/App/main.py new file mode 100644 index 0000000..d87e4cc --- /dev/null +++ b/Test/FakeDuckTest/App/main.py @@ -0,0 +1,313 @@ +from stdint import * +import w32.win32console +import t, c +from t import CInt, CExport +import _fakeduck +import stdio +import stdlib +import string +import mbuddy +import testcheck +import _withcontent + + +def main() -> CInt | CExport: + w32.win32console.SetConsoleCP(65001) + w32.win32console.SetConsoleOutputCP(65001) + + # FakeDuck 测试: str 类型调用扩展方法 b() + a: str = "Hello" + result: CInt = a.b() + + if result == 42: + stdio.printf("FakeDuck OK: a.b() = %d\n", result) + else: + stdio.printf("FakeDuck FAIL: a.b() = %d\n", result) + + # Type 通用基类测试: str 变量调用 Type 的方法 type_id() + tid: CInt = a.type_id() + + if tid == 99: + stdio.printf("Type OK: a.type_id() = %d\n", tid) + else: + stdio.printf("Type FAIL: a.type_id() = %d\n", tid) + + # SELF 测试: 返回 self.__data__,应指向原始字符串数据 + p: str = a.SELF() + stdio.printf("SELF test: %s\n", p) + + # 直接字段访问测试: 读取 a.__data__ (应等于 a 本身) + data_ptr: str = a.__data__ + stdio.printf("a.__data__ = %s\n", data_ptr) + + # upper() 测试: 通过 mbuddy 分配内存,返回大写字符串 + arena: bytes = stdlib.malloc(65536) + bd: mbuddy.MBuddy | t.CPtr = mbuddy.MBuddy(arena, 65536) + + # 直接字段赋值: a.__mbuddy__ = bd (语法糖, 等价于 a.set_mbuddy(bd)) + a.__mbuddy__ = bd + upper_str: str = a.upper() + stdio.printf("upper('Hello') = %s\n", upper_str) + + # 验证 per-instance 不污染: b 没有设置 __mbuddy__ (初始为 NULL) + b: str = "World" + + # 直接字段读取: b.__mbuddy__ (应返回 NULL) + b_buddy: mbuddy.MBuddy | t.CPtr = b.__mbuddy__ + if t.CInt(b_buddy) == 0: + stdio.printf("mbuddy OK: b.__mbuddy__ is NULL (no pollution)\n") + else: + stdio.printf("mbuddy FAIL: b.__mbuddy__ polluted!\n") + + # b 也设置 mbuddy 并 upper + b.__mbuddy__ = bd + upper_b: str = b.upper() + stdio.printf("upper('World') = %s\n", upper_b) + + # lower() 测试 + lower_str: str = a.lower() + stdio.printf("lower('Hello') = %s\n", lower_str) + + # capitalize() 测试 + cap_str: str = a.capitalize() + stdio.printf("capitalize('Hello') = %s\n", cap_str) + + # swapcase() 测试 + swap_str: str = a.swapcase() + stdio.printf("swapcase('Hello') = %s\n", swap_str) + + # casefold() 测试 + cf_str: str = a.casefold() + stdio.printf("casefold('Hello') = %s\n", cf_str) + + # title() 测试 + t_str: str = "hello world" + t_str.__mbuddy__ = bd + title_result: str = t_str.title() + stdio.printf("title('hello world') = %s\n", title_result) + + # 布尔判断函数测试 (不需要 __mbuddy__) + u: str = "HELLO" + lo: str = "hello" + dig: str = "12345" + alnum_s: str = "Hello123" + space_s: str = " " + title_s: str = "Hello World" + punct_s: str = "Hello!" + + stdio.printf("isupper('HELLO') = %d\n", u.isupper()) + stdio.printf("isupper('Hello') = %d\n", a.isupper()) + stdio.printf("islower('hello') = %d\n", lo.islower()) + stdio.printf("islower('Hello') = %d\n", a.islower()) + stdio.printf("isalpha('Hello') = %d\n", a.isalpha()) + stdio.printf("isalpha('Hello123') = %d\n", alnum_s.isalpha()) + stdio.printf("isdigit('12345') = %d\n", dig.isdigit()) + stdio.printf("isdigit('Hello') = %d\n", a.isdigit()) + stdio.printf("isalnum('Hello123') = %d\n", alnum_s.isalnum()) + stdio.printf("isalnum('Hello!') = %d\n", punct_s.isalnum()) + stdio.printf("isspace(' ') = %d\n", space_s.isspace()) + stdio.printf("isspace('Hello') = %d\n", a.isspace()) + stdio.printf("isascii('Hello') = %d\n", a.isascii()) + stdio.printf("istitle('Hello World') = %d\n", title_s.istitle()) + stdio.printf("istitle('hello world') = %d\n", t_str.istitle()) + + # === split() 测试 === + testcheck.begin("FakeDuck split() 测试") + + # Test 1: 基本分割 + testcheck.section("Test 1: 基本分割 'a,b,c'") + s1: str = "a,b,c" + s1.__mbuddy__ = bd + parts = s1.split(',') + n1: t.CSizeT = parts.__len__() + stdio.printf("split('a,b,c', ',') len=%lu\n", n1) + testcheck.check(n1 == 3, "split len OK (3)", "split len FAILED expect 3") + p0: str = parts[0] + p1: str = parts[1] + p2: str = parts[2] + stdio.printf("parts[0]='%s' [1]='%s' [2]='%s'\n", p0, p1, p2) + testcheck.check(p0 == "a", "split[0]=='a' OK", "split[0] FAILED") + testcheck.check(p1 == "b", "split[1]=='b' OK", "split[1] FAILED") + testcheck.check(p2 == "c", "split[2]=='c' OK", "split[2] FAILED") + + # Test 2: 空字符串分割 + testcheck.section("Test 2: 无分隔符 'hello'") + s2: str = "hello" + s2.__mbuddy__ = bd + parts2 = s2.split(',') + n2: t.CSizeT = parts2.__len__() + stdio.printf("split('hello', ',') len=%lu\n", n2) + testcheck.check(n2 == 1, "no-delim len OK (1)", "no-delim len FAILED expect 1") + h0: str = parts2.get(0) + testcheck.check(h0 == "hello", "no-delim[0]=='hello' OK", "no-delim[0] FAILED") + + # Test 3: 连续分隔符 + testcheck.section("Test 3: 连续分隔符 'a,,b'") + s3: str = "a,,b" + s3.__mbuddy__ = bd + parts3 = s3.split(',') + n3: t.CSizeT = parts3.__len__() + stdio.printf("split('a,,b', ',') len=%lu\n", n3) + testcheck.check(n3 == 3, "consecutive len OK (3)", "consecutive len FAILED expect 3") + e0: str = parts3.get(0) + e1: str = parts3.get(1) + e2: str = parts3.get(2) + stdio.printf("parts[0]='%s' [1]='%s' [2]='%s'\n", e0, e1, e2) + testcheck.check(e0 == "a", "consec[0]=='a' OK", "consec[0] FAILED") + testcheck.check(e1 == "", "consec[1]=='' OK", "consec[1] FAILED") + testcheck.check(e2 == "b", "consec[2]=='b' OK", "consec[2] FAILED") + + # Test 4: 空字符串 + testcheck.section("Test 4: 空字符串 ''") + s4: str = "" + s4.__mbuddy__ = bd + parts4 = s4.split(',') + n4: t.CSizeT = parts4.__len__() + stdio.printf("split('', ',') len=%lu\n", n4) + testcheck.check(n4 == 1, "empty len OK (1)", "empty len FAILED expect 1") + + # Test 5: 空格分割句子 + testcheck.section("Test 5: 空格分割 'hello world foo'") + s5: str = "hello world foo" + s5.__mbuddy__ = bd + parts5 = s5.split(' ') + n5: t.CSizeT = parts5.__len__() + stdio.printf("split('hello world foo', ' ') len=%lu\n", n5) + testcheck.check(n5 == 3, "space len OK (3)", "space len FAILED expect 3") + w0: str = parts5[0] + w1: str = parts5[1] + w2: str = parts5[2] + stdio.printf("words[0]='%s' [1]='%s' [2]='%s'\n", w0, w1, w2) + testcheck.check(w0 == "hello", "space[0]=='hello' OK", "space[0] FAILED") + testcheck.check(w1 == "world", "space[1]=='world' OK", "space[1] FAILED") + testcheck.check(w2 == "foo", "space[2]=='foo' OK", "space[2] FAILED") + + # Test 6: 多字符分隔符 '::' + testcheck.section("Test 6: 多字符分隔符 '::' on 'a::b::c'") + s6: str = "a::b::c" + s6.__mbuddy__ = bd + parts6 = s6.split("::") + n6: t.CSizeT = parts6.__len__() + stdio.printf("split('a::b::c', '::') len=%lu\n", n6) + testcheck.check(n6 == 3, "multi-colon len OK (3)", "multi-colon len FAILED expect 3") + m0: str = parts6[0] + m1: str = parts6[1] + m2: str = parts6[2] + stdio.printf("parts[0]='%s' [1]='%s' [2]='%s'\n", m0, m1, m2) + testcheck.check(m0 == "a", "multi-colon[0]=='a' OK", "multi-colon[0] FAILED") + testcheck.check(m1 == "b", "multi-colon[1]=='b' OK", "multi-colon[1] FAILED") + testcheck.check(m2 == "c", "multi-colon[2]=='c' OK", "multi-colon[2] FAILED") + + # Test 7: 多字符分隔符 ', ' (逗号+空格) + testcheck.section("Test 7: 多字符分隔符 ', ' on 'hello, world, foo'") + s7: str = "hello, world, foo" + s7.__mbuddy__ = bd + parts7 = s7.split(", ") + n7: t.CSizeT = parts7.__len__() + stdio.printf("split('hello, world, foo', ', ') len=%lu\n", n7) + testcheck.check(n7 == 3, "comma-space len OK (3)", "comma-space len FAILED expect 3") + cs0: str = parts7[0] + cs1: str = parts7[1] + cs2: str = parts7[2] + stdio.printf("parts[0]='%s' [1]='%s' [2]='%s'\n", cs0, cs1, cs2) + testcheck.check(cs0 == "hello", "comma-space[0]=='hello' OK", "comma-space[0] FAILED") + testcheck.check(cs1 == "world", "comma-space[1]=='world' OK", "comma-space[1] FAILED") + testcheck.check(cs2 == "foo", "comma-space[2]=='foo' OK", "comma-space[2] FAILED") + + # Test 8: 多字符分隔符在首尾 + testcheck.section("Test 8: 多字符分隔符首尾 '::a::b::'") + s8: str = "::a::b::" + s8.__mbuddy__ = bd + parts8 = s8.split("::") + n8: t.CSizeT = parts8.__len__() + stdio.printf("split('::a::b::', '::') len=%lu\n", n8) + testcheck.check(n8 == 4, "edge len OK (4)", "edge len FAILED expect 4") + ed0: str = parts8[0] + ed1: str = parts8[1] + ed2: str = parts8[2] + ed3: str = parts8[3] + stdio.printf("parts[0]='%s' [1]='%s' [2]='%s' [3]='%s'\n", ed0, ed1, ed2, ed3) + testcheck.check(ed0 == "", "edge[0]=='' OK", "edge[0] FAILED") + testcheck.check(ed1 == "a", "edge[1]=='a' OK", "edge[1] FAILED") + testcheck.check(ed2 == "b", "edge[2]=='b' OK", "edge[2] FAILED") + testcheck.check(ed3 == "", "edge[3]=='' OK", "edge[3] FAILED") + + # === with 上下文自动注入测试 === + testcheck.section("Test 9: with 上下文自动注入 __mbuddy__") + + arena2: bytes = stdlib.malloc(65536) + with mbuddy.MBuddy(arena2, 65536) as bd2: + # str 变量在 with 上下文内创建,__mbuddy__ 应自动注入(无需手动赋值) + w_str: str = "WithTest" + + # 验证 __mbuddy__ 已自动注入(非 NULL) + w_buddy: mbuddy.MBuddy | t.CPtr = w_str.__mbuddy__ + testcheck.check(t.CInt(w_buddy) != 0, "with inject OK: __mbuddy__ auto-injected", "with inject FAIL: __mbuddy__ is NULL") + + # upper() 不需要手动设置 __mbuddy__ + w_upper: str = w_str.upper() + stdio.printf("with upper('WithTest') = %s\n", w_upper) + testcheck.check(w_upper == "WITHTEST", "with upper OK", "with upper FAILED") + + # lower() 不需要手动设置 __mbuddy__ + w_lower: str = w_str.lower() + stdio.printf("with lower('WithTest') = %s\n", w_lower) + testcheck.check(w_lower == "withtest", "with lower OK", "with lower FAILED") + + # split() 不需要手动设置 __mbuddy__ + w_split_str: str = "x,y,z" + w_parts = w_split_str.split(',') + w_n: t.CSizeT = len(w_parts) + stdio.printf("with split('x,y,z') len=%lu\n", w_n) + testcheck.check(w_n == 3, "with split len OK (3)", "with split len FAILED") + + # 验证多个 str 变量都获得注入 + w_str2: str = "Multiple" + w_buddy2: mbuddy.MBuddy | t.CPtr = w_str2.__mbuddy__ + testcheck.check(t.CInt(w_buddy2) != 0, "with multi inject OK", "with multi inject FAIL") + + test_s: str = "www.gvsds.com" + list_s: list[str] = test_s.split('.') + # 迭代器测试: for idx, i in zip(range(len(list_s)), list_s) + iter_count: int = 0 + for iter_idx, i in zip(range(len(list_s)), list_s): + stdio.printf("list_s[%d]='%s'\n", iter_idx, i) + iter_count += 1 + testcheck.check(iter_count == 3, "zip(range(len), list) iter OK (3)", "zip(range(len), list) iter FAILED") + #for i in range(3): + # stdio.printf("list_s[%d]='%s'\n", i, list_s[i]) + + # === zip() 内置测试 === + testcheck.section("Test 10: zip(list, list) 元组解包") + za: str = "a,b,c" + zb: str = "1,2,3" + list_a: list[str] = za.split(',') + list_b: list[str] = zb.split(',') + zip_idx: int = 0 + for ca, cb in zip(list_a, list_b): + stdio.printf("zip[%d]: '%s'='%s'\n", zip_idx, ca, cb) + zip_idx += 1 + testcheck.check(zip_idx == 3, "zip list+list OK (3)", "zip list+list FAILED") + + testcheck.section("Test 11: zip(range, list) 混合迭代") + zip_idx2: int = 0 + for n, s in zip(range(3), list_a): + stdio.printf("zip range+list[%d]: %d='%s'\n", zip_idx2, n, s) + zip_idx2 += 1 + testcheck.check(zip_idx2 == 3, "zip range+list OK (3)", "zip range+list FAILED") + + testcheck.section("Test 12: zip(str, str) 字符级并行") + sa: str = "abc" + sb: str = "123" + zip_idx3: int = 0 + for ch_a, ch_b in zip(sa, sb): + stdio.printf("zip str+str[%d]: '%c'%c\n", zip_idx3, ch_a, ch_b) + zip_idx3 += 1 + testcheck.check(zip_idx3 == 3, "zip str+str OK (3)", "zip str+str FAILED") + + stdio.printf("%d\n", " ".isspace()) + + stdlib.free(arena2) + + stdlib.free(arena) + return testcheck.end() diff --git a/Test/FakeDuckTest/output/067c78e9f121dce3.deps.json b/Test/FakeDuckTest/output/067c78e9f121dce3.deps.json new file mode 100644 index 0000000..7bbac7b --- /dev/null +++ b/Test/FakeDuckTest/output/067c78e9f121dce3.deps.json @@ -0,0 +1 @@ +{"w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "mbuddy": "0eaa586c42dcd931", "atom": "271ea3decb810db2", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "_list": "9d9d71cf83da7ca4", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "_withcontent": "b9b237d0e206d76c", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "_fakeduck": "c6206460c42ccf10", "main": "ccd58bf663340b12", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1"} \ No newline at end of file diff --git a/Test/FakeDuckTest/output/06f53cc594b4ac6c.deps.json b/Test/FakeDuckTest/output/06f53cc594b4ac6c.deps.json new file mode 100644 index 0000000..9c3f3ce --- /dev/null +++ b/Test/FakeDuckTest/output/06f53cc594b4ac6c.deps.json @@ -0,0 +1 @@ +{"w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "mbuddy": "0eaa586c42dcd931", "atom": "271ea3decb810db2", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "_list": "9d9d71cf83da7ca4", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "_withcontent": "b9b237d0e206d76c", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "_fakeduck": "c6206460c42ccf10", "main": "ccd58bf663340b12", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "w32.win32sync": "06f53cc594b4ac6c", "win32sync": "06f53cc594b4ac6c"} \ No newline at end of file diff --git a/Test/FakeDuckTest/output/0eaa586c42dcd931.deps.json b/Test/FakeDuckTest/output/0eaa586c42dcd931.deps.json new file mode 100644 index 0000000..7afe0c3 --- /dev/null +++ b/Test/FakeDuckTest/output/0eaa586c42dcd931.deps.json @@ -0,0 +1 @@ +{"w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "mbuddy": "0eaa586c42dcd931", "atom": "271ea3decb810db2", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "_list": "9d9d71cf83da7ca4", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "_withcontent": "b9b237d0e206d76c", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "_fakeduck": "c6206460c42ccf10", "main": "ccd58bf663340b12"} \ No newline at end of file diff --git a/Test/FakeDuckTest/output/271ea3decb810db2.deps.json b/Test/FakeDuckTest/output/271ea3decb810db2.deps.json new file mode 100644 index 0000000..7afe0c3 --- /dev/null +++ b/Test/FakeDuckTest/output/271ea3decb810db2.deps.json @@ -0,0 +1 @@ +{"w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "mbuddy": "0eaa586c42dcd931", "atom": "271ea3decb810db2", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "_list": "9d9d71cf83da7ca4", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "_withcontent": "b9b237d0e206d76c", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "_fakeduck": "c6206460c42ccf10", "main": "ccd58bf663340b12"} \ No newline at end of file diff --git a/Test/FakeDuckTest/output/5a6a2137958c28c5.deps.json b/Test/FakeDuckTest/output/5a6a2137958c28c5.deps.json new file mode 100644 index 0000000..7afe0c3 --- /dev/null +++ b/Test/FakeDuckTest/output/5a6a2137958c28c5.deps.json @@ -0,0 +1 @@ +{"w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "mbuddy": "0eaa586c42dcd931", "atom": "271ea3decb810db2", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "_list": "9d9d71cf83da7ca4", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "_withcontent": "b9b237d0e206d76c", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "_fakeduck": "c6206460c42ccf10", "main": "ccd58bf663340b12"} \ No newline at end of file diff --git a/Test/FakeDuckTest/output/72e2d5ccb7cedcf1.deps.json b/Test/FakeDuckTest/output/72e2d5ccb7cedcf1.deps.json new file mode 100644 index 0000000..7bbac7b --- /dev/null +++ b/Test/FakeDuckTest/output/72e2d5ccb7cedcf1.deps.json @@ -0,0 +1 @@ +{"w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "mbuddy": "0eaa586c42dcd931", "atom": "271ea3decb810db2", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "_list": "9d9d71cf83da7ca4", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "_withcontent": "b9b237d0e206d76c", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "_fakeduck": "c6206460c42ccf10", "main": "ccd58bf663340b12", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1"} \ No newline at end of file diff --git a/Test/FakeDuckTest/output/9d9d71cf83da7ca4.deps.json b/Test/FakeDuckTest/output/9d9d71cf83da7ca4.deps.json new file mode 100644 index 0000000..7afe0c3 --- /dev/null +++ b/Test/FakeDuckTest/output/9d9d71cf83da7ca4.deps.json @@ -0,0 +1 @@ +{"w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "mbuddy": "0eaa586c42dcd931", "atom": "271ea3decb810db2", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "_list": "9d9d71cf83da7ca4", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "_withcontent": "b9b237d0e206d76c", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "_fakeduck": "c6206460c42ccf10", "main": "ccd58bf663340b12"} \ No newline at end of file diff --git a/Test/FakeDuckTest/output/9dbecd0942a39782.deps.json b/Test/FakeDuckTest/output/9dbecd0942a39782.deps.json new file mode 100644 index 0000000..7afe0c3 --- /dev/null +++ b/Test/FakeDuckTest/output/9dbecd0942a39782.deps.json @@ -0,0 +1 @@ +{"w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "mbuddy": "0eaa586c42dcd931", "atom": "271ea3decb810db2", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "_list": "9d9d71cf83da7ca4", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "_withcontent": "b9b237d0e206d76c", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "_fakeduck": "c6206460c42ccf10", "main": "ccd58bf663340b12"} \ No newline at end of file diff --git a/Test/FakeDuckTest/output/abf9ce3160c9279e.deps.json b/Test/FakeDuckTest/output/abf9ce3160c9279e.deps.json new file mode 100644 index 0000000..ede4ec7 --- /dev/null +++ b/Test/FakeDuckTest/output/abf9ce3160c9279e.deps.json @@ -0,0 +1 @@ +{"w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "mbuddy": "0eaa586c42dcd931", "atom": "271ea3decb810db2", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "_list": "9d9d71cf83da7ca4", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "_withcontent": "b9b237d0e206d76c", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "_fakeduck": "c6206460c42ccf10", "main": "ccd58bf663340b12", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e"} \ No newline at end of file diff --git a/Test/FakeDuckTest/output/b5f1dc665c52a1bd.deps.json b/Test/FakeDuckTest/output/b5f1dc665c52a1bd.deps.json new file mode 100644 index 0000000..7afe0c3 --- /dev/null +++ b/Test/FakeDuckTest/output/b5f1dc665c52a1bd.deps.json @@ -0,0 +1 @@ +{"w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "mbuddy": "0eaa586c42dcd931", "atom": "271ea3decb810db2", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "_list": "9d9d71cf83da7ca4", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "_withcontent": "b9b237d0e206d76c", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "_fakeduck": "c6206460c42ccf10", "main": "ccd58bf663340b12"} \ No newline at end of file diff --git a/Test/FakeDuckTest/output/b9b237d0e206d76c.deps.json b/Test/FakeDuckTest/output/b9b237d0e206d76c.deps.json new file mode 100644 index 0000000..7bbac7b --- /dev/null +++ b/Test/FakeDuckTest/output/b9b237d0e206d76c.deps.json @@ -0,0 +1 @@ +{"w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "mbuddy": "0eaa586c42dcd931", "atom": "271ea3decb810db2", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "_list": "9d9d71cf83da7ca4", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "_withcontent": "b9b237d0e206d76c", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "_fakeduck": "c6206460c42ccf10", "main": "ccd58bf663340b12", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1"} \ No newline at end of file diff --git a/Test/FakeDuckTest/output/bbdf3bbd4c3bc28c.deps.json b/Test/FakeDuckTest/output/bbdf3bbd4c3bc28c.deps.json new file mode 100644 index 0000000..7afe0c3 --- /dev/null +++ b/Test/FakeDuckTest/output/bbdf3bbd4c3bc28c.deps.json @@ -0,0 +1 @@ +{"w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "mbuddy": "0eaa586c42dcd931", "atom": "271ea3decb810db2", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "_list": "9d9d71cf83da7ca4", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "_withcontent": "b9b237d0e206d76c", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "_fakeduck": "c6206460c42ccf10", "main": "ccd58bf663340b12"} \ No newline at end of file diff --git a/Test/FakeDuckTest/output/c6206460c42ccf10.deps.json b/Test/FakeDuckTest/output/c6206460c42ccf10.deps.json new file mode 100644 index 0000000..7afe0c3 --- /dev/null +++ b/Test/FakeDuckTest/output/c6206460c42ccf10.deps.json @@ -0,0 +1 @@ +{"w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "mbuddy": "0eaa586c42dcd931", "atom": "271ea3decb810db2", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "_list": "9d9d71cf83da7ca4", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "_withcontent": "b9b237d0e206d76c", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "_fakeduck": "c6206460c42ccf10", "main": "ccd58bf663340b12"} \ No newline at end of file diff --git a/Test/FakeDuckTest/output/ccd58bf663340b12.deps.json b/Test/FakeDuckTest/output/ccd58bf663340b12.deps.json new file mode 100644 index 0000000..31206ff --- /dev/null +++ b/Test/FakeDuckTest/output/ccd58bf663340b12.deps.json @@ -0,0 +1 @@ +{"w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "mbuddy": "0eaa586c42dcd931", "atom": "271ea3decb810db2", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "_list": "9d9d71cf83da7ca4", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "_withcontent": "b9b237d0e206d76c", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "_fakeduck": "c6206460c42ccf10"} \ No newline at end of file diff --git a/Test/FakeDuckTest/output/fa3691e66b426950.deps.json b/Test/FakeDuckTest/output/fa3691e66b426950.deps.json new file mode 100644 index 0000000..ef2f914 --- /dev/null +++ b/Test/FakeDuckTest/output/fa3691e66b426950.deps.json @@ -0,0 +1 @@ +{"w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "mbuddy": "0eaa586c42dcd931", "atom": "271ea3decb810db2", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "_list": "9d9d71cf83da7ca4", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "_withcontent": "b9b237d0e206d76c", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "_fakeduck": "c6206460c42ccf10", "main": "ccd58bf663340b12", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file diff --git a/Test/FakeDuckTest/project.json b/Test/FakeDuckTest/project.json new file mode 100644 index 0000000..1107714 --- /dev/null +++ b/Test/FakeDuckTest/project.json @@ -0,0 +1,29 @@ +{ + "$schema": "https://raw.githubusercontent.com/TermiNexus/TransPyC/main/schemas/project-schema.json", + "name": "FakeDuckTest", + "version": "1.0.0", + "source_dir": "./App", + "temp_dir": "./temp", + "output_dir": "./output", + "compiler": { + "cmd": "llc", + "flags": ["-filetype=obj", "-relocation-model=pic"] + }, + "linker": { + "cmd": "clang++", + "flags": ["-lmsvcrt", "-lucrt", "-lpthread", "-lmingwex", "-lkernel32", "-Wl,--allow-multiple-definition"], + "output": "FakeDuckTest.exe" + }, + "includes": [ + "./includes" + ], + "target": { + "triple": "x86_64-pc-windows-gnu", + "datalayout": "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" + }, + "options": { + "slice_level": 3, + "target": "llvm", + "strict_mode": true + } +} diff --git a/Test/FakeDuckTest/temp/067c78e9f121dce3.pyi b/Test/FakeDuckTest/temp/067c78e9f121dce3.pyi new file mode 100644 index 0000000..f4f767c --- /dev/null +++ b/Test/FakeDuckTest/temp/067c78e9f121dce3.pyi @@ -0,0 +1,136 @@ +""" +Auto-generated Python stub file from w32.win32process.py +Module: w32.win32process +""" + +import c + + +import t +from stdint import * +from w32.win32base import * + +PROCESS_TERMINATE: t.CDefine = 0x0001 +PROCESS_CREATE_THREAD: t.CDefine = 0x0002 +PROCESS_VM_OPERATION: t.CDefine = 0x0008 +PROCESS_VM_READ: t.CDefine = 0x0010 +PROCESS_VM_WRITE: t.CDefine = 0x0020 +PROCESS_QUERY_INFORMATION: t.CDefine = 0x0400 +PROCESS_ALL_ACCESS: t.CDefine = 0x001FFFFF +THREAD_TERMINATE: t.CDefine = 0x0001 +THREAD_SUSPEND_RESUME: t.CDefine = 0x0002 +THREAD_GET_CONTEXT: t.CDefine = 0x0008 +THREAD_SET_CONTEXT: t.CDefine = 0x0010 +THREAD_QUERY_INFORMATION: t.CDefine = 0x0040 +THREAD_ALL_ACCESS: t.CDefine = 0x001FFFFF +CREATE_SUSPENDED: t.CDefine = 0x00000004 +CREATE_NEW_CONSOLE: t.CDefine = 0x00000010 +CREATE_NEW_PROCESS_GROUP: t.CDefine = 0x00000200 +CREATE_NO_WINDOW: t.CDefine = 0x08000000 +DETACHED_PROCESS: t.CDefine = 0x00000008 +STARTF_USESHOWWINDOW: t.CDefine = 0x00000001 +STARTF_USESTDHANDLES: t.CDefine = 0x00000100 +SW_HIDE: t.CDefine = 0 +SW_SHOW: t.CDefine = 5 +SW_MINIMIZE: t.CDefine = 6 +NORMAL_PRIORITY_CLASS: t.CDefine = 0x00000020 +IDLE_PRIORITY_CLASS: t.CDefine = 0x00000040 +HIGH_PRIORITY_CLASS: t.CDefine = 0x00000080 +REALTIME_PRIORITY_CLASS: t.CDefine = 0x00000100 +BELOW_NORMAL_PRIORITY_CLASS: t.CDefine = 0x00004000 +ABOVE_NORMAL_PRIORITY_CLASS: t.CDefine = 0x00008000 +STILL_ACTIVE: t.CDefine = 259 + +class STARTUPINFOA: + cb: ULONG + lpReserved: CHARPTR + lpDesktop: CHARPTR + lpTitle: CHARPTR + dwX: ULONG + dwY: ULONG + dwXSize: ULONG + dwYSize: ULONG + dwXCountChars: ULONG + dwYCountChars: ULONG + dwFillAttribute: ULONG + dwFlags: ULONG + wShowWindow: WORD + cbReserved2: WORD + lpReserved2: VOIDPTR + hStdInput: HANDLE + hStdOutput: HANDLE + hStdError: HANDLE +class STARTUPINFOW: + cb: ULONG + lpReserved: WCHARPTR + lpDesktop: WCHARPTR + lpTitle: WCHARPTR + dwX: ULONG + dwY: ULONG + dwXSize: ULONG + dwYSize: ULONG + dwXCountChars: ULONG + dwYCountChars: ULONG + dwFillAttribute: ULONG + dwFlags: ULONG + wShowWindow: WORD + cbReserved2: WORD + lpReserved2: VOIDPTR + hStdInput: HANDLE + hStdOutput: HANDLE + hStdError: HANDLE +class PROCESS_INFORMATION: + hProcess: HANDLE + hThread: HANDLE + dwProcessId: ULONG + dwThreadId: ULONG + +def CreateProcessA(lpApplicationName: LPCSTR, lpCommandLine: CHARPTR, lpProcessAttributes: SECURITY_ATTRIBUTES | t.CPtr, lpThreadAttributes: SECURITY_ATTRIBUTES | t.CPtr, bInheritHandles: BOOL, dwCreationFlags: ULONG, lpEnvironment: VOIDPTR, lpCurrentDirectory: LPCSTR, lpStartupInfo: STARTUPINFOA | t.CPtr, lpProcessInformation: PROCESS_INFORMATION | t.CPtr) -> BOOL | t.State: pass + +def CreateProcessW(lpApplicationName: LPCWSTR, lpCommandLine: WCHARPTR, lpProcessAttributes: SECURITY_ATTRIBUTES | t.CPtr, lpThreadAttributes: SECURITY_ATTRIBUTES | t.CPtr, bInheritHandles: BOOL, dwCreationFlags: ULONG, lpEnvironment: VOIDPTR, lpCurrentDirectory: LPCWSTR, lpStartupInfo: STARTUPINFOW | t.CPtr, lpProcessInformation: PROCESS_INFORMATION | t.CPtr) -> BOOL | t.State: pass + +def TerminateProcess(hProcess: HANDLE, uExitCode: UINT) -> BOOL | t.State: pass + +def GetExitCodeProcess(hProcess: HANDLE, lpExitCode: ULONG | t.CPtr) -> BOOL | t.State: pass + +def GetExitCodeThread(hThread: HANDLE, lpExitCode: ULONG | t.CPtr) -> BOOL | t.State: pass + +def OpenProcess(dwDesiredAccess: ULONG, bInheritHandle: BOOL, dwProcessId: ULONG) -> HANDLE | t.State: pass + +def GetCurrentProcess() -> HANDLE | t.State: pass + +def GetCurrentProcessId() -> ULONG | t.State: pass + +def CreateThread(lpThreadAttributes: SECURITY_ATTRIBUTES | t.CPtr, dwStackSize: t.CSizeT, lpStartAddress: VOIDPTR, lpParameter: VOIDPTR, dwCreationFlags: ULONG, lpThreadId: ULONG | t.CPtr) -> HANDLE | t.State: pass + +def OpenThread(dwDesiredAccess: ULONG, bInheritHandle: BOOL, dwThreadId: ULONG) -> HANDLE | t.State: pass + +def SuspendThread(hThread: HANDLE) -> ULONG | t.State: pass + +def ResumeThread(hThread: HANDLE) -> ULONG | t.State: pass + +def TerminateThread(hThread: HANDLE, dwExitCode: ULONG) -> BOOL | t.State: pass + +def GetCurrentThread() -> HANDLE | t.State: pass + +def GetCurrentThreadId() -> ULONG | t.State: pass + +def GetThreadId(hThread: HANDLE) -> ULONG | t.State: pass + +def GetProcessId(hProcess: HANDLE) -> ULONG | t.State: pass + +def SetThreadPriority(hThread: HANDLE, nPriority: INT) -> BOOL | t.State: pass + +def GetThreadPriority(hThread: HANDLE) -> INT | t.State: pass + +def ExitProcess(uExitCode: UINT) -> VOID | t.State: pass + +def ExitThread(dwExitCode: ULONG) -> VOID | t.State: pass + +def TlsAlloc() -> ULONG | t.State: pass + +def TlsFree(dwTlsIndex: ULONG) -> BOOL | t.State: pass + +def TlsGetValue(dwTlsIndex: ULONG) -> VOIDPTR | t.State: pass + +def TlsSetValue(dwTlsIndex: ULONG, lpTlsValue: VOIDPTR) -> BOOL | t.State: pass diff --git a/Test/FakeDuckTest/temp/06f53cc594b4ac6c.pyi b/Test/FakeDuckTest/temp/06f53cc594b4ac6c.pyi new file mode 100644 index 0000000..8b5a8cf --- /dev/null +++ b/Test/FakeDuckTest/temp/06f53cc594b4ac6c.pyi @@ -0,0 +1,109 @@ +""" +Auto-generated Python stub file from w32.win32sync.py +Module: w32.win32sync +""" + +import c + + +import t +from stdint import * +from w32.win32base import * + +class CRITICAL_SECTION: + DebugInfo: VOIDPTR + LockCount: LONG + RecursionCount: LONG + OwningThread: HANDLE + LockSemaphore: HANDLE + SpinCount: QWORD + +def InitializeCriticalSection(lpCriticalSection: CRITICAL_SECTION | t.CPtr) -> VOID | t.State: pass + +def EnterCriticalSection(lpCriticalSection: CRITICAL_SECTION | t.CPtr) -> VOID | t.State: pass + +def LeaveCriticalSection(lpCriticalSection: CRITICAL_SECTION | t.CPtr) -> VOID | t.State: pass + +def DeleteCriticalSection(lpCriticalSection: CRITICAL_SECTION | t.CPtr) -> VOID | t.State: pass + +def TryEnterCriticalSection(lpCriticalSection: CRITICAL_SECTION | t.CPtr) -> BOOL | t.State: pass + +def SetCriticalSectionSpinCount(lpCriticalSection: CRITICAL_SECTION | t.CPtr, dwSpinCount: ULONG) -> ULONG | t.State: pass + +def InitializeCriticalSectionAndSpinCount(lpCriticalSection: CRITICAL_SECTION | t.CPtr, dwSpinCount: ULONG) -> BOOL | t.State: pass + +def CreateMutexA(lpMutexAttributes: SECURITY_ATTRIBUTES | t.CPtr, bInitialOwner: BOOL, lpName: LPCSTR) -> HANDLE | t.State: pass + +def CreateMutexW(lpMutexAttributes: SECURITY_ATTRIBUTES | t.CPtr, bInitialOwner: BOOL, lpName: LPCWSTR) -> HANDLE | t.State: pass + +def OpenMutexA(dwDesiredAccess: ULONG, bInheritHandle: BOOL, lpName: LPCSTR) -> HANDLE | t.State: pass + +def OpenMutexW(dwDesiredAccess: ULONG, bInheritHandle: BOOL, lpName: LPCWSTR) -> HANDLE | t.State: pass + +def ReleaseMutex(hMutex: HANDLE) -> BOOL | t.State: pass + +def CreateEventA(lpEventAttributes: SECURITY_ATTRIBUTES | t.CPtr, bManualReset: BOOL, bInitialState: BOOL, lpName: LPCSTR) -> HANDLE | t.State: pass + +def CreateEventW(lpEventAttributes: SECURITY_ATTRIBUTES | t.CPtr, bManualReset: BOOL, bInitialState: BOOL, lpName: LPCWSTR) -> HANDLE | t.State: pass + +def OpenEventA(dwDesiredAccess: ULONG, bInheritHandle: BOOL, lpName: LPCSTR) -> HANDLE | t.State: pass + +def OpenEventW(dwDesiredAccess: ULONG, bInheritHandle: BOOL, lpName: LPCWSTR) -> HANDLE | t.State: pass + +def SetEvent(hEvent: HANDLE) -> BOOL | t.State: pass + +def ResetEvent(hEvent: HANDLE) -> BOOL | t.State: pass + +def PulseEvent(hEvent: HANDLE) -> BOOL | t.State: pass + +def CreateSemaphoreA(lpSemaphoreAttributes: SECURITY_ATTRIBUTES | t.CPtr, lInitialCount: LONG, lMaximumCount: LONG, lpName: LPCSTR) -> HANDLE | t.State: pass + +def CreateSemaphoreW(lpSemaphoreAttributes: SECURITY_ATTRIBUTES | t.CPtr, lInitialCount: LONG, lMaximumCount: LONG, lpName: LPCWSTR) -> HANDLE | t.State: pass + +def OpenSemaphoreA(dwDesiredAccess: ULONG, bInheritHandle: BOOL, lpName: LPCSTR) -> HANDLE | t.State: pass + +def OpenSemaphoreW(dwDesiredAccess: ULONG, bInheritHandle: BOOL, lpName: LPCWSTR) -> HANDLE | t.State: pass + +def ReleaseSemaphore(hSemaphore: HANDLE, lReleaseCount: LONG, lpPreviousCount: LONG | t.CPtr) -> BOOL | t.State: pass + +def WaitForSingleObject(hHandle: HANDLE, dwMilliseconds: ULONG) -> ULONG | t.State: pass + +def WaitForSingleObjectEx(hHandle: HANDLE, dwMilliseconds: ULONG, bAlertable: BOOL) -> ULONG | t.State: pass + +def WaitForMultipleObjects(nCount: ULONG, lpHandles: VOIDPTR, bWaitAll: BOOL, dwMilliseconds: ULONG) -> ULONG | t.State: pass + +def WaitForMultipleObjectsEx(nCount: ULONG, lpHandles: VOIDPTR, bWaitAll: BOOL, dwMilliseconds: ULONG, bAlertable: BOOL) -> ULONG | t.State: pass + +def InitializeSRWLock(SRWLock: VOIDPTR) -> VOID | t.State: pass + +def AcquireSRWLockExclusive(SRWLock: VOIDPTR) -> VOID | t.State: pass + +def AcquireSRWLockShared(SRWLock: VOIDPTR) -> VOID | t.State: pass + +def ReleaseSRWLockExclusive(SRWLock: VOIDPTR) -> VOID | t.State: pass + +def ReleaseSRWLockShared(SRWLock: VOIDPTR) -> VOID | t.State: pass + + +CONDITION_VARIABLE_LOCKMODE_SHARED: t.CDefine = 0x1 + +def InitializeConditionVariable(ConditionVariable: VOIDPTR) -> VOID | t.State: pass + +def SleepConditionVariableCS(ConditionVariable: VOIDPTR, CriticalSection: CRITICAL_SECTION | t.CPtr, dwMilliseconds: ULONG) -> BOOL | t.State: pass + +def SleepConditionVariableSRW(ConditionVariable: VOIDPTR, SRWLock: VOIDPTR, dwMilliseconds: ULONG, Flags: ULONG) -> BOOL | t.State: pass + +def WakeConditionVariable(ConditionVariable: VOIDPTR) -> VOID | t.State: pass + +def WakeAllConditionVariable(ConditionVariable: VOIDPTR) -> VOID | t.State: pass + + +INIT_ONCE_STATIC_INIT: t.CDefine = 0x00000001 +INIT_ONCE_CHECK_ONLY: t.CDefine = 0x00000002 +INIT_ONCE_ASYNC: t.CDefine = 0x00000004 +INIT_ONCE_INIT_FAILED: t.CDefine = 0x00000008 + +class INIT_ONCE: + Ptr: t.CPtr + +def InitOnceExecuteOnce(InitOnce: INIT_ONCE | t.CPtr, InitFn: VOIDPTR, Parameter: VOIDPTR, Context: VOIDPTR | t.CPtr) -> BOOL | t.State: pass diff --git a/Test/FakeDuckTest/temp/0eaa586c42dcd931.pyi b/Test/FakeDuckTest/temp/0eaa586c42dcd931.pyi new file mode 100644 index 0000000..7ce46eb --- /dev/null +++ b/Test/FakeDuckTest/temp/0eaa586c42dcd931.pyi @@ -0,0 +1,49 @@ +""" +Auto-generated Python stub file from mbuddy.py +Module: mbuddy +""" + + +import t, c +from stdint import * +import string +import atom + +MBUDDY_MIN_BLOCK: t.CDefine = 32 # 最小块大小 (字节),需 >= 16 以容纳链表指针 +MBUDDY_MAX_ORDERS: t.CDefine = 32 # 最大阶数数量 +MBUDDY_HEADER_SIZE: t.CDefine = 8 # 块头大小 (存储阶数) + +def _largest_pow2_le(val: t.CSizeT) -> t.CSizeT: pass + +def _block_size_at_order(order: t.CInt) -> t.CSizeT: pass + + +class MBuddy: + __provides__: list[str] = ['__mbuddy__'] + mem: t.CVoid | t.CPtr + mem_size: t.CSizeT + max_order: t.CInt + free_lists: t.CUInt64T | t.CPtr + lock_val: t.CVolatile | t.CInt + def __init__(self: MBuddy, arena: t.CVoid | t.CPtr, arena_size: t.CSizeT) -> t.CInt: pass + def __enter__(self: MBuddy) -> 'MBuddy' | t.CPtr: pass + def __exit__(self: MBuddy) -> t.CInt: pass + def reset(self: MBuddy) -> t.CInt: pass + def _fl_push(self: MBuddy, order: t.CInt, block: t.CVoid | t.CPtr) -> t.CInt: pass + def _fl_pop(self: MBuddy, order: t.CInt) -> t.CVoid | t.CPtr: pass + def _fl_find_and_remove(self: MBuddy, order: t.CInt, target: t.CVoid | t.CPtr) -> t.CInt: pass + def _buddy_of(self: MBuddy, block: t.CVoid | t.CPtr, order: t.CInt) -> t.CVoid | t.CPtr: pass + def _order_for_size(self: MBuddy, size: t.CSizeT) -> t.CInt: pass + def _split_to_order(self: MBuddy, to_order: t.CInt) -> t.CVoid | t.CPtr: pass + def _coalesce(self: MBuddy, block: t.CVoid | t.CPtr, order: t.CInt) -> t.CInt: pass + def _is_valid_ptr(self: MBuddy, ptr: t.CVoid | t.CPtr) -> t.CInt: pass + def _fl_count(self: MBuddy, order: t.CInt) -> t.CSizeT: pass + def _lock(self: MBuddy) -> t.CInt: pass + def _unlock(self: MBuddy) -> t.CInt: pass + def alloc(self: MBuddy, size: t.CSizeT) -> t.CVoid | t.CPtr: pass + def free(self: MBuddy, ptr: t.CVoid | t.CPtr) -> t.CInt: pass + def calloc(self: MBuddy, count: t.CSizeT, size: t.CSizeT) -> t.CVoid | t.CPtr: pass + def realloc(self: MBuddy, ptr: t.CVoid | t.CPtr, new_size: t.CSizeT) -> t.CVoid | t.CPtr: pass + def stats(self: MBuddy) -> t.CSizeT: pass + def free_count(self: MBuddy) -> t.CSizeT: pass + def self_check(self: MBuddy) -> t.CInt: pass \ No newline at end of file diff --git a/Test/FakeDuckTest/temp/271ea3decb810db2.pyi b/Test/FakeDuckTest/temp/271ea3decb810db2.pyi new file mode 100644 index 0000000..3d637bf --- /dev/null +++ b/Test/FakeDuckTest/temp/271ea3decb810db2.pyi @@ -0,0 +1,26 @@ +""" +Auto-generated Python stub file from atom.py +Module: atom +""" + + +import t, c + +ATOMIC_RELAXED: t.CDefine = 0 +ATOMIC_CONSUME: t.CDefine = 1 +ATOMIC_ACQUIRE: t.CDefine = 2 +ATOMIC_RELEASE: t.CDefine = 3 +ATOMIC_ACQ_REL: t.CDefine = 4 +ATOMIC_SEQ_CST: t.CDefine = 5 + +def __atomic_test_and_set(ptr: t.CUInt64T | t.CPtr, order: t.CInt) -> t.CBool: pass + +def __atomic_clear(ptr: t.CUInt64T | t.CPtr, order: t.CInt) -> t.CVoid: pass + +def __atomic_thread_fence(order: t.CInt) -> t.CVoid: pass + +def __atomic_signal_fence(order: t.CInt) -> t.CVoid: pass + +def __atomic_always_lock_free(size: t.CSizeT, ptr: t.CVoid | t.CPtr) -> t.CBool: pass + +def __atomic_is_lock_free(size: t.CSizeT, ptr: t.CVoid | t.CPtr) -> t.CBool: pass diff --git a/Test/FakeDuckTest/temp/49bd8cba55979f76.pyi b/Test/FakeDuckTest/temp/49bd8cba55979f76.pyi new file mode 100644 index 0000000..f1d844a --- /dev/null +++ b/Test/FakeDuckTest/temp/49bd8cba55979f76.pyi @@ -0,0 +1,75 @@ +""" +Auto-generated Python stub file from stdint.py +Module: stdint +""" + +import c + + +import t + +INT: t.CTypedef = t.CInt +INTPTR: t.CTypedef = t.CInt | t.CPtr +BOOL: t.CTypedef = t.CInt +UINT: t.CTypedef = t.CUnsignedInt +UINTPTR: t.CTypedef = UINT | t.CPtr +BYTE: t.CTypedef = t.CUnsignedChar +BYTEPTR: t.CTypedef = BYTE | t.CPtr +WORD: t.CTypedef = t.CUInt16T +DWORD: t.CTypedef = t.CUInt32T +QWORD: t.CTypedef = t.CUInt64T +TCHAR: t.CTypedef = t.CChar +CHARLIST: t.CTypedef = str | t.CPtr +VOID: t.CTypedef = t.CVoid +SHORT: t.CTypedef = t.CShort +SHORTPTR: t.CTypedef = t.CShort | t.CPtr +USHORT: t.CTypedef = t.CUnsignedShort +USHORTPTR: t.CTypedef = t.CUnsignedShort | t.CPtr +LONGLONG: t.CTypedef = t.CLong | t.CLong +ULONGLONG: t.CTypedef = t.CUnsignedLong | t.CLong +LONG: t.CTypedef = t.CLong +ULONG: t.CTypedef = t.CUnsignedLong +WCHAR: t.CTypedef = WORD +WCHARPTR: t.CTypedef = WORD | t.CPtr +CHARPTR: t.CTypedef = t.CChar | t.CPtr +FSIZE_t: t.CTypedef = DWORD +LBA_t: t.CTypedef = DWORD +UINTPTR: t.CTypedef = t.CUnsignedInt | t.CPtr +VOIDPTR: t.CTypedef = t.CVoid | t.CPtr +FLOAT: t.CTypedef = t.CFloat +DOUBLE: t.CTypedef = t.CDouble +FLOAT8: t.CTypedef = t.CFloat8T +FLOAT16: t.CTypedef = t.CFloat16T +FLOAT32: t.CTypedef = t.CFloat32T +FLOAT64: t.CTypedef = t.CFloat64T +FLOAT128: t.CTypedef = t.CFloat128T +INT8: t.CTypedef = t.CInt8T +INT16: t.CTypedef = t.CInt16T +INT32: t.CTypedef = t.CInt32T +INT64: t.CTypedef = t.CInt64T +UINT8: t.CTypedef = t.CUInt8T +UINT16: t.CTypedef = t.CUInt16T +UINT32: t.CTypedef = t.CUInt32T +UINT64: t.CTypedef = t.CUInt64T +INT8PTR: t.CTypedef = t.CInt8T | t.CPtr +INT16PTR: t.CTypedef = t.CInt16T | t.CPtr +INT32PTR: t.CTypedef = t.CInt32T | t.CPtr +INT64PTR: t.CTypedef = t.CInt64T | t.CPtr +UINT8PTR: t.CTypedef = t.CUInt8T | t.CPtr +UINT16PTR: t.CTypedef = t.CUInt16T | t.CPtr +UINT32PTR: t.CTypedef = t.CUInt32T | t.CPtr +UINT64PTR: t.CTypedef = t.CUInt64T | t.CPtr +CHAR8: t.CTypedef = t.CChar8T +CHAR16: t.CTypedef = t.CChar16T +CHAR32: t.CTypedef = t.CChar32T +CHAR8PTR: t.CTypedef = t.CChar8T | t.CPtr +CHAR16PTR: t.CTypedef = t.CChar16T | t.CPtr +CHAR32PTR: t.CTypedef = t.CChar32T | t.CPtr +i8: t.CTypedef = t.CInt8T +i16: t.CTypedef = t.CInt16T +i32: t.CTypedef = t.CInt32T +i64: t.CTypedef = t.CInt64T +u8: t.CTypedef = t.CUInt8T +u16: t.CTypedef = t.CUInt16T +u32: t.CTypedef = t.CUInt32T +u64: t.CTypedef = t.CUInt64T \ No newline at end of file diff --git a/Test/FakeDuckTest/temp/5a6a2137958c28c5.pyi b/Test/FakeDuckTest/temp/5a6a2137958c28c5.pyi new file mode 100644 index 0000000..a137977 --- /dev/null +++ b/Test/FakeDuckTest/temp/5a6a2137958c28c5.pyi @@ -0,0 +1,98 @@ +""" +Auto-generated Python stub file from w32.win32base.py +Module: w32.win32base +""" + +import c + + +import t +from stdint import * + +HANDLE: t.CTypedef = VOIDPTR +LPCSTR: t.CTypedef = t.CConst | t.CChar | t.CPtr +LPCWSTR: t.CTypedef = t.CConst | t.CUnsignedShort | t.CPtr +INVALID_HANDLE_VALUE: t.CDefine = t.CVoid(-1) +NULL: t.CDefine = 0 +TRUE: t.CDefine = 1 +FALSE: t.CDefine = 0 +INFINITE: t.CDefine = 0xFFFFFFFF +WAIT_FAILED: t.CDefine = 0xFFFFFFFF +WAIT_OBJECT_0: t.CDefine = 0 +WAIT_TIMEOUT: t.CDefine = 258 +WAIT_ABANDONED: t.CDefine = 0x80 +MAX_PATH: t.CDefine = 260 +ERROR_SUCCESS: t.CDefine = 0 +ERROR_FILE_NOT_FOUND: t.CDefine = 2 +ERROR_ACCESS_DENIED: t.CDefine = 5 +ERROR_INSUFFICIENT_BUFFER: t.CDefine = 122 + +class SECURITY_ATTRIBUTES: + nLength: ULONG + lpSecurityDescriptor: VOIDPTR + bInheritHandle: BOOL +class OVERLAPPED: + Internal: ULONGLONG + InternalHigh: ULONGLONG + Offset: ULONG + OffsetHigh: ULONG + hEvent: HANDLE +class FILETIME: + dwLowDateTime: DWORD + dwHighDateTime: DWORD +class SYSTEMTIME: + wYear: WORD + wMonth: WORD + wDayOfWeek: WORD + wDay: WORD + wHour: WORD + wMinute: WORD + wSecond: WORD + wMilliseconds: WORD +class GUID: + Data1: DWORD + Data2: WORD + Data3: WORD + Data4: BYTEPTR +class LARGE_INTEGER: + QuadPart: LONGLONG +class ULARGE_INTEGER: + QuadPart: ULONGLONG + +def GetLastError() -> ULONG | t.State: pass + +def SetLastError(dwErrCode: ULONG) -> t.State: pass + +def CloseHandle(hObject: HANDLE) -> BOOL | t.State: pass + +def GetProcAddress(hModule: HANDLE, lpProcName: LPCSTR) -> VOIDPTR | t.State: pass + +def GetModuleHandleA(lpModuleName: LPCSTR) -> HANDLE | t.State: pass + +def GetModuleHandleW(lpModuleName: LPCWSTR) -> HANDLE | t.State: pass + +def LoadLibraryA(lpLibFileName: LPCSTR) -> HANDLE | t.State: pass + +def LoadLibraryW(lpLibFileName: LPCWSTR) -> HANDLE | t.State: pass + +def FreeLibrary(hLibModule: HANDLE) -> BOOL | t.State: pass + +def GetSystemTime(lpSystemTime: SYSTEMTIME | t.CPtr) -> t.State: pass + +def GetLocalTime(lpSystemTime: SYSTEMTIME | t.CPtr) -> t.State: pass + +def FileTimeToSystemTime(lpFileTime: FILETIME | t.CPtr, lpSystemTime: SYSTEMTIME | t.CPtr) -> BOOL | t.State: pass + +def SystemTimeToFileTime(lpSystemTime: SYSTEMTIME | t.CPtr, lpFileTime: FILETIME | t.CPtr) -> BOOL | t.State: pass + +def QueryPerformanceCounter(lpPerformanceCount: LARGE_INTEGER | t.CPtr) -> BOOL | t.State: pass + +def QueryPerformanceFrequency(lpFrequency: LARGE_INTEGER | t.CPtr) -> BOOL | t.State: pass + +def Sleep(dwMilliseconds: ULONG) -> t.State: pass + +def SleepEx(dwMilliseconds: ULONG, bAlertable: BOOL) -> ULONG | t.State: pass + +def GetTickCount() -> ULONG | t.State: pass + +def GetTickCount64() -> ULONGLONG | t.State: pass diff --git a/Test/FakeDuckTest/temp/6c2029b306556c00.pyi b/Test/FakeDuckTest/temp/6c2029b306556c00.pyi new file mode 100644 index 0000000..98da680 --- /dev/null +++ b/Test/FakeDuckTest/temp/6c2029b306556c00.pyi @@ -0,0 +1,18 @@ +""" +Auto-generated Python stub file from stdlib.py +Module: stdlib +""" + +import c + + +from stdint import * +import t + +def malloc(size: t.CSizeT) -> t.CVoid | t.CPtr | t.State | t.CExtern | t.CExport: pass + +def calloc(nmemb: t.CSizeT, size: t.CSizeT) -> t.CVoid | t.CPtr | t.State | t.CExtern | t.CExport: pass + +def realloc(p: t.CVoid | t.CPtr, size: t.CSizeT) -> t.CVoid | t.CPtr | t.State | t.CExtern | t.CExport: pass + +def free(p: t.CVoid | t.CPtr) -> None | t.State | t.CExtern | t.CExport: pass diff --git a/Test/FakeDuckTest/temp/72e2d5ccb7cedcf1.pyi b/Test/FakeDuckTest/temp/72e2d5ccb7cedcf1.pyi new file mode 100644 index 0000000..5fceb08 --- /dev/null +++ b/Test/FakeDuckTest/temp/72e2d5ccb7cedcf1.pyi @@ -0,0 +1,91 @@ +""" +Auto-generated Python stub file from w32.win32memory.py +Module: w32.win32memory +""" + +import c + + +import t +from stdint import * +from w32.win32base import * + +MEM_COMMIT: t.CDefine = 0x00001000 +MEM_RESERVE: t.CDefine = 0x00002000 +MEM_DECOMMIT: t.CDefine = 0x00004000 +MEM_RELEASE: t.CDefine = 0x00008000 +MEM_FREE: t.CDefine = 0x00010000 +MEM_RESET: t.CDefine = 0x00080000 +MEM_TOP_DOWN: t.CDefine = 0x00100000 +MEM_WRITE_WATCH: t.CDefine = 0x00200000 +MEM_PHYSICAL: t.CDefine = 0x00400000 +MEM_LARGE_PAGES: t.CDefine = 0x20000000 +PAGE_NOACCESS: t.CDefine = 0x01 +PAGE_READONLY: t.CDefine = 0x02 +PAGE_READWRITE: t.CDefine = 0x04 +PAGE_WRITECOPY: t.CDefine = 0x08 +PAGE_EXECUTE: t.CDefine = 0x10 +PAGE_EXECUTE_READ: t.CDefine = 0x20 +PAGE_EXECUTE_READWRITE: t.CDefine = 0x40 +PAGE_EXECUTE_WRITECOPY: t.CDefine = 0x80 +PAGE_GUARD: t.CDefine = 0x100 +PAGE_NOCACHE: t.CDefine = 0x200 +PAGE_WRITECOMBINE: t.CDefine = 0x400 +HEAP_NO_SERIALIZE: t.CDefine = 0x00000001 +HEAP_GROWABLE: t.CDefine = 0x00000002 +HEAP_GENERATE_EXCEPTIONS: t.CDefine = 0x00000004 +HEAP_ZERO_MEMORY: t.CDefine = 0x00000008 +HEAP_REALLOC_IN_PLACE_ONLY: t.CDefine = 0x00000010 + +class MEMORY_BASIC_INFORMATION: + BaseAddress: VOIDPTR + AllocationBase: VOIDPTR + AllocationProtect: ULONG + RegionSize: t.CSizeT + State: ULONG + Protect: ULONG + Type: ULONG + +def VirtualAlloc(lpAddress: VOIDPTR, dwSize: t.CSizeT, flAllocationType: ULONG, flProtect: ULONG) -> VOIDPTR | t.State: pass + +def VirtualFree(lpAddress: VOIDPTR, dwSize: t.CSizeT, dwFreeType: ULONG) -> BOOL | t.State: pass + +def VirtualProtect(lpAddress: VOIDPTR, dwSize: t.CSizeT, flNewProtect: ULONG, lpflOldProtect: ULONG | t.CPtr) -> BOOL | t.State: pass + +def VirtualQuery(lpAddress: t.CConst | VOIDPTR, lpBuffer: MEMORY_BASIC_INFORMATION | t.CPtr, dwLength: t.CSizeT) -> t.CSizeT | t.State: pass + +def VirtualLock(lpAddress: VOIDPTR, dwSize: t.CSizeT) -> BOOL | t.State: pass + +def VirtualUnlock(lpAddress: VOIDPTR, dwSize: t.CSizeT) -> BOOL | t.State: pass + +def GetProcessHeap() -> HANDLE | t.State: pass + +def HeapCreate(flOptions: ULONG, dwInitialSize: t.CSizeT, dwMaximumSize: t.CSizeT) -> HANDLE | t.State: pass + +def HeapDestroy(hHeap: HANDLE) -> BOOL | t.State: pass + +def HeapAlloc(hHeap: HANDLE, dwFlags: ULONG, dwBytes: t.CSizeT) -> VOIDPTR | t.State: pass + +def HeapReAlloc(hHeap: HANDLE, dwFlags: ULONG, lpMem: VOIDPTR, dwBytes: t.CSizeT) -> VOIDPTR | t.State: pass + +def HeapFree(hHeap: HANDLE, dwFlags: ULONG, lpMem: VOIDPTR) -> BOOL | t.State: pass + +def HeapSize(hHeap: HANDLE, dwFlags: ULONG, lpMem: t.CConst | VOIDPTR) -> t.CSizeT | t.State: pass + +def HeapValidate(hHeap: HANDLE, dwFlags: ULONG, lpMem: t.CConst | VOIDPTR) -> BOOL | t.State: pass + +def HeapCompact(hHeap: HANDLE, dwFlags: ULONG) -> t.CSizeT | t.State: pass + +def GlobalAlloc(uFlags: UINT, dwBytes: t.CSizeT) -> VOIDPTR | t.State: pass + +def GlobalFree(hMem: VOIDPTR) -> VOIDPTR | t.State: pass + +def GlobalLock(hMem: VOIDPTR) -> VOIDPTR | t.State: pass + +def GlobalUnlock(hMem: VOIDPTR) -> BOOL | t.State: pass + +def GlobalSize(hMem: VOIDPTR) -> t.CSizeT | t.State: pass + +def LocalAlloc(uFlags: UINT, dwBytes: t.CSizeT) -> VOIDPTR | t.State: pass + +def LocalFree(hMem: VOIDPTR) -> VOIDPTR | t.State: pass diff --git a/Test/FakeDuckTest/temp/73edbcf76e32d00b.pyi b/Test/FakeDuckTest/temp/73edbcf76e32d00b.pyi new file mode 100644 index 0000000..ef712e3 --- /dev/null +++ b/Test/FakeDuckTest/temp/73edbcf76e32d00b.pyi @@ -0,0 +1,28 @@ +""" +Auto-generated Python stub file from stdio.py +Module: stdio +""" + + +import t, c + +def printf(fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass + +def fprintf(stream: t.CVoid | t.CPtr, fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass + +def sprintf(buf: t.CChar | t.CPtr, fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass + +def snprintf(buf: t.CChar | t.CPtr, size: t.CSizeT, fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass + +def puts(s: t.CChar | t.CConst | t.CPtr) -> t.CInt | t.CExtern | t.CExport: pass + +def fputs(s: t.CChar | t.CConst | t.CPtr, stream: t.CVoid | t.CPtr) -> t.CInt | t.CExtern | t.CExport: pass + +def fgets(buf: t.CChar | t.CPtr, size: t.CInt, stream: t.CVoid | t.CPtr) -> t.CChar | t.CPtr | t.CExtern | t.CExport: pass + +def fflush(stream: t.CVoid | t.CPtr) -> t.CInt | t.CExtern | t.CExport: pass + + +stdin: t.CExtern | t.CVoid | t.CPtr +stdout: t.CExtern | t.CVoid | t.CPtr +stderr: t.CExtern | t.CVoid | t.CPtr \ No newline at end of file diff --git a/Test/FakeDuckTest/temp/9d9d71cf83da7ca4.pyi b/Test/FakeDuckTest/temp/9d9d71cf83da7ca4.pyi new file mode 100644 index 0000000..083f774 --- /dev/null +++ b/Test/FakeDuckTest/temp/9d9d71cf83da7ca4.pyi @@ -0,0 +1,29 @@ +""" +Auto-generated Python stub file from _list.py +Module: _list +""" + + +import t, c +import mbuddy +import string +from stdint import * + +class list[T]: + __data__: t.CVoid | t.CPtr + __count__: t.CSizeT + __capacity__: t.CSizeT + __mbuddy__: mbuddy.MBuddy | t.CPtr + __iter_index__: t.CSizeT + def __new__(self: list, mb: mbuddy.MBuddy | t.CPtr) -> t.CInt: pass + def __init__(self: list, mb: mbuddy.MBuddy | t.CPtr) -> t.CInt: pass + def __len__(self: list) -> t.CSizeT: pass + def append(self: list, item: T) -> t.CInt: pass + def get(self: list, index: t.CSizeT) -> T: pass + def __getitem__(self: list, index: t.CSizeT) -> T: pass + def set(self: list, index: t.CSizeT, value: T) -> t.CInt: pass + def __setitem__(self: list, index: t.CSizeT, value: T) -> t.CInt: pass + def pop(self: list) -> T: pass + def clear(self: list) -> t.CInt: pass + def __iter__(self: list) -> t.CInt: pass + def __next__(self: list) -> T: pass \ No newline at end of file diff --git a/Test/FakeDuckTest/temp/9dbecd0942a39782.pyi b/Test/FakeDuckTest/temp/9dbecd0942a39782.pyi new file mode 100644 index 0000000..41648c1 --- /dev/null +++ b/Test/FakeDuckTest/temp/9dbecd0942a39782.pyi @@ -0,0 +1,25 @@ +""" +Auto-generated Python stub file from testcheck.py +Module: testcheck +""" + + +import t, c +import stdio + +_pass_count: t.CExtern | t.CInt +_fail_count: t.CExtern | t.CInt + +def begin(name: str) -> t.CInt: pass + +def section(name: str) -> t.CInt: pass + +def ok(msg: str) -> t.CInt: pass + +def fail(msg: str) -> t.CInt: pass + +def check(cond: t.CInt, ok_msg: str, fail_msg: str) -> t.CInt: pass + +def info(msg: str) -> t.CInt: pass + +def end() -> t.CInt: pass diff --git a/Test/FakeDuckTest/temp/_sha1_map.txt b/Test/FakeDuckTest/temp/_sha1_map.txt new file mode 100644 index 0000000..8f14730 --- /dev/null +++ b/Test/FakeDuckTest/temp/_sha1_map.txt @@ -0,0 +1,14 @@ +067c78e9f121dce3:includes/w32\win32process.py +0eaa586c42dcd931:includes/mbuddy.py +271ea3decb810db2:includes/atom.py +49bd8cba55979f76:includes/stdint.py +5a6a2137958c28c5:includes/w32\win32base.py +6c2029b306556c00:includes/stdlib.py +73edbcf76e32d00b:includes/stdio.py +9d9d71cf83da7ca4:includes/_list.py +9dbecd0942a39782:includes/testcheck.py +b5f1dc665c52a1bd:includes/string.py +b9b237d0e206d76c:includes/_withcontent.py +bbdf3bbd4c3bc28c:includes/w32\win32console.py +c6206460c42ccf10:includes/_fakeduck.py +ccd58bf663340b12:main.py diff --git a/Test/FakeDuckTest/temp/abf9ce3160c9279e.pyi b/Test/FakeDuckTest/temp/abf9ce3160c9279e.pyi new file mode 100644 index 0000000..4249b58 --- /dev/null +++ b/Test/FakeDuckTest/temp/abf9ce3160c9279e.pyi @@ -0,0 +1,179 @@ +""" +Auto-generated Python stub file from w32.win32file.py +Module: w32.win32file +""" + +import c + + +import t +from stdint import * +from w32.win32base import * + +GENERIC_READ: t.CDefine = 0x80000000 +GENERIC_WRITE: t.CDefine = 0x40000000 +GENERIC_EXECUTE: t.CDefine = 0x20000000 +GENERIC_ALL: t.CDefine = 0x10000000 +FILE_SHARE_READ: t.CDefine = 0x00000001 +FILE_SHARE_WRITE: t.CDefine = 0x00000002 +FILE_SHARE_DELETE: t.CDefine = 0x00000004 +CREATE_NEW: t.CDefine = 1 +CREATE_ALWAYS: t.CDefine = 2 +OPEN_EXISTING: t.CDefine = 3 +OPEN_ALWAYS: t.CDefine = 4 +TRUNCATE_EXISTING: t.CDefine = 5 +FILE_ATTRIBUTE_READONLY: t.CDefine = 0x00000001 +FILE_ATTRIBUTE_HIDDEN: t.CDefine = 0x00000002 +FILE_ATTRIBUTE_SYSTEM: t.CDefine = 0x00000004 +FILE_ATTRIBUTE_DIRECTORY: t.CDefine = 0x00000010 +FILE_ATTRIBUTE_ARCHIVE: t.CDefine = 0x00000020 +FILE_ATTRIBUTE_NORMAL: t.CDefine = 0x00000080 +FILE_ATTRIBUTE_TEMPORARY: t.CDefine = 0x00000100 +FILE_ATTRIBUTE_COMPRESSED: t.CDefine = 0x00000800 +FILE_ATTRIBUTE_OFFLINE: t.CDefine = 0x00001000 +FILE_ATTRIBUTE_ENCRYPTED: t.CDefine = 0x00004000 +FILE_FLAG_WRITE_THROUGH: t.CDefine = 0x80000000 +FILE_FLAG_OVERLAPPED: t.CDefine = 0x40000000 +FILE_FLAG_NO_BUFFERING: t.CDefine = 0x20000000 +FILE_FLAG_RANDOM_ACCESS: t.CDefine = 0x10000000 +FILE_FLAG_SEQUENTIAL_SCAN: t.CDefine = 0x08000000 +FILE_FLAG_DELETE_ON_CLOSE: t.CDefine = 0x04000000 +FILE_FLAG_BACKUP_SEMANTICS: t.CDefine = 0x02000000 +FILE_FLAG_POSIX_SEMANTICS: t.CDefine = 0x01000000 +FILE_BEGIN: t.CDefine = 0 +FILE_CURRENT: t.CDefine = 1 +FILE_END: t.CDefine = 2 +STD_INPUT_HANDLE: t.CDefine = t.CUnsignedLong(-10) +STD_OUTPUT_HANDLE: t.CDefine = t.CUnsignedLong(-11) +STD_ERROR_HANDLE: t.CDefine = t.CUnsignedLong(-12) +MOVEFILE_REPLACE_EXISTING: t.CDefine = 0x00000001 +MOVEFILE_COPY_ALLOWED: t.CDefine = 0x00000002 +MOVEFILE_WRITE_THROUGH: t.CDefine = 0x00000008 + +class BY_HANDLE_FILE_INFORMATION: + dwFileAttributes: ULONG + ftCreationTime: FILETIME + ftLastAccessTime: FILETIME + ftLastWriteTime: FILETIME + dwVolumeSerialNumber: ULONG + nFileSizeHigh: ULONG + nFileSizeLow: ULONG + nNumberOfLinks: ULONG + nFileIndexHigh: ULONG + nFileIndexLow: ULONG +class WIN32_FIND_DATAA: + dwFileAttributes: ULONG + ftCreationTime: FILETIME + ftLastAccessTime: FILETIME + ftLastWriteTime: FILETIME + nFileSizeHigh: ULONG + nFileSizeLow: ULONG + dwReserved0: ULONG + dwReserved1: ULONG + cFileName: CHARPTR + cAlternateFileName: CHARPTR +class WIN32_FIND_DATAW: + dwFileAttributes: ULONG + ftCreationTime: FILETIME + ftLastAccessTime: FILETIME + ftLastWriteTime: FILETIME + nFileSizeHigh: ULONG + nFileSizeLow: ULONG + dwReserved0: ULONG + dwReserved1: ULONG + cFileName: WCHARPTR + cAlternateFileName: WCHARPTR + +def CreateFileA(lpFileName: LPCSTR, dwDesiredAccess: ULONG, dwShareMode: ULONG, lpSecurityAttributes: SECURITY_ATTRIBUTES | t.CPtr, dwCreationDisposition: ULONG, dwFlagsAndAttributes: ULONG, hTemplateFile: HANDLE) -> HANDLE | t.State: pass + +def CreateFileW(lpFileName: LPCWSTR, dwDesiredAccess: ULONG, dwShareMode: ULONG, lpSecurityAttributes: SECURITY_ATTRIBUTES | t.CPtr, dwCreationDisposition: ULONG, dwFlagsAndAttributes: ULONG, hTemplateFile: HANDLE) -> HANDLE | t.State: pass + +def ReadFile(hFile: HANDLE, lpBuffer: VOIDPTR, nNumberOfBytesToRead: ULONG, lpNumberOfBytesRead: ULONG | t.CPtr, lpOverlapped: OVERLAPPED | t.CPtr) -> BOOL | t.State: pass + +def WriteFile(hFile: HANDLE, lpBuffer: t.CConst | VOIDPTR, nNumberOfBytesToWrite: ULONG, lpNumberOfBytesWritten: ULONG | t.CPtr, lpOverlapped: OVERLAPPED | t.CPtr) -> BOOL | t.State: pass + +def SetFilePointer(hFile: HANDLE, lDistanceToMove: LONG, lpDistanceToMoveHigh: LONG | t.CPtr, dwMoveMethod: ULONG) -> LONG | t.State: pass + +def SetFilePointerEx(hFile: HANDLE, liDistanceToMove: LARGE_INTEGER | t.CPtr, lpNewFilePointer: LARGE_INTEGER | t.CPtr, dwMoveMethod: ULONG) -> BOOL | t.State: pass + +def GetFileSize(hFile: HANDLE, lpFileSizeHigh: ULONG | t.CPtr) -> ULONG | t.State: pass + +def GetFileSizeEx(hFile: HANDLE, lpFileSize: LARGE_INTEGER | t.CPtr) -> BOOL | t.State: pass + +def SetEndOfFile(hFile: HANDLE) -> BOOL | t.State: pass + +def FlushFileBuffers(hFile: HANDLE) -> BOOL | t.State: pass + +def GetFileType(hFile: HANDLE) -> ULONG | t.State: pass + +def GetFileAttributesA(lpFileName: LPCSTR) -> ULONG | t.State: pass + +def GetFileAttributesW(lpFileName: LPCWSTR) -> ULONG | t.State: pass + +def SetFileAttributesA(lpFileName: LPCSTR, dwFileAttributes: ULONG) -> BOOL | t.State: pass + +def SetFileAttributesW(lpFileName: LPCWSTR, dwFileAttributes: ULONG) -> BOOL | t.State: pass + +def DeleteFileA(lpFileName: LPCSTR) -> BOOL | t.State: pass + +def DeleteFileW(lpFileName: LPCWSTR) -> BOOL | t.State: pass + +def MoveFileA(lpExistingFileName: LPCSTR, lpNewFileName: LPCSTR) -> BOOL | t.State: pass + +def MoveFileW(lpExistingFileName: LPCWSTR, lpNewFileName: LPCWSTR) -> BOOL | t.State: pass + +def MoveFileExA(lpExistingFileName: LPCSTR, lpNewFileName: LPCSTR, dwFlags: ULONG) -> BOOL | t.State: pass + +def MoveFileExW(lpExistingFileName: LPCWSTR, lpNewFileName: LPCWSTR, dwFlags: ULONG) -> BOOL | t.State: pass + +def CopyFileA(lpExistingFileName: LPCSTR, lpNewFileName: LPCSTR, bFailIfExists: BOOL) -> BOOL | t.State: pass + +def CopyFileW(lpExistingFileName: LPCWSTR, lpNewFileName: LPCWSTR, bFailIfExists: BOOL) -> BOOL | t.State: pass + +def CreateDirectoryA(lpPathName: LPCSTR, lpSecurityAttributes: SECURITY_ATTRIBUTES | t.CPtr) -> BOOL | t.State: pass + +def CreateDirectoryW(lpPathName: LPCWSTR, lpSecurityAttributes: SECURITY_ATTRIBUTES | t.CPtr) -> BOOL | t.State: pass + +def RemoveDirectoryA(lpPathName: LPCSTR) -> BOOL | t.State: pass + +def RemoveDirectoryW(lpPathName: LPCWSTR) -> BOOL | t.State: pass + +def FindFirstFileA(lpFileName: LPCSTR, lpFindFileData: WIN32_FIND_DATAA | t.CPtr) -> HANDLE | t.State: pass + +def FindFirstFileW(lpFileName: LPCWSTR, lpFindFileData: WIN32_FIND_DATAW | t.CPtr) -> HANDLE | t.State: pass + +def FindNextFileA(hFindFile: HANDLE, lpFindFileData: WIN32_FIND_DATAA | t.CPtr) -> BOOL | t.State: pass + +def FindNextFileW(hFindFile: HANDLE, lpFindFileData: WIN32_FIND_DATAW | t.CPtr) -> BOOL | t.State: pass + +def FindClose(hFindFile: HANDLE) -> BOOL | t.State: pass + +def GetStdHandle(nStdHandle: ULONG) -> HANDLE | t.State: pass + +def SetStdHandle(nStdHandle: ULONG, hHandle: HANDLE) -> BOOL | t.State: pass + +def GetFileInformationByHandle(hFile: HANDLE, lpFileInformation: BY_HANDLE_FILE_INFORMATION | t.CPtr) -> BOOL | t.State: pass + +def LockFile(hFile: HANDLE, dwFileOffsetLow: ULONG, dwFileOffsetHigh: ULONG, nNumberOfBytesToLockLow: ULONG, nNumberOfBytesToLockHigh: ULONG) -> BOOL | t.State: pass + +def UnlockFile(hFile: HANDLE, dwFileOffsetLow: ULONG, dwFileOffsetHigh: ULONG, nNumberOfBytesToUnlockLow: ULONG, nNumberOfBytesToUnlockHigh: ULONG) -> BOOL | t.State: pass + +def GetTempPathA(nBufferLength: ULONG, lpBuffer: CHARPTR) -> ULONG | t.State: pass + +def GetTempPathW(nBufferLength: ULONG, lpBuffer: WCHARPTR) -> ULONG | t.State: pass + +def GetTempFileNameA(lpPathName: LPCSTR, lpPrefixString: LPCSTR, uUnique: UINT, lpTempFileName: CHARPTR) -> UINT | t.State: pass + +def GetTempFileNameW(lpPathName: LPCWSTR, lpPrefixString: LPCWSTR, uUnique: UINT, lpTempFileName: WCHARPTR) -> UINT | t.State: pass + +def GetCurrentDirectoryA(nBufferLength: ULONG, lpBuffer: CHARPTR) -> ULONG | t.State: pass + +def GetCurrentDirectoryW(nBufferLength: ULONG, lpBuffer: WCHARPTR) -> ULONG | t.State: pass + +def SetCurrentDirectoryA(lpPathName: LPCSTR) -> BOOL | t.State: pass + +def SetCurrentDirectoryW(lpPathName: LPCWSTR) -> BOOL | t.State: pass + +def GetModuleFileNameA(hModule: HANDLE, lpFilename: CHARPTR, nSize: ULONG) -> ULONG | t.State: pass + +def GetModuleFileNameW(hModule: HANDLE, lpFilename: WCHARPTR, nSize: ULONG) -> ULONG | t.State: pass diff --git a/Test/PointerTest/temp/6aee24fdefa3cbc0.pyi b/Test/FakeDuckTest/temp/b5f1dc665c52a1bd.pyi similarity index 94% rename from Test/PointerTest/temp/6aee24fdefa3cbc0.pyi rename to Test/FakeDuckTest/temp/b5f1dc665c52a1bd.pyi index c17475f..8b6959e 100644 --- a/Test/PointerTest/temp/6aee24fdefa3cbc0.pyi +++ b/Test/FakeDuckTest/temp/b5f1dc665c52a1bd.pyi @@ -41,4 +41,4 @@ def atoll(src: str) -> t.CInt64T: pass def atof(src: str) -> t.CDouble: pass -def split(s: str, delim: str, result: list[str]) -> int: pass +def split(s: str, delim: str, result: t.CArray[str]) -> int: pass diff --git a/Test/FakeDuckTest/temp/b9b237d0e206d76c.pyi b/Test/FakeDuckTest/temp/b9b237d0e206d76c.pyi new file mode 100644 index 0000000..364be1a --- /dev/null +++ b/Test/FakeDuckTest/temp/b9b237d0e206d76c.pyi @@ -0,0 +1,33 @@ +""" +Auto-generated Python stub file from _withcontent.py +Module: _withcontent +""" + + +import t, c +from stdint import * +from w32.win32process import TlsAlloc, TlsGetValue, TlsSetValue +import stdlib +import stdio +import string + +_MAX_PROVIDER_DEPTH: t.CDefine = 32 + +@t.Object +class _ProviderStack: + names: t.CArray[VOIDPTR, 32] + ptrs: t.CArray[VOIDPTR, 32] + top: UINT64 + +_tls_index: t.CExtern | ULONG + +@t.TLS +def _init_tls() -> t.CInt: pass + +def _get_stack() -> _ProviderStack | t.CPtr: pass + +def _push_provider(field_name: str, ptr: t.CPtr) -> t.CInt: pass + +def _pop_provider() -> t.CInt: pass + +def _find_provider(field_name: str) -> t.CPtr: pass diff --git a/Test/FakeDuckTest/temp/bbdf3bbd4c3bc28c.pyi b/Test/FakeDuckTest/temp/bbdf3bbd4c3bc28c.pyi new file mode 100644 index 0000000..70dcdbc --- /dev/null +++ b/Test/FakeDuckTest/temp/bbdf3bbd4c3bc28c.pyi @@ -0,0 +1,138 @@ +""" +Auto-generated Python stub file from w32.win32console.py +Module: w32.win32console +""" + +import c + + +import t +from stdint import * +from w32.win32base import * + +ENABLE_PROCESSED_INPUT: t.CDefine = 0x0001 +ENABLE_LINE_INPUT: t.CDefine = 0x0002 +ENABLE_ECHO_INPUT: t.CDefine = 0x0004 +ENABLE_WINDOW_INPUT: t.CDefine = 0x0008 +ENABLE_MOUSE_INPUT: t.CDefine = 0x0010 +ENABLE_INSERT_MODE: t.CDefine = 0x0020 +ENABLE_QUICK_EDIT_MODE: t.CDefine = 0x0040 +ENABLE_EXTENDED_FLAGS: t.CDefine = 0x0080 +ENABLE_PROCESSED_OUTPUT: t.CDefine = 0x0001 +ENABLE_WRAP_AT_EOL_OUTPUT: t.CDefine = 0x0002 +ENABLE_VIRTUAL_TERMINAL_PROCESSING: t.CDefine = 0x0004 +DISABLE_NEWLINE_AUTO_RETURN: t.CDefine = 0x0008 +ENABLE_LVB_GRID_WORLDWIDE: t.CDefine = 0x0010 +FOREGROUND_BLUE: t.CDefine = 0x0001 +FOREGROUND_GREEN: t.CDefine = 0x0002 +FOREGROUND_RED: t.CDefine = 0x0004 +FOREGROUND_INTENSITY: t.CDefine = 0x0008 +BACKGROUND_BLUE: t.CDefine = 0x0010 +BACKGROUND_GREEN: t.CDefine = 0x0020 +BACKGROUND_RED: t.CDefine = 0x0040 +BACKGROUND_INTENSITY: t.CDefine = 0x0080 +KEY_EVENT: t.CDefine = 0x0001 +MOUSE_EVENT: t.CDefine = 0x0002 +WINDOW_BUFFER_SIZE_EVENT: t.CDefine = 0x0004 +MENU_EVENT: t.CDefine = 0x0008 +FOCUS_EVENT: t.CDefine = 0x0010 + +class COORD: + X: SHORT + Y: SHORT +class SMALL_RECT: + Left: SHORT + Top: SHORT + Right: SHORT + Bottom: SHORT +class CONSOLE_SCREEN_BUFFER_INFO: + dwSize: COORD + dwCursorPosition: COORD + wAttributes: WORD + srWindow: SMALL_RECT + dwMaximumWindowSize: COORD +class CONSOLE_CURSOR_INFO: + dwSize: ULONG + bVisible: BOOL +class CHAR_INFO: + UnicodeChar: WCHAR + Attributes: WORD +class KEY_EVENT_RECORD: + bKeyDown: BOOL + wRepeatCount: WORD + wVirtualKeyCode: WORD + wVirtualScanCode: WORD + uChar: WCHAR + dwControlKeyState: ULONG +class MOUSE_EVENT_RECORD: + dwMousePosition: COORD + dwButtonState: ULONG + dwControlKeyState: ULONG + dwEventFlags: ULONG +class WINDOW_BUFFER_SIZE_RECORD: + dwSize: COORD +class INPUT_RECORD: + EventType: WORD + Event: KEY_EVENT_RECORD + +def SetConsoleOutputCP(codepage: UINT) -> BOOL | t.State: pass + +def SetConsoleCP(codepage: UINT) -> BOOL | t.State: pass + +def GetConsoleCP() -> UINT | t.State: pass + +def GetConsoleOutputCP() -> UINT | t.State: pass + +def GetConsoleScreenBufferInfo(hConsoleOutput: HANDLE, lpConsoleScreenBufferInfo: CONSOLE_SCREEN_BUFFER_INFO | t.CPtr) -> BOOL | t.State: pass + +def SetConsoleScreenBufferSize(hConsoleOutput: HANDLE, dwSize: COORD) -> BOOL | t.State: pass + +def SetConsoleCursorPosition(hConsoleOutput: HANDLE, dwCursorPosition: COORD) -> BOOL | t.State: pass + +def GetConsoleCursorInfo(hConsoleOutput: HANDLE, lpConsoleCursorInfo: CONSOLE_CURSOR_INFO | t.CPtr) -> BOOL | t.State: pass + +def SetConsoleCursorInfo(hConsoleOutput: HANDLE, lpConsoleCursorInfo: CONSOLE_CURSOR_INFO | t.CPtr) -> BOOL | t.State: pass + +def SetConsoleTextAttribute(hConsoleOutput: HANDLE, wAttributes: WORD) -> BOOL | t.State: pass + +def FillConsoleOutputCharacterA(hConsoleOutput: HANDLE, cCharacter: t.CChar, nLength: ULONG, dwWriteCoord: COORD, lpNumberOfCharsWritten: ULONG | t.CPtr) -> BOOL | t.State: pass + +def FillConsoleOutputCharacterW(hConsoleOutput: HANDLE, cCharacter: WCHAR, nLength: ULONG, dwWriteCoord: COORD, lpNumberOfCharsWritten: ULONG | t.CPtr) -> BOOL | t.State: pass + +def FillConsoleOutputAttribute(hConsoleOutput: HANDLE, wAttribute: WORD, nLength: ULONG, dwWriteCoord: COORD, lpNumberOfAttrsWritten: ULONG | t.CPtr) -> BOOL | t.State: pass + +def WriteConsoleA(hConsoleOutput: HANDLE, lpBuffer: t.CConst | VOIDPTR, nNumberOfCharsToWrite: ULONG, lpNumberOfCharsWritten: ULONG | t.CPtr, lpReserved: VOIDPTR) -> BOOL | t.State: pass + +def WriteConsoleW(hConsoleOutput: HANDLE, lpBuffer: t.CConst | VOIDPTR, nNumberOfCharsToWrite: ULONG, lpNumberOfCharsWritten: ULONG | t.CPtr, lpReserved: VOIDPTR) -> BOOL | t.State: pass + +def ReadConsoleA(hConsoleInput: HANDLE, lpBuffer: VOIDPTR, nNumberOfCharsToRead: ULONG, lpNumberOfCharsRead: ULONG | t.CPtr, pInputControl: VOIDPTR) -> BOOL | t.State: pass + +def ReadConsoleW(hConsoleInput: HANDLE, lpBuffer: VOIDPTR, nNumberOfCharsToRead: ULONG, lpNumberOfCharsRead: ULONG | t.CPtr, pInputControl: VOIDPTR) -> BOOL | t.State: pass + +def GetConsoleMode(hConsoleHandle: HANDLE, lpMode: ULONG | t.CPtr) -> BOOL | t.State: pass + +def SetConsoleMode(hConsoleHandle: HANDLE, dwMode: ULONG) -> BOOL | t.State: pass + +def ReadConsoleInputA(hConsoleInput: HANDLE, lpBuffer: INPUT_RECORD | t.CPtr, nLength: ULONG, lpNumberOfEventsRead: ULONG | t.CPtr) -> BOOL | t.State: pass + +def ReadConsoleInputW(hConsoleInput: HANDLE, lpBuffer: INPUT_RECORD | t.CPtr, nLength: ULONG, lpNumberOfEventsRead: ULONG | t.CPtr) -> BOOL | t.State: pass + +def GetNumberOfConsoleInputEvents(hConsoleInput: HANDLE, lpNumberOfEvents: ULONG | t.CPtr) -> BOOL | t.State: pass + +def FlushConsoleInputBuffer(hConsoleInput: HANDLE) -> BOOL | t.State: pass + +def SetConsoleTitleA(lpConsoleTitle: LPCSTR) -> BOOL | t.State: pass + +def SetConsoleTitleW(lpConsoleTitle: LPCWSTR) -> BOOL | t.State: pass + +def GetConsoleTitleA(lpConsoleTitle: CHARPTR, nSize: ULONG) -> ULONG | t.State: pass + +def GetConsoleTitleW(lpConsoleTitle: WCHARPTR, nSize: ULONG) -> ULONG | t.State: pass + +def AllocConsole() -> BOOL | t.State: pass + +def FreeConsole() -> BOOL | t.State: pass + +def SetConsoleWindowInfo(hConsoleOutput: HANDLE, bAbsolute: BOOL, lpConsoleWindow: SMALL_RECT | t.CPtr) -> BOOL | t.State: pass + +def ScrollConsoleScreenBufferA(hConsoleOutput: HANDLE, lpScrollRectangle: SMALL_RECT | t.CPtr, lpClipRectangle: SMALL_RECT | t.CPtr, dwDestinationOrigin: COORD, lpFill: CHAR_INFO | t.CPtr) -> BOOL | t.State: pass diff --git a/Test/FakeDuckTest/temp/c6206460c42ccf10.pyi b/Test/FakeDuckTest/temp/c6206460c42ccf10.pyi new file mode 100644 index 0000000..e4738ab --- /dev/null +++ b/Test/FakeDuckTest/temp/c6206460c42ccf10.pyi @@ -0,0 +1,35 @@ +""" +Auto-generated Python stub file from _fakeduck.py +Module: _fakeduck +""" + +import c + + +import t +import mbuddy +import string + +class _Type: + def type_id(self: _Type) -> int: pass +class _str: + __requires__: list[str] = ['__mbuddy__'] + __data__: str + __mbuddy__: mbuddy.MBuddy | t.CPtr + def b(self: _str) -> int: pass + def SELF(self: _str) -> str: pass + def upper(self: _str) -> str: pass + def lower(self: _str) -> str: pass + def capitalize(self: _str) -> str: pass + def swapcase(self: _str) -> str: pass + def title(self: _str) -> str: pass + def casefold(self: _str) -> str: pass + def isupper(self: _str) -> bool: pass + def islower(self: _str) -> bool: pass + def isalpha(self: _str) -> bool: pass + def isdigit(self: _str) -> bool: pass + def isalnum(self: _str) -> bool: pass + def isspace(self: _str) -> bool: pass + def isascii(self: _str) -> bool: pass + def istitle(self: _str) -> bool: pass + def split(self: _str, delimiter: str) -> list[str]: pass \ No newline at end of file diff --git a/Test/FakeDuckTest/temp/ccd58bf663340b12.pyi b/Test/FakeDuckTest/temp/ccd58bf663340b12.pyi new file mode 100644 index 0000000..9914254 --- /dev/null +++ b/Test/FakeDuckTest/temp/ccd58bf663340b12.pyi @@ -0,0 +1,19 @@ +""" +Auto-generated Python stub file from main.py +Module: main +""" + + +from stdint import * +import w32.win32console +import t, c +from t import CInt, CExport +import _fakeduck +import stdio +import stdlib +import string +import mbuddy +import testcheck +import _withcontent + +def main() -> CInt | CExport: pass diff --git a/Test/FakeDuckTest/temp/fa3691e66b426950.pyi b/Test/FakeDuckTest/temp/fa3691e66b426950.pyi new file mode 100644 index 0000000..48fd36c --- /dev/null +++ b/Test/FakeDuckTest/temp/fa3691e66b426950.pyi @@ -0,0 +1,80 @@ +""" +Auto-generated Python stub file from w32.fileio.py +Module: w32.fileio +""" + + +import t, c +from stdint import * +import w32.win32base +import w32.win32file + +class MODE(t.CEnum): + R = 0 + W = 1 + A = 2 + RP = 3 + WP = 4 + AP = 5 + X = 6 + XP = 7 +class FRESULT(t.CEnum): + OK = 0 + ERR = -1 + ERR_CLOSED = -2 + ERR_PERM = -3 + ERR_IO = -4 + ERR_NOTFOUND = -5 + +SEEK_SET: t.CDefine = 0 +SEEK_CUR: t.CDefine = 1 +SEEK_END: t.CDefine = 2 +INVALID_SET_FILE_POINTER: t.CDefine = -1 +SHARE_READ: t.CDefine = 0x00000001 +SHARE_WRITE: t.CDefine = 0x00000002 +SHARE_DELETE: t.CDefine = 0x00000004 + +class File: + handle: w32.win32base.HANDLE + closed: bool + can_read: bool + can_write: bool + is_append: bool + _share_mode: ULONG + def __init__(self: File, filename: str, mode: ULONG, share: ULONG) -> t.CInt: pass + def __enter__(self: File) -> 'File' | t.CPtr: pass + def __exit__(self: File) -> t.CInt: pass + def read(self: File, buf: bytes, count: ULONG) -> LONG: pass + def write(self: File, buf: bytes, count: ULONG) -> LONG: pass + def write_str(self: File, s: str) -> LONG: pass + def seek(self: File, offset: LONG, origin: ULONG) -> LONG: pass + def tell(self: File) -> LONG: pass + def close(self: File) -> LONG: pass + def flush(self: File) -> LONG: pass + def size(self: File) -> LONGLONG: pass + def readline(self: File, buf: bytes, max_count: ULONG) -> LONG: pass + def read_all(self: File, buf: bytes, max_count: ULONG) -> LONG: pass +class FileW: + handle: HANDLE + closed: bool + can_read: bool + can_write: bool + is_append: bool + _share_mode: ULONG + def __init__(self: FileW, filename: LPCWSTR, mode: ULONG, share: ULONG) -> t.CInt: pass + def __enter__(self: FileW) -> 'FileW' | t.CPtr: pass + def __exit__(self: FileW) -> t.CInt: pass + def read(self: FileW, buf: bytes, count: ULONG) -> LONG: pass + def write(self: FileW, buf: bytes, count: ULONG) -> LONG: pass + def write_str(self: FileW, s: str) -> LONG: pass + def seek(self: FileW, offset: LONG, origin: ULONG) -> LONG: pass + def tell(self: FileW) -> LONG: pass + def close(self: FileW) -> LONG: pass + def flush(self: FileW) -> LONG: pass + def size(self: FileW) -> LONGLONG: pass + def readline(self: FileW, buf: bytes, max_count: ULONG) -> LONG: pass + def read_all(self: FileW, buf: bytes, max_count: ULONG) -> LONG: pass + +def open(filename: str, mode: ULONG, share: ULONG) -> File | t.CPtr: pass + +def openw(filename: LPCWSTR, mode: ULONG, share: ULONG) -> FileW | t.CPtr: pass diff --git a/Test/ForAndLoopTest/App/main.py b/Test/ForAndLoopTest/App/main.py new file mode 100644 index 0000000..9398afd --- /dev/null +++ b/Test/ForAndLoopTest/App/main.py @@ -0,0 +1,159 @@ +import t +import c +import stdio +import stdlib +import string +import mbuddy +import testcheck +import _fakeduck + + +def test_for_in_range(): + testcheck.section("Test 1: for i in range(n)") + s: t.CInt = 0 + for i in range(10): + s += i + testcheck.check(s == 45, "range sum OK (45)", "range sum FAILED expect 45") + + +def test_for_in_str(): + testcheck.section("Test 2: for ch in str") + cnt: t.CInt = 0 + for ch in "hello": + cnt += 1 + testcheck.check(cnt == 5, "str iter OK (5)", "str iter FAILED expect 5") + + +def test_for_in_list(): + testcheck.section("Test 3: for v in list[str]") + arena: bytes = stdlib.malloc(65536) + bd: mbuddy.MBuddy | t.CPtr = mbuddy.MBuddy(arena, 65536) + src: str = "x,y,z,w" + src.__mbuddy__ = bd + lst: list[str] = src.split(',') + total: t.CInt = 0 + for v in lst: + total += 1 + testcheck.check(total == 4, "list iter OK (4)", "list iter FAILED expect 4") + stdlib.free(arena) + + +def test_zip_list_list(): + testcheck.section("Test 4: zip(list, list)") + arena: bytes = stdlib.malloc(65536) + bd: mbuddy.MBuddy | t.CPtr = mbuddy.MBuddy(arena, 65536) + a: str = "a,b,c" + a.__mbuddy__ = bd + b: str = "1,2,3" + b.__mbuddy__ = bd + la: list[str] = a.split(',') + lb: list[str] = b.split(',') + cnt: t.CInt = 0 + for ca, cb in zip(la, lb): + stdio.printf("zip[%d]: '%s'='%s'\n", cnt, ca, cb) + cnt += 1 + testcheck.check(cnt == 3, "zip list+list OK (3)", "zip list+list FAILED") + stdlib.free(arena) + + +def test_zip_range_list(): + testcheck.section("Test 5: zip(range, list)") + arena: bytes = stdlib.malloc(65536) + bd: mbuddy.MBuddy | t.CPtr = mbuddy.MBuddy(arena, 65536) + s: str = "p,q,r" + s.__mbuddy__ = bd + lst: list[str] = s.split(',') + cnt: t.CInt = 0 + for n, v in zip(range(3), lst): + stdio.printf("zip range+list[%d]: %d='%s'\n", cnt, n, v) + cnt += 1 + testcheck.check(cnt == 3, "zip range+list OK (3)", "zip range+list FAILED") + stdlib.free(arena) + + +def test_zip_str_str(): + testcheck.section("Test 6: zip(str, str)") + sa: str = "abc" + sb: str = "123" + cnt: t.CInt = 0 + for ca, cb in zip(sa, sb): + stdio.printf("zip str+str[%d]: '%c'%c\n", cnt, ca, cb) + cnt += 1 + testcheck.check(cnt == 3, "zip str+str OK (3)", "zip str+str FAILED") + + +def test_zip_range_len_list(): + testcheck.section("Test 7: zip(range(len), list)") + arena: bytes = stdlib.malloc(65536) + bd: mbuddy.MBuddy | t.CPtr = mbuddy.MBuddy(arena, 65536) + s: str = "www.gvsds.com" + s.__mbuddy__ = bd + lst: list[str] = s.split('.') + cnt: t.CInt = 0 + for idx, v in zip(range(len(lst)), lst): + stdio.printf("lst[%d]='%s'\n", idx, v) + cnt += 1 + testcheck.check(cnt == 3, "zip(range(len),list) OK (3)", "zip(range(len),list) FAILED") + stdlib.free(arena) + + +def test_enumerate_list(): + testcheck.section("Test 8: enumerate(list)") + arena: bytes = stdlib.malloc(65536) + bd: mbuddy.MBuddy | t.CPtr = mbuddy.MBuddy(arena, 65536) + s: str = "alpha,beta,gamma" + s.__mbuddy__ = bd + lst: list[str] = s.split(',') + cnt: t.CInt = 0 + last_idx: t.CInt = -1 + for idx, v in enumerate(lst): + stdio.printf("enum[%d]='%s'\n", idx, v) + last_idx = idx + cnt += 1 + testcheck.check(cnt == 3, "enumerate list OK (3)", "enumerate list FAILED") + testcheck.check(last_idx == 2, "enumerate last_idx OK (2)", "enumerate last_idx FAILED expect 2") + stdlib.free(arena) + + +def test_enumerate_str(): + testcheck.section("Test 9: enumerate(str)") + cnt: t.CInt = 0 + last_idx: t.CInt = -1 + for idx, ch in enumerate("ABCD"): + stdio.printf("enum str[%d]='%c'\n", idx, ch) + last_idx = idx + cnt += 1 + testcheck.check(cnt == 4, "enumerate str OK (4)", "enumerate str FAILED expect 4") + testcheck.check(last_idx == 3, "enumerate str last_idx OK (3)", "enumerate str last_idx FAILED expect 3") + + +def test_enumerate_range(): + testcheck.section("Test 10: enumerate(range)") + cnt: t.CInt = 0 + last_idx: t.CInt = -1 + last_val: t.CInt = -1 + for idx, v in enumerate(range(5)): + stdio.printf("enum range[%d]=%d\n", idx, v) + last_idx = idx + last_val = v + cnt += 1 + testcheck.check(cnt == 5, "enumerate range OK (5)", "enumerate range FAILED expect 5") + testcheck.check(last_idx == 4, "enumerate range last_idx OK (4)", "enumerate range last_idx FAILED expect 4") + testcheck.check(last_val == 4, "enumerate range last_val OK (4)", "enumerate range last_val FAILED expect 4") + + +def main() -> t.CInt: + testcheck.begin("ForAndLoopTest: 迭代器与循环测试") + + test_for_in_range() + test_for_in_str() + test_for_in_list() + test_zip_list_list() + test_zip_range_list() + test_zip_str_str() + test_zip_range_len_list() + test_enumerate_list() + test_enumerate_str() + test_enumerate_range() + + return testcheck.end() diff --git a/Test/ForAndLoopTest/output/0eaa586c42dcd931.deps.json b/Test/ForAndLoopTest/output/0eaa586c42dcd931.deps.json new file mode 100644 index 0000000..7ef4a41 --- /dev/null +++ b/Test/ForAndLoopTest/output/0eaa586c42dcd931.deps.json @@ -0,0 +1 @@ +{"mbuddy": "0eaa586c42dcd931", "atom": "271ea3decb810db2", "main": "2e079471575f937d", "stdint": "49bd8cba55979f76", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "_fakeduck": "9163064cf3eb88f4", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd"} \ No newline at end of file diff --git a/Test/ForAndLoopTest/output/271ea3decb810db2.deps.json b/Test/ForAndLoopTest/output/271ea3decb810db2.deps.json new file mode 100644 index 0000000..7ef4a41 --- /dev/null +++ b/Test/ForAndLoopTest/output/271ea3decb810db2.deps.json @@ -0,0 +1 @@ +{"mbuddy": "0eaa586c42dcd931", "atom": "271ea3decb810db2", "main": "2e079471575f937d", "stdint": "49bd8cba55979f76", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "_fakeduck": "9163064cf3eb88f4", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd"} \ No newline at end of file diff --git a/Test/ForAndLoopTest/output/2e079471575f937d.deps.json b/Test/ForAndLoopTest/output/2e079471575f937d.deps.json new file mode 100644 index 0000000..46e6457 --- /dev/null +++ b/Test/ForAndLoopTest/output/2e079471575f937d.deps.json @@ -0,0 +1 @@ +{"mbuddy": "0eaa586c42dcd931", "atom": "271ea3decb810db2", "stdint": "49bd8cba55979f76", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "_fakeduck": "9163064cf3eb88f4", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd"} \ No newline at end of file diff --git a/Test/ForAndLoopTest/output/9163064cf3eb88f4.deps.json b/Test/ForAndLoopTest/output/9163064cf3eb88f4.deps.json new file mode 100644 index 0000000..7ef4a41 --- /dev/null +++ b/Test/ForAndLoopTest/output/9163064cf3eb88f4.deps.json @@ -0,0 +1 @@ +{"mbuddy": "0eaa586c42dcd931", "atom": "271ea3decb810db2", "main": "2e079471575f937d", "stdint": "49bd8cba55979f76", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "_fakeduck": "9163064cf3eb88f4", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd"} \ No newline at end of file diff --git a/Test/ForAndLoopTest/output/9dbecd0942a39782.deps.json b/Test/ForAndLoopTest/output/9dbecd0942a39782.deps.json new file mode 100644 index 0000000..7ef4a41 --- /dev/null +++ b/Test/ForAndLoopTest/output/9dbecd0942a39782.deps.json @@ -0,0 +1 @@ +{"mbuddy": "0eaa586c42dcd931", "atom": "271ea3decb810db2", "main": "2e079471575f937d", "stdint": "49bd8cba55979f76", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "_fakeduck": "9163064cf3eb88f4", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd"} \ No newline at end of file diff --git a/Test/ForAndLoopTest/output/b5f1dc665c52a1bd.deps.json b/Test/ForAndLoopTest/output/b5f1dc665c52a1bd.deps.json new file mode 100644 index 0000000..7ef4a41 --- /dev/null +++ b/Test/ForAndLoopTest/output/b5f1dc665c52a1bd.deps.json @@ -0,0 +1 @@ +{"mbuddy": "0eaa586c42dcd931", "atom": "271ea3decb810db2", "main": "2e079471575f937d", "stdint": "49bd8cba55979f76", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "_fakeduck": "9163064cf3eb88f4", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd"} \ No newline at end of file diff --git a/Test/ForAndLoopTest/project.json b/Test/ForAndLoopTest/project.json new file mode 100644 index 0000000..0a6fdaa --- /dev/null +++ b/Test/ForAndLoopTest/project.json @@ -0,0 +1,29 @@ +{ + "$schema": "https://raw.githubusercontent.com/TermiNexus/TransPyC/main/schemas/project-schema.json", + "name": "ForAndLoopTest", + "version": "1.0.0", + "source_dir": "./App", + "temp_dir": "./temp", + "output_dir": "./output", + "compiler": { + "cmd": "llc", + "flags": ["-filetype=obj", "-relocation-model=pic"] + }, + "linker": { + "cmd": "clang++", + "flags": ["-Wl,--allow-multiple-definition", "-lmsvcrt", "-lucrt", "-lpthread", "-lmingwex", "-lkernel32"], + "output": "ForAndLoopTest.exe" + }, + "includes": [ + "../../includes" + ], + "target": { + "triple": "x86_64-pc-windows-gnu", + "datalayout": "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" + }, + "options": { + "slice_level": 3, + "target": "llvm", + "strict_mode": true + } +} diff --git a/Test/ForAndLoopTest/temp/0eaa586c42dcd931.pyi b/Test/ForAndLoopTest/temp/0eaa586c42dcd931.pyi new file mode 100644 index 0000000..7ce46eb --- /dev/null +++ b/Test/ForAndLoopTest/temp/0eaa586c42dcd931.pyi @@ -0,0 +1,49 @@ +""" +Auto-generated Python stub file from mbuddy.py +Module: mbuddy +""" + + +import t, c +from stdint import * +import string +import atom + +MBUDDY_MIN_BLOCK: t.CDefine = 32 # 最小块大小 (字节),需 >= 16 以容纳链表指针 +MBUDDY_MAX_ORDERS: t.CDefine = 32 # 最大阶数数量 +MBUDDY_HEADER_SIZE: t.CDefine = 8 # 块头大小 (存储阶数) + +def _largest_pow2_le(val: t.CSizeT) -> t.CSizeT: pass + +def _block_size_at_order(order: t.CInt) -> t.CSizeT: pass + + +class MBuddy: + __provides__: list[str] = ['__mbuddy__'] + mem: t.CVoid | t.CPtr + mem_size: t.CSizeT + max_order: t.CInt + free_lists: t.CUInt64T | t.CPtr + lock_val: t.CVolatile | t.CInt + def __init__(self: MBuddy, arena: t.CVoid | t.CPtr, arena_size: t.CSizeT) -> t.CInt: pass + def __enter__(self: MBuddy) -> 'MBuddy' | t.CPtr: pass + def __exit__(self: MBuddy) -> t.CInt: pass + def reset(self: MBuddy) -> t.CInt: pass + def _fl_push(self: MBuddy, order: t.CInt, block: t.CVoid | t.CPtr) -> t.CInt: pass + def _fl_pop(self: MBuddy, order: t.CInt) -> t.CVoid | t.CPtr: pass + def _fl_find_and_remove(self: MBuddy, order: t.CInt, target: t.CVoid | t.CPtr) -> t.CInt: pass + def _buddy_of(self: MBuddy, block: t.CVoid | t.CPtr, order: t.CInt) -> t.CVoid | t.CPtr: pass + def _order_for_size(self: MBuddy, size: t.CSizeT) -> t.CInt: pass + def _split_to_order(self: MBuddy, to_order: t.CInt) -> t.CVoid | t.CPtr: pass + def _coalesce(self: MBuddy, block: t.CVoid | t.CPtr, order: t.CInt) -> t.CInt: pass + def _is_valid_ptr(self: MBuddy, ptr: t.CVoid | t.CPtr) -> t.CInt: pass + def _fl_count(self: MBuddy, order: t.CInt) -> t.CSizeT: pass + def _lock(self: MBuddy) -> t.CInt: pass + def _unlock(self: MBuddy) -> t.CInt: pass + def alloc(self: MBuddy, size: t.CSizeT) -> t.CVoid | t.CPtr: pass + def free(self: MBuddy, ptr: t.CVoid | t.CPtr) -> t.CInt: pass + def calloc(self: MBuddy, count: t.CSizeT, size: t.CSizeT) -> t.CVoid | t.CPtr: pass + def realloc(self: MBuddy, ptr: t.CVoid | t.CPtr, new_size: t.CSizeT) -> t.CVoid | t.CPtr: pass + def stats(self: MBuddy) -> t.CSizeT: pass + def free_count(self: MBuddy) -> t.CSizeT: pass + def self_check(self: MBuddy) -> t.CInt: pass \ No newline at end of file diff --git a/Test/ForAndLoopTest/temp/271ea3decb810db2.pyi b/Test/ForAndLoopTest/temp/271ea3decb810db2.pyi new file mode 100644 index 0000000..3d637bf --- /dev/null +++ b/Test/ForAndLoopTest/temp/271ea3decb810db2.pyi @@ -0,0 +1,26 @@ +""" +Auto-generated Python stub file from atom.py +Module: atom +""" + + +import t, c + +ATOMIC_RELAXED: t.CDefine = 0 +ATOMIC_CONSUME: t.CDefine = 1 +ATOMIC_ACQUIRE: t.CDefine = 2 +ATOMIC_RELEASE: t.CDefine = 3 +ATOMIC_ACQ_REL: t.CDefine = 4 +ATOMIC_SEQ_CST: t.CDefine = 5 + +def __atomic_test_and_set(ptr: t.CUInt64T | t.CPtr, order: t.CInt) -> t.CBool: pass + +def __atomic_clear(ptr: t.CUInt64T | t.CPtr, order: t.CInt) -> t.CVoid: pass + +def __atomic_thread_fence(order: t.CInt) -> t.CVoid: pass + +def __atomic_signal_fence(order: t.CInt) -> t.CVoid: pass + +def __atomic_always_lock_free(size: t.CSizeT, ptr: t.CVoid | t.CPtr) -> t.CBool: pass + +def __atomic_is_lock_free(size: t.CSizeT, ptr: t.CVoid | t.CPtr) -> t.CBool: pass diff --git a/Test/ForAndLoopTest/temp/2e079471575f937d.pyi b/Test/ForAndLoopTest/temp/2e079471575f937d.pyi new file mode 100644 index 0000000..c2061e2 --- /dev/null +++ b/Test/ForAndLoopTest/temp/2e079471575f937d.pyi @@ -0,0 +1,36 @@ +""" +Auto-generated Python stub file from main.py +Module: main +""" + + +import t +import c +import stdio +import stdlib +import string +import mbuddy +import testcheck +import _fakeduck + +def test_for_in_range() -> t.CInt: pass + +def test_for_in_str() -> t.CInt: pass + +def test_for_in_list() -> t.CInt: pass + +def test_zip_list_list() -> t.CInt: pass + +def test_zip_range_list() -> t.CInt: pass + +def test_zip_str_str() -> t.CInt: pass + +def test_zip_range_len_list() -> t.CInt: pass + +def test_enumerate_list() -> t.CInt: pass + +def test_enumerate_str() -> t.CInt: pass + +def test_enumerate_range() -> t.CInt: pass + +def main() -> t.CInt: pass diff --git a/Test/ForAndLoopTest/temp/49bd8cba55979f76.pyi b/Test/ForAndLoopTest/temp/49bd8cba55979f76.pyi new file mode 100644 index 0000000..f1d844a --- /dev/null +++ b/Test/ForAndLoopTest/temp/49bd8cba55979f76.pyi @@ -0,0 +1,75 @@ +""" +Auto-generated Python stub file from stdint.py +Module: stdint +""" + +import c + + +import t + +INT: t.CTypedef = t.CInt +INTPTR: t.CTypedef = t.CInt | t.CPtr +BOOL: t.CTypedef = t.CInt +UINT: t.CTypedef = t.CUnsignedInt +UINTPTR: t.CTypedef = UINT | t.CPtr +BYTE: t.CTypedef = t.CUnsignedChar +BYTEPTR: t.CTypedef = BYTE | t.CPtr +WORD: t.CTypedef = t.CUInt16T +DWORD: t.CTypedef = t.CUInt32T +QWORD: t.CTypedef = t.CUInt64T +TCHAR: t.CTypedef = t.CChar +CHARLIST: t.CTypedef = str | t.CPtr +VOID: t.CTypedef = t.CVoid +SHORT: t.CTypedef = t.CShort +SHORTPTR: t.CTypedef = t.CShort | t.CPtr +USHORT: t.CTypedef = t.CUnsignedShort +USHORTPTR: t.CTypedef = t.CUnsignedShort | t.CPtr +LONGLONG: t.CTypedef = t.CLong | t.CLong +ULONGLONG: t.CTypedef = t.CUnsignedLong | t.CLong +LONG: t.CTypedef = t.CLong +ULONG: t.CTypedef = t.CUnsignedLong +WCHAR: t.CTypedef = WORD +WCHARPTR: t.CTypedef = WORD | t.CPtr +CHARPTR: t.CTypedef = t.CChar | t.CPtr +FSIZE_t: t.CTypedef = DWORD +LBA_t: t.CTypedef = DWORD +UINTPTR: t.CTypedef = t.CUnsignedInt | t.CPtr +VOIDPTR: t.CTypedef = t.CVoid | t.CPtr +FLOAT: t.CTypedef = t.CFloat +DOUBLE: t.CTypedef = t.CDouble +FLOAT8: t.CTypedef = t.CFloat8T +FLOAT16: t.CTypedef = t.CFloat16T +FLOAT32: t.CTypedef = t.CFloat32T +FLOAT64: t.CTypedef = t.CFloat64T +FLOAT128: t.CTypedef = t.CFloat128T +INT8: t.CTypedef = t.CInt8T +INT16: t.CTypedef = t.CInt16T +INT32: t.CTypedef = t.CInt32T +INT64: t.CTypedef = t.CInt64T +UINT8: t.CTypedef = t.CUInt8T +UINT16: t.CTypedef = t.CUInt16T +UINT32: t.CTypedef = t.CUInt32T +UINT64: t.CTypedef = t.CUInt64T +INT8PTR: t.CTypedef = t.CInt8T | t.CPtr +INT16PTR: t.CTypedef = t.CInt16T | t.CPtr +INT32PTR: t.CTypedef = t.CInt32T | t.CPtr +INT64PTR: t.CTypedef = t.CInt64T | t.CPtr +UINT8PTR: t.CTypedef = t.CUInt8T | t.CPtr +UINT16PTR: t.CTypedef = t.CUInt16T | t.CPtr +UINT32PTR: t.CTypedef = t.CUInt32T | t.CPtr +UINT64PTR: t.CTypedef = t.CUInt64T | t.CPtr +CHAR8: t.CTypedef = t.CChar8T +CHAR16: t.CTypedef = t.CChar16T +CHAR32: t.CTypedef = t.CChar32T +CHAR8PTR: t.CTypedef = t.CChar8T | t.CPtr +CHAR16PTR: t.CTypedef = t.CChar16T | t.CPtr +CHAR32PTR: t.CTypedef = t.CChar32T | t.CPtr +i8: t.CTypedef = t.CInt8T +i16: t.CTypedef = t.CInt16T +i32: t.CTypedef = t.CInt32T +i64: t.CTypedef = t.CInt64T +u8: t.CTypedef = t.CUInt8T +u16: t.CTypedef = t.CUInt16T +u32: t.CTypedef = t.CUInt32T +u64: t.CTypedef = t.CUInt64T \ No newline at end of file diff --git a/Test/ForAndLoopTest/temp/6c2029b306556c00.pyi b/Test/ForAndLoopTest/temp/6c2029b306556c00.pyi new file mode 100644 index 0000000..98da680 --- /dev/null +++ b/Test/ForAndLoopTest/temp/6c2029b306556c00.pyi @@ -0,0 +1,18 @@ +""" +Auto-generated Python stub file from stdlib.py +Module: stdlib +""" + +import c + + +from stdint import * +import t + +def malloc(size: t.CSizeT) -> t.CVoid | t.CPtr | t.State | t.CExtern | t.CExport: pass + +def calloc(nmemb: t.CSizeT, size: t.CSizeT) -> t.CVoid | t.CPtr | t.State | t.CExtern | t.CExport: pass + +def realloc(p: t.CVoid | t.CPtr, size: t.CSizeT) -> t.CVoid | t.CPtr | t.State | t.CExtern | t.CExport: pass + +def free(p: t.CVoid | t.CPtr) -> None | t.State | t.CExtern | t.CExport: pass diff --git a/Test/ForAndLoopTest/temp/73edbcf76e32d00b.pyi b/Test/ForAndLoopTest/temp/73edbcf76e32d00b.pyi new file mode 100644 index 0000000..ef712e3 --- /dev/null +++ b/Test/ForAndLoopTest/temp/73edbcf76e32d00b.pyi @@ -0,0 +1,28 @@ +""" +Auto-generated Python stub file from stdio.py +Module: stdio +""" + + +import t, c + +def printf(fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass + +def fprintf(stream: t.CVoid | t.CPtr, fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass + +def sprintf(buf: t.CChar | t.CPtr, fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass + +def snprintf(buf: t.CChar | t.CPtr, size: t.CSizeT, fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass + +def puts(s: t.CChar | t.CConst | t.CPtr) -> t.CInt | t.CExtern | t.CExport: pass + +def fputs(s: t.CChar | t.CConst | t.CPtr, stream: t.CVoid | t.CPtr) -> t.CInt | t.CExtern | t.CExport: pass + +def fgets(buf: t.CChar | t.CPtr, size: t.CInt, stream: t.CVoid | t.CPtr) -> t.CChar | t.CPtr | t.CExtern | t.CExport: pass + +def fflush(stream: t.CVoid | t.CPtr) -> t.CInt | t.CExtern | t.CExport: pass + + +stdin: t.CExtern | t.CVoid | t.CPtr +stdout: t.CExtern | t.CVoid | t.CPtr +stderr: t.CExtern | t.CVoid | t.CPtr \ No newline at end of file diff --git a/Test/ForAndLoopTest/temp/9163064cf3eb88f4.pyi b/Test/ForAndLoopTest/temp/9163064cf3eb88f4.pyi new file mode 100644 index 0000000..22ff1af --- /dev/null +++ b/Test/ForAndLoopTest/temp/9163064cf3eb88f4.pyi @@ -0,0 +1,35 @@ +""" +Auto-generated Python stub file from _fakeduck.py +Module: _fakeduck +""" + +import c + + +import t +import mbuddy +import string + +class _Type: + def type_id(self: _Type) -> int: pass +class _str: + __requires__: list[str] = ['__mbuddy__'] + __data__: str + __mbuddy__: mbuddy.MBuddy | t.CPtr + def b(self: _str) -> int: pass + def SELF(self: _str) -> str: pass + def upper(self: _str) -> str: pass + def lower(self: _str) -> str: pass + def capitalize(self: _str) -> str: pass + def swapcase(self: _str) -> str: pass + def title(self: _str) -> str: pass + def casefold(self: _str) -> str: pass + def isupper(self: _str) -> int: pass + def islower(self: _str) -> int: pass + def isalpha(self: _str) -> int: pass + def isdigit(self: _str) -> int: pass + def isalnum(self: _str) -> int: pass + def isspace(self: _str) -> int: pass + def isascii(self: _str) -> int: pass + def istitle(self: _str) -> int: pass + def split(self: _str, delimiter: str) -> list[str]: pass \ No newline at end of file diff --git a/Test/ForAndLoopTest/temp/9dbecd0942a39782.pyi b/Test/ForAndLoopTest/temp/9dbecd0942a39782.pyi new file mode 100644 index 0000000..41648c1 --- /dev/null +++ b/Test/ForAndLoopTest/temp/9dbecd0942a39782.pyi @@ -0,0 +1,25 @@ +""" +Auto-generated Python stub file from testcheck.py +Module: testcheck +""" + + +import t, c +import stdio + +_pass_count: t.CExtern | t.CInt +_fail_count: t.CExtern | t.CInt + +def begin(name: str) -> t.CInt: pass + +def section(name: str) -> t.CInt: pass + +def ok(msg: str) -> t.CInt: pass + +def fail(msg: str) -> t.CInt: pass + +def check(cond: t.CInt, ok_msg: str, fail_msg: str) -> t.CInt: pass + +def info(msg: str) -> t.CInt: pass + +def end() -> t.CInt: pass diff --git a/Test/ForAndLoopTest/temp/_sha1_map.txt b/Test/ForAndLoopTest/temp/_sha1_map.txt new file mode 100644 index 0000000..5845f26 --- /dev/null +++ b/Test/ForAndLoopTest/temp/_sha1_map.txt @@ -0,0 +1,9 @@ +0eaa586c42dcd931:includes/mbuddy.py +271ea3decb810db2:includes/atom.py +2e079471575f937d:main.py +49bd8cba55979f76:includes/stdint.py +6c2029b306556c00:includes/stdlib.py +73edbcf76e32d00b:includes/stdio.py +9163064cf3eb88f4:includes/_fakeduck.py +9dbecd0942a39782:includes/testcheck.py +b5f1dc665c52a1bd:includes/string.py diff --git a/Test/ForAndLoopTest/temp/b5f1dc665c52a1bd.pyi b/Test/ForAndLoopTest/temp/b5f1dc665c52a1bd.pyi new file mode 100644 index 0000000..8b6959e --- /dev/null +++ b/Test/ForAndLoopTest/temp/b5f1dc665c52a1bd.pyi @@ -0,0 +1,44 @@ +""" +Auto-generated Python stub file from string.py +Module: string +""" + + +from stdint import * +import t, c + +def strcpy(dest: str, src: str) -> str: pass + +def strncpy(dest: str, src: str, n: t.CSizeT) -> str: pass + +def strlen(src: str) -> t.CSizeT | t.CExport: pass + +def strcmp(str1: str, str2: str) -> t.CInt: pass + +def samestr(str1: str, str2: str) -> bool: pass + +def strncmp(str1: str, str2: str, n: t.CSizeT) -> t.CInt: pass + +def memcmp(ptr1: t.CVoid | t.CPtr, ptr2: t.CVoid | t.CPtr, n: t.CSizeT) -> t.CInt: pass + +def strchr(s: str, cr: t.CInt) -> str: pass + +def strrchr(s: str, cr: t.CInt) -> str: pass + +def strspn(s: str, skip: str) -> int: pass + +def memset(ptr: t.CVoid | t.CPtr, value: t.CInt, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass + +def memset32(ptr: t.CVoid | t.CPtr, value: t.CUInt32T, count: t.CSizeT) -> t.CVoid | t.CPtr: pass + +def memcpy(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass + +def memmove(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr: pass + +def atoi(src: str) -> t.CInt: pass + +def atoll(src: str) -> t.CInt64T: pass + +def atof(src: str) -> t.CDouble: pass + +def split(s: str, delim: str, result: t.CArray[str]) -> int: pass diff --git a/Test/FormatStringTest/App/main.py b/Test/FormatStringTest/App/main.py new file mode 100644 index 0000000..0af881a --- /dev/null +++ b/Test/FormatStringTest/App/main.py @@ -0,0 +1,52 @@ +from stdint import * +import t, c +import ctraits +import stdio +import testcheck + + +# ============================================================ +# FormatStringTest - 格式化字符串回归测试 +# ============================================================ +@t.CExport +def main() -> int: + testcheck.begin("FormatStringTest: Format String Regression") + + b: str = "hello world" + for i in b: + stdio.printf("%c\n", i) + b += 1 + print(b-11) + + l: t.CArray[u64] = [0, 43, 2, 3, 4] + l[0] = 1000 + for i in l: + stdio.printf("%llu\n", i) + + print("Value: ", f"0x{ULONGLONG(0x11)}") + print("ULL Hex: ", f"0x{ULONGLONG(0x11):016X}") + print("LL Hex: ", f"{LONGLONG(0x11):016X}") + print("ULL Dec: ", f"{ULONGLONG(42):d}") + print("LL Dec: ", f"{LONGLONG(42):d}") + print("Hex: ", f"{0x11:016X}") + print("Dec: ", f"{42:d}") + print("Float: ", f"{3.14159:.2f}") + + # f-string 赋值测试(验证不再直接 printf,而是生成字符串) + s: str = f"Value=0x{ULONGLONG(42)}, Hex=0x{ULONGLONG(0x11):016X}" + print("Assigned: ", s) + + # ctraits.isptr 编译时类型判断测试 + ptr_var: INTPTR = c.Addr(s) + val_var: int = 42 + if c.CIf(ctraits.isptr(ptr_var)): + print("ptr_var is pointer") + if c.CIf(not ctraits.isptr(val_var)): + print("val_var is not pointer") + + testcheck.section("placeholder") + testcheck.ok("testcheck framework ready") + testcheck.info("placeholder test") + + return testcheck.end() + diff --git a/Test/FormatStringTest/output/9dbecd0942a39782.deps.json b/Test/FormatStringTest/output/9dbecd0942a39782.deps.json new file mode 100644 index 0000000..5e6d0a7 --- /dev/null +++ b/Test/FormatStringTest/output/9dbecd0942a39782.deps.json @@ -0,0 +1 @@ +{"ctraits": "42ced27d9e76aef5", "stdint": "49bd8cba55979f76", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "main": "cdff0d7b58fc935b"} \ No newline at end of file diff --git a/Test/FormatStringTest/output/cdff0d7b58fc935b.deps.json b/Test/FormatStringTest/output/cdff0d7b58fc935b.deps.json new file mode 100644 index 0000000..9fc824c --- /dev/null +++ b/Test/FormatStringTest/output/cdff0d7b58fc935b.deps.json @@ -0,0 +1 @@ +{"ctraits": "42ced27d9e76aef5", "stdint": "49bd8cba55979f76", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782"} \ No newline at end of file diff --git a/Test/FormatStringTest/project.json b/Test/FormatStringTest/project.json new file mode 100644 index 0000000..b5be263 --- /dev/null +++ b/Test/FormatStringTest/project.json @@ -0,0 +1,29 @@ +{ + "$schema": "https://raw.githubusercontent.com/TermiNexus/TransPyC/main/schemas/project-schema.json", + "name": "FormatStringTest", + "version": "1.0.0", + "source_dir": "./App", + "temp_dir": "./temp", + "output_dir": "./output", + "compiler": { + "cmd": "llc", + "flags": ["-filetype=obj", "-relocation-model=pic"] + }, + "linker": { + "cmd": "clang++", + "flags": ["-lmsvcrt", "-lucrt", "-lpthread", "-lmingwex", "-lkernel32", "-Wl,--allow-multiple-definition"], + "output": "FormatStringTest.exe" + }, + "includes": [ + "../../includes" + ], + "target": { + "triple": "x86_64-pc-windows-gnu", + "datalayout": "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" + }, + "options": { + "slice_level": 3, + "target": "llvm", + "strict_mode": true + } +} diff --git a/Test/FormatStringTest/temp/42ced27d9e76aef5.pyi b/Test/FormatStringTest/temp/42ced27d9e76aef5.pyi new file mode 100644 index 0000000..f1d44b9 --- /dev/null +++ b/Test/FormatStringTest/temp/42ced27d9e76aef5.pyi @@ -0,0 +1,11 @@ +""" +Auto-generated Python stub file from ctraits.py +Module: ctraits +""" + +import c + + +import t + +def isptr(x: t.CType) -> bool: pass diff --git a/Test/FormatStringTest/temp/49bd8cba55979f76.pyi b/Test/FormatStringTest/temp/49bd8cba55979f76.pyi new file mode 100644 index 0000000..f1d844a --- /dev/null +++ b/Test/FormatStringTest/temp/49bd8cba55979f76.pyi @@ -0,0 +1,75 @@ +""" +Auto-generated Python stub file from stdint.py +Module: stdint +""" + +import c + + +import t + +INT: t.CTypedef = t.CInt +INTPTR: t.CTypedef = t.CInt | t.CPtr +BOOL: t.CTypedef = t.CInt +UINT: t.CTypedef = t.CUnsignedInt +UINTPTR: t.CTypedef = UINT | t.CPtr +BYTE: t.CTypedef = t.CUnsignedChar +BYTEPTR: t.CTypedef = BYTE | t.CPtr +WORD: t.CTypedef = t.CUInt16T +DWORD: t.CTypedef = t.CUInt32T +QWORD: t.CTypedef = t.CUInt64T +TCHAR: t.CTypedef = t.CChar +CHARLIST: t.CTypedef = str | t.CPtr +VOID: t.CTypedef = t.CVoid +SHORT: t.CTypedef = t.CShort +SHORTPTR: t.CTypedef = t.CShort | t.CPtr +USHORT: t.CTypedef = t.CUnsignedShort +USHORTPTR: t.CTypedef = t.CUnsignedShort | t.CPtr +LONGLONG: t.CTypedef = t.CLong | t.CLong +ULONGLONG: t.CTypedef = t.CUnsignedLong | t.CLong +LONG: t.CTypedef = t.CLong +ULONG: t.CTypedef = t.CUnsignedLong +WCHAR: t.CTypedef = WORD +WCHARPTR: t.CTypedef = WORD | t.CPtr +CHARPTR: t.CTypedef = t.CChar | t.CPtr +FSIZE_t: t.CTypedef = DWORD +LBA_t: t.CTypedef = DWORD +UINTPTR: t.CTypedef = t.CUnsignedInt | t.CPtr +VOIDPTR: t.CTypedef = t.CVoid | t.CPtr +FLOAT: t.CTypedef = t.CFloat +DOUBLE: t.CTypedef = t.CDouble +FLOAT8: t.CTypedef = t.CFloat8T +FLOAT16: t.CTypedef = t.CFloat16T +FLOAT32: t.CTypedef = t.CFloat32T +FLOAT64: t.CTypedef = t.CFloat64T +FLOAT128: t.CTypedef = t.CFloat128T +INT8: t.CTypedef = t.CInt8T +INT16: t.CTypedef = t.CInt16T +INT32: t.CTypedef = t.CInt32T +INT64: t.CTypedef = t.CInt64T +UINT8: t.CTypedef = t.CUInt8T +UINT16: t.CTypedef = t.CUInt16T +UINT32: t.CTypedef = t.CUInt32T +UINT64: t.CTypedef = t.CUInt64T +INT8PTR: t.CTypedef = t.CInt8T | t.CPtr +INT16PTR: t.CTypedef = t.CInt16T | t.CPtr +INT32PTR: t.CTypedef = t.CInt32T | t.CPtr +INT64PTR: t.CTypedef = t.CInt64T | t.CPtr +UINT8PTR: t.CTypedef = t.CUInt8T | t.CPtr +UINT16PTR: t.CTypedef = t.CUInt16T | t.CPtr +UINT32PTR: t.CTypedef = t.CUInt32T | t.CPtr +UINT64PTR: t.CTypedef = t.CUInt64T | t.CPtr +CHAR8: t.CTypedef = t.CChar8T +CHAR16: t.CTypedef = t.CChar16T +CHAR32: t.CTypedef = t.CChar32T +CHAR8PTR: t.CTypedef = t.CChar8T | t.CPtr +CHAR16PTR: t.CTypedef = t.CChar16T | t.CPtr +CHAR32PTR: t.CTypedef = t.CChar32T | t.CPtr +i8: t.CTypedef = t.CInt8T +i16: t.CTypedef = t.CInt16T +i32: t.CTypedef = t.CInt32T +i64: t.CTypedef = t.CInt64T +u8: t.CTypedef = t.CUInt8T +u16: t.CTypedef = t.CUInt16T +u32: t.CTypedef = t.CUInt32T +u64: t.CTypedef = t.CUInt64T \ No newline at end of file diff --git a/Test/FormatStringTest/temp/73edbcf76e32d00b.pyi b/Test/FormatStringTest/temp/73edbcf76e32d00b.pyi new file mode 100644 index 0000000..ef712e3 --- /dev/null +++ b/Test/FormatStringTest/temp/73edbcf76e32d00b.pyi @@ -0,0 +1,28 @@ +""" +Auto-generated Python stub file from stdio.py +Module: stdio +""" + + +import t, c + +def printf(fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass + +def fprintf(stream: t.CVoid | t.CPtr, fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass + +def sprintf(buf: t.CChar | t.CPtr, fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass + +def snprintf(buf: t.CChar | t.CPtr, size: t.CSizeT, fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass + +def puts(s: t.CChar | t.CConst | t.CPtr) -> t.CInt | t.CExtern | t.CExport: pass + +def fputs(s: t.CChar | t.CConst | t.CPtr, stream: t.CVoid | t.CPtr) -> t.CInt | t.CExtern | t.CExport: pass + +def fgets(buf: t.CChar | t.CPtr, size: t.CInt, stream: t.CVoid | t.CPtr) -> t.CChar | t.CPtr | t.CExtern | t.CExport: pass + +def fflush(stream: t.CVoid | t.CPtr) -> t.CInt | t.CExtern | t.CExport: pass + + +stdin: t.CExtern | t.CVoid | t.CPtr +stdout: t.CExtern | t.CVoid | t.CPtr +stderr: t.CExtern | t.CVoid | t.CPtr \ No newline at end of file diff --git a/Test/FormatStringTest/temp/9dbecd0942a39782.pyi b/Test/FormatStringTest/temp/9dbecd0942a39782.pyi new file mode 100644 index 0000000..41648c1 --- /dev/null +++ b/Test/FormatStringTest/temp/9dbecd0942a39782.pyi @@ -0,0 +1,25 @@ +""" +Auto-generated Python stub file from testcheck.py +Module: testcheck +""" + + +import t, c +import stdio + +_pass_count: t.CExtern | t.CInt +_fail_count: t.CExtern | t.CInt + +def begin(name: str) -> t.CInt: pass + +def section(name: str) -> t.CInt: pass + +def ok(msg: str) -> t.CInt: pass + +def fail(msg: str) -> t.CInt: pass + +def check(cond: t.CInt, ok_msg: str, fail_msg: str) -> t.CInt: pass + +def info(msg: str) -> t.CInt: pass + +def end() -> t.CInt: pass diff --git a/Test/FormatStringTest/temp/_sha1_map.txt b/Test/FormatStringTest/temp/_sha1_map.txt new file mode 100644 index 0000000..cf58689 --- /dev/null +++ b/Test/FormatStringTest/temp/_sha1_map.txt @@ -0,0 +1,5 @@ +42ced27d9e76aef5:includes/ctraits.pyi +49bd8cba55979f76:includes/stdint.py +73edbcf76e32d00b:includes/stdio.py +9dbecd0942a39782:includes/testcheck.py +cdff0d7b58fc935b:main.py diff --git a/Test/FormatStringTest/temp/cdff0d7b58fc935b.pyi b/Test/FormatStringTest/temp/cdff0d7b58fc935b.pyi new file mode 100644 index 0000000..0fb8976 --- /dev/null +++ b/Test/FormatStringTest/temp/cdff0d7b58fc935b.pyi @@ -0,0 +1,14 @@ +""" +Auto-generated Python stub file from main.py +Module: main +""" + + +from stdint import * +import t, c +import ctraits +import stdio +import testcheck + +@t.CExport +def main() -> int: pass diff --git a/Test/FuncTest/App/main.py b/Test/FuncTest/App/main.py index 62be0fa..77a7372 100644 --- a/Test/FuncTest/App/main.py +++ b/Test/FuncTest/App/main.py @@ -1,5 +1,6 @@ import t import stdio +import testcheck # 测试基本函数调用 def add(a: t.CInt, b: t.CInt) -> t.CInt: @@ -39,85 +40,61 @@ def is_even(n: t.CInt) -> t.CBool: return n % 2 == 0 def test_basic_call(): - stdio.printf("--- Test 1: basic function call ---\n") + testcheck.section("Test 1: basic function call") r: t.CInt = add(10, 20) - if r == 30: - stdio.printf("PASS: add(10,20)=%d\n", r) - else: - stdio.printf("FAIL: add(10,20)=%d, expect 30\n", r) + testcheck.check(r == 30, "add(10,20)=30", "add(10,20) expect 30") def test_multi_args(): - stdio.printf("--- Test 2: multi args ---\n") + testcheck.section("Test 2: multi args") r: t.CInt = multi_args(1, 2, 3, 4) - if r == 10: - stdio.printf("PASS: multi_args(1,2,3,4)=%d\n", r) - else: - stdio.printf("FAIL: multi_args(1,2,3,4)=%d, expect 10\n", r) + testcheck.check(r == 10, "multi_args(1,2,3,4)=10", "multi_args(1,2,3,4) expect 10") def test_recursion(): - stdio.printf("--- Test 3: recursion (factorial) ---\n") + testcheck.section("Test 3: recursion (factorial)") r: t.CInt = factorial(10) # 10! = 3628800 - if r == 3628800: - stdio.printf("PASS: factorial(10)=%d\n", r) - else: - stdio.printf("FAIL: factorial(10)=%d, expect 3628800\n", r) + testcheck.check(r == 3628800, "factorial(10)=3628800", "factorial(10) expect 3628800") def test_fibonacci(): - stdio.printf("--- Test 4: fibonacci ---\n") + testcheck.section("Test 4: fibonacci") r: t.CInt = fib(10) # fib(10) = 55 - if r == 55: - stdio.printf("PASS: fib(10)=%d\n", r) - else: - stdio.printf("FAIL: fib(10)=%d, expect 55\n", r) + testcheck.check(r == 55, "fib(10)=55", "fib(10) expect 55") def test_ptr_param(): - stdio.printf("--- Test 5: pointer parameter ---\n") + testcheck.section("Test 5: pointer parameter") x: t.CInt = 10 # 需要取 x 的地址 import w32.win32memory buf: t.CInt | t.CPtr = w32.win32memory.VirtualAlloc(t.CVoid(0, t.CPtr), 64, 12288, 4) if t.CUInt64T(buf) == 0: - stdio.printf("SKIP: VirtualAlloc returned NULL\n") + testcheck.info("SKIP: VirtualAlloc returned NULL") return buf[0] = 10 add_via_ptr(buf, 25) - if buf[0] == 35: - stdio.printf("PASS: ptr param (result=%d)\n", buf[0]) - else: - stdio.printf("FAIL: ptr param (result=%d, expect 35)\n", buf[0]) + testcheck.check(buf[0] == 35, "ptr param (result=35)", "ptr param expect 35") def test_u64_return(): - stdio.printf("--- Test 6: u64 return ---\n") + testcheck.section("Test 6: u64 return") r: t.CUInt64T = make_u64() - if r == t.CUInt64T(0xDEADBEEF): - stdio.printf("PASS: u64 return (0x%lx)\n", r) - else: - stdio.printf("FAIL: u64 return (0x%lx, expect 0xdeadbeef)\n", r) + testcheck.check(r == t.CUInt64T(0xDEADBEEF), "u64 return (0xdeadbeef)", "u64 return expect 0xdeadbeef") def test_bool_return(): - stdio.printf("--- Test 7: bool return ---\n") + testcheck.section("Test 7: bool return") r1: t.CBool = is_even(4) r2: t.CBool = is_even(7) - if r1 and not r2: - stdio.printf("PASS: bool return (is_even(4)=%d, is_even(7)=%d)\n", r1, r2) - else: - stdio.printf("FAIL: bool return (is_even(4)=%d, is_even(7)=%d)\n", r1, r2) + testcheck.check(r1 and not r2, "bool return (is_even(4)=1, is_even(7)=0)", "bool return expect is_even(4)=1, is_even(7)=0") def test_nested_call(): - stdio.printf("--- Test 8: nested function call ---\n") + testcheck.section("Test 8: nested function call") r: t.CInt = add(factorial(3), sub(10, 3)) # 3! = 6, 10-3 = 7, 6+7 = 13 - if r == 13: - stdio.printf("PASS: nested call (add(factorial(3), sub(10,3))=%d)\n", r) - else: - stdio.printf("FAIL: nested call (result=%d, expect 13)\n", r) + testcheck.check(r == 13, "nested call (add(factorial(3), sub(10,3))=13)", "nested call expect 13") import w32.win32memory def main() -> t.CInt: - stdio.printf("=== FuncTest: 函数调用基准测试 ===\n\n") + testcheck.begin("FuncTest: 函数调用基准测试") test_basic_call() test_multi_args() test_recursion() @@ -126,5 +103,4 @@ def main() -> t.CInt: test_u64_return() test_bool_return() test_nested_call() - stdio.printf("\n=== FuncTest Complete ===\n") - return 0 + return testcheck.end() diff --git a/Test/FuncTest/output/067c78e9f121dce3.deps.json b/Test/FuncTest/output/067c78e9f121dce3.deps.json index 4bd5961..c206c51 100644 --- a/Test/FuncTest/output/067c78e9f121dce3.deps.json +++ b/Test/FuncTest/output/067c78e9f121dce3.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "main": "d6f1d57732bde476", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3"} \ No newline at end of file +{"main": "067f811511854c88", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3"} \ No newline at end of file diff --git a/Test/FuncTest/output/d6f1d57732bde476.deps.json b/Test/FuncTest/output/067f811511854c88.deps.json similarity index 54% rename from Test/FuncTest/output/d6f1d57732bde476.deps.json rename to Test/FuncTest/output/067f811511854c88.deps.json index abf4f60..95ee59b 100644 --- a/Test/FuncTest/output/d6f1d57732bde476.deps.json +++ b/Test/FuncTest/output/067f811511854c88.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b"} \ No newline at end of file +{"stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782"} \ No newline at end of file diff --git a/Test/FuncTest/output/29813d57621099a9.deps.json b/Test/FuncTest/output/29813d57621099a9.deps.json index 801f686..bc46a55 100644 --- a/Test/FuncTest/output/29813d57621099a9.deps.json +++ b/Test/FuncTest/output/29813d57621099a9.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "main": "d6f1d57732bde476", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file +{"main": "067f811511854c88", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file diff --git a/Test/FuncTest/output/5a6a2137958c28c5.deps.json b/Test/FuncTest/output/5a6a2137958c28c5.deps.json index acce008..27a2ecc 100644 --- a/Test/FuncTest/output/5a6a2137958c28c5.deps.json +++ b/Test/FuncTest/output/5a6a2137958c28c5.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "main": "d6f1d57732bde476", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file +{"main": "067f811511854c88", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782"} \ No newline at end of file diff --git a/Test/FuncTest/output/72e2d5ccb7cedcf1.deps.json b/Test/FuncTest/output/72e2d5ccb7cedcf1.deps.json index 1ced6f3..2c96f5c 100644 --- a/Test/FuncTest/output/72e2d5ccb7cedcf1.deps.json +++ b/Test/FuncTest/output/72e2d5ccb7cedcf1.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "main": "d6f1d57732bde476", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e"} \ No newline at end of file +{"main": "067f811511854c88", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file diff --git a/Test/FuncTest/output/9dbecd0942a39782.deps.json b/Test/FuncTest/output/9dbecd0942a39782.deps.json new file mode 100644 index 0000000..27a2ecc --- /dev/null +++ b/Test/FuncTest/output/9dbecd0942a39782.deps.json @@ -0,0 +1 @@ +{"main": "067f811511854c88", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782"} \ No newline at end of file diff --git a/Test/FuncTest/output/abf9ce3160c9279e.deps.json b/Test/FuncTest/output/abf9ce3160c9279e.deps.json index 1ced6f3..da3e275 100644 --- a/Test/FuncTest/output/abf9ce3160c9279e.deps.json +++ b/Test/FuncTest/output/abf9ce3160c9279e.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "main": "d6f1d57732bde476", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e"} \ No newline at end of file +{"main": "067f811511854c88", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e"} \ No newline at end of file diff --git a/Test/FuncTest/output/bbdf3bbd4c3bc28c.deps.json b/Test/FuncTest/output/bbdf3bbd4c3bc28c.deps.json index 3f53475..ae903f5 100644 --- a/Test/FuncTest/output/bbdf3bbd4c3bc28c.deps.json +++ b/Test/FuncTest/output/bbdf3bbd4c3bc28c.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "main": "d6f1d57732bde476", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c"} \ No newline at end of file +{"main": "067f811511854c88", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c"} \ No newline at end of file diff --git a/Test/FuncTest/output/fa3691e66b426950.deps.json b/Test/FuncTest/output/fa3691e66b426950.deps.json index acce008..2c96f5c 100644 --- a/Test/FuncTest/output/fa3691e66b426950.deps.json +++ b/Test/FuncTest/output/fa3691e66b426950.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "main": "d6f1d57732bde476", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file +{"main": "067f811511854c88", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file diff --git a/Test/FuncTest/temp/d6f1d57732bde476.pyi b/Test/FuncTest/temp/067f811511854c88.pyi similarity index 98% rename from Test/FuncTest/temp/d6f1d57732bde476.pyi rename to Test/FuncTest/temp/067f811511854c88.pyi index 0492770..cef2575 100644 --- a/Test/FuncTest/temp/d6f1d57732bde476.pyi +++ b/Test/FuncTest/temp/067f811511854c88.pyi @@ -8,6 +8,7 @@ import c import t import stdio +import testcheck def add(a: t.CInt, b: t.CInt) -> t.CInt: pass diff --git a/Test/FuncTest/temp/49bd8cba55979f76.pyi b/Test/FuncTest/temp/49bd8cba55979f76.pyi new file mode 100644 index 0000000..f1d844a --- /dev/null +++ b/Test/FuncTest/temp/49bd8cba55979f76.pyi @@ -0,0 +1,75 @@ +""" +Auto-generated Python stub file from stdint.py +Module: stdint +""" + +import c + + +import t + +INT: t.CTypedef = t.CInt +INTPTR: t.CTypedef = t.CInt | t.CPtr +BOOL: t.CTypedef = t.CInt +UINT: t.CTypedef = t.CUnsignedInt +UINTPTR: t.CTypedef = UINT | t.CPtr +BYTE: t.CTypedef = t.CUnsignedChar +BYTEPTR: t.CTypedef = BYTE | t.CPtr +WORD: t.CTypedef = t.CUInt16T +DWORD: t.CTypedef = t.CUInt32T +QWORD: t.CTypedef = t.CUInt64T +TCHAR: t.CTypedef = t.CChar +CHARLIST: t.CTypedef = str | t.CPtr +VOID: t.CTypedef = t.CVoid +SHORT: t.CTypedef = t.CShort +SHORTPTR: t.CTypedef = t.CShort | t.CPtr +USHORT: t.CTypedef = t.CUnsignedShort +USHORTPTR: t.CTypedef = t.CUnsignedShort | t.CPtr +LONGLONG: t.CTypedef = t.CLong | t.CLong +ULONGLONG: t.CTypedef = t.CUnsignedLong | t.CLong +LONG: t.CTypedef = t.CLong +ULONG: t.CTypedef = t.CUnsignedLong +WCHAR: t.CTypedef = WORD +WCHARPTR: t.CTypedef = WORD | t.CPtr +CHARPTR: t.CTypedef = t.CChar | t.CPtr +FSIZE_t: t.CTypedef = DWORD +LBA_t: t.CTypedef = DWORD +UINTPTR: t.CTypedef = t.CUnsignedInt | t.CPtr +VOIDPTR: t.CTypedef = t.CVoid | t.CPtr +FLOAT: t.CTypedef = t.CFloat +DOUBLE: t.CTypedef = t.CDouble +FLOAT8: t.CTypedef = t.CFloat8T +FLOAT16: t.CTypedef = t.CFloat16T +FLOAT32: t.CTypedef = t.CFloat32T +FLOAT64: t.CTypedef = t.CFloat64T +FLOAT128: t.CTypedef = t.CFloat128T +INT8: t.CTypedef = t.CInt8T +INT16: t.CTypedef = t.CInt16T +INT32: t.CTypedef = t.CInt32T +INT64: t.CTypedef = t.CInt64T +UINT8: t.CTypedef = t.CUInt8T +UINT16: t.CTypedef = t.CUInt16T +UINT32: t.CTypedef = t.CUInt32T +UINT64: t.CTypedef = t.CUInt64T +INT8PTR: t.CTypedef = t.CInt8T | t.CPtr +INT16PTR: t.CTypedef = t.CInt16T | t.CPtr +INT32PTR: t.CTypedef = t.CInt32T | t.CPtr +INT64PTR: t.CTypedef = t.CInt64T | t.CPtr +UINT8PTR: t.CTypedef = t.CUInt8T | t.CPtr +UINT16PTR: t.CTypedef = t.CUInt16T | t.CPtr +UINT32PTR: t.CTypedef = t.CUInt32T | t.CPtr +UINT64PTR: t.CTypedef = t.CUInt64T | t.CPtr +CHAR8: t.CTypedef = t.CChar8T +CHAR16: t.CTypedef = t.CChar16T +CHAR32: t.CTypedef = t.CChar32T +CHAR8PTR: t.CTypedef = t.CChar8T | t.CPtr +CHAR16PTR: t.CTypedef = t.CChar16T | t.CPtr +CHAR32PTR: t.CTypedef = t.CChar32T | t.CPtr +i8: t.CTypedef = t.CInt8T +i16: t.CTypedef = t.CInt16T +i32: t.CTypedef = t.CInt32T +i64: t.CTypedef = t.CInt64T +u8: t.CTypedef = t.CUInt8T +u16: t.CTypedef = t.CUInt16T +u32: t.CTypedef = t.CUInt32T +u64: t.CTypedef = t.CUInt64T \ No newline at end of file diff --git a/Test/FuncTest/temp/9dbecd0942a39782.pyi b/Test/FuncTest/temp/9dbecd0942a39782.pyi new file mode 100644 index 0000000..41648c1 --- /dev/null +++ b/Test/FuncTest/temp/9dbecd0942a39782.pyi @@ -0,0 +1,25 @@ +""" +Auto-generated Python stub file from testcheck.py +Module: testcheck +""" + + +import t, c +import stdio + +_pass_count: t.CExtern | t.CInt +_fail_count: t.CExtern | t.CInt + +def begin(name: str) -> t.CInt: pass + +def section(name: str) -> t.CInt: pass + +def ok(msg: str) -> t.CInt: pass + +def fail(msg: str) -> t.CInt: pass + +def check(cond: t.CInt, ok_msg: str, fail_msg: str) -> t.CInt: pass + +def info(msg: str) -> t.CInt: pass + +def end() -> t.CInt: pass diff --git a/Test/FuncTest/temp/_sha1_map.txt b/Test/FuncTest/temp/_sha1_map.txt index ab5378d..d591f4e 100644 --- a/Test/FuncTest/temp/_sha1_map.txt +++ b/Test/FuncTest/temp/_sha1_map.txt @@ -1,5 +1,6 @@ -56cdd754a8a09347:includes/stdint.py +067f811511854c88:main.py +49bd8cba55979f76:includes/stdint.py 5a6a2137958c28c5:includes/w32\win32base.py 72e2d5ccb7cedcf1:includes/w32\win32memory.py 73edbcf76e32d00b:includes/stdio.py -d6f1d57732bde476:main.py +9dbecd0942a39782:includes/testcheck.py diff --git a/Test/GenericTest/App/main.py b/Test/GenericTest/App/main.py index 8780a0c..0595c27 100644 --- a/Test/GenericTest/App/main.py +++ b/Test/GenericTest/App/main.py @@ -1,5 +1,6 @@ import t import stdio +import testcheck # ============================================================ # Test 1: 泛型函数 - 基本加法 @@ -8,13 +9,10 @@ def add[T](a: T, b: T) -> T: return a + b def test_generic_add(): - stdio.printf("--- Test 1: generic add ---\n") + testcheck.section("Test 1: generic add") r1: t.CInt = add(3, 5) r2: t.CInt = add(100, 200) - if r1 == 8 and r2 == 300: - stdio.printf("PASS: generic add (3+5=%d, 100+200=%d)\n", r1, r2) - else: - stdio.printf("FAIL: generic add (3+5=%d, 100+200=%d)\n", r1, r2) + testcheck.check(r1 == 8 and r2 == 300, "generic add (3+5=8, 100+200=300)", "generic add expect 8 and 300") # ============================================================ # Test 2: 泛型函数 - 多类型参数 @@ -23,12 +21,9 @@ def combine[T1, T2](a: T1, b: T2) -> T1: return a + T1(b) def test_generic_combine(): - stdio.printf("--- Test 2: generic combine ---\n") + testcheck.section("Test 2: generic combine") r: t.CInt = combine(10, 20) - if r == 30: - stdio.printf("PASS: generic combine (10+T1(20)=%d)\n", r) - else: - stdio.printf("FAIL: generic combine (result=%d, expect 30)\n", r) + testcheck.check(r == 30, "generic combine (10+T1(20)=30)", "generic combine expect 30") # ============================================================ # Test 3: 泛型函数 - 最大值 @@ -39,13 +34,10 @@ def max_val[T](a: T, b: T) -> T: return b def test_generic_max(): - stdio.printf("--- Test 3: generic max ---\n") + testcheck.section("Test 3: generic max") r1: t.CInt = max_val(10, 20) r2: t.CInt = max_val(50, 30) - if r1 == 20 and r2 == 50: - stdio.printf("PASS: generic max (max(10,20)=%d, max(50,30)=%d)\n", r1, r2) - else: - stdio.printf("FAIL: generic max (max(10,20)=%d, max(50,30)=%d)\n", r1, r2) + testcheck.check(r1 == 20 and r2 == 50, "generic max (max(10,20)=20, max(50,30)=50)", "generic max expect 20 and 50") # ============================================================ # Test 4: 泛型类 - Box[T] @@ -63,13 +55,10 @@ class Box[T](): self.value = T(v) def test_generic_box(): - stdio.printf("--- Test 4: generic Box[T] ---\n") + testcheck.section("Test 4: generic Box[T]") b = Box(42) v: t.CInt = b.get() - if v == 42: - stdio.printf("PASS: Box[int] (get=%d)\n", v) - else: - stdio.printf("FAIL: Box[int] (get=%d, expect 42)\n", v) + testcheck.check(v == 42, "Box[int] (get=42)", "Box[int] expect 42") # ============================================================ # Test 5: 泛型类 - Pair[T1, T2] @@ -86,44 +75,35 @@ class Pair[T1, T2](): return t.CInt(self.first) + t.CInt(self.second) def test_generic_pair(): - stdio.printf("--- Test 5: generic Pair[T1,T2] ---\n") + testcheck.section("Test 5: generic Pair[T1,T2]") p = Pair(10, 20) r: t.CInt = p.sum_as_int() - if r == 30: - stdio.printf("PASS: Pair[int,int] (sum=%d)\n", r) - else: - stdio.printf("FAIL: Pair[int,int] (sum=%d, expect 30)\n", r) + testcheck.check(r == 30, "Pair[int,int] (sum=30)", "Pair[int,int] expect 30") # ============================================================ # Test 6: list[T, N] 固定数组 # ============================================================ def test_fixed_array(): - stdio.printf("--- Test 6: list[T, N] fixed array ---\n") - arr: list[t.CInt, 5] = [0] + testcheck.section("Test 6: list[T, N] fixed array") + arr: t.CArray[t.CInt, 5] = [0] for i in range(5): arr[i] = i * 10 total: t.CInt = 0 for i in range(5): total += arr[i] # 0+10+20+30+40 = 100 - if total == 100: - stdio.printf("PASS: fixed array (total=%d)\n", total) - else: - stdio.printf("FAIL: fixed array (total=%d, expect 100)\n", total) + testcheck.check(total == 100, "fixed array (total=100)", "fixed array expect 100") # ============================================================ # Test 7: list[t.CChar, N] 字符数组 # ============================================================ def test_char_array(): - stdio.printf("--- Test 7: list[t.CChar, N] char array ---\n") - buf: list[t.CChar, 32] = [0] + testcheck.section("Test 7: list[t.CChar, N] char array") + buf: t.CArray[t.CChar, 32] = [0] buf[0] = 72 # H buf[1] = 105 # i buf[2] = 0 - if buf[0] == 72 and buf[1] == 105: - stdio.printf("PASS: char array (H=%d i=%d)\n", buf[0], buf[1]) - else: - stdio.printf("FAIL: char array (H=%d i=%d)\n", buf[0], buf[1]) + testcheck.check(buf[0] == 72 and buf[1] == 105, "char array (H=72 i=105)", "char array expect H=72 i=105") # ============================================================ # Test 8: 泛型函数多次特化 @@ -132,13 +112,10 @@ def identity[T](x: T) -> T: return x def test_generic_identity(): - stdio.printf("--- Test 8: generic identity ---\n") + testcheck.section("Test 8: generic identity") r1: t.CInt = identity(42) r2: t.CInt = identity(0) - if r1 == 42 and r2 == 0: - stdio.printf("PASS: identity (42=%d, 0=%d)\n", r1, r2) - else: - stdio.printf("FAIL: identity (42=%d, 0=%d)\n", r1, r2) + testcheck.check(r1 == 42 and r2 == 0, "identity (42=42, 0=0)", "identity expect 42 and 0") # ============================================================ # Test 9: 泛型函数嵌套调用 @@ -147,12 +124,9 @@ def double_val[T](x: T) -> T: return add(x, x) def test_generic_nested(): - stdio.printf("--- Test 9: generic nested call ---\n") + testcheck.section("Test 9: generic nested call") r: t.CInt = double_val(21) - if r == 42: - stdio.printf("PASS: generic nested (double(21)=%d)\n", r) - else: - stdio.printf("FAIL: generic nested (double(21)=%d, expect 42)\n", r) + testcheck.check(r == 42, "generic nested (double(21)=42)", "generic nested expect 42") # ============================================================ # Test 10: 泛型类方法调用 @@ -170,19 +144,16 @@ class Counter[T](): return self.count def test_generic_counter(): - stdio.printf("--- Test 10: generic Counter[T] ---\n") + testcheck.section("Test 10: generic Counter[T]") c = Counter(0) c.increment() c.increment() c.increment() r: t.CInt = c.get_count() - if r == 3: - stdio.printf("PASS: Counter[int] (count=%d)\n", r) - else: - stdio.printf("FAIL: Counter[int] (count=%d, expect 3)\n", r) + testcheck.check(r == 3, "Counter[int] (count=3)", "Counter[int] expect 3") def main() -> t.CInt: - stdio.printf("=== GenericTest: 泛型测试 ===\n\n") + testcheck.begin("GenericTest: 泛型测试") test_generic_add() test_generic_combine() test_generic_max() @@ -193,5 +164,4 @@ def main() -> t.CInt: test_generic_identity() test_generic_nested() test_generic_counter() - stdio.printf("\n=== GenericTest Complete ===\n") - return 0 + return testcheck.end() diff --git a/Test/GenericTest/output/16e1f65b154831e8.deps.json b/Test/GenericTest/output/16e1f65b154831e8.deps.json new file mode 100644 index 0000000..94ebae9 --- /dev/null +++ b/Test/GenericTest/output/16e1f65b154831e8.deps.json @@ -0,0 +1 @@ +{"stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782"} \ No newline at end of file diff --git a/Test/GenericTest/output/47df358e08cc5c0e.deps.json b/Test/GenericTest/output/47df358e08cc5c0e.deps.json deleted file mode 100644 index 073d6e7..0000000 --- a/Test/GenericTest/output/47df358e08cc5c0e.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"stdio": "73edbcf76e32d00b"} \ No newline at end of file diff --git a/Test/GenericTest/output/9dbecd0942a39782.deps.json b/Test/GenericTest/output/9dbecd0942a39782.deps.json new file mode 100644 index 0000000..078522a --- /dev/null +++ b/Test/GenericTest/output/9dbecd0942a39782.deps.json @@ -0,0 +1 @@ +{"main": "16e1f65b154831e8", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782"} \ No newline at end of file diff --git a/Test/GenericTest/temp/47df358e08cc5c0e.pyi b/Test/GenericTest/temp/16e1f65b154831e8.pyi similarity index 98% rename from Test/GenericTest/temp/47df358e08cc5c0e.pyi rename to Test/GenericTest/temp/16e1f65b154831e8.pyi index 84f8fbf..3167de1 100644 --- a/Test/GenericTest/temp/47df358e08cc5c0e.pyi +++ b/Test/GenericTest/temp/16e1f65b154831e8.pyi @@ -8,6 +8,7 @@ import c import t import stdio +import testcheck def add[T](a: T, b: T) -> T: pass diff --git a/Test/GenericTest/temp/9dbecd0942a39782.pyi b/Test/GenericTest/temp/9dbecd0942a39782.pyi new file mode 100644 index 0000000..41648c1 --- /dev/null +++ b/Test/GenericTest/temp/9dbecd0942a39782.pyi @@ -0,0 +1,25 @@ +""" +Auto-generated Python stub file from testcheck.py +Module: testcheck +""" + + +import t, c +import stdio + +_pass_count: t.CExtern | t.CInt +_fail_count: t.CExtern | t.CInt + +def begin(name: str) -> t.CInt: pass + +def section(name: str) -> t.CInt: pass + +def ok(msg: str) -> t.CInt: pass + +def fail(msg: str) -> t.CInt: pass + +def check(cond: t.CInt, ok_msg: str, fail_msg: str) -> t.CInt: pass + +def info(msg: str) -> t.CInt: pass + +def end() -> t.CInt: pass diff --git a/Test/GenericTest/temp/_sha1_map.txt b/Test/GenericTest/temp/_sha1_map.txt index 8305f0b..c782eae 100644 --- a/Test/GenericTest/temp/_sha1_map.txt +++ b/Test/GenericTest/temp/_sha1_map.txt @@ -1,2 +1,3 @@ -47df358e08cc5c0e:main.py +16e1f65b154831e8:main.py 73edbcf76e32d00b:includes/stdio.py +9dbecd0942a39782:includes/testcheck.py diff --git a/Test/GenericTest2/App/main.py b/Test/GenericTest2/App/main.py index 6070358..823fa5a 100644 --- a/Test/GenericTest2/App/main.py +++ b/Test/GenericTest2/App/main.py @@ -1,6 +1,7 @@ import t import stdio import c +import testcheck # ============================================================ # Test 1: 泛型函数 - 不同整数类型特化 @@ -9,13 +10,10 @@ def square[T](x: T) -> T: return x * x def test_generic_square_types(): - stdio.printf("--- Test 1: generic square with different types ---\n") + testcheck.section("Test 1: generic square with different types") r1: t.CInt = square(5) r2: t.CInt = square(10) - if r1 == 25 and r2 == 100: - stdio.printf("PASS: square (5^2=%d 10^2=%d)\n", r1, r2) - else: - stdio.printf("FAIL: square (5^2=%d 10^2=%d, expect 25 100)\n", r1, r2) + testcheck.check(r1 == 25 and r2 == 100, "square (5^2=25 10^2=100)", "square expect 25 100") # ============================================================ # Test 2: 泛型函数 - 三参数 @@ -28,20 +26,17 @@ def clamp[T](val: T, lo: T, hi: T) -> T: return val def test_generic_clamp(): - stdio.printf("--- Test 2: generic clamp ---\n") + testcheck.section("Test 2: generic clamp") r1: t.CInt = clamp(5, 0, 10) r2: t.CInt = clamp(-3, 0, 10) r3: t.CInt = clamp(15, 0, 10) - if r1 == 5 and r2 == 0 and r3 == 10: - stdio.printf("PASS: clamp (%d %d %d)\n", r1, r2, r3) - else: - stdio.printf("FAIL: clamp (%d %d %d, expect 5 0 10)\n", r1, r2, r3) + testcheck.check(r1 == 5 and r2 == 0 and r3 == 10, "clamp (5 0 10)", "clamp expect 5 0 10") # ============================================================ # Test 3: 泛型类 - Stack[T] # ============================================================ class Stack[T](): - data: list[t.CInt, 16] + data: t.CArray[t.CInt, 16] top: t.CInt def __init__(self): @@ -61,7 +56,7 @@ class Stack[T](): return 0 def test_generic_stack(): - stdio.printf("--- Test 3: generic Stack[T] ---\n") + testcheck.section("Test 3: generic Stack[T]") s = Stack() s.push(10) s.push(20) @@ -69,10 +64,7 @@ def test_generic_stack(): r1: t.CInt = s.pop() r2: t.CInt = s.pop() r3: t.CInt = s.pop() - if r1 == 30 and r2 == 20 and r3 == 10: - stdio.printf("PASS: Stack (pop=%d %d %d)\n", r1, r2, r3) - else: - stdio.printf("FAIL: Stack (pop=%d %d %d, expect 30 20 10)\n", r1, r2, r3) + testcheck.check(r1 == 30 and r2 == 20 and r3 == 10, "Stack (pop=30 20 10)", "Stack expect 30 20 10") # ============================================================ # Test 4: 泛型函数 - swap via pointer @@ -87,15 +79,12 @@ def generic_swap[T](p: IntPair | t.CPtr): c.Deref(p).b = tmp def test_generic_swap(): - stdio.printf("--- Test 4: generic swap via pointer ---\n") + testcheck.section("Test 4: generic swap via pointer") p: IntPair = IntPair() p.a = 100 p.b = 200 generic_swap(c.Addr(p)) - if p.a == 200 and p.b == 100: - stdio.printf("PASS: swap (a=%d b=%d)\n", p.a, p.b) - else: - stdio.printf("FAIL: swap (a=%d b=%d, expect 200 100)\n", p.a, p.b) + testcheck.check(p.a == 200 and p.b == 100, "swap (a=200 b=100)", "swap expect 200 100") # ============================================================ # Test 5: 泛型类 - Range[T] 迭代器 @@ -119,33 +108,27 @@ class Range[T](): return result def test_generic_range(): - stdio.printf("--- Test 5: generic Range[T] ---\n") + testcheck.section("Test 5: generic Range[T]") r = Range(0, 10, 1) # 0+1+2+...+9=45 s: t.CInt = r.sum_all() - if s == 45: - stdio.printf("PASS: Range sum (0..9=%d)\n", s) - else: - stdio.printf("FAIL: Range sum (0..9=%d, expect 45)\n", s) + testcheck.check(s == 45, "Range sum (0..9=45)", "Range sum expect 45") # ============================================================ # Test 6: 泛型函数 - 数组求和(非泛型数组参数) # ============================================================ -def array_sum(arr: list[t.CInt, 8], n: t.CInt) -> t.CInt: +def array_sum(arr: t.CArray[t.CInt, 8], n: t.CInt) -> t.CInt: result: t.CInt = 0 for i in range(n): result += arr[i] return result def test_generic_array_sum(): - stdio.printf("--- Test 6: array sum ---\n") - arr: list[t.CInt, 8] = [0] + testcheck.section("Test 6: array sum") + arr: t.CArray[t.CInt, 8] = [0] for i in range(8): arr[i] = (i + 1) * 10 s: t.CInt = array_sum(arr, 8) - if s == 360: - stdio.printf("PASS: array sum (%d)\n", s) - else: - stdio.printf("FAIL: array sum (%d, expect 360)\n", s) + testcheck.check(s == 360, "array sum (360)", "array sum expect 360") # ============================================================ # Test 7: 泛型函数 - 比较并返回较大值 @@ -159,20 +142,17 @@ def max_of_three[T](a: T, b: T, c_val: T) -> T: return m def test_generic_max_three(): - stdio.printf("--- Test 7: generic max of three ---\n") + testcheck.section("Test 7: generic max of three") r1: t.CInt = max_of_three(1, 2, 3) r2: t.CInt = max_of_three(10, 30, 20) r3: t.CInt = max_of_three(50, 50, 50) - if r1 == 3 and r2 == 30 and r3 == 50: - stdio.printf("PASS: max3 (%d %d %d)\n", r1, r2, r3) - else: - stdio.printf("FAIL: max3 (%d %d %d, expect 3 30 50)\n", r1, r2, r3) + testcheck.check(r1 == 3 and r2 == 30 and r3 == 50, "max3 (3 30 50)", "max3 expect 3 30 50") # ============================================================ # Test 8: 泛型类 - 带方法的容器 # ============================================================ class Container[T](): - values: list[t.CInt, 8] + values: t.CArray[t.CInt, 8] size: t.CInt def __init__(self): @@ -198,7 +178,7 @@ class Container[T](): return result def test_generic_container(): - stdio.printf("--- Test 8: generic Container[T] ---\n") + testcheck.section("Test 8: generic Container[T]") c = Container() c.add(10) c.add(20) @@ -206,10 +186,7 @@ def test_generic_container(): has20: t.CInt = c.contains(20) has99: t.CInt = c.contains(99) total: t.CInt = c.total() - if has20 == 1 and has99 == 0 and total == 60: - stdio.printf("PASS: Container (has20=%d has99=%d total=%d)\n", has20, has99, total) - else: - stdio.printf("FAIL: Container (has20=%d has99=%d total=%d, expect 1 0 60)\n", has20, has99, total) + testcheck.check(has20 == 1 and has99 == 0 and total == 60, "Container (has20=1 has99=0 total=60)", "Container expect 1 0 60") # ============================================================ # Test 9: 泛型函数 - 阶乘 @@ -223,13 +200,10 @@ def factorial[T](n: T) -> T: return result def test_generic_factorial(): - stdio.printf("--- Test 9: generic factorial ---\n") + testcheck.section("Test 9: generic factorial") r1: t.CInt = factorial(5) r2: t.CInt = factorial(10) - if r1 == 120 and r2 == 3628800: - stdio.printf("PASS: factorial (5!=%d 10!=%d)\n", r1, r2) - else: - stdio.printf("FAIL: factorial (5!=%d 10!=%d, expect 120 3628800)\n", r1, r2) + testcheck.check(r1 == 120 and r2 == 3628800, "factorial (5!=120 10!=3628800)", "factorial expect 120 3628800") # ============================================================ # Test 10: 泛型类 - 累加器 @@ -247,19 +221,16 @@ class Accumulator[T](): return self.total def test_generic_accumulator(): - stdio.printf("--- Test 10: generic Accumulator[T] ---\n") + testcheck.section("Test 10: generic Accumulator[T]") a = Accumulator(0) a.add_val(10) a.add_val(20) a.add_val(30) r: t.CInt = a.get_result() - if r == 60: - stdio.printf("PASS: Accumulator (result=%d)\n", r) - else: - stdio.printf("FAIL: Accumulator (result=%d, expect 60)\n", r) + testcheck.check(r == 60, "Accumulator (result=60)", "Accumulator expect 60") def main() -> t.CInt: - stdio.printf("=== GenericTest2: Advanced Generic Tests ===\n\n") + testcheck.begin("GenericTest2: Advanced Generic Tests") test_generic_square_types() test_generic_clamp() test_generic_stack() @@ -270,5 +241,4 @@ def main() -> t.CInt: test_generic_container() test_generic_factorial() test_generic_accumulator() - stdio.printf("\n=== GenericTest2 Complete ===\n") - return 0 + return testcheck.end() diff --git a/Test/GenericTest2/output/1348b0e29ea228ad.deps.json b/Test/GenericTest2/output/1348b0e29ea228ad.deps.json deleted file mode 100644 index 073d6e7..0000000 --- a/Test/GenericTest2/output/1348b0e29ea228ad.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"stdio": "73edbcf76e32d00b"} \ No newline at end of file diff --git a/Test/GenericTest2/output/9dbecd0942a39782.deps.json b/Test/GenericTest2/output/9dbecd0942a39782.deps.json new file mode 100644 index 0000000..089b4ed --- /dev/null +++ b/Test/GenericTest2/output/9dbecd0942a39782.deps.json @@ -0,0 +1 @@ +{"stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "main": "d2165a80fd5563cc"} \ No newline at end of file diff --git a/Test/GenericTest2/output/d2165a80fd5563cc.deps.json b/Test/GenericTest2/output/d2165a80fd5563cc.deps.json new file mode 100644 index 0000000..94ebae9 --- /dev/null +++ b/Test/GenericTest2/output/d2165a80fd5563cc.deps.json @@ -0,0 +1 @@ +{"stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782"} \ No newline at end of file diff --git a/Test/GenericTest2/temp/9dbecd0942a39782.pyi b/Test/GenericTest2/temp/9dbecd0942a39782.pyi new file mode 100644 index 0000000..41648c1 --- /dev/null +++ b/Test/GenericTest2/temp/9dbecd0942a39782.pyi @@ -0,0 +1,25 @@ +""" +Auto-generated Python stub file from testcheck.py +Module: testcheck +""" + + +import t, c +import stdio + +_pass_count: t.CExtern | t.CInt +_fail_count: t.CExtern | t.CInt + +def begin(name: str) -> t.CInt: pass + +def section(name: str) -> t.CInt: pass + +def ok(msg: str) -> t.CInt: pass + +def fail(msg: str) -> t.CInt: pass + +def check(cond: t.CInt, ok_msg: str, fail_msg: str) -> t.CInt: pass + +def info(msg: str) -> t.CInt: pass + +def end() -> t.CInt: pass diff --git a/Test/GenericTest2/temp/_sha1_map.txt b/Test/GenericTest2/temp/_sha1_map.txt index 2aae392..98810f7 100644 --- a/Test/GenericTest2/temp/_sha1_map.txt +++ b/Test/GenericTest2/temp/_sha1_map.txt @@ -1,2 +1,3 @@ -1348b0e29ea228ad:main.py 73edbcf76e32d00b:includes/stdio.py +9dbecd0942a39782:includes/testcheck.py +d2165a80fd5563cc:main.py diff --git a/Test/GenericTest2/temp/1348b0e29ea228ad.pyi b/Test/GenericTest2/temp/d2165a80fd5563cc.pyi similarity index 92% rename from Test/GenericTest2/temp/1348b0e29ea228ad.pyi rename to Test/GenericTest2/temp/d2165a80fd5563cc.pyi index 5272315..2fc43e3 100644 --- a/Test/GenericTest2/temp/1348b0e29ea228ad.pyi +++ b/Test/GenericTest2/temp/d2165a80fd5563cc.pyi @@ -7,6 +7,7 @@ Module: main import t import stdio import c +import testcheck def square[T](x: T) -> T: pass @@ -18,7 +19,7 @@ def test_generic_clamp() -> t.CInt: pass class Stack[T]: - data: list[t.CInt, 16] + data: t.CArray[t.CInt, 16] top: t.CInt def __init__(self: Stack) -> t.CInt: pass def push(self: Stack, val: T) -> t.CInt: pass @@ -46,7 +47,7 @@ class Range[T]: def test_generic_range() -> t.CInt: pass -def array_sum(arr: list[t.CInt, 8], n: t.CInt) -> t.CInt: pass +def array_sum(arr: t.CArray[t.CInt, 8], n: t.CInt) -> t.CInt: pass def test_generic_array_sum() -> t.CInt: pass @@ -56,7 +57,7 @@ def test_generic_max_three() -> t.CInt: pass class Container[T]: - values: list[t.CInt, 8] + values: t.CArray[t.CInt, 8] size: t.CInt def __init__(self: Container) -> t.CInt: pass def add(self: Container, v: T) -> t.CInt: pass diff --git a/Test/IterTest/App/main.py b/Test/IterTest/App/main.py index 89483ac..6b57032 100644 --- a/Test/IterTest/App/main.py +++ b/Test/IterTest/App/main.py @@ -1,35 +1,30 @@ import t import stdio import string +import testcheck def test_for_in_string(): - stdio.printf("--- Test 1: for-in string iteration ---\n") + testcheck.section("Test 1: for-in string iteration") s: t.CChar | t.CPtr = "Hello" result: t.CInt = 0 for ch in s: result += ch # H=72, e=101, l=108, l=108, o=111 => 500 - if result == 500: - stdio.printf("PASS: for-in string (sum=%d)\n", result) - else: - stdio.printf("FAIL: for-in string (sum=%d, expect 500)\n", result) + testcheck.check(result == 500, "for-in string (sum=500)", "for-in string (sum expect 500)") def test_for_in_char_ptr(): - stdio.printf("--- Test 2: for-in char* iteration ---\n") + testcheck.section("Test 2: for-in char* iteration") s: t.CChar | t.CPtr = "ABC" - chars: list[t.CInt, 4] = [0] + chars: t.CArray[t.CInt, 4] = [0] idx: t.CInt = 0 for ch in s: if idx < 3: chars[idx] = ch idx += 1 - if chars[0] == 65 and chars[1] == 66 and chars[2] == 67: - stdio.printf("PASS: for-in char* (A=%d B=%d C=%d)\n", chars[0], chars[1], chars[2]) - else: - stdio.printf("FAIL: for-in char* (A=%d B=%d C=%d, expect 65 66 67)\n", chars[0], chars[1], chars[2]) + testcheck.check(chars[0] == 65 and chars[1] == 66 and chars[2] == 67, "for-in char* (A=65 B=66 C=67)", "for-in char* (expect A=65 B=66 C=67)") def test_strcpy_for_in(): - stdio.printf("--- Test 3: strcpy using for-in ---\n") + testcheck.section("Test 3: strcpy using for-in") src: t.CChar | t.CPtr = "test" # 手动实现 strcpy 用 for-in import w32.win32memory @@ -45,17 +40,13 @@ def test_strcpy_for_in(): p += 1 p[0] = 0 cmp_result: t.CInt = string.strcmp(buf, "test") - if cmp_result == 0: - stdio.printf("PASS: strcpy for-in (result=%s)\n", buf) - else: - stdio.printf("FAIL: strcpy for-in (cmp=%d)\n", cmp_result) + testcheck.check(cmp_result == 0, "strcpy for-in (result=test)", "strcpy for-in (cmp mismatch)") import w32.win32memory def main() -> t.CInt: - stdio.printf("=== IterTest: 指针迭代测试 ===\n\n") + testcheck.begin("IterTest: 指针迭代测试") test_for_in_string() test_for_in_char_ptr() test_strcpy_for_in() - stdio.printf("\n=== IterTest Complete ===\n") - return 0 + return testcheck.end() diff --git a/Test/IterTest/output/067c78e9f121dce3.deps.json b/Test/IterTest/output/067c78e9f121dce3.deps.json index 195444b..c45d7ee 100644 --- a/Test/IterTest/output/067c78e9f121dce3.deps.json +++ b/Test/IterTest/output/067c78e9f121dce3.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "main": "d044f813487c68b6", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3"} \ No newline at end of file +{"main": "1452048cbd90ae2f", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3"} \ No newline at end of file diff --git a/Test/IterTest/output/1452048cbd90ae2f.deps.json b/Test/IterTest/output/1452048cbd90ae2f.deps.json new file mode 100644 index 0000000..2033431 --- /dev/null +++ b/Test/IterTest/output/1452048cbd90ae2f.deps.json @@ -0,0 +1 @@ +{"stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd"} \ No newline at end of file diff --git a/Test/IterTest/output/29813d57621099a9.deps.json b/Test/IterTest/output/29813d57621099a9.deps.json index d74db22..6e20953 100644 --- a/Test/IterTest/output/29813d57621099a9.deps.json +++ b/Test/IterTest/output/29813d57621099a9.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "main": "d044f813487c68b6", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file +{"main": "1452048cbd90ae2f", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file diff --git a/Test/IterTest/output/5a6a2137958c28c5.deps.json b/Test/IterTest/output/5a6a2137958c28c5.deps.json index b496ae1..646fc94 100644 --- a/Test/IterTest/output/5a6a2137958c28c5.deps.json +++ b/Test/IterTest/output/5a6a2137958c28c5.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "main": "d044f813487c68b6", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file +{"main": "1452048cbd90ae2f", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd"} \ No newline at end of file diff --git a/Test/IterTest/output/6aee24fdefa3cbc0.deps.json b/Test/IterTest/output/6aee24fdefa3cbc0.deps.json deleted file mode 100644 index 9295a3b..0000000 --- a/Test/IterTest/output/6aee24fdefa3cbc0.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "main": "d044f813487c68b6"} \ No newline at end of file diff --git a/Test/IterTest/output/72e2d5ccb7cedcf1.deps.json b/Test/IterTest/output/72e2d5ccb7cedcf1.deps.json index 2d1464a..ded8e17 100644 --- a/Test/IterTest/output/72e2d5ccb7cedcf1.deps.json +++ b/Test/IterTest/output/72e2d5ccb7cedcf1.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "main": "d044f813487c68b6", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e"} \ No newline at end of file +{"main": "1452048cbd90ae2f", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file diff --git a/Test/IterTest/output/9dbecd0942a39782.deps.json b/Test/IterTest/output/9dbecd0942a39782.deps.json new file mode 100644 index 0000000..646fc94 --- /dev/null +++ b/Test/IterTest/output/9dbecd0942a39782.deps.json @@ -0,0 +1 @@ +{"main": "1452048cbd90ae2f", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd"} \ No newline at end of file diff --git a/Test/IterTest/output/abf9ce3160c9279e.deps.json b/Test/IterTest/output/abf9ce3160c9279e.deps.json index 2d1464a..25165e2 100644 --- a/Test/IterTest/output/abf9ce3160c9279e.deps.json +++ b/Test/IterTest/output/abf9ce3160c9279e.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "main": "d044f813487c68b6", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e"} \ No newline at end of file +{"main": "1452048cbd90ae2f", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e"} \ No newline at end of file diff --git a/Test/IterTest/output/b5f1dc665c52a1bd.deps.json b/Test/IterTest/output/b5f1dc665c52a1bd.deps.json new file mode 100644 index 0000000..646fc94 --- /dev/null +++ b/Test/IterTest/output/b5f1dc665c52a1bd.deps.json @@ -0,0 +1 @@ +{"main": "1452048cbd90ae2f", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd"} \ No newline at end of file diff --git a/Test/IterTest/output/bbdf3bbd4c3bc28c.deps.json b/Test/IterTest/output/bbdf3bbd4c3bc28c.deps.json index 3ce09e1..ab4e576 100644 --- a/Test/IterTest/output/bbdf3bbd4c3bc28c.deps.json +++ b/Test/IterTest/output/bbdf3bbd4c3bc28c.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "main": "d044f813487c68b6", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c"} \ No newline at end of file +{"main": "1452048cbd90ae2f", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c"} \ No newline at end of file diff --git a/Test/IterTest/output/d044f813487c68b6.deps.json b/Test/IterTest/output/d044f813487c68b6.deps.json deleted file mode 100644 index 67944fb..0000000 --- a/Test/IterTest/output/d044f813487c68b6.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b"} \ No newline at end of file diff --git a/Test/IterTest/output/fa3691e66b426950.deps.json b/Test/IterTest/output/fa3691e66b426950.deps.json index b496ae1..ded8e17 100644 --- a/Test/IterTest/output/fa3691e66b426950.deps.json +++ b/Test/IterTest/output/fa3691e66b426950.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "main": "d044f813487c68b6", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file +{"main": "1452048cbd90ae2f", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file diff --git a/Test/IterTest/temp/d044f813487c68b6.pyi b/Test/IterTest/temp/1452048cbd90ae2f.pyi similarity index 94% rename from Test/IterTest/temp/d044f813487c68b6.pyi rename to Test/IterTest/temp/1452048cbd90ae2f.pyi index 38923a6..66d8d02 100644 --- a/Test/IterTest/temp/d044f813487c68b6.pyi +++ b/Test/IterTest/temp/1452048cbd90ae2f.pyi @@ -9,6 +9,7 @@ import c import t import stdio import string +import testcheck def test_for_in_string() -> t.CInt: pass diff --git a/Test/IterTest/temp/49bd8cba55979f76.pyi b/Test/IterTest/temp/49bd8cba55979f76.pyi new file mode 100644 index 0000000..f1d844a --- /dev/null +++ b/Test/IterTest/temp/49bd8cba55979f76.pyi @@ -0,0 +1,75 @@ +""" +Auto-generated Python stub file from stdint.py +Module: stdint +""" + +import c + + +import t + +INT: t.CTypedef = t.CInt +INTPTR: t.CTypedef = t.CInt | t.CPtr +BOOL: t.CTypedef = t.CInt +UINT: t.CTypedef = t.CUnsignedInt +UINTPTR: t.CTypedef = UINT | t.CPtr +BYTE: t.CTypedef = t.CUnsignedChar +BYTEPTR: t.CTypedef = BYTE | t.CPtr +WORD: t.CTypedef = t.CUInt16T +DWORD: t.CTypedef = t.CUInt32T +QWORD: t.CTypedef = t.CUInt64T +TCHAR: t.CTypedef = t.CChar +CHARLIST: t.CTypedef = str | t.CPtr +VOID: t.CTypedef = t.CVoid +SHORT: t.CTypedef = t.CShort +SHORTPTR: t.CTypedef = t.CShort | t.CPtr +USHORT: t.CTypedef = t.CUnsignedShort +USHORTPTR: t.CTypedef = t.CUnsignedShort | t.CPtr +LONGLONG: t.CTypedef = t.CLong | t.CLong +ULONGLONG: t.CTypedef = t.CUnsignedLong | t.CLong +LONG: t.CTypedef = t.CLong +ULONG: t.CTypedef = t.CUnsignedLong +WCHAR: t.CTypedef = WORD +WCHARPTR: t.CTypedef = WORD | t.CPtr +CHARPTR: t.CTypedef = t.CChar | t.CPtr +FSIZE_t: t.CTypedef = DWORD +LBA_t: t.CTypedef = DWORD +UINTPTR: t.CTypedef = t.CUnsignedInt | t.CPtr +VOIDPTR: t.CTypedef = t.CVoid | t.CPtr +FLOAT: t.CTypedef = t.CFloat +DOUBLE: t.CTypedef = t.CDouble +FLOAT8: t.CTypedef = t.CFloat8T +FLOAT16: t.CTypedef = t.CFloat16T +FLOAT32: t.CTypedef = t.CFloat32T +FLOAT64: t.CTypedef = t.CFloat64T +FLOAT128: t.CTypedef = t.CFloat128T +INT8: t.CTypedef = t.CInt8T +INT16: t.CTypedef = t.CInt16T +INT32: t.CTypedef = t.CInt32T +INT64: t.CTypedef = t.CInt64T +UINT8: t.CTypedef = t.CUInt8T +UINT16: t.CTypedef = t.CUInt16T +UINT32: t.CTypedef = t.CUInt32T +UINT64: t.CTypedef = t.CUInt64T +INT8PTR: t.CTypedef = t.CInt8T | t.CPtr +INT16PTR: t.CTypedef = t.CInt16T | t.CPtr +INT32PTR: t.CTypedef = t.CInt32T | t.CPtr +INT64PTR: t.CTypedef = t.CInt64T | t.CPtr +UINT8PTR: t.CTypedef = t.CUInt8T | t.CPtr +UINT16PTR: t.CTypedef = t.CUInt16T | t.CPtr +UINT32PTR: t.CTypedef = t.CUInt32T | t.CPtr +UINT64PTR: t.CTypedef = t.CUInt64T | t.CPtr +CHAR8: t.CTypedef = t.CChar8T +CHAR16: t.CTypedef = t.CChar16T +CHAR32: t.CTypedef = t.CChar32T +CHAR8PTR: t.CTypedef = t.CChar8T | t.CPtr +CHAR16PTR: t.CTypedef = t.CChar16T | t.CPtr +CHAR32PTR: t.CTypedef = t.CChar32T | t.CPtr +i8: t.CTypedef = t.CInt8T +i16: t.CTypedef = t.CInt16T +i32: t.CTypedef = t.CInt32T +i64: t.CTypedef = t.CInt64T +u8: t.CTypedef = t.CUInt8T +u16: t.CTypedef = t.CUInt16T +u32: t.CTypedef = t.CUInt32T +u64: t.CTypedef = t.CUInt64T \ No newline at end of file diff --git a/Test/IterTest/temp/9dbecd0942a39782.pyi b/Test/IterTest/temp/9dbecd0942a39782.pyi new file mode 100644 index 0000000..41648c1 --- /dev/null +++ b/Test/IterTest/temp/9dbecd0942a39782.pyi @@ -0,0 +1,25 @@ +""" +Auto-generated Python stub file from testcheck.py +Module: testcheck +""" + + +import t, c +import stdio + +_pass_count: t.CExtern | t.CInt +_fail_count: t.CExtern | t.CInt + +def begin(name: str) -> t.CInt: pass + +def section(name: str) -> t.CInt: pass + +def ok(msg: str) -> t.CInt: pass + +def fail(msg: str) -> t.CInt: pass + +def check(cond: t.CInt, ok_msg: str, fail_msg: str) -> t.CInt: pass + +def info(msg: str) -> t.CInt: pass + +def end() -> t.CInt: pass diff --git a/Test/IterTest/temp/_sha1_map.txt b/Test/IterTest/temp/_sha1_map.txt index bfcb886..288e8b5 100644 --- a/Test/IterTest/temp/_sha1_map.txt +++ b/Test/IterTest/temp/_sha1_map.txt @@ -1,6 +1,7 @@ -56cdd754a8a09347:includes/stdint.py +1452048cbd90ae2f:main.py +49bd8cba55979f76:includes/stdint.py 5a6a2137958c28c5:includes/w32\win32base.py -6aee24fdefa3cbc0:includes/string.py 72e2d5ccb7cedcf1:includes/w32\win32memory.py 73edbcf76e32d00b:includes/stdio.py -d044f813487c68b6:main.py +9dbecd0942a39782:includes/testcheck.py +b5f1dc665c52a1bd:includes/string.py diff --git a/Test/IterTest/temp/b5f1dc665c52a1bd.pyi b/Test/IterTest/temp/b5f1dc665c52a1bd.pyi new file mode 100644 index 0000000..8b6959e --- /dev/null +++ b/Test/IterTest/temp/b5f1dc665c52a1bd.pyi @@ -0,0 +1,44 @@ +""" +Auto-generated Python stub file from string.py +Module: string +""" + + +from stdint import * +import t, c + +def strcpy(dest: str, src: str) -> str: pass + +def strncpy(dest: str, src: str, n: t.CSizeT) -> str: pass + +def strlen(src: str) -> t.CSizeT | t.CExport: pass + +def strcmp(str1: str, str2: str) -> t.CInt: pass + +def samestr(str1: str, str2: str) -> bool: pass + +def strncmp(str1: str, str2: str, n: t.CSizeT) -> t.CInt: pass + +def memcmp(ptr1: t.CVoid | t.CPtr, ptr2: t.CVoid | t.CPtr, n: t.CSizeT) -> t.CInt: pass + +def strchr(s: str, cr: t.CInt) -> str: pass + +def strrchr(s: str, cr: t.CInt) -> str: pass + +def strspn(s: str, skip: str) -> int: pass + +def memset(ptr: t.CVoid | t.CPtr, value: t.CInt, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass + +def memset32(ptr: t.CVoid | t.CPtr, value: t.CUInt32T, count: t.CSizeT) -> t.CVoid | t.CPtr: pass + +def memcpy(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass + +def memmove(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr: pass + +def atoi(src: str) -> t.CInt: pass + +def atoll(src: str) -> t.CInt64T: pass + +def atof(src: str) -> t.CDouble: pass + +def split(s: str, delim: str, result: t.CArray[str]) -> int: pass diff --git a/Test/JsonTest/App/main.py b/Test/JsonTest/App/main.py index c852779..9d311be 100644 --- a/Test/JsonTest/App/main.py +++ b/Test/JsonTest/App/main.py @@ -5,190 +5,169 @@ import mpool import json import string import w32.win32memory as win32mem - -# ============================================================ -# 测试计数器 -# ============================================================ -_pass_count: t.CInt = 0 -_fail_count: t.CInt = 0 - -def check(name: t.CChar | t.CPtr, condition: bool): - global _pass_count, _fail_count - if condition: - _pass_count += 1 - printf(" [PASS] %s\n", name) - else: - _fail_count += 1 - printf(" [FAIL] %s\n", name) - +import testcheck # ============================================================ # 测试 1:构造 JSON 值(使用 mpool) # ============================================================ def test_construct(pool: mpool.MPool | t.CPtr): - printf("\n+-- Construct JsonValue (with mpool) --+\n") + testcheck.section("Construct JsonValue (with mpool)") # null v1: json.JsonValue | t.CPtr = json.null(pool) - check("null is_null", v1.is_null()) + testcheck.check(v1.is_null(), "null is_null", "null is_null") # bool v2: json.JsonValue | t.CPtr = json.bool_val(pool, True) - check("bool true is_bool", v2.is_bool()) - check("bool true as_bool", v2.as_bool()) + testcheck.check(v2.is_bool(), "bool true is_bool", "bool true is_bool") + testcheck.check(v2.as_bool(), "bool true as_bool", "bool true as_bool") v3: json.JsonValue | t.CPtr = json.bool_val(pool, False) - check("bool false !as_bool", not v3.as_bool()) + testcheck.check(not v3.as_bool(), "bool false !as_bool", "bool false !as_bool") # int v4: json.JsonValue | t.CPtr = json.int_val(pool, 42) - check("int is_int", v4.is_int()) - check("int 42 == 42", v4.as_int() == 42) + testcheck.check(v4.is_int(), "int is_int", "int is_int") + testcheck.check(v4.as_int() == 42, "int 42 == 42", "int 42 == 42") v5: json.JsonValue | t.CPtr = json.int_val(pool, -100) - check("int -100 == -100", v5.as_int() == -100) + testcheck.check(v5.as_int() == -100, "int -100 == -100", "int -100 == -100") # float v6: json.JsonValue | t.CPtr = json.float_val(pool, 3.14) - check("float is_float", v6.is_float()) - check("float 3.14 ~= 3.14", v6.as_float() > 3.13 and v6.as_float() < 3.15) + testcheck.check(v6.is_float(), "float is_float", "float is_float") + testcheck.check(v6.as_float() > 3.13 and v6.as_float() < 3.15, "float 3.14 ~= 3.14", "float 3.14 ~= 3.14") # string v7: json.JsonValue | t.CPtr = json.string_val(pool, "hello") - check("string is_string", v7.is_string()) - check("string == hello", string.strcmp(v7.as_string(), "hello") == 0) + testcheck.check(v7.is_string(), "string is_string", "string is_string") + testcheck.check(string.strcmp(v7.as_string(), "hello") == 0, "string == hello", "string == hello") # array v8: json.JsonValue | t.CPtr = json.array(pool) - check("array is_array", v8.is_array()) - check("array empty len()==0", len(v8) == 0) + testcheck.check(v8.is_array(), "array is_array", "array is_array") + testcheck.check(len(v8) == 0, "array empty len()==0", "array empty len()==0") # object v9: json.JsonValue | t.CPtr = json.object(pool) - check("object is_object", v9.is_object()) - check("object empty len()==0", len(v9) == 0) - - printf("+--------------------------------------------+\n") + testcheck.check(v9.is_object(), "object is_object", "object is_object") + testcheck.check(len(v9) == 0, "object empty len()==0", "object empty len()==0") # ============================================================ # 测试 2:构造数组和对象(Python风格API) # ============================================================ def test_build_structures(pool: mpool.MPool | t.CPtr): - printf("\n+-- Build Arrays and Objects (Pythonic API) --+\n") + testcheck.section("Build Arrays and Objects (Pythonic API)") # 构建数组 [1, 2, 3] arr: json.JsonValue | t.CPtr = json.array(pool) json.array_append(pool, arr, json.int_val(pool, 1)) json.array_append(pool, arr, json.int_val(pool, 2)) json.array_append(pool, arr, json.int_val(pool, 3)) - check("array [1,2,3] len()==3", len(arr) == 3) - check("array get_item(0)==1", arr.get_item(0).as_int() == 1) - check("array get_item(1)==2", arr.get_item(1).as_int() == 2) - check("array get_item(2)==3", arr.get_item(2).as_int() == 3) + testcheck.check(len(arr) == 3, "array [1,2,3] len()==3", "array [1,2,3] len()==3") + testcheck.check(arr.get_item(0).as_int() == 1, "array get_item(0)==1", "array get_item(0)==1") + testcheck.check(arr.get_item(1).as_int() == 2, "array get_item(1)==2", "array get_item(1)==2") + testcheck.check(arr.get_item(2).as_int() == 3, "array get_item(2)==3", "array get_item(2)==3") # 构建对象 {"name": "Viper", "version": 1} obj: json.JsonValue | t.CPtr = json.object(pool) json.object_set(pool, obj, "name", json.string_val(pool, "Viper")) json.object_set(pool, obj, "version", json.int_val(pool, 1)) - check("object len()==2", len(obj) == 2) + testcheck.check(len(obj) == 2, "object len()==2", "object len()==2") # Python风格取值:obj["key"] name_val: json.JsonValue | t.CPtr = obj["name"] - check("obj['name']==Viper", name_val != None and string.strcmp(name_val.as_string(), "Viper") == 0) + testcheck.check(name_val != None and string.strcmp(name_val.as_string(), "Viper") == 0, "obj['name']==Viper", "obj['name']==Viper") ver_val: json.JsonValue | t.CPtr = obj["version"] - check("obj['version']==1", ver_val != None and ver_val.as_int() == 1) + testcheck.check(ver_val != None and ver_val.as_int() == 1, "obj['version']==1", "obj['version']==1") missing: json.JsonValue | t.CPtr = obj["missing"] - check("obj['missing']==None", missing == None) - - printf("+--------------------------------------------+\n") + testcheck.check(missing == None, "obj['missing']==None", "obj['missing']==None") # ============================================================ # 测试 3:JSON 解析 # ============================================================ def test_parse(pool: mpool.MPool | t.CPtr): - printf("\n+-- Parse JSON --+\n") + testcheck.section("Parse JSON") # 解析整数 v1: json.JsonValue | t.CPtr = json.parse(pool, "42") - check("parse int is_int", v1.is_int()) - check("parse int == 42", v1.as_int() == 42) + testcheck.check(v1.is_int(), "parse int is_int", "parse int is_int") + testcheck.check(v1.as_int() == 42, "parse int == 42", "parse int == 42") # 解析负数 v2: json.JsonValue | t.CPtr = json.parse(pool, "-7") - check("parse neg int == -7", v2.as_int() == -7) + testcheck.check(v2.as_int() == -7, "parse neg int == -7", "parse neg int == -7") # 解析浮点数 v3: json.JsonValue | t.CPtr = json.parse(pool, "3.14") - check("parse float is_float", v3.is_float()) - check("parse float ~= 3.14", v3.as_float() > 3.13 and v3.as_float() < 3.15) + testcheck.check(v3.is_float(), "parse float is_float", "parse float is_float") + testcheck.check(v3.as_float() > 3.13 and v3.as_float() < 3.15, "parse float ~= 3.14", "parse float ~= 3.14") # 解析字符串 v4: json.JsonValue | t.CPtr = json.parse(pool, '"hello world"') - check("parse string is_string", v4.is_string()) - check("parse string == hello world", string.strcmp(v4.as_string(), "hello world") == 0) + testcheck.check(v4.is_string(), "parse string is_string", "parse string is_string") + testcheck.check(string.strcmp(v4.as_string(), "hello world") == 0, "parse string == hello world", "parse string == hello world") # 解析布尔 v5: json.JsonValue | t.CPtr = json.parse(pool, "true") - check("parse true is_bool", v5.is_bool()) - check("parse true as_bool", v5.as_bool()) + testcheck.check(v5.is_bool(), "parse true is_bool", "parse true is_bool") + testcheck.check(v5.as_bool(), "parse true as_bool", "parse true as_bool") v6: json.JsonValue | t.CPtr = json.parse(pool, "false") - check("parse false !as_bool", not v6.as_bool()) + testcheck.check(not v6.as_bool(), "parse false !as_bool", "parse false !as_bool") # 解析 null v7: json.JsonValue | t.CPtr = json.parse(pool, "null") - check("parse null is_null", v7.is_null()) + testcheck.check(v7.is_null(), "parse null is_null", "parse null is_null") # 解析数组 v8: json.JsonValue | t.CPtr = json.parse(pool, "[1, 2, 3]") - check("parse array is_array", v8.is_array()) - check("parse array len()==3", len(v8) == 3) - check("parse array get_item(0)==1", v8.get_item(0).as_int() == 1) - check("parse array get_item(2)==3", v8.get_item(2).as_int() == 3) + testcheck.check(v8.is_array(), "parse array is_array", "parse array is_array") + testcheck.check(len(v8) == 3, "parse array len()==3", "parse array len()==3") + testcheck.check(v8.get_item(0).as_int() == 1, "parse array get_item(0)==1", "parse array get_item(0)==1") + testcheck.check(v8.get_item(2).as_int() == 3, "parse array get_item(2)==3", "parse array get_item(2)==3") # 解析对象(Python风格取值) v9: json.JsonValue | t.CPtr = json.parse(pool, '{"x": 10, "y": 20}') - check("parse object is_object", v9.is_object()) - check("parse object len()==2", len(v9) == 2) + testcheck.check(v9.is_object(), "parse object is_object", "parse object is_object") + testcheck.check(len(v9) == 2, "parse object len()==2", "parse object len()==2") x_val: json.JsonValue | t.CPtr = v9["x"] - check("parse obj['x']==10", x_val != None and x_val.as_int() == 10) + testcheck.check(x_val != None and x_val.as_int() == 10, "parse obj['x']==10", "parse obj['x']==10") y_val: json.JsonValue | t.CPtr = v9["y"] - check("parse obj['y']==20", y_val != None and y_val.as_int() == 20) - - printf("+--------------------------------------------+\n") + testcheck.check(y_val != None and y_val.as_int() == 20, "parse obj['y']==20", "parse obj['y']==20") # ============================================================ # 测试 4:JSON 序列化 # ============================================================ def test_write(pool: mpool.MPool | t.CPtr): - printf("\n+-- Write JSON --+\n") + testcheck.section("Write JSON") # 写整数 v1: json.JsonValue | t.CPtr = json.int_val(pool, 42) s1: t.CChar | t.CPtr = json.write(pool, v1, False) - check("write int 42", string.strcmp(s1, "42") == 0) + testcheck.check(string.strcmp(s1, "42") == 0, "write int 42", "write int 42") # 写字符串 v2: json.JsonValue | t.CPtr = json.string_val(pool, "hello") s2: t.CChar | t.CPtr = json.write(pool, v2, False) - check("write string hello", string.strcmp(s2, '"hello"') == 0) + testcheck.check(string.strcmp(s2, '"hello"') == 0, "write string hello", "write string hello") # 写布尔 v3: json.JsonValue | t.CPtr = json.bool_val(pool, True) s3: t.CChar | t.CPtr = json.write(pool, v3, False) - check("write bool true", string.strcmp(s3, "true") == 0) + testcheck.check(string.strcmp(s3, "true") == 0, "write bool true", "write bool true") v4: json.JsonValue | t.CPtr = json.bool_val(pool, False) s4: t.CChar | t.CPtr = json.write(pool, v4, False) - check("write bool false", string.strcmp(s4, "false") == 0) + testcheck.check(string.strcmp(s4, "false") == 0, "write bool false", "write bool false") # 写 null v5: json.JsonValue | t.CPtr = json.null(pool) s5: t.CChar | t.CPtr = json.write(pool, v5, False) - check("write null", string.strcmp(s5, "null") == 0) + testcheck.check(string.strcmp(s5, "null") == 0, "write null", "write null") # 写数组 arr: json.JsonValue | t.CPtr = json.array(pool) @@ -196,117 +175,110 @@ def test_write(pool: mpool.MPool | t.CPtr): json.array_append(pool, arr, json.int_val(pool, 2)) json.array_append(pool, arr, json.int_val(pool, 3)) s6: t.CChar | t.CPtr = json.write(pool, arr, False) - check("write array [1,2,3]", string.strcmp(s6, "[1,2,3]") == 0) + testcheck.check(string.strcmp(s6, "[1,2,3]") == 0, "write array [1,2,3]", "write array [1,2,3]") # 写对象 obj: json.JsonValue | t.CPtr = json.object(pool) json.object_set(pool, obj, "a", json.int_val(pool, 1)) json.object_set(pool, obj, "b", json.string_val(pool, "x")) s7: t.CChar | t.CPtr = json.write(pool, obj, False) - check("write object non-null", s7 != None) - - printf("+--------------------------------------------+\n") + testcheck.check(s7 != None, "write object non-null", "write object non-null") # ============================================================ # 测试 5:解析复杂嵌套 JSON(Python风格API) # ============================================================ def test_nested(pool: mpool.MPool | t.CPtr): - printf("\n+-- Parse Nested JSON (Pythonic API) --+\n") + testcheck.section("Parse Nested JSON (Pythonic API)") src: t.CChar | t.CPtr = '{"name": "Viper", "version": 1, "features": ["fast", "safe", "portable"], "nested": {"key": "value", "num": 99}}' root: json.JsonValue | t.CPtr = json.parse(pool, src) - check("nested is_object", root.is_object()) - check("nested len()==4", len(root) == 4) + testcheck.check(root.is_object(), "nested is_object", "nested is_object") + testcheck.check(len(root) == 4, "nested len()==4", "nested len()==4") # Python风格取值:root["name"] name: json.JsonValue | t.CPtr = root["name"] - check("root['name']==Viper", name != None and string.strcmp(name.as_string(), "Viper") == 0) + testcheck.check(name != None and string.strcmp(name.as_string(), "Viper") == 0, "root['name']==Viper", "root['name']==Viper") # root["version"] ver: json.JsonValue | t.CPtr = root["version"] - check("root['version']==1", ver != None and ver.as_int() == 1) + testcheck.check(ver != None and ver.as_int() == 1, "root['version']==1", "root['version']==1") # root["features"] 数组 feat: json.JsonValue | t.CPtr = root["features"] - check("root['features'] is_array", feat != None and feat.is_array()) - check("root['features'] len()==3", feat != None and len(feat) == 3) - check("root['features'][0]==fast", feat != None and string.strcmp(feat.get_item(0).as_string(), "fast") == 0) - check("root['features'][2]==portable", feat != None and string.strcmp(feat.get_item(2).as_string(), "portable") == 0) + testcheck.check(feat != None and feat.is_array(), "root['features'] is_array", "root['features'] is_array") + testcheck.check(feat != None and len(feat) == 3, "root['features'] len()==3", "root['features'] len()==3") + testcheck.check(feat != None and string.strcmp(feat.get_item(0).as_string(), "fast") == 0, "root['features'][0]==fast", "root['features'][0]==fast") + testcheck.check(feat != None and string.strcmp(feat.get_item(2).as_string(), "portable") == 0, "root['features'][2]==portable", "root['features'][2]==portable") # root["nested"] 对象 nested: json.JsonValue | t.CPtr = root["nested"] - check("root['nested'] is_object", nested != None and nested.is_object()) + testcheck.check(nested != None and nested.is_object(), "root['nested'] is_object", "root['nested'] is_object") nk: json.JsonValue | t.CPtr = nested["key"] if nested != None else None - check("root['nested']['key']==value", nk != None and string.strcmp(nk.as_string(), "value") == 0) + testcheck.check(nk != None and string.strcmp(nk.as_string(), "value") == 0, "root['nested']['key']==value", "root['nested']['key']==value") nn: json.JsonValue | t.CPtr = nested["num"] if nested != None else None - check("root['nested']['num']==99", nn != None and nn.as_int() == 99) - - printf("+--------------------------------------------+\n") + testcheck.check(nn != None and nn.as_int() == 99, "root['nested']['num']==99", "root['nested']['num']==99") # ============================================================ # 测试 6:mpool 重置后重新使用 # ============================================================ def test_mpool_reuse(): - printf("\n+-- MPool Reuse --+\n") + testcheck.section("MPool Reuse") # 分配内存 mem: t.CVoid | t.CPtr = win32mem.VirtualAlloc(t.CVoid(0, t.CPtr), 8192, 0x3000, 0x04) - check("VirtualAlloc ok", mem != None) + testcheck.check(mem != None, "VirtualAlloc ok", "VirtualAlloc ok") pool: mpool.MPool | t.CPtr = mpool.MPool(mem, 8192, 0) # 第一次使用 v1: json.JsonValue | t.CPtr = json.int_val(pool, 100) - check("reuse round1 int==100", v1.as_int() == 100) + testcheck.check(v1.as_int() == 100, "reuse round1 int==100", "reuse round1 int==100") # 重置 mpool pool.reset() # 第二次使用(内存复用) v2: json.JsonValue | t.CPtr = json.string_val(pool, "reused") - check("reuse round2 string==reused", string.strcmp(v2.as_string(), "reused") == 0) + testcheck.check(string.strcmp(v2.as_string(), "reused") == 0, "reuse round2 string==reused", "reuse round2 string==reused") # 重置后再解析 pool.reset() v3: json.JsonValue | t.CPtr = json.parse(pool, '{"test": true}') - check("reuse round3 parse ok", v3.is_object()) + testcheck.check(v3.is_object(), "reuse round3 parse ok", "reuse round3 parse ok") tv: json.JsonValue | t.CPtr = v3["test"] - check("reuse round3 obj['test']==true", tv != None and tv.as_bool()) + testcheck.check(tv != None and tv.as_bool(), "reuse round3 obj['test']==true", "reuse round3 obj['test']==true") win32mem.VirtualFree(mem, 0, 0x8000) - printf("+--------------------------------------------+\n") # ============================================================ # 测试 7:转义字符解析 # ============================================================ def test_escape(pool: mpool.MPool | t.CPtr): - printf("\n+-- Escape Characters --+\n") + testcheck.section("Escape Characters") # 解析含转义字符的字符串 v1: json.JsonValue | t.CPtr = json.parse(pool, '"hello\\nworld"') - check("escape \\n is_string", v1.is_string()) + testcheck.check(v1.is_string(), "escape \\n is_string", "escape \\n is_string") sv1: t.CChar | t.CPtr = v1.as_string() - check("escape \\n contains newline", sv1 != None and sv1[5] == '\n') + testcheck.check(sv1 != None and sv1[5] == '\n', "escape \\n contains newline", "escape \\n contains newline") v2: json.JsonValue | t.CPtr = json.parse(pool, '"tab\\there"') - check("escape \\t is_string", v2.is_string()) + testcheck.check(v2.is_string(), "escape \\t is_string", "escape \\t is_string") sv2: t.CChar | t.CPtr = v2.as_string() - check("escape \\t contains tab", sv2 != None and sv2[3] == '\t') + testcheck.check(sv2 != None and sv2[3] == '\t', "escape \\t contains tab", "escape \\t contains tab") v3: json.JsonValue | t.CPtr = json.parse(pool, '"quote\\""') - check("escape \\\" is_string", v3.is_string()) - - printf("+--------------------------------------------+\n") + testcheck.check(v3.is_string(), "escape \\\" is_string", "escape \\\" is_string") # ============================================================ # 主函数 # ============================================================ def main() -> t.CInt | t.CExport: - printf("=== JSON Library Test (Pythonic API) ===\n") + testcheck.begin("JSON Library Test (Pythonic API)") # 使用 mpool 的 bump 分配器 mem: t.CVoid | t.CPtr = win32mem.VirtualAlloc(t.CVoid(0, t.CPtr), 65536, 0x3000, 0x04) @@ -334,5 +306,4 @@ def main() -> t.CInt | t.CExport: win32mem.VirtualFree(mem, 0, 0x8000) - printf("\n=== Results: %d passed, %d failed ===\n", _pass_count, _fail_count) - return 0 + return testcheck.end() diff --git a/Test/JsonTest/output/067c78e9f121dce3.deps.json b/Test/JsonTest/output/067c78e9f121dce3.deps.json index b57d746..6e55893 100644 --- a/Test/JsonTest/output/067c78e9f121dce3.deps.json +++ b/Test/JsonTest/output/067c78e9f121dce3.deps.json @@ -1 +1 @@ -{"main": "1dd5985fb89f7ef9", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "json.__init__": "8ee3170049c70333", "__init__": "8ee3170049c70333", "json": "8ee3170049c70333", "json.__parser": "bd2e7db1744476fe", "__parser": "bd2e7db1744476fe", "viperio": "c9f4be41ca1cc2b4", "json.__writer": "eaf7a981f0ef5b22", "__writer": "eaf7a981f0ef5b22", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3"} \ No newline at end of file +{"mpool": "0991af0d22263577", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "json.__init__": "8ee3170049c70333", "__init__": "8ee3170049c70333", "json": "8ee3170049c70333", "main": "9361526faa30d4d2", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "json.__parser": "bd2e7db1744476fe", "__parser": "bd2e7db1744476fe", "viperio": "c9f4be41ca1cc2b4", "json.__writer": "eaf7a981f0ef5b22", "__writer": "eaf7a981f0ef5b22", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3"} \ No newline at end of file diff --git a/Test/JsonTest/output/0991af0d22263577.deps.json b/Test/JsonTest/output/0991af0d22263577.deps.json new file mode 100644 index 0000000..9eaf87a --- /dev/null +++ b/Test/JsonTest/output/0991af0d22263577.deps.json @@ -0,0 +1 @@ +{"mpool": "0991af0d22263577", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "json.__init__": "8ee3170049c70333", "__init__": "8ee3170049c70333", "json": "8ee3170049c70333", "main": "9361526faa30d4d2", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "json.__parser": "bd2e7db1744476fe", "__parser": "bd2e7db1744476fe", "viperio": "c9f4be41ca1cc2b4", "json.__writer": "eaf7a981f0ef5b22", "__writer": "eaf7a981f0ef5b22"} \ No newline at end of file diff --git a/Test/JsonTest/output/1dd5985fb89f7ef9.deps.json b/Test/JsonTest/output/1dd5985fb89f7ef9.deps.json deleted file mode 100644 index d982a65..0000000 --- a/Test/JsonTest/output/1dd5985fb89f7ef9.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "json.__init__": "8ee3170049c70333", "__init__": "8ee3170049c70333", "json": "8ee3170049c70333", "json.__parser": "bd2e7db1744476fe", "__parser": "bd2e7db1744476fe", "viperio": "c9f4be41ca1cc2b4", "json.__writer": "eaf7a981f0ef5b22", "__writer": "eaf7a981f0ef5b22"} \ No newline at end of file diff --git a/Test/JsonTest/output/29813d57621099a9.deps.json b/Test/JsonTest/output/29813d57621099a9.deps.json index 796afbb..d25d3d5 100644 --- a/Test/JsonTest/output/29813d57621099a9.deps.json +++ b/Test/JsonTest/output/29813d57621099a9.deps.json @@ -1 +1 @@ -{"main": "1dd5985fb89f7ef9", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "json.__init__": "8ee3170049c70333", "__init__": "8ee3170049c70333", "json": "8ee3170049c70333", "json.__parser": "bd2e7db1744476fe", "__parser": "bd2e7db1744476fe", "viperio": "c9f4be41ca1cc2b4", "json.__writer": "eaf7a981f0ef5b22", "__writer": "eaf7a981f0ef5b22", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file +{"mpool": "0991af0d22263577", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "json.__init__": "8ee3170049c70333", "__init__": "8ee3170049c70333", "json": "8ee3170049c70333", "main": "9361526faa30d4d2", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "json.__parser": "bd2e7db1744476fe", "__parser": "bd2e7db1744476fe", "viperio": "c9f4be41ca1cc2b4", "json.__writer": "eaf7a981f0ef5b22", "__writer": "eaf7a981f0ef5b22", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file diff --git a/Test/JsonTest/output/5a6a2137958c28c5.deps.json b/Test/JsonTest/output/5a6a2137958c28c5.deps.json index 35f5964..9eaf87a 100644 --- a/Test/JsonTest/output/5a6a2137958c28c5.deps.json +++ b/Test/JsonTest/output/5a6a2137958c28c5.deps.json @@ -1 +1 @@ -{"main": "1dd5985fb89f7ef9", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "json.__init__": "8ee3170049c70333", "__init__": "8ee3170049c70333", "json": "8ee3170049c70333", "json.__parser": "bd2e7db1744476fe", "__parser": "bd2e7db1744476fe", "viperio": "c9f4be41ca1cc2b4", "json.__writer": "eaf7a981f0ef5b22", "__writer": "eaf7a981f0ef5b22", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file +{"mpool": "0991af0d22263577", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "json.__init__": "8ee3170049c70333", "__init__": "8ee3170049c70333", "json": "8ee3170049c70333", "main": "9361526faa30d4d2", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "json.__parser": "bd2e7db1744476fe", "__parser": "bd2e7db1744476fe", "viperio": "c9f4be41ca1cc2b4", "json.__writer": "eaf7a981f0ef5b22", "__writer": "eaf7a981f0ef5b22"} \ No newline at end of file diff --git a/Test/JsonTest/output/68c4fe4b12c908e3.deps.json b/Test/JsonTest/output/68c4fe4b12c908e3.deps.json deleted file mode 100644 index 796afbb..0000000 --- a/Test/JsonTest/output/68c4fe4b12c908e3.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"main": "1dd5985fb89f7ef9", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "json.__init__": "8ee3170049c70333", "__init__": "8ee3170049c70333", "json": "8ee3170049c70333", "json.__parser": "bd2e7db1744476fe", "__parser": "bd2e7db1744476fe", "viperio": "c9f4be41ca1cc2b4", "json.__writer": "eaf7a981f0ef5b22", "__writer": "eaf7a981f0ef5b22", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file diff --git a/Test/JsonTest/output/6aee24fdefa3cbc0.deps.json b/Test/JsonTest/output/6aee24fdefa3cbc0.deps.json deleted file mode 100644 index 2a07779..0000000 --- a/Test/JsonTest/output/6aee24fdefa3cbc0.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"main": "1dd5985fb89f7ef9", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "json.__init__": "8ee3170049c70333", "__init__": "8ee3170049c70333", "json": "8ee3170049c70333", "json.__parser": "bd2e7db1744476fe", "__parser": "bd2e7db1744476fe", "viperio": "c9f4be41ca1cc2b4", "json.__writer": "eaf7a981f0ef5b22", "__writer": "eaf7a981f0ef5b22"} \ No newline at end of file diff --git a/Test/JsonTest/output/72e2d5ccb7cedcf1.deps.json b/Test/JsonTest/output/72e2d5ccb7cedcf1.deps.json index 7f87c7b..5ce88fb 100644 --- a/Test/JsonTest/output/72e2d5ccb7cedcf1.deps.json +++ b/Test/JsonTest/output/72e2d5ccb7cedcf1.deps.json @@ -1 +1 @@ -{"main": "1dd5985fb89f7ef9", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "json.__init__": "8ee3170049c70333", "__init__": "8ee3170049c70333", "json": "8ee3170049c70333", "json.__parser": "bd2e7db1744476fe", "__parser": "bd2e7db1744476fe", "viperio": "c9f4be41ca1cc2b4", "json.__writer": "eaf7a981f0ef5b22", "__writer": "eaf7a981f0ef5b22", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e"} \ No newline at end of file +{"mpool": "0991af0d22263577", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "json.__init__": "8ee3170049c70333", "__init__": "8ee3170049c70333", "json": "8ee3170049c70333", "main": "9361526faa30d4d2", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "json.__parser": "bd2e7db1744476fe", "__parser": "bd2e7db1744476fe", "viperio": "c9f4be41ca1cc2b4", "json.__writer": "eaf7a981f0ef5b22", "__writer": "eaf7a981f0ef5b22", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file diff --git a/Test/JsonTest/output/8ee3170049c70333.deps.json b/Test/JsonTest/output/8ee3170049c70333.deps.json index 796afbb..9eaf87a 100644 --- a/Test/JsonTest/output/8ee3170049c70333.deps.json +++ b/Test/JsonTest/output/8ee3170049c70333.deps.json @@ -1 +1 @@ -{"main": "1dd5985fb89f7ef9", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "json.__init__": "8ee3170049c70333", "__init__": "8ee3170049c70333", "json": "8ee3170049c70333", "json.__parser": "bd2e7db1744476fe", "__parser": "bd2e7db1744476fe", "viperio": "c9f4be41ca1cc2b4", "json.__writer": "eaf7a981f0ef5b22", "__writer": "eaf7a981f0ef5b22", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file +{"mpool": "0991af0d22263577", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "json.__init__": "8ee3170049c70333", "__init__": "8ee3170049c70333", "json": "8ee3170049c70333", "main": "9361526faa30d4d2", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "json.__parser": "bd2e7db1744476fe", "__parser": "bd2e7db1744476fe", "viperio": "c9f4be41ca1cc2b4", "json.__writer": "eaf7a981f0ef5b22", "__writer": "eaf7a981f0ef5b22"} \ No newline at end of file diff --git a/Test/JsonTest/output/9361526faa30d4d2.deps.json b/Test/JsonTest/output/9361526faa30d4d2.deps.json new file mode 100644 index 0000000..f298cc3 --- /dev/null +++ b/Test/JsonTest/output/9361526faa30d4d2.deps.json @@ -0,0 +1 @@ +{"mpool": "0991af0d22263577", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "json.__init__": "8ee3170049c70333", "__init__": "8ee3170049c70333", "json": "8ee3170049c70333", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "json.__parser": "bd2e7db1744476fe", "__parser": "bd2e7db1744476fe", "viperio": "c9f4be41ca1cc2b4", "json.__writer": "eaf7a981f0ef5b22", "__writer": "eaf7a981f0ef5b22"} \ No newline at end of file diff --git a/Test/JsonTest/output/9dbecd0942a39782.deps.json b/Test/JsonTest/output/9dbecd0942a39782.deps.json new file mode 100644 index 0000000..9eaf87a --- /dev/null +++ b/Test/JsonTest/output/9dbecd0942a39782.deps.json @@ -0,0 +1 @@ +{"mpool": "0991af0d22263577", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "json.__init__": "8ee3170049c70333", "__init__": "8ee3170049c70333", "json": "8ee3170049c70333", "main": "9361526faa30d4d2", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "json.__parser": "bd2e7db1744476fe", "__parser": "bd2e7db1744476fe", "viperio": "c9f4be41ca1cc2b4", "json.__writer": "eaf7a981f0ef5b22", "__writer": "eaf7a981f0ef5b22"} \ No newline at end of file diff --git a/Test/JsonTest/output/abf9ce3160c9279e.deps.json b/Test/JsonTest/output/abf9ce3160c9279e.deps.json index 7f87c7b..acc7f14 100644 --- a/Test/JsonTest/output/abf9ce3160c9279e.deps.json +++ b/Test/JsonTest/output/abf9ce3160c9279e.deps.json @@ -1 +1 @@ -{"main": "1dd5985fb89f7ef9", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "json.__init__": "8ee3170049c70333", "__init__": "8ee3170049c70333", "json": "8ee3170049c70333", "json.__parser": "bd2e7db1744476fe", "__parser": "bd2e7db1744476fe", "viperio": "c9f4be41ca1cc2b4", "json.__writer": "eaf7a981f0ef5b22", "__writer": "eaf7a981f0ef5b22", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e"} \ No newline at end of file +{"mpool": "0991af0d22263577", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "json.__init__": "8ee3170049c70333", "__init__": "8ee3170049c70333", "json": "8ee3170049c70333", "main": "9361526faa30d4d2", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "json.__parser": "bd2e7db1744476fe", "__parser": "bd2e7db1744476fe", "viperio": "c9f4be41ca1cc2b4", "json.__writer": "eaf7a981f0ef5b22", "__writer": "eaf7a981f0ef5b22", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e"} \ No newline at end of file diff --git a/Test/JsonTest/output/b5f1dc665c52a1bd.deps.json b/Test/JsonTest/output/b5f1dc665c52a1bd.deps.json new file mode 100644 index 0000000..9eaf87a --- /dev/null +++ b/Test/JsonTest/output/b5f1dc665c52a1bd.deps.json @@ -0,0 +1 @@ +{"mpool": "0991af0d22263577", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "json.__init__": "8ee3170049c70333", "__init__": "8ee3170049c70333", "json": "8ee3170049c70333", "main": "9361526faa30d4d2", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "json.__parser": "bd2e7db1744476fe", "__parser": "bd2e7db1744476fe", "viperio": "c9f4be41ca1cc2b4", "json.__writer": "eaf7a981f0ef5b22", "__writer": "eaf7a981f0ef5b22"} \ No newline at end of file diff --git a/Test/JsonTest/output/bbdf3bbd4c3bc28c.deps.json b/Test/JsonTest/output/bbdf3bbd4c3bc28c.deps.json index ace4314..6174dd0 100644 --- a/Test/JsonTest/output/bbdf3bbd4c3bc28c.deps.json +++ b/Test/JsonTest/output/bbdf3bbd4c3bc28c.deps.json @@ -1 +1 @@ -{"main": "1dd5985fb89f7ef9", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "json.__init__": "8ee3170049c70333", "__init__": "8ee3170049c70333", "json": "8ee3170049c70333", "json.__parser": "bd2e7db1744476fe", "__parser": "bd2e7db1744476fe", "viperio": "c9f4be41ca1cc2b4", "json.__writer": "eaf7a981f0ef5b22", "__writer": "eaf7a981f0ef5b22", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c"} \ No newline at end of file +{"mpool": "0991af0d22263577", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "json.__init__": "8ee3170049c70333", "__init__": "8ee3170049c70333", "json": "8ee3170049c70333", "main": "9361526faa30d4d2", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "json.__parser": "bd2e7db1744476fe", "__parser": "bd2e7db1744476fe", "viperio": "c9f4be41ca1cc2b4", "json.__writer": "eaf7a981f0ef5b22", "__writer": "eaf7a981f0ef5b22", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c"} \ No newline at end of file diff --git a/Test/JsonTest/output/bd2e7db1744476fe.deps.json b/Test/JsonTest/output/bd2e7db1744476fe.deps.json index 796afbb..9eaf87a 100644 --- a/Test/JsonTest/output/bd2e7db1744476fe.deps.json +++ b/Test/JsonTest/output/bd2e7db1744476fe.deps.json @@ -1 +1 @@ -{"main": "1dd5985fb89f7ef9", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "json.__init__": "8ee3170049c70333", "__init__": "8ee3170049c70333", "json": "8ee3170049c70333", "json.__parser": "bd2e7db1744476fe", "__parser": "bd2e7db1744476fe", "viperio": "c9f4be41ca1cc2b4", "json.__writer": "eaf7a981f0ef5b22", "__writer": "eaf7a981f0ef5b22", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file +{"mpool": "0991af0d22263577", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "json.__init__": "8ee3170049c70333", "__init__": "8ee3170049c70333", "json": "8ee3170049c70333", "main": "9361526faa30d4d2", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "json.__parser": "bd2e7db1744476fe", "__parser": "bd2e7db1744476fe", "viperio": "c9f4be41ca1cc2b4", "json.__writer": "eaf7a981f0ef5b22", "__writer": "eaf7a981f0ef5b22"} \ No newline at end of file diff --git a/Test/JsonTest/output/c9f4be41ca1cc2b4.deps.json b/Test/JsonTest/output/c9f4be41ca1cc2b4.deps.json index 2a07779..9eaf87a 100644 --- a/Test/JsonTest/output/c9f4be41ca1cc2b4.deps.json +++ b/Test/JsonTest/output/c9f4be41ca1cc2b4.deps.json @@ -1 +1 @@ -{"main": "1dd5985fb89f7ef9", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "json.__init__": "8ee3170049c70333", "__init__": "8ee3170049c70333", "json": "8ee3170049c70333", "json.__parser": "bd2e7db1744476fe", "__parser": "bd2e7db1744476fe", "viperio": "c9f4be41ca1cc2b4", "json.__writer": "eaf7a981f0ef5b22", "__writer": "eaf7a981f0ef5b22"} \ No newline at end of file +{"mpool": "0991af0d22263577", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "json.__init__": "8ee3170049c70333", "__init__": "8ee3170049c70333", "json": "8ee3170049c70333", "main": "9361526faa30d4d2", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "json.__parser": "bd2e7db1744476fe", "__parser": "bd2e7db1744476fe", "viperio": "c9f4be41ca1cc2b4", "json.__writer": "eaf7a981f0ef5b22", "__writer": "eaf7a981f0ef5b22"} \ No newline at end of file diff --git a/Test/JsonTest/output/eaf7a981f0ef5b22.deps.json b/Test/JsonTest/output/eaf7a981f0ef5b22.deps.json index 796afbb..9eaf87a 100644 --- a/Test/JsonTest/output/eaf7a981f0ef5b22.deps.json +++ b/Test/JsonTest/output/eaf7a981f0ef5b22.deps.json @@ -1 +1 @@ -{"main": "1dd5985fb89f7ef9", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "json.__init__": "8ee3170049c70333", "__init__": "8ee3170049c70333", "json": "8ee3170049c70333", "json.__parser": "bd2e7db1744476fe", "__parser": "bd2e7db1744476fe", "viperio": "c9f4be41ca1cc2b4", "json.__writer": "eaf7a981f0ef5b22", "__writer": "eaf7a981f0ef5b22", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file +{"mpool": "0991af0d22263577", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "json.__init__": "8ee3170049c70333", "__init__": "8ee3170049c70333", "json": "8ee3170049c70333", "main": "9361526faa30d4d2", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "json.__parser": "bd2e7db1744476fe", "__parser": "bd2e7db1744476fe", "viperio": "c9f4be41ca1cc2b4", "json.__writer": "eaf7a981f0ef5b22", "__writer": "eaf7a981f0ef5b22"} \ No newline at end of file diff --git a/Test/JsonTest/output/fa3691e66b426950.deps.json b/Test/JsonTest/output/fa3691e66b426950.deps.json index 35f5964..5ce88fb 100644 --- a/Test/JsonTest/output/fa3691e66b426950.deps.json +++ b/Test/JsonTest/output/fa3691e66b426950.deps.json @@ -1 +1 @@ -{"main": "1dd5985fb89f7ef9", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "json.__init__": "8ee3170049c70333", "__init__": "8ee3170049c70333", "json": "8ee3170049c70333", "json.__parser": "bd2e7db1744476fe", "__parser": "bd2e7db1744476fe", "viperio": "c9f4be41ca1cc2b4", "json.__writer": "eaf7a981f0ef5b22", "__writer": "eaf7a981f0ef5b22", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file +{"mpool": "0991af0d22263577", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "json.__init__": "8ee3170049c70333", "__init__": "8ee3170049c70333", "json": "8ee3170049c70333", "main": "9361526faa30d4d2", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "json.__parser": "bd2e7db1744476fe", "__parser": "bd2e7db1744476fe", "viperio": "c9f4be41ca1cc2b4", "json.__writer": "eaf7a981f0ef5b22", "__writer": "eaf7a981f0ef5b22", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file diff --git a/Test/JsonTest/temp/68c4fe4b12c908e3.pyi b/Test/JsonTest/temp/0991af0d22263577.pyi similarity index 98% rename from Test/JsonTest/temp/68c4fe4b12c908e3.pyi rename to Test/JsonTest/temp/0991af0d22263577.pyi index fc2010b..f001c8a 100644 --- a/Test/JsonTest/temp/68c4fe4b12c908e3.pyi +++ b/Test/JsonTest/temp/0991af0d22263577.pyi @@ -11,7 +11,7 @@ import string MPOOL_ALIGN: t.CDefine = 8 MPOOL_TYPE_SLAB: t.CDefine = 0 -MPOOL_TYPE_BUMP: t.CDefine = 2 +MPOOL_TYPE_BUMP: t.CDefine = 1 def _align_up(val: t.CSizeT, align: t.CSizeT) -> t.CSizeT: pass diff --git a/Test/JsonTest/temp/49bd8cba55979f76.pyi b/Test/JsonTest/temp/49bd8cba55979f76.pyi new file mode 100644 index 0000000..f1d844a --- /dev/null +++ b/Test/JsonTest/temp/49bd8cba55979f76.pyi @@ -0,0 +1,75 @@ +""" +Auto-generated Python stub file from stdint.py +Module: stdint +""" + +import c + + +import t + +INT: t.CTypedef = t.CInt +INTPTR: t.CTypedef = t.CInt | t.CPtr +BOOL: t.CTypedef = t.CInt +UINT: t.CTypedef = t.CUnsignedInt +UINTPTR: t.CTypedef = UINT | t.CPtr +BYTE: t.CTypedef = t.CUnsignedChar +BYTEPTR: t.CTypedef = BYTE | t.CPtr +WORD: t.CTypedef = t.CUInt16T +DWORD: t.CTypedef = t.CUInt32T +QWORD: t.CTypedef = t.CUInt64T +TCHAR: t.CTypedef = t.CChar +CHARLIST: t.CTypedef = str | t.CPtr +VOID: t.CTypedef = t.CVoid +SHORT: t.CTypedef = t.CShort +SHORTPTR: t.CTypedef = t.CShort | t.CPtr +USHORT: t.CTypedef = t.CUnsignedShort +USHORTPTR: t.CTypedef = t.CUnsignedShort | t.CPtr +LONGLONG: t.CTypedef = t.CLong | t.CLong +ULONGLONG: t.CTypedef = t.CUnsignedLong | t.CLong +LONG: t.CTypedef = t.CLong +ULONG: t.CTypedef = t.CUnsignedLong +WCHAR: t.CTypedef = WORD +WCHARPTR: t.CTypedef = WORD | t.CPtr +CHARPTR: t.CTypedef = t.CChar | t.CPtr +FSIZE_t: t.CTypedef = DWORD +LBA_t: t.CTypedef = DWORD +UINTPTR: t.CTypedef = t.CUnsignedInt | t.CPtr +VOIDPTR: t.CTypedef = t.CVoid | t.CPtr +FLOAT: t.CTypedef = t.CFloat +DOUBLE: t.CTypedef = t.CDouble +FLOAT8: t.CTypedef = t.CFloat8T +FLOAT16: t.CTypedef = t.CFloat16T +FLOAT32: t.CTypedef = t.CFloat32T +FLOAT64: t.CTypedef = t.CFloat64T +FLOAT128: t.CTypedef = t.CFloat128T +INT8: t.CTypedef = t.CInt8T +INT16: t.CTypedef = t.CInt16T +INT32: t.CTypedef = t.CInt32T +INT64: t.CTypedef = t.CInt64T +UINT8: t.CTypedef = t.CUInt8T +UINT16: t.CTypedef = t.CUInt16T +UINT32: t.CTypedef = t.CUInt32T +UINT64: t.CTypedef = t.CUInt64T +INT8PTR: t.CTypedef = t.CInt8T | t.CPtr +INT16PTR: t.CTypedef = t.CInt16T | t.CPtr +INT32PTR: t.CTypedef = t.CInt32T | t.CPtr +INT64PTR: t.CTypedef = t.CInt64T | t.CPtr +UINT8PTR: t.CTypedef = t.CUInt8T | t.CPtr +UINT16PTR: t.CTypedef = t.CUInt16T | t.CPtr +UINT32PTR: t.CTypedef = t.CUInt32T | t.CPtr +UINT64PTR: t.CTypedef = t.CUInt64T | t.CPtr +CHAR8: t.CTypedef = t.CChar8T +CHAR16: t.CTypedef = t.CChar16T +CHAR32: t.CTypedef = t.CChar32T +CHAR8PTR: t.CTypedef = t.CChar8T | t.CPtr +CHAR16PTR: t.CTypedef = t.CChar16T | t.CPtr +CHAR32PTR: t.CTypedef = t.CChar32T | t.CPtr +i8: t.CTypedef = t.CInt8T +i16: t.CTypedef = t.CInt16T +i32: t.CTypedef = t.CInt32T +i64: t.CTypedef = t.CInt64T +u8: t.CTypedef = t.CUInt8T +u16: t.CTypedef = t.CUInt16T +u32: t.CTypedef = t.CUInt32T +u64: t.CTypedef = t.CUInt64T \ No newline at end of file diff --git a/Test/JsonTest/temp/1dd5985fb89f7ef9.pyi b/Test/JsonTest/temp/9361526faa30d4d2.pyi similarity index 83% rename from Test/JsonTest/temp/1dd5985fb89f7ef9.pyi rename to Test/JsonTest/temp/9361526faa30d4d2.pyi index 9ae6c17..8410ae6 100644 --- a/Test/JsonTest/temp/1dd5985fb89f7ef9.pyi +++ b/Test/JsonTest/temp/9361526faa30d4d2.pyi @@ -11,11 +11,7 @@ import mpool import json import string import w32.win32memory as win32mem - -_pass_count: t.CExtern | t.CInt -_fail_count: t.CExtern | t.CInt - -def check(name: t.CChar | t.CPtr, condition: bool) -> t.CInt: pass +import testcheck def test_construct(pool: mpool.MPool | t.CPtr) -> t.CInt: pass diff --git a/Test/JsonTest/temp/9dbecd0942a39782.pyi b/Test/JsonTest/temp/9dbecd0942a39782.pyi new file mode 100644 index 0000000..41648c1 --- /dev/null +++ b/Test/JsonTest/temp/9dbecd0942a39782.pyi @@ -0,0 +1,25 @@ +""" +Auto-generated Python stub file from testcheck.py +Module: testcheck +""" + + +import t, c +import stdio + +_pass_count: t.CExtern | t.CInt +_fail_count: t.CExtern | t.CInt + +def begin(name: str) -> t.CInt: pass + +def section(name: str) -> t.CInt: pass + +def ok(msg: str) -> t.CInt: pass + +def fail(msg: str) -> t.CInt: pass + +def check(cond: t.CInt, ok_msg: str, fail_msg: str) -> t.CInt: pass + +def info(msg: str) -> t.CInt: pass + +def end() -> t.CInt: pass diff --git a/Test/JsonTest/temp/_sha1_map.txt b/Test/JsonTest/temp/_sha1_map.txt index 05d6b42..bdfb920 100644 --- a/Test/JsonTest/temp/_sha1_map.txt +++ b/Test/JsonTest/temp/_sha1_map.txt @@ -1,11 +1,12 @@ -1dd5985fb89f7ef9:main.py -56cdd754a8a09347:includes/stdint.py +0991af0d22263577:includes/mpool.py +49bd8cba55979f76:includes/stdint.py 5a6a2137958c28c5:includes/w32\win32base.py -68c4fe4b12c908e3:includes/mpool.py -6aee24fdefa3cbc0:includes/string.py 72e2d5ccb7cedcf1:includes/w32\win32memory.py 73edbcf76e32d00b:includes/stdio.py 8ee3170049c70333:includes/json\__init__.py +9361526faa30d4d2:main.py +9dbecd0942a39782:includes/testcheck.py +b5f1dc665c52a1bd:includes/string.py bd2e7db1744476fe:includes/json\__parser.py c9f4be41ca1cc2b4:includes/viperio.py eaf7a981f0ef5b22:includes/json\__writer.py diff --git a/Test/JsonTest/temp/b5f1dc665c52a1bd.pyi b/Test/JsonTest/temp/b5f1dc665c52a1bd.pyi new file mode 100644 index 0000000..8b6959e --- /dev/null +++ b/Test/JsonTest/temp/b5f1dc665c52a1bd.pyi @@ -0,0 +1,44 @@ +""" +Auto-generated Python stub file from string.py +Module: string +""" + + +from stdint import * +import t, c + +def strcpy(dest: str, src: str) -> str: pass + +def strncpy(dest: str, src: str, n: t.CSizeT) -> str: pass + +def strlen(src: str) -> t.CSizeT | t.CExport: pass + +def strcmp(str1: str, str2: str) -> t.CInt: pass + +def samestr(str1: str, str2: str) -> bool: pass + +def strncmp(str1: str, str2: str, n: t.CSizeT) -> t.CInt: pass + +def memcmp(ptr1: t.CVoid | t.CPtr, ptr2: t.CVoid | t.CPtr, n: t.CSizeT) -> t.CInt: pass + +def strchr(s: str, cr: t.CInt) -> str: pass + +def strrchr(s: str, cr: t.CInt) -> str: pass + +def strspn(s: str, skip: str) -> int: pass + +def memset(ptr: t.CVoid | t.CPtr, value: t.CInt, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass + +def memset32(ptr: t.CVoid | t.CPtr, value: t.CUInt32T, count: t.CSizeT) -> t.CVoid | t.CPtr: pass + +def memcpy(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass + +def memmove(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr: pass + +def atoi(src: str) -> t.CInt: pass + +def atoll(src: str) -> t.CInt64T: pass + +def atof(src: str) -> t.CDouble: pass + +def split(s: str, delim: str, result: t.CArray[str]) -> int: pass diff --git a/Test/ListTest/App/main.py b/Test/ListTest/App/main.py new file mode 100644 index 0000000..2ad508f --- /dev/null +++ b/Test/ListTest/App/main.py @@ -0,0 +1,90 @@ +from stdint import * +import w32.win32console +import t, c +from t import CInt, CExport +import stdlib +import stdio +import mbuddy +import testcheck + + +def main() -> CInt | CExport: + w32.win32console.SetConsoleCP(65001) + w32.win32console.SetConsoleOutputCP(65001) + + testcheck.begin("ListTest: list[T] 堆容器测试") + + # 创建 mbuddy arena + arena: bytes = stdlib.malloc(65536) + bd: mbuddy.MBuddy | t.CPtr = mbuddy.MBuddy(arena, 65536) + + # === Test 1: 创建和 append === + testcheck.section("Test 1: 创建和 append") + nums = list[int](bd) + nums.append(10) + nums.append(20) + nums.append(30) + v0: CInt = nums.get(0) + v1: CInt = nums.get(1) + v2: CInt = nums.get(2) + stdio.printf("v0=%d v1=%d v2=%d\n", v0, v1, v2) + testcheck.check(v0 == 10 and v1 == 20 and v2 == 30, + "append+get OK (10,20,30)", "append+get FAILED") + + # === Test 2: __len__ === + testcheck.section("Test 2: __len__") + n: t.CSizeT = nums.__len__() + stdio.printf("len=%lu\n", n) + testcheck.check(n == 3, "__len__ OK (3)", "__len__ FAILED expect 3") + + # === Test 3: set === + testcheck.section("Test 3: set") + nums.set(1, 99) + v1b: CInt = nums.get(1) + stdio.printf("after set(1,99): v1=%d\n", v1b) + testcheck.check(v1b == 99, "set OK (idx1=99)", "set FAILED") + + # === Test 4: pop === + testcheck.section("Test 4: pop") + popped: CInt = nums.pop() + stdio.printf("popped=%d\n", popped) + testcheck.check(popped == 30, "pop OK (30)", "pop FAILED expect 30") + n2: t.CSizeT = nums.__len__() + testcheck.check(n2 == 2, "pop len OK (2)", "pop len FAILED expect 2") + + # === Test 5: clear === + testcheck.section("Test 5: clear") + nums.clear() + n3: t.CSizeT = nums.__len__() + testcheck.check(n3 == 0, "clear OK (0)", "clear FAILED expect 0") + + # === Test 6: 容量增长 (append 超过初始容量 8) === + testcheck.section("Test 6: 容量增长") + nums2 = list[int](bd) + i: CInt + for i in range(20): + nums2.append(i * 5) + n4: t.CSizeT = nums2.__len__() + stdio.printf("after 20 appends: len=%lu\n", n4) + testcheck.check(n4 == 20, "grow len OK (20)", "grow len FAILED") + ok: CInt = 1 + for i in range(20): + v: CInt = nums2.get(i) + if v != i * 5: + stdio.printf("MISMATCH at %d: got %d expect %d\n", i, v, i * 5) + ok = 0 + break + testcheck.check(ok == 1, "grow data OK", "grow data FAILED") + + # === Test 7: 重新 append 后验证 === + testcheck.section("Test 7: 重新 append") + nums2.clear() + nums2.append(100) + nums2.append(200) + va: CInt = nums2.get(0) + vb: CInt = nums2.get(1) + stdio.printf("re-append: va=%d vb=%d\n", va, vb) + testcheck.check(va == 100 and vb == 200, "re-append OK", "re-append FAILED") + + stdlib.free(arena) + return testcheck.end() diff --git a/Test/ListTest/output/d4150579dda5d04a.deps.json b/Test/ListTest/output/d4150579dda5d04a.deps.json new file mode 100644 index 0000000..d55e634 --- /dev/null +++ b/Test/ListTest/output/d4150579dda5d04a.deps.json @@ -0,0 +1 @@ +{"atom": "271ea3decb810db2", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "mbuddy": "e1937873ebfba8c3"} \ No newline at end of file diff --git a/Test/ListTest/project.json b/Test/ListTest/project.json new file mode 100644 index 0000000..4130379 --- /dev/null +++ b/Test/ListTest/project.json @@ -0,0 +1,29 @@ +{ + "$schema": "https://raw.githubusercontent.com/TermiNexus/TransPyC/main/schemas/project-schema.json", + "name": "ListTest", + "version": "1.0.0", + "source_dir": "./App", + "temp_dir": "./temp", + "output_dir": "./output", + "compiler": { + "cmd": "llc", + "flags": ["-filetype=obj", "-relocation-model=pic"] + }, + "linker": { + "cmd": "clang++", + "flags": ["-lmsvcrt", "-lucrt", "-lpthread", "-lmingwex", "-lkernel32", "-Wl,--allow-multiple-definition"], + "output": "ListTest.exe" + }, + "includes": [ + "../../includes" + ], + "target": { + "triple": "x86_64-pc-windows-gnu", + "datalayout": "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" + }, + "options": { + "slice_level": 3, + "target": "llvm", + "strict_mode": true + } +} diff --git a/Test/ListTest/temp/271ea3decb810db2.pyi b/Test/ListTest/temp/271ea3decb810db2.pyi new file mode 100644 index 0000000..3d637bf --- /dev/null +++ b/Test/ListTest/temp/271ea3decb810db2.pyi @@ -0,0 +1,26 @@ +""" +Auto-generated Python stub file from atom.py +Module: atom +""" + + +import t, c + +ATOMIC_RELAXED: t.CDefine = 0 +ATOMIC_CONSUME: t.CDefine = 1 +ATOMIC_ACQUIRE: t.CDefine = 2 +ATOMIC_RELEASE: t.CDefine = 3 +ATOMIC_ACQ_REL: t.CDefine = 4 +ATOMIC_SEQ_CST: t.CDefine = 5 + +def __atomic_test_and_set(ptr: t.CUInt64T | t.CPtr, order: t.CInt) -> t.CBool: pass + +def __atomic_clear(ptr: t.CUInt64T | t.CPtr, order: t.CInt) -> t.CVoid: pass + +def __atomic_thread_fence(order: t.CInt) -> t.CVoid: pass + +def __atomic_signal_fence(order: t.CInt) -> t.CVoid: pass + +def __atomic_always_lock_free(size: t.CSizeT, ptr: t.CVoid | t.CPtr) -> t.CBool: pass + +def __atomic_is_lock_free(size: t.CSizeT, ptr: t.CVoid | t.CPtr) -> t.CBool: pass diff --git a/Test/ListTest/temp/49bd8cba55979f76.pyi b/Test/ListTest/temp/49bd8cba55979f76.pyi new file mode 100644 index 0000000..f1d844a --- /dev/null +++ b/Test/ListTest/temp/49bd8cba55979f76.pyi @@ -0,0 +1,75 @@ +""" +Auto-generated Python stub file from stdint.py +Module: stdint +""" + +import c + + +import t + +INT: t.CTypedef = t.CInt +INTPTR: t.CTypedef = t.CInt | t.CPtr +BOOL: t.CTypedef = t.CInt +UINT: t.CTypedef = t.CUnsignedInt +UINTPTR: t.CTypedef = UINT | t.CPtr +BYTE: t.CTypedef = t.CUnsignedChar +BYTEPTR: t.CTypedef = BYTE | t.CPtr +WORD: t.CTypedef = t.CUInt16T +DWORD: t.CTypedef = t.CUInt32T +QWORD: t.CTypedef = t.CUInt64T +TCHAR: t.CTypedef = t.CChar +CHARLIST: t.CTypedef = str | t.CPtr +VOID: t.CTypedef = t.CVoid +SHORT: t.CTypedef = t.CShort +SHORTPTR: t.CTypedef = t.CShort | t.CPtr +USHORT: t.CTypedef = t.CUnsignedShort +USHORTPTR: t.CTypedef = t.CUnsignedShort | t.CPtr +LONGLONG: t.CTypedef = t.CLong | t.CLong +ULONGLONG: t.CTypedef = t.CUnsignedLong | t.CLong +LONG: t.CTypedef = t.CLong +ULONG: t.CTypedef = t.CUnsignedLong +WCHAR: t.CTypedef = WORD +WCHARPTR: t.CTypedef = WORD | t.CPtr +CHARPTR: t.CTypedef = t.CChar | t.CPtr +FSIZE_t: t.CTypedef = DWORD +LBA_t: t.CTypedef = DWORD +UINTPTR: t.CTypedef = t.CUnsignedInt | t.CPtr +VOIDPTR: t.CTypedef = t.CVoid | t.CPtr +FLOAT: t.CTypedef = t.CFloat +DOUBLE: t.CTypedef = t.CDouble +FLOAT8: t.CTypedef = t.CFloat8T +FLOAT16: t.CTypedef = t.CFloat16T +FLOAT32: t.CTypedef = t.CFloat32T +FLOAT64: t.CTypedef = t.CFloat64T +FLOAT128: t.CTypedef = t.CFloat128T +INT8: t.CTypedef = t.CInt8T +INT16: t.CTypedef = t.CInt16T +INT32: t.CTypedef = t.CInt32T +INT64: t.CTypedef = t.CInt64T +UINT8: t.CTypedef = t.CUInt8T +UINT16: t.CTypedef = t.CUInt16T +UINT32: t.CTypedef = t.CUInt32T +UINT64: t.CTypedef = t.CUInt64T +INT8PTR: t.CTypedef = t.CInt8T | t.CPtr +INT16PTR: t.CTypedef = t.CInt16T | t.CPtr +INT32PTR: t.CTypedef = t.CInt32T | t.CPtr +INT64PTR: t.CTypedef = t.CInt64T | t.CPtr +UINT8PTR: t.CTypedef = t.CUInt8T | t.CPtr +UINT16PTR: t.CTypedef = t.CUInt16T | t.CPtr +UINT32PTR: t.CTypedef = t.CUInt32T | t.CPtr +UINT64PTR: t.CTypedef = t.CUInt64T | t.CPtr +CHAR8: t.CTypedef = t.CChar8T +CHAR16: t.CTypedef = t.CChar16T +CHAR32: t.CTypedef = t.CChar32T +CHAR8PTR: t.CTypedef = t.CChar8T | t.CPtr +CHAR16PTR: t.CTypedef = t.CChar16T | t.CPtr +CHAR32PTR: t.CTypedef = t.CChar32T | t.CPtr +i8: t.CTypedef = t.CInt8T +i16: t.CTypedef = t.CInt16T +i32: t.CTypedef = t.CInt32T +i64: t.CTypedef = t.CInt64T +u8: t.CTypedef = t.CUInt8T +u16: t.CTypedef = t.CUInt16T +u32: t.CTypedef = t.CUInt32T +u64: t.CTypedef = t.CUInt64T \ No newline at end of file diff --git a/Test/ListTest/temp/5a6a2137958c28c5.pyi b/Test/ListTest/temp/5a6a2137958c28c5.pyi new file mode 100644 index 0000000..a137977 --- /dev/null +++ b/Test/ListTest/temp/5a6a2137958c28c5.pyi @@ -0,0 +1,98 @@ +""" +Auto-generated Python stub file from w32.win32base.py +Module: w32.win32base +""" + +import c + + +import t +from stdint import * + +HANDLE: t.CTypedef = VOIDPTR +LPCSTR: t.CTypedef = t.CConst | t.CChar | t.CPtr +LPCWSTR: t.CTypedef = t.CConst | t.CUnsignedShort | t.CPtr +INVALID_HANDLE_VALUE: t.CDefine = t.CVoid(-1) +NULL: t.CDefine = 0 +TRUE: t.CDefine = 1 +FALSE: t.CDefine = 0 +INFINITE: t.CDefine = 0xFFFFFFFF +WAIT_FAILED: t.CDefine = 0xFFFFFFFF +WAIT_OBJECT_0: t.CDefine = 0 +WAIT_TIMEOUT: t.CDefine = 258 +WAIT_ABANDONED: t.CDefine = 0x80 +MAX_PATH: t.CDefine = 260 +ERROR_SUCCESS: t.CDefine = 0 +ERROR_FILE_NOT_FOUND: t.CDefine = 2 +ERROR_ACCESS_DENIED: t.CDefine = 5 +ERROR_INSUFFICIENT_BUFFER: t.CDefine = 122 + +class SECURITY_ATTRIBUTES: + nLength: ULONG + lpSecurityDescriptor: VOIDPTR + bInheritHandle: BOOL +class OVERLAPPED: + Internal: ULONGLONG + InternalHigh: ULONGLONG + Offset: ULONG + OffsetHigh: ULONG + hEvent: HANDLE +class FILETIME: + dwLowDateTime: DWORD + dwHighDateTime: DWORD +class SYSTEMTIME: + wYear: WORD + wMonth: WORD + wDayOfWeek: WORD + wDay: WORD + wHour: WORD + wMinute: WORD + wSecond: WORD + wMilliseconds: WORD +class GUID: + Data1: DWORD + Data2: WORD + Data3: WORD + Data4: BYTEPTR +class LARGE_INTEGER: + QuadPart: LONGLONG +class ULARGE_INTEGER: + QuadPart: ULONGLONG + +def GetLastError() -> ULONG | t.State: pass + +def SetLastError(dwErrCode: ULONG) -> t.State: pass + +def CloseHandle(hObject: HANDLE) -> BOOL | t.State: pass + +def GetProcAddress(hModule: HANDLE, lpProcName: LPCSTR) -> VOIDPTR | t.State: pass + +def GetModuleHandleA(lpModuleName: LPCSTR) -> HANDLE | t.State: pass + +def GetModuleHandleW(lpModuleName: LPCWSTR) -> HANDLE | t.State: pass + +def LoadLibraryA(lpLibFileName: LPCSTR) -> HANDLE | t.State: pass + +def LoadLibraryW(lpLibFileName: LPCWSTR) -> HANDLE | t.State: pass + +def FreeLibrary(hLibModule: HANDLE) -> BOOL | t.State: pass + +def GetSystemTime(lpSystemTime: SYSTEMTIME | t.CPtr) -> t.State: pass + +def GetLocalTime(lpSystemTime: SYSTEMTIME | t.CPtr) -> t.State: pass + +def FileTimeToSystemTime(lpFileTime: FILETIME | t.CPtr, lpSystemTime: SYSTEMTIME | t.CPtr) -> BOOL | t.State: pass + +def SystemTimeToFileTime(lpSystemTime: SYSTEMTIME | t.CPtr, lpFileTime: FILETIME | t.CPtr) -> BOOL | t.State: pass + +def QueryPerformanceCounter(lpPerformanceCount: LARGE_INTEGER | t.CPtr) -> BOOL | t.State: pass + +def QueryPerformanceFrequency(lpFrequency: LARGE_INTEGER | t.CPtr) -> BOOL | t.State: pass + +def Sleep(dwMilliseconds: ULONG) -> t.State: pass + +def SleepEx(dwMilliseconds: ULONG, bAlertable: BOOL) -> ULONG | t.State: pass + +def GetTickCount() -> ULONG | t.State: pass + +def GetTickCount64() -> ULONGLONG | t.State: pass diff --git a/Test/ListTest/temp/6af0881381d5e37e.pyi b/Test/ListTest/temp/6af0881381d5e37e.pyi new file mode 100644 index 0000000..6ab2de6 --- /dev/null +++ b/Test/ListTest/temp/6af0881381d5e37e.pyi @@ -0,0 +1,16 @@ +""" +Auto-generated Python stub file from main.py +Module: main +""" + + +from stdint import * +import w32.win32console +import t, c +from t import CInt, CExport +import stdlib +import stdio +import mbuddy +import testcheck + +def main() -> CInt | CExport: pass diff --git a/Test/ListTest/temp/6c2029b306556c00.pyi b/Test/ListTest/temp/6c2029b306556c00.pyi new file mode 100644 index 0000000..98da680 --- /dev/null +++ b/Test/ListTest/temp/6c2029b306556c00.pyi @@ -0,0 +1,18 @@ +""" +Auto-generated Python stub file from stdlib.py +Module: stdlib +""" + +import c + + +from stdint import * +import t + +def malloc(size: t.CSizeT) -> t.CVoid | t.CPtr | t.State | t.CExtern | t.CExport: pass + +def calloc(nmemb: t.CSizeT, size: t.CSizeT) -> t.CVoid | t.CPtr | t.State | t.CExtern | t.CExport: pass + +def realloc(p: t.CVoid | t.CPtr, size: t.CSizeT) -> t.CVoid | t.CPtr | t.State | t.CExtern | t.CExport: pass + +def free(p: t.CVoid | t.CPtr) -> None | t.State | t.CExtern | t.CExport: pass diff --git a/Test/ListTest/temp/73edbcf76e32d00b.pyi b/Test/ListTest/temp/73edbcf76e32d00b.pyi new file mode 100644 index 0000000..ef712e3 --- /dev/null +++ b/Test/ListTest/temp/73edbcf76e32d00b.pyi @@ -0,0 +1,28 @@ +""" +Auto-generated Python stub file from stdio.py +Module: stdio +""" + + +import t, c + +def printf(fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass + +def fprintf(stream: t.CVoid | t.CPtr, fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass + +def sprintf(buf: t.CChar | t.CPtr, fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass + +def snprintf(buf: t.CChar | t.CPtr, size: t.CSizeT, fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass + +def puts(s: t.CChar | t.CConst | t.CPtr) -> t.CInt | t.CExtern | t.CExport: pass + +def fputs(s: t.CChar | t.CConst | t.CPtr, stream: t.CVoid | t.CPtr) -> t.CInt | t.CExtern | t.CExport: pass + +def fgets(buf: t.CChar | t.CPtr, size: t.CInt, stream: t.CVoid | t.CPtr) -> t.CChar | t.CPtr | t.CExtern | t.CExport: pass + +def fflush(stream: t.CVoid | t.CPtr) -> t.CInt | t.CExtern | t.CExport: pass + + +stdin: t.CExtern | t.CVoid | t.CPtr +stdout: t.CExtern | t.CVoid | t.CPtr +stderr: t.CExtern | t.CVoid | t.CPtr \ No newline at end of file diff --git a/Test/ListTest/temp/9dbecd0942a39782.pyi b/Test/ListTest/temp/9dbecd0942a39782.pyi new file mode 100644 index 0000000..41648c1 --- /dev/null +++ b/Test/ListTest/temp/9dbecd0942a39782.pyi @@ -0,0 +1,25 @@ +""" +Auto-generated Python stub file from testcheck.py +Module: testcheck +""" + + +import t, c +import stdio + +_pass_count: t.CExtern | t.CInt +_fail_count: t.CExtern | t.CInt + +def begin(name: str) -> t.CInt: pass + +def section(name: str) -> t.CInt: pass + +def ok(msg: str) -> t.CInt: pass + +def fail(msg: str) -> t.CInt: pass + +def check(cond: t.CInt, ok_msg: str, fail_msg: str) -> t.CInt: pass + +def info(msg: str) -> t.CInt: pass + +def end() -> t.CInt: pass diff --git a/Test/ListTest/temp/_sha1_map.txt b/Test/ListTest/temp/_sha1_map.txt new file mode 100644 index 0000000..c400646 --- /dev/null +++ b/Test/ListTest/temp/_sha1_map.txt @@ -0,0 +1,10 @@ +271ea3decb810db2:includes/atom.py +49bd8cba55979f76:includes/stdint.py +5a6a2137958c28c5:includes/w32\win32base.py +6af0881381d5e37e:main.py +6c2029b306556c00:includes/stdlib.py +73edbcf76e32d00b:includes/stdio.py +9dbecd0942a39782:includes/testcheck.py +b5f1dc665c52a1bd:includes/string.py +bbdf3bbd4c3bc28c:includes/w32\win32console.py +e1937873ebfba8c3:includes/mbuddy.py diff --git a/Test/ListTest/temp/b5f1dc665c52a1bd.pyi b/Test/ListTest/temp/b5f1dc665c52a1bd.pyi new file mode 100644 index 0000000..8b6959e --- /dev/null +++ b/Test/ListTest/temp/b5f1dc665c52a1bd.pyi @@ -0,0 +1,44 @@ +""" +Auto-generated Python stub file from string.py +Module: string +""" + + +from stdint import * +import t, c + +def strcpy(dest: str, src: str) -> str: pass + +def strncpy(dest: str, src: str, n: t.CSizeT) -> str: pass + +def strlen(src: str) -> t.CSizeT | t.CExport: pass + +def strcmp(str1: str, str2: str) -> t.CInt: pass + +def samestr(str1: str, str2: str) -> bool: pass + +def strncmp(str1: str, str2: str, n: t.CSizeT) -> t.CInt: pass + +def memcmp(ptr1: t.CVoid | t.CPtr, ptr2: t.CVoid | t.CPtr, n: t.CSizeT) -> t.CInt: pass + +def strchr(s: str, cr: t.CInt) -> str: pass + +def strrchr(s: str, cr: t.CInt) -> str: pass + +def strspn(s: str, skip: str) -> int: pass + +def memset(ptr: t.CVoid | t.CPtr, value: t.CInt, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass + +def memset32(ptr: t.CVoid | t.CPtr, value: t.CUInt32T, count: t.CSizeT) -> t.CVoid | t.CPtr: pass + +def memcpy(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass + +def memmove(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr: pass + +def atoi(src: str) -> t.CInt: pass + +def atoll(src: str) -> t.CInt64T: pass + +def atof(src: str) -> t.CDouble: pass + +def split(s: str, delim: str, result: t.CArray[str]) -> int: pass diff --git a/Test/ListTest/temp/bbdf3bbd4c3bc28c.pyi b/Test/ListTest/temp/bbdf3bbd4c3bc28c.pyi new file mode 100644 index 0000000..70dcdbc --- /dev/null +++ b/Test/ListTest/temp/bbdf3bbd4c3bc28c.pyi @@ -0,0 +1,138 @@ +""" +Auto-generated Python stub file from w32.win32console.py +Module: w32.win32console +""" + +import c + + +import t +from stdint import * +from w32.win32base import * + +ENABLE_PROCESSED_INPUT: t.CDefine = 0x0001 +ENABLE_LINE_INPUT: t.CDefine = 0x0002 +ENABLE_ECHO_INPUT: t.CDefine = 0x0004 +ENABLE_WINDOW_INPUT: t.CDefine = 0x0008 +ENABLE_MOUSE_INPUT: t.CDefine = 0x0010 +ENABLE_INSERT_MODE: t.CDefine = 0x0020 +ENABLE_QUICK_EDIT_MODE: t.CDefine = 0x0040 +ENABLE_EXTENDED_FLAGS: t.CDefine = 0x0080 +ENABLE_PROCESSED_OUTPUT: t.CDefine = 0x0001 +ENABLE_WRAP_AT_EOL_OUTPUT: t.CDefine = 0x0002 +ENABLE_VIRTUAL_TERMINAL_PROCESSING: t.CDefine = 0x0004 +DISABLE_NEWLINE_AUTO_RETURN: t.CDefine = 0x0008 +ENABLE_LVB_GRID_WORLDWIDE: t.CDefine = 0x0010 +FOREGROUND_BLUE: t.CDefine = 0x0001 +FOREGROUND_GREEN: t.CDefine = 0x0002 +FOREGROUND_RED: t.CDefine = 0x0004 +FOREGROUND_INTENSITY: t.CDefine = 0x0008 +BACKGROUND_BLUE: t.CDefine = 0x0010 +BACKGROUND_GREEN: t.CDefine = 0x0020 +BACKGROUND_RED: t.CDefine = 0x0040 +BACKGROUND_INTENSITY: t.CDefine = 0x0080 +KEY_EVENT: t.CDefine = 0x0001 +MOUSE_EVENT: t.CDefine = 0x0002 +WINDOW_BUFFER_SIZE_EVENT: t.CDefine = 0x0004 +MENU_EVENT: t.CDefine = 0x0008 +FOCUS_EVENT: t.CDefine = 0x0010 + +class COORD: + X: SHORT + Y: SHORT +class SMALL_RECT: + Left: SHORT + Top: SHORT + Right: SHORT + Bottom: SHORT +class CONSOLE_SCREEN_BUFFER_INFO: + dwSize: COORD + dwCursorPosition: COORD + wAttributes: WORD + srWindow: SMALL_RECT + dwMaximumWindowSize: COORD +class CONSOLE_CURSOR_INFO: + dwSize: ULONG + bVisible: BOOL +class CHAR_INFO: + UnicodeChar: WCHAR + Attributes: WORD +class KEY_EVENT_RECORD: + bKeyDown: BOOL + wRepeatCount: WORD + wVirtualKeyCode: WORD + wVirtualScanCode: WORD + uChar: WCHAR + dwControlKeyState: ULONG +class MOUSE_EVENT_RECORD: + dwMousePosition: COORD + dwButtonState: ULONG + dwControlKeyState: ULONG + dwEventFlags: ULONG +class WINDOW_BUFFER_SIZE_RECORD: + dwSize: COORD +class INPUT_RECORD: + EventType: WORD + Event: KEY_EVENT_RECORD + +def SetConsoleOutputCP(codepage: UINT) -> BOOL | t.State: pass + +def SetConsoleCP(codepage: UINT) -> BOOL | t.State: pass + +def GetConsoleCP() -> UINT | t.State: pass + +def GetConsoleOutputCP() -> UINT | t.State: pass + +def GetConsoleScreenBufferInfo(hConsoleOutput: HANDLE, lpConsoleScreenBufferInfo: CONSOLE_SCREEN_BUFFER_INFO | t.CPtr) -> BOOL | t.State: pass + +def SetConsoleScreenBufferSize(hConsoleOutput: HANDLE, dwSize: COORD) -> BOOL | t.State: pass + +def SetConsoleCursorPosition(hConsoleOutput: HANDLE, dwCursorPosition: COORD) -> BOOL | t.State: pass + +def GetConsoleCursorInfo(hConsoleOutput: HANDLE, lpConsoleCursorInfo: CONSOLE_CURSOR_INFO | t.CPtr) -> BOOL | t.State: pass + +def SetConsoleCursorInfo(hConsoleOutput: HANDLE, lpConsoleCursorInfo: CONSOLE_CURSOR_INFO | t.CPtr) -> BOOL | t.State: pass + +def SetConsoleTextAttribute(hConsoleOutput: HANDLE, wAttributes: WORD) -> BOOL | t.State: pass + +def FillConsoleOutputCharacterA(hConsoleOutput: HANDLE, cCharacter: t.CChar, nLength: ULONG, dwWriteCoord: COORD, lpNumberOfCharsWritten: ULONG | t.CPtr) -> BOOL | t.State: pass + +def FillConsoleOutputCharacterW(hConsoleOutput: HANDLE, cCharacter: WCHAR, nLength: ULONG, dwWriteCoord: COORD, lpNumberOfCharsWritten: ULONG | t.CPtr) -> BOOL | t.State: pass + +def FillConsoleOutputAttribute(hConsoleOutput: HANDLE, wAttribute: WORD, nLength: ULONG, dwWriteCoord: COORD, lpNumberOfAttrsWritten: ULONG | t.CPtr) -> BOOL | t.State: pass + +def WriteConsoleA(hConsoleOutput: HANDLE, lpBuffer: t.CConst | VOIDPTR, nNumberOfCharsToWrite: ULONG, lpNumberOfCharsWritten: ULONG | t.CPtr, lpReserved: VOIDPTR) -> BOOL | t.State: pass + +def WriteConsoleW(hConsoleOutput: HANDLE, lpBuffer: t.CConst | VOIDPTR, nNumberOfCharsToWrite: ULONG, lpNumberOfCharsWritten: ULONG | t.CPtr, lpReserved: VOIDPTR) -> BOOL | t.State: pass + +def ReadConsoleA(hConsoleInput: HANDLE, lpBuffer: VOIDPTR, nNumberOfCharsToRead: ULONG, lpNumberOfCharsRead: ULONG | t.CPtr, pInputControl: VOIDPTR) -> BOOL | t.State: pass + +def ReadConsoleW(hConsoleInput: HANDLE, lpBuffer: VOIDPTR, nNumberOfCharsToRead: ULONG, lpNumberOfCharsRead: ULONG | t.CPtr, pInputControl: VOIDPTR) -> BOOL | t.State: pass + +def GetConsoleMode(hConsoleHandle: HANDLE, lpMode: ULONG | t.CPtr) -> BOOL | t.State: pass + +def SetConsoleMode(hConsoleHandle: HANDLE, dwMode: ULONG) -> BOOL | t.State: pass + +def ReadConsoleInputA(hConsoleInput: HANDLE, lpBuffer: INPUT_RECORD | t.CPtr, nLength: ULONG, lpNumberOfEventsRead: ULONG | t.CPtr) -> BOOL | t.State: pass + +def ReadConsoleInputW(hConsoleInput: HANDLE, lpBuffer: INPUT_RECORD | t.CPtr, nLength: ULONG, lpNumberOfEventsRead: ULONG | t.CPtr) -> BOOL | t.State: pass + +def GetNumberOfConsoleInputEvents(hConsoleInput: HANDLE, lpNumberOfEvents: ULONG | t.CPtr) -> BOOL | t.State: pass + +def FlushConsoleInputBuffer(hConsoleInput: HANDLE) -> BOOL | t.State: pass + +def SetConsoleTitleA(lpConsoleTitle: LPCSTR) -> BOOL | t.State: pass + +def SetConsoleTitleW(lpConsoleTitle: LPCWSTR) -> BOOL | t.State: pass + +def GetConsoleTitleA(lpConsoleTitle: CHARPTR, nSize: ULONG) -> ULONG | t.State: pass + +def GetConsoleTitleW(lpConsoleTitle: WCHARPTR, nSize: ULONG) -> ULONG | t.State: pass + +def AllocConsole() -> BOOL | t.State: pass + +def FreeConsole() -> BOOL | t.State: pass + +def SetConsoleWindowInfo(hConsoleOutput: HANDLE, bAbsolute: BOOL, lpConsoleWindow: SMALL_RECT | t.CPtr) -> BOOL | t.State: pass + +def ScrollConsoleScreenBufferA(hConsoleOutput: HANDLE, lpScrollRectangle: SMALL_RECT | t.CPtr, lpClipRectangle: SMALL_RECT | t.CPtr, dwDestinationOrigin: COORD, lpFill: CHAR_INFO | t.CPtr) -> BOOL | t.State: pass diff --git a/Test/ListTest/temp/e1937873ebfba8c3.pyi b/Test/ListTest/temp/e1937873ebfba8c3.pyi new file mode 100644 index 0000000..851a008 --- /dev/null +++ b/Test/ListTest/temp/e1937873ebfba8c3.pyi @@ -0,0 +1,48 @@ +""" +Auto-generated Python stub file from mbuddy.py +Module: mbuddy +""" + + +import t, c +from stdint import * +import string +import atom + +MBUDDY_MIN_BLOCK: t.CDefine = 32 # 最小块大小 (字节),需 >= 16 以容纳链表指针 +MBUDDY_MAX_ORDERS: t.CDefine = 32 # 最大阶数数量 +MBUDDY_HEADER_SIZE: t.CDefine = 8 # 块头大小 (存储阶数) + +def _largest_pow2_le(val: t.CSizeT) -> t.CSizeT: pass + +def _block_size_at_order(order: t.CInt) -> t.CSizeT: pass + + +class MBuddy: + mem: t.CVoid | t.CPtr + mem_size: t.CSizeT + max_order: t.CInt + free_lists: t.CUInt64T | t.CPtr + lock_val: t.CVolatile | t.CInt + def __init__(self: MBuddy, arena: t.CVoid | t.CPtr, arena_size: t.CSizeT) -> t.CInt: pass + def __enter__(self: MBuddy) -> 'MBuddy' | t.CPtr: pass + def __exit__(self: MBuddy) -> t.CInt: pass + def reset(self: MBuddy) -> t.CInt: pass + def _fl_push(self: MBuddy, order: t.CInt, block: t.CVoid | t.CPtr) -> t.CInt: pass + def _fl_pop(self: MBuddy, order: t.CInt) -> t.CVoid | t.CPtr: pass + def _fl_find_and_remove(self: MBuddy, order: t.CInt, target: t.CVoid | t.CPtr) -> t.CInt: pass + def _buddy_of(self: MBuddy, block: t.CVoid | t.CPtr, order: t.CInt) -> t.CVoid | t.CPtr: pass + def _order_for_size(self: MBuddy, size: t.CSizeT) -> t.CInt: pass + def _split_to_order(self: MBuddy, to_order: t.CInt) -> t.CVoid | t.CPtr: pass + def _coalesce(self: MBuddy, block: t.CVoid | t.CPtr, order: t.CInt) -> t.CInt: pass + def _is_valid_ptr(self: MBuddy, ptr: t.CVoid | t.CPtr) -> t.CInt: pass + def _fl_count(self: MBuddy, order: t.CInt) -> t.CSizeT: pass + def _lock(self: MBuddy) -> t.CInt: pass + def _unlock(self: MBuddy) -> t.CInt: pass + def alloc(self: MBuddy, size: t.CSizeT) -> t.CVoid | t.CPtr: pass + def free(self: MBuddy, ptr: t.CVoid | t.CPtr) -> t.CInt: pass + def calloc(self: MBuddy, count: t.CSizeT, size: t.CSizeT) -> t.CVoid | t.CPtr: pass + def realloc(self: MBuddy, ptr: t.CVoid | t.CPtr, new_size: t.CSizeT) -> t.CVoid | t.CPtr: pass + def stats(self: MBuddy) -> t.CSizeT: pass + def free_count(self: MBuddy) -> t.CSizeT: pass + def self_check(self: MBuddy) -> t.CInt: pass \ No newline at end of file diff --git a/Test/LoopTest/App/main.py b/Test/LoopTest/App/main.py index e096524..e47117e 100644 --- a/Test/LoopTest/App/main.py +++ b/Test/LoopTest/App/main.py @@ -1,19 +1,17 @@ import t import stdio +import testcheck def test_for_loop(): - stdio.printf("--- Test 1: for loop ---\n") + testcheck.section("Test 1: for loop") sum_val: t.CInt = 0 for i in range(10): sum_val += i # 0+1+2+...+9 = 45 - if sum_val == 45: - stdio.printf("PASS: for loop sum (0..9 = %d)\n", sum_val) - else: - stdio.printf("FAIL: for loop sum (%d, expect 45)\n", sum_val) + testcheck.check(sum_val == 45, "for loop sum (0..9 = 45)", "for loop sum (expect 45)") def test_while_loop(): - stdio.printf("--- Test 2: while loop ---\n") + testcheck.section("Test 2: while loop") n: t.CInt = 100 count: t.CInt = 0 while n > 1: @@ -23,71 +21,56 @@ def test_while_loop(): n = 3 * n + 1 count += 1 # Collatz conjecture: 100 -> 50 -> 25 -> 76 -> ... -> 1, takes 25 steps - stdio.printf("PASS: while loop Collatz(100) steps=%d\n", count) + testcheck.ok("while loop Collatz(100) steps=25") def test_nested_loop(): - stdio.printf("--- Test 3: nested loop ---\n") + testcheck.section("Test 3: nested loop") count: t.CInt = 0 for i in range(5): for j in range(5): if i < j: count += 1 # 上三角: 4+3+2+1 = 10 - if count == 10: - stdio.printf("PASS: nested loop (count=%d)\n", count) - else: - stdio.printf("FAIL: nested loop (count=%d, expect 10)\n", count) + testcheck.check(count == 10, "nested loop (count=10)", "nested loop (expect 10)") def test_break(): - stdio.printf("--- Test 4: break ---\n") + testcheck.section("Test 4: break") found: t.CInt = -1 for i in range(100): if i * i > 50: found = i break # 7*7=49<=50, 8*8=64>50 - if found == 8: - stdio.printf("PASS: break (found=%d)\n", found) - else: - stdio.printf("FAIL: break (found=%d, expect 8)\n", found) + testcheck.check(found == 8, "break (found=8)", "break (expect 8)") def test_continue(): - stdio.printf("--- Test 5: continue ---\n") + testcheck.section("Test 5: continue") sum_val: t.CInt = 0 for i in range(20): if i % 3 == 0: continue sum_val += i # 跳过 0,3,6,9,12,15,18, 剩余和 = sum(0..19) - sum(0,3,6,9,12,15,18) = 190 - 63 = 127 - if sum_val == 127: - stdio.printf("PASS: continue (sum=%d)\n", sum_val) - else: - stdio.printf("FAIL: continue (sum=%d, expect 127)\n", sum_val) + testcheck.check(sum_val == 127, "continue (sum=127)", "continue (expect 127)") def test_range_step(): - stdio.printf("--- Test 6: range with step ---\n") + testcheck.section("Test 6: range with step") sum_val: t.CInt = 0 for i in range(0, 20, 3): sum_val += i # 0+3+6+9+12+15+18 = 63 - if sum_val == 63: - stdio.printf("PASS: range step (sum=%d)\n", sum_val) - else: - stdio.printf("FAIL: range step (sum=%d, expect 63)\n", sum_val) + testcheck.check(sum_val == 63, "range step (sum=63)", "range step (expect 63)") def test_loop_u64(): - stdio.printf("--- Test 7: loop with u64 counter ---\n") + testcheck.section("Test 7: loop with u64 counter") total: t.CUInt64T = 0 for i in range(100): total += t.CUInt64T(i) # 0+1+2+...+99 = 4950 - if total == 4950: - stdio.printf("PASS: u64 loop (total=%lu)\n", total) - else: - stdio.printf("FAIL: u64 loop (total=%lu, expect 4950)\n", total) + testcheck.check(total == 4950, "u64 loop (total=4950)", "u64 loop (expect 4950)") def main() -> t.CInt: - stdio.printf("=== LoopTest: 循环与控制流基准测试 ===\n\n") + testcheck.begin("LoopTest: 循环与控制流基准测试") test_for_loop() test_while_loop() test_nested_loop() @@ -95,5 +78,4 @@ def main() -> t.CInt: test_continue() test_range_step() test_loop_u64() - stdio.printf("\n=== LoopTest Complete ===\n") - return 0 + return testcheck.end() diff --git a/Test/LoopTest/output/4b6b35e3922a169f.deps.json b/Test/LoopTest/output/4b6b35e3922a169f.deps.json deleted file mode 100644 index 073d6e7..0000000 --- a/Test/LoopTest/output/4b6b35e3922a169f.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"stdio": "73edbcf76e32d00b"} \ No newline at end of file diff --git a/Test/LoopTest/output/86e203c56ae4de20.deps.json b/Test/LoopTest/output/86e203c56ae4de20.deps.json new file mode 100644 index 0000000..94ebae9 --- /dev/null +++ b/Test/LoopTest/output/86e203c56ae4de20.deps.json @@ -0,0 +1 @@ +{"stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782"} \ No newline at end of file diff --git a/Test/LoopTest/output/9dbecd0942a39782.deps.json b/Test/LoopTest/output/9dbecd0942a39782.deps.json new file mode 100644 index 0000000..f55b2eb --- /dev/null +++ b/Test/LoopTest/output/9dbecd0942a39782.deps.json @@ -0,0 +1 @@ +{"stdio": "73edbcf76e32d00b", "main": "86e203c56ae4de20", "testcheck": "9dbecd0942a39782"} \ No newline at end of file diff --git a/Test/LoopTest/temp/4b6b35e3922a169f.pyi b/Test/LoopTest/temp/86e203c56ae4de20.pyi similarity index 95% rename from Test/LoopTest/temp/4b6b35e3922a169f.pyi rename to Test/LoopTest/temp/86e203c56ae4de20.pyi index b2fe521..ba09b5a 100644 --- a/Test/LoopTest/temp/4b6b35e3922a169f.pyi +++ b/Test/LoopTest/temp/86e203c56ae4de20.pyi @@ -8,6 +8,7 @@ import c import t import stdio +import testcheck def test_for_loop() -> t.CInt: pass diff --git a/Test/LoopTest/temp/9dbecd0942a39782.pyi b/Test/LoopTest/temp/9dbecd0942a39782.pyi new file mode 100644 index 0000000..41648c1 --- /dev/null +++ b/Test/LoopTest/temp/9dbecd0942a39782.pyi @@ -0,0 +1,25 @@ +""" +Auto-generated Python stub file from testcheck.py +Module: testcheck +""" + + +import t, c +import stdio + +_pass_count: t.CExtern | t.CInt +_fail_count: t.CExtern | t.CInt + +def begin(name: str) -> t.CInt: pass + +def section(name: str) -> t.CInt: pass + +def ok(msg: str) -> t.CInt: pass + +def fail(msg: str) -> t.CInt: pass + +def check(cond: t.CInt, ok_msg: str, fail_msg: str) -> t.CInt: pass + +def info(msg: str) -> t.CInt: pass + +def end() -> t.CInt: pass diff --git a/Test/LoopTest/temp/_sha1_map.txt b/Test/LoopTest/temp/_sha1_map.txt index 176573f..c2bffdb 100644 --- a/Test/LoopTest/temp/_sha1_map.txt +++ b/Test/LoopTest/temp/_sha1_map.txt @@ -1,2 +1,3 @@ -4b6b35e3922a169f:main.py 73edbcf76e32d00b:includes/stdio.py +86e203c56ae4de20:main.py +9dbecd0942a39782:includes/testcheck.py diff --git a/Test/PointerTest/App/main.py b/Test/PointerTest/App/main.py index bc6be7e..93bbd22 100644 --- a/Test/PointerTest/App/main.py +++ b/Test/PointerTest/App/main.py @@ -4,6 +4,7 @@ import stdio import string import w32.win32console import w32.win32memory +import testcheck # ============================================================ # PointerTest - 测试指针操作、global声明、数组退化、指针算术 @@ -49,7 +50,7 @@ def test_pointer_arithmetic(): """测试指针算术:偏移计算是否正确""" buf: t.CUInt32T | t.CPtr = w32.win32memory.VirtualAlloc(None, 256, 0x3000, 0x04) if not buf: - stdio.printf("FAIL: VirtualAlloc returned NULL\n") + testcheck.fail("pointer arithmetic: VirtualAlloc returned NULL") return string.memset(buf, 0, 256) @@ -63,16 +64,15 @@ def test_pointer_arithmetic(): v: t.CUInt32T = buf[i] expected: t.CUInt32T = t.CUInt32T(i * 100) if v != expected: - stdio.printf("FAIL: buf[%d] = 0x%x, expected 0x%x\n", i, v, expected) + stdio.printf("buf[%d] = 0x%x, expected 0x%x\n", i, v, expected) ok = 0 - if ok: - stdio.printf("PASS: pointer arithmetic (buf[i] = i*100)\n") + testcheck.check(ok, "pointer arithmetic (buf[i] = i*100)", "pointer arithmetic mismatch") # --- Test 3: 数组退化为指针 --- def test_array_decay(): """测试 list[t.CChar, N] 传递给 t.CConst | str 参数""" - arr: list[t.CChar, 32] + arr: t.CArray[t.CChar, 32] string.memset(c.Addr(arr), 0, 32) # 手动写入字符串 src: str = "Hello" @@ -81,7 +81,8 @@ def test_array_decay(): arr[5] = 0 # 传递给 print (接受 t.CConst | str) - stdio.printf("PASS: array decay -> %s\n", c.Addr(arr)) + stdio.printf("array decay -> %s\n", c.Addr(arr)) + testcheck.ok("array decay (Hello)") # --- Test 4: 指针类型转换 (CVoid/CPtr) --- @@ -89,7 +90,7 @@ def test_pointer_cast(): """测试指针与整数之间的类型转换""" buf: t.CUInt32T | t.CPtr = w32.win32memory.VirtualAlloc(None, 256, 0x3000, 0x04) if not buf: - stdio.printf("FAIL: VirtualAlloc returned NULL\n") + testcheck.fail("pointer cast: VirtualAlloc returned NULL") return string.memset(buf, 0, 256) @@ -101,9 +102,10 @@ def test_pointer_cast(): # 通过原始指针读取 if buf[0] == 0xDEADBEEF: - stdio.printf("PASS: pointer cast CVoid -> CUInt32T*\n") + testcheck.ok("pointer cast CVoid -> CUInt32T*") else: - stdio.printf("FAIL: pointer cast, got 0x%x\n", buf[0]) + stdio.printf("got 0x%x\n", buf[0]) + testcheck.fail("pointer cast failed") # --- Test 5: 指针偏移计算 (byte offset vs element offset) --- @@ -111,7 +113,7 @@ def test_pointer_offset(): """测试指针偏移:CUInt8T* + N 应该偏移 N 字节,CUInt32T* + N 应该偏移 N*4 字节""" buf: t.CUInt8T | t.CPtr = w32.win32memory.VirtualAlloc(None, 256, 0x3000, 0x04) if not buf: - stdio.printf("FAIL: VirtualAlloc returned NULL\n") + testcheck.fail("pointer offset: VirtualAlloc returned NULL") return string.memset(buf, 0, 256) @@ -127,9 +129,10 @@ def test_pointer_offset(): # little-endian: 0x44434241 if val == 0x44434241: - stdio.printf("PASS: byte offset vs element offset (0x%x)\n", val) + testcheck.ok("byte offset vs element offset (0x44434241)") else: - stdio.printf("FAIL: expected 0x44434241, got 0x%x\n", val) + stdio.printf("expected 0x44434241, got 0x%x\n", val) + testcheck.fail("byte offset vs element offset") # --- Test 6: 结构体指针访问 --- @@ -146,10 +149,8 @@ def test_struct_pointer(): s.c = 0x123456789ABCDEF0 p: TestStruct | t.CPtr = c.Addr(s) - if p.a == 10 and p.b == 20 and p.c == 0x123456789ABCDEF0: - stdio.printf("PASS: struct pointer access (a=%d b=%d c=0x%llx)\n", p.a, p.b, p.c) - else: - stdio.printf("FAIL: struct pointer access (a=%d b=%d c=0x%llx)\n", p.a, p.b, p.c) + stdio.printf("struct pointer access (a=%d b=%d c=0x%llx)\n", p.a, p.b, p.c) + testcheck.check(p.a == 10 and p.b == 20 and p.c == 0x123456789ABCDEF0, "struct pointer access", "struct pointer access mismatch") # --- Test 7: memcpy/memset 通过指针 --- @@ -158,7 +159,7 @@ def test_memcpy_pointers(): src_buf: t.CUInt32T | t.CPtr = w32.win32memory.VirtualAlloc(None, 64, 0x3000, 0x04) dst_buf: t.CUInt32T | t.CPtr = w32.win32memory.VirtualAlloc(None, 64, 0x3000, 0x04) if not src_buf or not dst_buf: - stdio.printf("FAIL: VirtualAlloc returned NULL\n") + testcheck.fail("memcpy: VirtualAlloc returned NULL") return # 初始化 src @@ -172,10 +173,9 @@ def test_memcpy_pointers(): ok: t.CInt = 1 for i in range(8): if dst_buf[i] != t.CUInt32T(i + 1000): - stdio.printf("FAIL: dst[%d] = %u, expected %u\n", i, dst_buf[i], i + 1000) + stdio.printf("dst[%d] = %u, expected %u\n", i, dst_buf[i], i + 1000) ok = 0 - if ok: - stdio.printf("PASS: memcpy between pointers\n") + testcheck.check(ok, "memcpy between pointers", "memcpy between pointers failed") # --- Test 8: 指针作为函数参数 --- @@ -187,7 +187,7 @@ def test_pointer_param(): """测试指针作为函数参数传递""" buf: t.CUInt32T | t.CPtr = w32.win32memory.VirtualAlloc(None, 64, 0x3000, 0x04) if not buf: - stdio.printf("FAIL: VirtualAlloc returned NULL\n") + testcheck.fail("pointer param: VirtualAlloc returned NULL") return fill_array(buf, 8, 0xCAFEBABE) @@ -196,72 +196,77 @@ def test_pointer_param(): for i in range(8): if buf[i] != 0xCAFEBABE: ok = 0 - if ok: - stdio.printf("PASS: pointer as function parameter\n") - else: - stdio.printf("FAIL: pointer as function parameter\n") + testcheck.check(ok, "pointer as function parameter", "pointer as function parameter failed") def main() -> t.CInt | t.CExport: w32.win32console.SetConsoleCP(65001) w32.win32console.SetConsoleOutputCP(65001) - stdio.printf("=== PointerTest: 指针操作基准测试 ===\n\n") + print("你好") + l: t.CArray[t.CChar, 2] = 0 + for i in "hello": + l[0] = i + print(l) + + u: t.CArray[t.CUInt64T | t.BigEndian, 2] = [0x4141414141414141, 0x0000000000000000] + for i in c.Addr(u): + # l[0] = i + stdio.printf("0x%llx\n", i) + + k: t.CArray[t.CChar, 12] = ['1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C'] + for i in k: + stdio.printf("%c\n", i) + + testcheck.begin("PointerTest: 指针操作基准测试") # Test 1: global 声明 - stdio.printf("--- Test 1: global declaration ---\n") + testcheck.section("Test 1: global declaration") _g_val = 0 test_global_write() stdio.printf("After test_global_write(): _g_val = %d (expect 42)\n", _g_val) test_global_write_no_decl() stdio.printf("After test_global_write_no_decl(): _g_val = %d (expect 42, not 99)\n", _g_val) - stdio.printf("\n") + testcheck.check(_g_val == 42, "global declaration (_g_val = 42)", "global declaration failed") # Test 1b: global pointer - stdio.printf("--- Test 1b: global pointer ---\n") + testcheck.section("Test 1b: global pointer") test_global_ptr() if _g_ptr: p: t.CUInt32T | t.CPtr = _g_ptr stdio.printf("_g_ptr[0] = 0x%x (expect 0xAABBCCDD)\n", p[0]) stdio.printf("_g_ptr[1] = 0x%x (expect 0x11223344)\n", p[1]) + testcheck.check(p[0] == 0xAABBCCDD and p[1] == 0x11223344, "global pointer values", "global pointer mismatch") test_global_ptr_no_decl() stdio.printf("After test_global_ptr_no_decl(): _g_ptr = %p (expect NULL/0)\n", t.CVoid(t.CUInt64T(_g_ptr), t.CPtr)) - stdio.printf("\n") + testcheck.ok("global ptr no decl (set to NULL)") # Test 2: pointer arithmetic - stdio.printf("--- Test 2: pointer arithmetic ---\n") + testcheck.section("Test 2: pointer arithmetic") test_pointer_arithmetic() - stdio.printf("\n") # Test 3: array decay - stdio.printf("--- Test 3: array decay ---\n") + testcheck.section("Test 3: array decay") test_array_decay() - stdio.printf("\n") # Test 4: pointer cast - stdio.printf("--- Test 4: pointer cast ---\n") + testcheck.section("Test 4: pointer cast") test_pointer_cast() - stdio.printf("\n") # Test 5: pointer offset - stdio.printf("--- Test 5: pointer offset (byte vs element) ---\n") + testcheck.section("Test 5: pointer offset (byte vs element)") test_pointer_offset() - stdio.printf("\n") # Test 6: struct pointer - stdio.printf("--- Test 6: struct pointer access ---\n") + testcheck.section("Test 6: struct pointer access") test_struct_pointer() - stdio.printf("\n") # Test 7: memcpy pointers - stdio.printf("--- Test 7: memcpy between pointers ---\n") + testcheck.section("Test 7: memcpy between pointers") test_memcpy_pointers() - stdio.printf("\n") # Test 8: pointer as param - stdio.printf("--- Test 8: pointer as function parameter ---\n") + testcheck.section("Test 8: pointer as function parameter") test_pointer_param() - stdio.printf("\n") - stdio.printf("=== PointerTest Complete ===\n") - return 0 + return testcheck.end() diff --git a/Test/PointerTest/output/067c78e9f121dce3.deps.json b/Test/PointerTest/output/067c78e9f121dce3.deps.json index d127b4f..5402d19 100644 --- a/Test/PointerTest/output/067c78e9f121dce3.deps.json +++ b/Test/PointerTest/output/067c78e9f121dce3.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "main": "e0c894447ac34ed3", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3"} \ No newline at end of file +{"stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "main": "b436212dcff1be29", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3"} \ No newline at end of file diff --git a/Test/PointerTest/output/29813d57621099a9.deps.json b/Test/PointerTest/output/29813d57621099a9.deps.json index 2104859..bfe22dc 100644 --- a/Test/PointerTest/output/29813d57621099a9.deps.json +++ b/Test/PointerTest/output/29813d57621099a9.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "main": "e0c894447ac34ed3", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file +{"stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "main": "b436212dcff1be29", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file diff --git a/Test/PointerTest/output/5a6a2137958c28c5.deps.json b/Test/PointerTest/output/5a6a2137958c28c5.deps.json index e0323b2..477ea34 100644 --- a/Test/PointerTest/output/5a6a2137958c28c5.deps.json +++ b/Test/PointerTest/output/5a6a2137958c28c5.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "main": "e0c894447ac34ed3", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file +{"stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "main": "b436212dcff1be29", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c"} \ No newline at end of file diff --git a/Test/PointerTest/output/6aee24fdefa3cbc0.deps.json b/Test/PointerTest/output/6aee24fdefa3cbc0.deps.json deleted file mode 100644 index ee07c04..0000000 --- a/Test/PointerTest/output/6aee24fdefa3cbc0.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "main": "e0c894447ac34ed3"} \ No newline at end of file diff --git a/Test/PointerTest/output/72e2d5ccb7cedcf1.deps.json b/Test/PointerTest/output/72e2d5ccb7cedcf1.deps.json index eb46ab1..c5d8cf7 100644 --- a/Test/PointerTest/output/72e2d5ccb7cedcf1.deps.json +++ b/Test/PointerTest/output/72e2d5ccb7cedcf1.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "main": "e0c894447ac34ed3", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e"} \ No newline at end of file +{"stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "main": "b436212dcff1be29", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file diff --git a/Test/PointerTest/output/9dbecd0942a39782.deps.json b/Test/PointerTest/output/9dbecd0942a39782.deps.json new file mode 100644 index 0000000..477ea34 --- /dev/null +++ b/Test/PointerTest/output/9dbecd0942a39782.deps.json @@ -0,0 +1 @@ +{"stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "main": "b436212dcff1be29", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c"} \ No newline at end of file diff --git a/Test/PointerTest/output/abf9ce3160c9279e.deps.json b/Test/PointerTest/output/abf9ce3160c9279e.deps.json index eb46ab1..5f4258d 100644 --- a/Test/PointerTest/output/abf9ce3160c9279e.deps.json +++ b/Test/PointerTest/output/abf9ce3160c9279e.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "main": "e0c894447ac34ed3", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e"} \ No newline at end of file +{"stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "main": "b436212dcff1be29", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e"} \ No newline at end of file diff --git a/Test/PointerTest/output/b436212dcff1be29.deps.json b/Test/PointerTest/output/b436212dcff1be29.deps.json new file mode 100644 index 0000000..6aae5c2 --- /dev/null +++ b/Test/PointerTest/output/b436212dcff1be29.deps.json @@ -0,0 +1 @@ +{"stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c"} \ No newline at end of file diff --git a/Test/PointerTest/output/b5f1dc665c52a1bd.deps.json b/Test/PointerTest/output/b5f1dc665c52a1bd.deps.json new file mode 100644 index 0000000..477ea34 --- /dev/null +++ b/Test/PointerTest/output/b5f1dc665c52a1bd.deps.json @@ -0,0 +1 @@ +{"stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "main": "b436212dcff1be29", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c"} \ No newline at end of file diff --git a/Test/PointerTest/output/bbdf3bbd4c3bc28c.deps.json b/Test/PointerTest/output/bbdf3bbd4c3bc28c.deps.json index e0323b2..477ea34 100644 --- a/Test/PointerTest/output/bbdf3bbd4c3bc28c.deps.json +++ b/Test/PointerTest/output/bbdf3bbd4c3bc28c.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "main": "e0c894447ac34ed3", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file +{"stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "main": "b436212dcff1be29", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c"} \ No newline at end of file diff --git a/Test/PointerTest/output/e0c894447ac34ed3.deps.json b/Test/PointerTest/output/e0c894447ac34ed3.deps.json deleted file mode 100644 index 2fc9271..0000000 --- a/Test/PointerTest/output/e0c894447ac34ed3.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c"} \ No newline at end of file diff --git a/Test/PointerTest/output/fa3691e66b426950.deps.json b/Test/PointerTest/output/fa3691e66b426950.deps.json index e0323b2..c5d8cf7 100644 --- a/Test/PointerTest/output/fa3691e66b426950.deps.json +++ b/Test/PointerTest/output/fa3691e66b426950.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "main": "e0c894447ac34ed3", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file +{"stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "main": "b436212dcff1be29", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file diff --git a/Test/PointerTest/temp/49bd8cba55979f76.pyi b/Test/PointerTest/temp/49bd8cba55979f76.pyi new file mode 100644 index 0000000..f1d844a --- /dev/null +++ b/Test/PointerTest/temp/49bd8cba55979f76.pyi @@ -0,0 +1,75 @@ +""" +Auto-generated Python stub file from stdint.py +Module: stdint +""" + +import c + + +import t + +INT: t.CTypedef = t.CInt +INTPTR: t.CTypedef = t.CInt | t.CPtr +BOOL: t.CTypedef = t.CInt +UINT: t.CTypedef = t.CUnsignedInt +UINTPTR: t.CTypedef = UINT | t.CPtr +BYTE: t.CTypedef = t.CUnsignedChar +BYTEPTR: t.CTypedef = BYTE | t.CPtr +WORD: t.CTypedef = t.CUInt16T +DWORD: t.CTypedef = t.CUInt32T +QWORD: t.CTypedef = t.CUInt64T +TCHAR: t.CTypedef = t.CChar +CHARLIST: t.CTypedef = str | t.CPtr +VOID: t.CTypedef = t.CVoid +SHORT: t.CTypedef = t.CShort +SHORTPTR: t.CTypedef = t.CShort | t.CPtr +USHORT: t.CTypedef = t.CUnsignedShort +USHORTPTR: t.CTypedef = t.CUnsignedShort | t.CPtr +LONGLONG: t.CTypedef = t.CLong | t.CLong +ULONGLONG: t.CTypedef = t.CUnsignedLong | t.CLong +LONG: t.CTypedef = t.CLong +ULONG: t.CTypedef = t.CUnsignedLong +WCHAR: t.CTypedef = WORD +WCHARPTR: t.CTypedef = WORD | t.CPtr +CHARPTR: t.CTypedef = t.CChar | t.CPtr +FSIZE_t: t.CTypedef = DWORD +LBA_t: t.CTypedef = DWORD +UINTPTR: t.CTypedef = t.CUnsignedInt | t.CPtr +VOIDPTR: t.CTypedef = t.CVoid | t.CPtr +FLOAT: t.CTypedef = t.CFloat +DOUBLE: t.CTypedef = t.CDouble +FLOAT8: t.CTypedef = t.CFloat8T +FLOAT16: t.CTypedef = t.CFloat16T +FLOAT32: t.CTypedef = t.CFloat32T +FLOAT64: t.CTypedef = t.CFloat64T +FLOAT128: t.CTypedef = t.CFloat128T +INT8: t.CTypedef = t.CInt8T +INT16: t.CTypedef = t.CInt16T +INT32: t.CTypedef = t.CInt32T +INT64: t.CTypedef = t.CInt64T +UINT8: t.CTypedef = t.CUInt8T +UINT16: t.CTypedef = t.CUInt16T +UINT32: t.CTypedef = t.CUInt32T +UINT64: t.CTypedef = t.CUInt64T +INT8PTR: t.CTypedef = t.CInt8T | t.CPtr +INT16PTR: t.CTypedef = t.CInt16T | t.CPtr +INT32PTR: t.CTypedef = t.CInt32T | t.CPtr +INT64PTR: t.CTypedef = t.CInt64T | t.CPtr +UINT8PTR: t.CTypedef = t.CUInt8T | t.CPtr +UINT16PTR: t.CTypedef = t.CUInt16T | t.CPtr +UINT32PTR: t.CTypedef = t.CUInt32T | t.CPtr +UINT64PTR: t.CTypedef = t.CUInt64T | t.CPtr +CHAR8: t.CTypedef = t.CChar8T +CHAR16: t.CTypedef = t.CChar16T +CHAR32: t.CTypedef = t.CChar32T +CHAR8PTR: t.CTypedef = t.CChar8T | t.CPtr +CHAR16PTR: t.CTypedef = t.CChar16T | t.CPtr +CHAR32PTR: t.CTypedef = t.CChar32T | t.CPtr +i8: t.CTypedef = t.CInt8T +i16: t.CTypedef = t.CInt16T +i32: t.CTypedef = t.CInt32T +i64: t.CTypedef = t.CInt64T +u8: t.CTypedef = t.CUInt8T +u16: t.CTypedef = t.CUInt16T +u32: t.CTypedef = t.CUInt32T +u64: t.CTypedef = t.CUInt64T \ No newline at end of file diff --git a/Test/PointerTest/temp/56cdd754a8a09347.pyi b/Test/PointerTest/temp/56cdd754a8a09347.pyi deleted file mode 100644 index 007ccb8..0000000 --- a/Test/PointerTest/temp/56cdd754a8a09347.pyi +++ /dev/null @@ -1,67 +0,0 @@ -""" -Auto-generated Python stub file from stdint.py -Module: stdint -""" - -import c - - -import t - -INT: t.CTypedef = t.CInt -INTPTR: t.CTypedef = t.CInt | t.CPtr -BOOL: t.CTypedef = t.CInt -UINT: t.CTypedef = t.CUnsignedInt -UINTPTR: t.CTypedef = UINT | t.CPtr -BYTE: t.CTypedef = t.CUnsignedChar -BYTEPTR: t.CTypedef = BYTE | t.CPtr -WORD: t.CTypedef = t.CUInt16T -DWORD: t.CTypedef = t.CUInt32T -QWORD: t.CTypedef = t.CUInt64T -TCHAR: t.CTypedef = t.CChar -CHARLIST: t.CTypedef = str | t.CPtr -VOID: t.CTypedef = t.CVoid -SHORT: t.CTypedef = t.CShort -SHORTPTR: t.CTypedef = t.CShort | t.CPtr -USHORT: t.CTypedef = t.CUnsignedShort -USHORTPTR: t.CTypedef = t.CUnsignedShort | t.CPtr -LONGLONG: t.CTypedef = t.CLong | t.CLong -ULONGLONG: t.CTypedef = t.CUnsignedLong | t.CLong -LONG: t.CTypedef = t.CLong -ULONG: t.CTypedef = t.CUnsignedLong -WCHAR: t.CTypedef = WORD -WCHARPTR: t.CTypedef = WORD | t.CPtr -CHARPTR: t.CTypedef = t.CChar | t.CPtr -FSIZE_t: t.CTypedef = DWORD -LBA_t: t.CTypedef = DWORD -UINTPTR: t.CTypedef = t.CUnsignedInt | t.CPtr -VOIDPTR: t.CTypedef = t.CVoid | t.CPtr -FLOAT: t.CTypedef = t.CFloat -DOUBLE: t.CTypedef = t.CDouble -FLOAT8: t.CTypedef = t.CFloat8T -FLOAT16: t.CTypedef = t.CFloat16T -FLOAT32: t.CTypedef = t.CFloat32T -FLOAT64: t.CTypedef = t.CFloat64T -FLOAT128: t.CTypedef = t.CFloat128T -INT8: t.CTypedef = t.CInt8T -INT16: t.CTypedef = t.CInt16T -INT32: t.CTypedef = t.CInt32T -INT64: t.CTypedef = t.CInt64T -UINT8: t.CTypedef = t.CUInt8T -UINT16: t.CTypedef = t.CUInt16T -UINT32: t.CTypedef = t.CUInt32T -UINT64: t.CTypedef = t.CUInt64T -INT8PTR: t.CTypedef = t.CInt8T | t.CPtr -INT16PTR: t.CTypedef = t.CInt16T | t.CPtr -INT32PTR: t.CTypedef = t.CInt32T | t.CPtr -INT64PTR: t.CTypedef = t.CInt64T | t.CPtr -UINT8PTR: t.CTypedef = t.CUInt8T | t.CPtr -UINT16PTR: t.CTypedef = t.CUInt16T | t.CPtr -UINT32PTR: t.CTypedef = t.CUInt32T | t.CPtr -UINT64PTR: t.CTypedef = t.CUInt64T | t.CPtr -CHAR8: t.CTypedef = t.CChar8T -CHAR16: t.CTypedef = t.CChar16T -CHAR32: t.CTypedef = t.CChar32T -CHAR8PTR: t.CTypedef = t.CChar8T | t.CPtr -CHAR16PTR: t.CTypedef = t.CChar16T | t.CPtr -CHAR32PTR: t.CTypedef = t.CChar32T | t.CPtr \ No newline at end of file diff --git a/Test/PointerTest/temp/9dbecd0942a39782.pyi b/Test/PointerTest/temp/9dbecd0942a39782.pyi new file mode 100644 index 0000000..41648c1 --- /dev/null +++ b/Test/PointerTest/temp/9dbecd0942a39782.pyi @@ -0,0 +1,25 @@ +""" +Auto-generated Python stub file from testcheck.py +Module: testcheck +""" + + +import t, c +import stdio + +_pass_count: t.CExtern | t.CInt +_fail_count: t.CExtern | t.CInt + +def begin(name: str) -> t.CInt: pass + +def section(name: str) -> t.CInt: pass + +def ok(msg: str) -> t.CInt: pass + +def fail(msg: str) -> t.CInt: pass + +def check(cond: t.CInt, ok_msg: str, fail_msg: str) -> t.CInt: pass + +def info(msg: str) -> t.CInt: pass + +def end() -> t.CInt: pass diff --git a/Test/PointerTest/temp/_sha1_map.txt b/Test/PointerTest/temp/_sha1_map.txt index ce6bb1a..3c430c0 100644 --- a/Test/PointerTest/temp/_sha1_map.txt +++ b/Test/PointerTest/temp/_sha1_map.txt @@ -1,7 +1,8 @@ -56cdd754a8a09347:includes/stdint.py +49bd8cba55979f76:includes/stdint.py 5a6a2137958c28c5:includes/w32\win32base.py -6aee24fdefa3cbc0:includes/string.py 72e2d5ccb7cedcf1:includes/w32\win32memory.py 73edbcf76e32d00b:includes/stdio.py +9dbecd0942a39782:includes/testcheck.py +b436212dcff1be29:main.py +b5f1dc665c52a1bd:includes/string.py bbdf3bbd4c3bc28c:includes/w32\win32console.py -e0c894447ac34ed3:main.py diff --git a/Test/PointerTest/temp/e0c894447ac34ed3.pyi b/Test/PointerTest/temp/b436212dcff1be29.pyi similarity index 98% rename from Test/PointerTest/temp/e0c894447ac34ed3.pyi rename to Test/PointerTest/temp/b436212dcff1be29.pyi index 1f0670c..ab57c0d 100644 --- a/Test/PointerTest/temp/e0c894447ac34ed3.pyi +++ b/Test/PointerTest/temp/b436212dcff1be29.pyi @@ -10,6 +10,7 @@ import stdio import string import w32.win32console import w32.win32memory +import testcheck _g_val: t.CExtern | t.CInt _g_ptr: t.CExtern | t.CUInt32T | t.CPtr diff --git a/Test/PointerTest/temp/b5f1dc665c52a1bd.pyi b/Test/PointerTest/temp/b5f1dc665c52a1bd.pyi new file mode 100644 index 0000000..8b6959e --- /dev/null +++ b/Test/PointerTest/temp/b5f1dc665c52a1bd.pyi @@ -0,0 +1,44 @@ +""" +Auto-generated Python stub file from string.py +Module: string +""" + + +from stdint import * +import t, c + +def strcpy(dest: str, src: str) -> str: pass + +def strncpy(dest: str, src: str, n: t.CSizeT) -> str: pass + +def strlen(src: str) -> t.CSizeT | t.CExport: pass + +def strcmp(str1: str, str2: str) -> t.CInt: pass + +def samestr(str1: str, str2: str) -> bool: pass + +def strncmp(str1: str, str2: str, n: t.CSizeT) -> t.CInt: pass + +def memcmp(ptr1: t.CVoid | t.CPtr, ptr2: t.CVoid | t.CPtr, n: t.CSizeT) -> t.CInt: pass + +def strchr(s: str, cr: t.CInt) -> str: pass + +def strrchr(s: str, cr: t.CInt) -> str: pass + +def strspn(s: str, skip: str) -> int: pass + +def memset(ptr: t.CVoid | t.CPtr, value: t.CInt, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass + +def memset32(ptr: t.CVoid | t.CPtr, value: t.CUInt32T, count: t.CSizeT) -> t.CVoid | t.CPtr: pass + +def memcpy(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass + +def memmove(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr: pass + +def atoi(src: str) -> t.CInt: pass + +def atoll(src: str) -> t.CInt64T: pass + +def atof(src: str) -> t.CDouble: pass + +def split(s: str, delim: str, result: t.CArray[str]) -> int: pass diff --git a/Test/ShortCircuitTest/App/main.py b/Test/ShortCircuitTest/App/main.py new file mode 100644 index 0000000..925866b --- /dev/null +++ b/Test/ShortCircuitTest/App/main.py @@ -0,0 +1,122 @@ +from stdint import * +import w32.win32console +import t, c +from t import CInt, CExport +import stdio +import stdlib +import string +import testcheck + + +# 副作用函数:将 buf[0] 置为 1,返回 True +def bump_true(buf: bytes) -> bool: + buf[0] = 1 + return True + + +# 副作用函数:将 buf[0] 置为 1,返回 False +def bump_false(buf: bytes) -> bool: + buf[0] = 1 + return False + + +def main() -> CInt | CExport: + w32.win32console.SetConsoleCP(65001) + w32.win32console.SetConsoleOutputCP(65001) + + testcheck.begin("if 短路机制测试") + + buf: bytes = stdlib.malloc(1) + + # === Test 1: False and bump_true() - bump 不应被调用 === + testcheck.section("Test 1: False and bump_true()") + buf[0] = 0 + r1: bool = False and bump_true(buf) + testcheck.check(buf[0] == 0, "and short-circuit OK (bump not called)", "and short-circuit FAILED (bump called)") + + # === Test 2: True or bump_true() - bump 不应被调用 === + testcheck.section("Test 2: True or bump_true()") + buf[0] = 0 + r2: bool = True or bump_true(buf) + testcheck.check(buf[0] == 0, "or short-circuit OK (bump not called)", "or short-circuit FAILED (bump called)") + + # === Test 3: True and bump_true() - bump 应被调用 === + testcheck.section("Test 3: True and bump_true()") + buf[0] = 0 + r3: bool = True and bump_true(buf) + testcheck.check(buf[0] == 1, "and eval OK (bump called)", "and eval FAILED (bump not called)") + + # === Test 4: False or bump_true() - bump 应被调用 === + testcheck.section("Test 4: False or bump_true()") + buf[0] = 0 + r4: bool = False or bump_true(buf) + testcheck.check(buf[0] == 1, "or eval OK (bump called)", "or eval FAILED (bump not called)") + + # === Test 5: if 语句中的短路 === + testcheck.section("Test 5: if 语句中的短路") + buf[0] = 0 + if False and bump_true(buf): + testcheck.check(False, "should not enter if", "if False and entered") + testcheck.check(buf[0] == 0, "if and short-circuit OK", "if and short-circuit FAILED") + + buf[0] = 0 + if True or bump_true(buf): + testcheck.check(True, "if True or entered OK", "if True or not entered") + else: + testcheck.check(False, "should enter if", "if True or else") + testcheck.check(buf[0] == 0, "if or short-circuit OK", "if or short-circuit FAILED") + + # === Test 6: 嵌套短路 === + testcheck.section("Test 6: 嵌套短路") + buf[0] = 0 + r6: bool = False and (True or bump_true(buf)) + testcheck.check(buf[0] == 0, "nested and short-circuit OK", "nested and short-circuit FAILED") + + buf[0] = 0 + r7: bool = True or (False and bump_true(buf)) + testcheck.check(buf[0] == 0, "nested or short-circuit OK", "nested or short-circuit FAILED") + + # === Test 7: not 与短路 === + testcheck.section("Test 7: not 与短路") + buf[0] = 0 + r8: bool = not False and bump_true(buf) + testcheck.check(buf[0] == 1, "not and eval OK (bump called)", "not and eval FAILED (bump not called)") + + buf[0] = 0 + r9: bool = not True or bump_true(buf) + testcheck.check(buf[0] == 1, "not or eval OK (bump called)", "not or eval FAILED (bump not called)") + + # === Test 8: and 链中第一个为 False,后续不评估 === + testcheck.section("Test 8: and 链短路") + buf[0] = 0 + r10: bool = False and bump_true(buf) and bump_true(buf) + testcheck.check(buf[0] == 0, "and chain short-circuit OK", "and chain short-circuit FAILED") + + # === Test 9: or 链中第一个为 True,后续不评估 === + testcheck.section("Test 9: or 链短路") + buf[0] = 0 + r11: bool = True or bump_true(buf) or bump_true(buf) + testcheck.check(buf[0] == 0, "or chain short-circuit OK", "or chain short-circuit FAILED") + + # === Test 10: and 返回值正确性 === + testcheck.section("Test 10: and 返回值正确性") + buf[0] = 0 + r12: bool = True and bump_true(buf) + testcheck.check(r12, "and return True OK", "and return True FAILED") + + buf[0] = 0 + r13: bool = True and bump_false(buf) + testcheck.check(not r13, "and return False OK", "and return False FAILED") + + # === Test 11: or 返回值正确性 === + testcheck.section("Test 11: or 返回值正确性") + buf[0] = 0 + r14: bool = False or bump_true(buf) + testcheck.check(r14, "or return True OK", "or return True FAILED") + + buf[0] = 0 + r15: bool = False or bump_false(buf) + testcheck.check(not r15, "or return False OK", "or return False FAILED") + + stdlib.free(buf) + return testcheck.end() diff --git a/Test/ShortCircuitTest/output/067c78e9f121dce3.deps.json b/Test/ShortCircuitTest/output/067c78e9f121dce3.deps.json new file mode 100644 index 0000000..b94340f --- /dev/null +++ b/Test/ShortCircuitTest/output/067c78e9f121dce3.deps.json @@ -0,0 +1 @@ +{"stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "main": "a711c9c66fd7c6ca", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3"} \ No newline at end of file diff --git a/Test/ShortCircuitTest/output/06f53cc594b4ac6c.deps.json b/Test/ShortCircuitTest/output/06f53cc594b4ac6c.deps.json new file mode 100644 index 0000000..fd69cc6 --- /dev/null +++ b/Test/ShortCircuitTest/output/06f53cc594b4ac6c.deps.json @@ -0,0 +1 @@ +{"stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "main": "a711c9c66fd7c6ca", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "06f53cc594b4ac6c", "win32sync": "06f53cc594b4ac6c"} \ No newline at end of file diff --git a/Test/ShortCircuitTest/output/5a6a2137958c28c5.deps.json b/Test/ShortCircuitTest/output/5a6a2137958c28c5.deps.json new file mode 100644 index 0000000..0285767 --- /dev/null +++ b/Test/ShortCircuitTest/output/5a6a2137958c28c5.deps.json @@ -0,0 +1 @@ +{"stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "main": "a711c9c66fd7c6ca", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c"} \ No newline at end of file diff --git a/Test/ShortCircuitTest/output/72e2d5ccb7cedcf1.deps.json b/Test/ShortCircuitTest/output/72e2d5ccb7cedcf1.deps.json new file mode 100644 index 0000000..672f5fb --- /dev/null +++ b/Test/ShortCircuitTest/output/72e2d5ccb7cedcf1.deps.json @@ -0,0 +1 @@ +{"stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "main": "a711c9c66fd7c6ca", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1"} \ No newline at end of file diff --git a/Test/ShortCircuitTest/output/9dbecd0942a39782.deps.json b/Test/ShortCircuitTest/output/9dbecd0942a39782.deps.json new file mode 100644 index 0000000..0285767 --- /dev/null +++ b/Test/ShortCircuitTest/output/9dbecd0942a39782.deps.json @@ -0,0 +1 @@ +{"stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "main": "a711c9c66fd7c6ca", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c"} \ No newline at end of file diff --git a/Test/ShortCircuitTest/output/a711c9c66fd7c6ca.deps.json b/Test/ShortCircuitTest/output/a711c9c66fd7c6ca.deps.json new file mode 100644 index 0000000..1406042 --- /dev/null +++ b/Test/ShortCircuitTest/output/a711c9c66fd7c6ca.deps.json @@ -0,0 +1 @@ +{"stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c"} \ No newline at end of file diff --git a/Test/ShortCircuitTest/output/abf9ce3160c9279e.deps.json b/Test/ShortCircuitTest/output/abf9ce3160c9279e.deps.json new file mode 100644 index 0000000..2087f32 --- /dev/null +++ b/Test/ShortCircuitTest/output/abf9ce3160c9279e.deps.json @@ -0,0 +1 @@ +{"stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "main": "a711c9c66fd7c6ca", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e"} \ No newline at end of file diff --git a/Test/ShortCircuitTest/output/b5f1dc665c52a1bd.deps.json b/Test/ShortCircuitTest/output/b5f1dc665c52a1bd.deps.json new file mode 100644 index 0000000..0285767 --- /dev/null +++ b/Test/ShortCircuitTest/output/b5f1dc665c52a1bd.deps.json @@ -0,0 +1 @@ +{"stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "main": "a711c9c66fd7c6ca", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c"} \ No newline at end of file diff --git a/Test/ShortCircuitTest/output/bbdf3bbd4c3bc28c.deps.json b/Test/ShortCircuitTest/output/bbdf3bbd4c3bc28c.deps.json new file mode 100644 index 0000000..0285767 --- /dev/null +++ b/Test/ShortCircuitTest/output/bbdf3bbd4c3bc28c.deps.json @@ -0,0 +1 @@ +{"stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "main": "a711c9c66fd7c6ca", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c"} \ No newline at end of file diff --git a/Test/ShortCircuitTest/output/fa3691e66b426950.deps.json b/Test/ShortCircuitTest/output/fa3691e66b426950.deps.json new file mode 100644 index 0000000..a2fc43c --- /dev/null +++ b/Test/ShortCircuitTest/output/fa3691e66b426950.deps.json @@ -0,0 +1 @@ +{"stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "main": "a711c9c66fd7c6ca", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file diff --git a/Test/ShortCircuitTest/project.json b/Test/ShortCircuitTest/project.json new file mode 100644 index 0000000..de206e7 --- /dev/null +++ b/Test/ShortCircuitTest/project.json @@ -0,0 +1,29 @@ +{ + "$schema": "https://raw.githubusercontent.com/TermiNexus/TransPyC/main/schemas/project-schema.json", + "name": "ShortCircuitTest", + "version": "1.0.0", + "source_dir": "./App", + "temp_dir": "./temp", + "output_dir": "./output", + "compiler": { + "cmd": "llc", + "flags": ["-filetype=obj", "-relocation-model=pic"] + }, + "linker": { + "cmd": "clang++", + "flags": ["-lmsvcrt", "-lucrt", "-lpthread", "-lmingwex", "-lkernel32", "-Wl,--allow-multiple-definition"], + "output": "ShortCircuitTest.exe" + }, + "includes": [ + "./includes" + ], + "target": { + "triple": "x86_64-pc-windows-gnu", + "datalayout": "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" + }, + "options": { + "slice_level": 3, + "target": "llvm", + "strict_mode": true + } +} diff --git a/Test/ShortCircuitTest/temp/067c78e9f121dce3.pyi b/Test/ShortCircuitTest/temp/067c78e9f121dce3.pyi new file mode 100644 index 0000000..f4f767c --- /dev/null +++ b/Test/ShortCircuitTest/temp/067c78e9f121dce3.pyi @@ -0,0 +1,136 @@ +""" +Auto-generated Python stub file from w32.win32process.py +Module: w32.win32process +""" + +import c + + +import t +from stdint import * +from w32.win32base import * + +PROCESS_TERMINATE: t.CDefine = 0x0001 +PROCESS_CREATE_THREAD: t.CDefine = 0x0002 +PROCESS_VM_OPERATION: t.CDefine = 0x0008 +PROCESS_VM_READ: t.CDefine = 0x0010 +PROCESS_VM_WRITE: t.CDefine = 0x0020 +PROCESS_QUERY_INFORMATION: t.CDefine = 0x0400 +PROCESS_ALL_ACCESS: t.CDefine = 0x001FFFFF +THREAD_TERMINATE: t.CDefine = 0x0001 +THREAD_SUSPEND_RESUME: t.CDefine = 0x0002 +THREAD_GET_CONTEXT: t.CDefine = 0x0008 +THREAD_SET_CONTEXT: t.CDefine = 0x0010 +THREAD_QUERY_INFORMATION: t.CDefine = 0x0040 +THREAD_ALL_ACCESS: t.CDefine = 0x001FFFFF +CREATE_SUSPENDED: t.CDefine = 0x00000004 +CREATE_NEW_CONSOLE: t.CDefine = 0x00000010 +CREATE_NEW_PROCESS_GROUP: t.CDefine = 0x00000200 +CREATE_NO_WINDOW: t.CDefine = 0x08000000 +DETACHED_PROCESS: t.CDefine = 0x00000008 +STARTF_USESHOWWINDOW: t.CDefine = 0x00000001 +STARTF_USESTDHANDLES: t.CDefine = 0x00000100 +SW_HIDE: t.CDefine = 0 +SW_SHOW: t.CDefine = 5 +SW_MINIMIZE: t.CDefine = 6 +NORMAL_PRIORITY_CLASS: t.CDefine = 0x00000020 +IDLE_PRIORITY_CLASS: t.CDefine = 0x00000040 +HIGH_PRIORITY_CLASS: t.CDefine = 0x00000080 +REALTIME_PRIORITY_CLASS: t.CDefine = 0x00000100 +BELOW_NORMAL_PRIORITY_CLASS: t.CDefine = 0x00004000 +ABOVE_NORMAL_PRIORITY_CLASS: t.CDefine = 0x00008000 +STILL_ACTIVE: t.CDefine = 259 + +class STARTUPINFOA: + cb: ULONG + lpReserved: CHARPTR + lpDesktop: CHARPTR + lpTitle: CHARPTR + dwX: ULONG + dwY: ULONG + dwXSize: ULONG + dwYSize: ULONG + dwXCountChars: ULONG + dwYCountChars: ULONG + dwFillAttribute: ULONG + dwFlags: ULONG + wShowWindow: WORD + cbReserved2: WORD + lpReserved2: VOIDPTR + hStdInput: HANDLE + hStdOutput: HANDLE + hStdError: HANDLE +class STARTUPINFOW: + cb: ULONG + lpReserved: WCHARPTR + lpDesktop: WCHARPTR + lpTitle: WCHARPTR + dwX: ULONG + dwY: ULONG + dwXSize: ULONG + dwYSize: ULONG + dwXCountChars: ULONG + dwYCountChars: ULONG + dwFillAttribute: ULONG + dwFlags: ULONG + wShowWindow: WORD + cbReserved2: WORD + lpReserved2: VOIDPTR + hStdInput: HANDLE + hStdOutput: HANDLE + hStdError: HANDLE +class PROCESS_INFORMATION: + hProcess: HANDLE + hThread: HANDLE + dwProcessId: ULONG + dwThreadId: ULONG + +def CreateProcessA(lpApplicationName: LPCSTR, lpCommandLine: CHARPTR, lpProcessAttributes: SECURITY_ATTRIBUTES | t.CPtr, lpThreadAttributes: SECURITY_ATTRIBUTES | t.CPtr, bInheritHandles: BOOL, dwCreationFlags: ULONG, lpEnvironment: VOIDPTR, lpCurrentDirectory: LPCSTR, lpStartupInfo: STARTUPINFOA | t.CPtr, lpProcessInformation: PROCESS_INFORMATION | t.CPtr) -> BOOL | t.State: pass + +def CreateProcessW(lpApplicationName: LPCWSTR, lpCommandLine: WCHARPTR, lpProcessAttributes: SECURITY_ATTRIBUTES | t.CPtr, lpThreadAttributes: SECURITY_ATTRIBUTES | t.CPtr, bInheritHandles: BOOL, dwCreationFlags: ULONG, lpEnvironment: VOIDPTR, lpCurrentDirectory: LPCWSTR, lpStartupInfo: STARTUPINFOW | t.CPtr, lpProcessInformation: PROCESS_INFORMATION | t.CPtr) -> BOOL | t.State: pass + +def TerminateProcess(hProcess: HANDLE, uExitCode: UINT) -> BOOL | t.State: pass + +def GetExitCodeProcess(hProcess: HANDLE, lpExitCode: ULONG | t.CPtr) -> BOOL | t.State: pass + +def GetExitCodeThread(hThread: HANDLE, lpExitCode: ULONG | t.CPtr) -> BOOL | t.State: pass + +def OpenProcess(dwDesiredAccess: ULONG, bInheritHandle: BOOL, dwProcessId: ULONG) -> HANDLE | t.State: pass + +def GetCurrentProcess() -> HANDLE | t.State: pass + +def GetCurrentProcessId() -> ULONG | t.State: pass + +def CreateThread(lpThreadAttributes: SECURITY_ATTRIBUTES | t.CPtr, dwStackSize: t.CSizeT, lpStartAddress: VOIDPTR, lpParameter: VOIDPTR, dwCreationFlags: ULONG, lpThreadId: ULONG | t.CPtr) -> HANDLE | t.State: pass + +def OpenThread(dwDesiredAccess: ULONG, bInheritHandle: BOOL, dwThreadId: ULONG) -> HANDLE | t.State: pass + +def SuspendThread(hThread: HANDLE) -> ULONG | t.State: pass + +def ResumeThread(hThread: HANDLE) -> ULONG | t.State: pass + +def TerminateThread(hThread: HANDLE, dwExitCode: ULONG) -> BOOL | t.State: pass + +def GetCurrentThread() -> HANDLE | t.State: pass + +def GetCurrentThreadId() -> ULONG | t.State: pass + +def GetThreadId(hThread: HANDLE) -> ULONG | t.State: pass + +def GetProcessId(hProcess: HANDLE) -> ULONG | t.State: pass + +def SetThreadPriority(hThread: HANDLE, nPriority: INT) -> BOOL | t.State: pass + +def GetThreadPriority(hThread: HANDLE) -> INT | t.State: pass + +def ExitProcess(uExitCode: UINT) -> VOID | t.State: pass + +def ExitThread(dwExitCode: ULONG) -> VOID | t.State: pass + +def TlsAlloc() -> ULONG | t.State: pass + +def TlsFree(dwTlsIndex: ULONG) -> BOOL | t.State: pass + +def TlsGetValue(dwTlsIndex: ULONG) -> VOIDPTR | t.State: pass + +def TlsSetValue(dwTlsIndex: ULONG, lpTlsValue: VOIDPTR) -> BOOL | t.State: pass diff --git a/Test/ShortCircuitTest/temp/06f53cc594b4ac6c.pyi b/Test/ShortCircuitTest/temp/06f53cc594b4ac6c.pyi new file mode 100644 index 0000000..8b5a8cf --- /dev/null +++ b/Test/ShortCircuitTest/temp/06f53cc594b4ac6c.pyi @@ -0,0 +1,109 @@ +""" +Auto-generated Python stub file from w32.win32sync.py +Module: w32.win32sync +""" + +import c + + +import t +from stdint import * +from w32.win32base import * + +class CRITICAL_SECTION: + DebugInfo: VOIDPTR + LockCount: LONG + RecursionCount: LONG + OwningThread: HANDLE + LockSemaphore: HANDLE + SpinCount: QWORD + +def InitializeCriticalSection(lpCriticalSection: CRITICAL_SECTION | t.CPtr) -> VOID | t.State: pass + +def EnterCriticalSection(lpCriticalSection: CRITICAL_SECTION | t.CPtr) -> VOID | t.State: pass + +def LeaveCriticalSection(lpCriticalSection: CRITICAL_SECTION | t.CPtr) -> VOID | t.State: pass + +def DeleteCriticalSection(lpCriticalSection: CRITICAL_SECTION | t.CPtr) -> VOID | t.State: pass + +def TryEnterCriticalSection(lpCriticalSection: CRITICAL_SECTION | t.CPtr) -> BOOL | t.State: pass + +def SetCriticalSectionSpinCount(lpCriticalSection: CRITICAL_SECTION | t.CPtr, dwSpinCount: ULONG) -> ULONG | t.State: pass + +def InitializeCriticalSectionAndSpinCount(lpCriticalSection: CRITICAL_SECTION | t.CPtr, dwSpinCount: ULONG) -> BOOL | t.State: pass + +def CreateMutexA(lpMutexAttributes: SECURITY_ATTRIBUTES | t.CPtr, bInitialOwner: BOOL, lpName: LPCSTR) -> HANDLE | t.State: pass + +def CreateMutexW(lpMutexAttributes: SECURITY_ATTRIBUTES | t.CPtr, bInitialOwner: BOOL, lpName: LPCWSTR) -> HANDLE | t.State: pass + +def OpenMutexA(dwDesiredAccess: ULONG, bInheritHandle: BOOL, lpName: LPCSTR) -> HANDLE | t.State: pass + +def OpenMutexW(dwDesiredAccess: ULONG, bInheritHandle: BOOL, lpName: LPCWSTR) -> HANDLE | t.State: pass + +def ReleaseMutex(hMutex: HANDLE) -> BOOL | t.State: pass + +def CreateEventA(lpEventAttributes: SECURITY_ATTRIBUTES | t.CPtr, bManualReset: BOOL, bInitialState: BOOL, lpName: LPCSTR) -> HANDLE | t.State: pass + +def CreateEventW(lpEventAttributes: SECURITY_ATTRIBUTES | t.CPtr, bManualReset: BOOL, bInitialState: BOOL, lpName: LPCWSTR) -> HANDLE | t.State: pass + +def OpenEventA(dwDesiredAccess: ULONG, bInheritHandle: BOOL, lpName: LPCSTR) -> HANDLE | t.State: pass + +def OpenEventW(dwDesiredAccess: ULONG, bInheritHandle: BOOL, lpName: LPCWSTR) -> HANDLE | t.State: pass + +def SetEvent(hEvent: HANDLE) -> BOOL | t.State: pass + +def ResetEvent(hEvent: HANDLE) -> BOOL | t.State: pass + +def PulseEvent(hEvent: HANDLE) -> BOOL | t.State: pass + +def CreateSemaphoreA(lpSemaphoreAttributes: SECURITY_ATTRIBUTES | t.CPtr, lInitialCount: LONG, lMaximumCount: LONG, lpName: LPCSTR) -> HANDLE | t.State: pass + +def CreateSemaphoreW(lpSemaphoreAttributes: SECURITY_ATTRIBUTES | t.CPtr, lInitialCount: LONG, lMaximumCount: LONG, lpName: LPCWSTR) -> HANDLE | t.State: pass + +def OpenSemaphoreA(dwDesiredAccess: ULONG, bInheritHandle: BOOL, lpName: LPCSTR) -> HANDLE | t.State: pass + +def OpenSemaphoreW(dwDesiredAccess: ULONG, bInheritHandle: BOOL, lpName: LPCWSTR) -> HANDLE | t.State: pass + +def ReleaseSemaphore(hSemaphore: HANDLE, lReleaseCount: LONG, lpPreviousCount: LONG | t.CPtr) -> BOOL | t.State: pass + +def WaitForSingleObject(hHandle: HANDLE, dwMilliseconds: ULONG) -> ULONG | t.State: pass + +def WaitForSingleObjectEx(hHandle: HANDLE, dwMilliseconds: ULONG, bAlertable: BOOL) -> ULONG | t.State: pass + +def WaitForMultipleObjects(nCount: ULONG, lpHandles: VOIDPTR, bWaitAll: BOOL, dwMilliseconds: ULONG) -> ULONG | t.State: pass + +def WaitForMultipleObjectsEx(nCount: ULONG, lpHandles: VOIDPTR, bWaitAll: BOOL, dwMilliseconds: ULONG, bAlertable: BOOL) -> ULONG | t.State: pass + +def InitializeSRWLock(SRWLock: VOIDPTR) -> VOID | t.State: pass + +def AcquireSRWLockExclusive(SRWLock: VOIDPTR) -> VOID | t.State: pass + +def AcquireSRWLockShared(SRWLock: VOIDPTR) -> VOID | t.State: pass + +def ReleaseSRWLockExclusive(SRWLock: VOIDPTR) -> VOID | t.State: pass + +def ReleaseSRWLockShared(SRWLock: VOIDPTR) -> VOID | t.State: pass + + +CONDITION_VARIABLE_LOCKMODE_SHARED: t.CDefine = 0x1 + +def InitializeConditionVariable(ConditionVariable: VOIDPTR) -> VOID | t.State: pass + +def SleepConditionVariableCS(ConditionVariable: VOIDPTR, CriticalSection: CRITICAL_SECTION | t.CPtr, dwMilliseconds: ULONG) -> BOOL | t.State: pass + +def SleepConditionVariableSRW(ConditionVariable: VOIDPTR, SRWLock: VOIDPTR, dwMilliseconds: ULONG, Flags: ULONG) -> BOOL | t.State: pass + +def WakeConditionVariable(ConditionVariable: VOIDPTR) -> VOID | t.State: pass + +def WakeAllConditionVariable(ConditionVariable: VOIDPTR) -> VOID | t.State: pass + + +INIT_ONCE_STATIC_INIT: t.CDefine = 0x00000001 +INIT_ONCE_CHECK_ONLY: t.CDefine = 0x00000002 +INIT_ONCE_ASYNC: t.CDefine = 0x00000004 +INIT_ONCE_INIT_FAILED: t.CDefine = 0x00000008 + +class INIT_ONCE: + Ptr: t.CPtr + +def InitOnceExecuteOnce(InitOnce: INIT_ONCE | t.CPtr, InitFn: VOIDPTR, Parameter: VOIDPTR, Context: VOIDPTR | t.CPtr) -> BOOL | t.State: pass diff --git a/Test/ShortCircuitTest/temp/49bd8cba55979f76.pyi b/Test/ShortCircuitTest/temp/49bd8cba55979f76.pyi new file mode 100644 index 0000000..f1d844a --- /dev/null +++ b/Test/ShortCircuitTest/temp/49bd8cba55979f76.pyi @@ -0,0 +1,75 @@ +""" +Auto-generated Python stub file from stdint.py +Module: stdint +""" + +import c + + +import t + +INT: t.CTypedef = t.CInt +INTPTR: t.CTypedef = t.CInt | t.CPtr +BOOL: t.CTypedef = t.CInt +UINT: t.CTypedef = t.CUnsignedInt +UINTPTR: t.CTypedef = UINT | t.CPtr +BYTE: t.CTypedef = t.CUnsignedChar +BYTEPTR: t.CTypedef = BYTE | t.CPtr +WORD: t.CTypedef = t.CUInt16T +DWORD: t.CTypedef = t.CUInt32T +QWORD: t.CTypedef = t.CUInt64T +TCHAR: t.CTypedef = t.CChar +CHARLIST: t.CTypedef = str | t.CPtr +VOID: t.CTypedef = t.CVoid +SHORT: t.CTypedef = t.CShort +SHORTPTR: t.CTypedef = t.CShort | t.CPtr +USHORT: t.CTypedef = t.CUnsignedShort +USHORTPTR: t.CTypedef = t.CUnsignedShort | t.CPtr +LONGLONG: t.CTypedef = t.CLong | t.CLong +ULONGLONG: t.CTypedef = t.CUnsignedLong | t.CLong +LONG: t.CTypedef = t.CLong +ULONG: t.CTypedef = t.CUnsignedLong +WCHAR: t.CTypedef = WORD +WCHARPTR: t.CTypedef = WORD | t.CPtr +CHARPTR: t.CTypedef = t.CChar | t.CPtr +FSIZE_t: t.CTypedef = DWORD +LBA_t: t.CTypedef = DWORD +UINTPTR: t.CTypedef = t.CUnsignedInt | t.CPtr +VOIDPTR: t.CTypedef = t.CVoid | t.CPtr +FLOAT: t.CTypedef = t.CFloat +DOUBLE: t.CTypedef = t.CDouble +FLOAT8: t.CTypedef = t.CFloat8T +FLOAT16: t.CTypedef = t.CFloat16T +FLOAT32: t.CTypedef = t.CFloat32T +FLOAT64: t.CTypedef = t.CFloat64T +FLOAT128: t.CTypedef = t.CFloat128T +INT8: t.CTypedef = t.CInt8T +INT16: t.CTypedef = t.CInt16T +INT32: t.CTypedef = t.CInt32T +INT64: t.CTypedef = t.CInt64T +UINT8: t.CTypedef = t.CUInt8T +UINT16: t.CTypedef = t.CUInt16T +UINT32: t.CTypedef = t.CUInt32T +UINT64: t.CTypedef = t.CUInt64T +INT8PTR: t.CTypedef = t.CInt8T | t.CPtr +INT16PTR: t.CTypedef = t.CInt16T | t.CPtr +INT32PTR: t.CTypedef = t.CInt32T | t.CPtr +INT64PTR: t.CTypedef = t.CInt64T | t.CPtr +UINT8PTR: t.CTypedef = t.CUInt8T | t.CPtr +UINT16PTR: t.CTypedef = t.CUInt16T | t.CPtr +UINT32PTR: t.CTypedef = t.CUInt32T | t.CPtr +UINT64PTR: t.CTypedef = t.CUInt64T | t.CPtr +CHAR8: t.CTypedef = t.CChar8T +CHAR16: t.CTypedef = t.CChar16T +CHAR32: t.CTypedef = t.CChar32T +CHAR8PTR: t.CTypedef = t.CChar8T | t.CPtr +CHAR16PTR: t.CTypedef = t.CChar16T | t.CPtr +CHAR32PTR: t.CTypedef = t.CChar32T | t.CPtr +i8: t.CTypedef = t.CInt8T +i16: t.CTypedef = t.CInt16T +i32: t.CTypedef = t.CInt32T +i64: t.CTypedef = t.CInt64T +u8: t.CTypedef = t.CUInt8T +u16: t.CTypedef = t.CUInt16T +u32: t.CTypedef = t.CUInt32T +u64: t.CTypedef = t.CUInt64T \ No newline at end of file diff --git a/Test/ShortCircuitTest/temp/5a6a2137958c28c5.pyi b/Test/ShortCircuitTest/temp/5a6a2137958c28c5.pyi new file mode 100644 index 0000000..a137977 --- /dev/null +++ b/Test/ShortCircuitTest/temp/5a6a2137958c28c5.pyi @@ -0,0 +1,98 @@ +""" +Auto-generated Python stub file from w32.win32base.py +Module: w32.win32base +""" + +import c + + +import t +from stdint import * + +HANDLE: t.CTypedef = VOIDPTR +LPCSTR: t.CTypedef = t.CConst | t.CChar | t.CPtr +LPCWSTR: t.CTypedef = t.CConst | t.CUnsignedShort | t.CPtr +INVALID_HANDLE_VALUE: t.CDefine = t.CVoid(-1) +NULL: t.CDefine = 0 +TRUE: t.CDefine = 1 +FALSE: t.CDefine = 0 +INFINITE: t.CDefine = 0xFFFFFFFF +WAIT_FAILED: t.CDefine = 0xFFFFFFFF +WAIT_OBJECT_0: t.CDefine = 0 +WAIT_TIMEOUT: t.CDefine = 258 +WAIT_ABANDONED: t.CDefine = 0x80 +MAX_PATH: t.CDefine = 260 +ERROR_SUCCESS: t.CDefine = 0 +ERROR_FILE_NOT_FOUND: t.CDefine = 2 +ERROR_ACCESS_DENIED: t.CDefine = 5 +ERROR_INSUFFICIENT_BUFFER: t.CDefine = 122 + +class SECURITY_ATTRIBUTES: + nLength: ULONG + lpSecurityDescriptor: VOIDPTR + bInheritHandle: BOOL +class OVERLAPPED: + Internal: ULONGLONG + InternalHigh: ULONGLONG + Offset: ULONG + OffsetHigh: ULONG + hEvent: HANDLE +class FILETIME: + dwLowDateTime: DWORD + dwHighDateTime: DWORD +class SYSTEMTIME: + wYear: WORD + wMonth: WORD + wDayOfWeek: WORD + wDay: WORD + wHour: WORD + wMinute: WORD + wSecond: WORD + wMilliseconds: WORD +class GUID: + Data1: DWORD + Data2: WORD + Data3: WORD + Data4: BYTEPTR +class LARGE_INTEGER: + QuadPart: LONGLONG +class ULARGE_INTEGER: + QuadPart: ULONGLONG + +def GetLastError() -> ULONG | t.State: pass + +def SetLastError(dwErrCode: ULONG) -> t.State: pass + +def CloseHandle(hObject: HANDLE) -> BOOL | t.State: pass + +def GetProcAddress(hModule: HANDLE, lpProcName: LPCSTR) -> VOIDPTR | t.State: pass + +def GetModuleHandleA(lpModuleName: LPCSTR) -> HANDLE | t.State: pass + +def GetModuleHandleW(lpModuleName: LPCWSTR) -> HANDLE | t.State: pass + +def LoadLibraryA(lpLibFileName: LPCSTR) -> HANDLE | t.State: pass + +def LoadLibraryW(lpLibFileName: LPCWSTR) -> HANDLE | t.State: pass + +def FreeLibrary(hLibModule: HANDLE) -> BOOL | t.State: pass + +def GetSystemTime(lpSystemTime: SYSTEMTIME | t.CPtr) -> t.State: pass + +def GetLocalTime(lpSystemTime: SYSTEMTIME | t.CPtr) -> t.State: pass + +def FileTimeToSystemTime(lpFileTime: FILETIME | t.CPtr, lpSystemTime: SYSTEMTIME | t.CPtr) -> BOOL | t.State: pass + +def SystemTimeToFileTime(lpSystemTime: SYSTEMTIME | t.CPtr, lpFileTime: FILETIME | t.CPtr) -> BOOL | t.State: pass + +def QueryPerformanceCounter(lpPerformanceCount: LARGE_INTEGER | t.CPtr) -> BOOL | t.State: pass + +def QueryPerformanceFrequency(lpFrequency: LARGE_INTEGER | t.CPtr) -> BOOL | t.State: pass + +def Sleep(dwMilliseconds: ULONG) -> t.State: pass + +def SleepEx(dwMilliseconds: ULONG, bAlertable: BOOL) -> ULONG | t.State: pass + +def GetTickCount() -> ULONG | t.State: pass + +def GetTickCount64() -> ULONGLONG | t.State: pass diff --git a/Test/ShortCircuitTest/temp/6c2029b306556c00.pyi b/Test/ShortCircuitTest/temp/6c2029b306556c00.pyi new file mode 100644 index 0000000..98da680 --- /dev/null +++ b/Test/ShortCircuitTest/temp/6c2029b306556c00.pyi @@ -0,0 +1,18 @@ +""" +Auto-generated Python stub file from stdlib.py +Module: stdlib +""" + +import c + + +from stdint import * +import t + +def malloc(size: t.CSizeT) -> t.CVoid | t.CPtr | t.State | t.CExtern | t.CExport: pass + +def calloc(nmemb: t.CSizeT, size: t.CSizeT) -> t.CVoid | t.CPtr | t.State | t.CExtern | t.CExport: pass + +def realloc(p: t.CVoid | t.CPtr, size: t.CSizeT) -> t.CVoid | t.CPtr | t.State | t.CExtern | t.CExport: pass + +def free(p: t.CVoid | t.CPtr) -> None | t.State | t.CExtern | t.CExport: pass diff --git a/Test/ShortCircuitTest/temp/72e2d5ccb7cedcf1.pyi b/Test/ShortCircuitTest/temp/72e2d5ccb7cedcf1.pyi new file mode 100644 index 0000000..5fceb08 --- /dev/null +++ b/Test/ShortCircuitTest/temp/72e2d5ccb7cedcf1.pyi @@ -0,0 +1,91 @@ +""" +Auto-generated Python stub file from w32.win32memory.py +Module: w32.win32memory +""" + +import c + + +import t +from stdint import * +from w32.win32base import * + +MEM_COMMIT: t.CDefine = 0x00001000 +MEM_RESERVE: t.CDefine = 0x00002000 +MEM_DECOMMIT: t.CDefine = 0x00004000 +MEM_RELEASE: t.CDefine = 0x00008000 +MEM_FREE: t.CDefine = 0x00010000 +MEM_RESET: t.CDefine = 0x00080000 +MEM_TOP_DOWN: t.CDefine = 0x00100000 +MEM_WRITE_WATCH: t.CDefine = 0x00200000 +MEM_PHYSICAL: t.CDefine = 0x00400000 +MEM_LARGE_PAGES: t.CDefine = 0x20000000 +PAGE_NOACCESS: t.CDefine = 0x01 +PAGE_READONLY: t.CDefine = 0x02 +PAGE_READWRITE: t.CDefine = 0x04 +PAGE_WRITECOPY: t.CDefine = 0x08 +PAGE_EXECUTE: t.CDefine = 0x10 +PAGE_EXECUTE_READ: t.CDefine = 0x20 +PAGE_EXECUTE_READWRITE: t.CDefine = 0x40 +PAGE_EXECUTE_WRITECOPY: t.CDefine = 0x80 +PAGE_GUARD: t.CDefine = 0x100 +PAGE_NOCACHE: t.CDefine = 0x200 +PAGE_WRITECOMBINE: t.CDefine = 0x400 +HEAP_NO_SERIALIZE: t.CDefine = 0x00000001 +HEAP_GROWABLE: t.CDefine = 0x00000002 +HEAP_GENERATE_EXCEPTIONS: t.CDefine = 0x00000004 +HEAP_ZERO_MEMORY: t.CDefine = 0x00000008 +HEAP_REALLOC_IN_PLACE_ONLY: t.CDefine = 0x00000010 + +class MEMORY_BASIC_INFORMATION: + BaseAddress: VOIDPTR + AllocationBase: VOIDPTR + AllocationProtect: ULONG + RegionSize: t.CSizeT + State: ULONG + Protect: ULONG + Type: ULONG + +def VirtualAlloc(lpAddress: VOIDPTR, dwSize: t.CSizeT, flAllocationType: ULONG, flProtect: ULONG) -> VOIDPTR | t.State: pass + +def VirtualFree(lpAddress: VOIDPTR, dwSize: t.CSizeT, dwFreeType: ULONG) -> BOOL | t.State: pass + +def VirtualProtect(lpAddress: VOIDPTR, dwSize: t.CSizeT, flNewProtect: ULONG, lpflOldProtect: ULONG | t.CPtr) -> BOOL | t.State: pass + +def VirtualQuery(lpAddress: t.CConst | VOIDPTR, lpBuffer: MEMORY_BASIC_INFORMATION | t.CPtr, dwLength: t.CSizeT) -> t.CSizeT | t.State: pass + +def VirtualLock(lpAddress: VOIDPTR, dwSize: t.CSizeT) -> BOOL | t.State: pass + +def VirtualUnlock(lpAddress: VOIDPTR, dwSize: t.CSizeT) -> BOOL | t.State: pass + +def GetProcessHeap() -> HANDLE | t.State: pass + +def HeapCreate(flOptions: ULONG, dwInitialSize: t.CSizeT, dwMaximumSize: t.CSizeT) -> HANDLE | t.State: pass + +def HeapDestroy(hHeap: HANDLE) -> BOOL | t.State: pass + +def HeapAlloc(hHeap: HANDLE, dwFlags: ULONG, dwBytes: t.CSizeT) -> VOIDPTR | t.State: pass + +def HeapReAlloc(hHeap: HANDLE, dwFlags: ULONG, lpMem: VOIDPTR, dwBytes: t.CSizeT) -> VOIDPTR | t.State: pass + +def HeapFree(hHeap: HANDLE, dwFlags: ULONG, lpMem: VOIDPTR) -> BOOL | t.State: pass + +def HeapSize(hHeap: HANDLE, dwFlags: ULONG, lpMem: t.CConst | VOIDPTR) -> t.CSizeT | t.State: pass + +def HeapValidate(hHeap: HANDLE, dwFlags: ULONG, lpMem: t.CConst | VOIDPTR) -> BOOL | t.State: pass + +def HeapCompact(hHeap: HANDLE, dwFlags: ULONG) -> t.CSizeT | t.State: pass + +def GlobalAlloc(uFlags: UINT, dwBytes: t.CSizeT) -> VOIDPTR | t.State: pass + +def GlobalFree(hMem: VOIDPTR) -> VOIDPTR | t.State: pass + +def GlobalLock(hMem: VOIDPTR) -> VOIDPTR | t.State: pass + +def GlobalUnlock(hMem: VOIDPTR) -> BOOL | t.State: pass + +def GlobalSize(hMem: VOIDPTR) -> t.CSizeT | t.State: pass + +def LocalAlloc(uFlags: UINT, dwBytes: t.CSizeT) -> VOIDPTR | t.State: pass + +def LocalFree(hMem: VOIDPTR) -> VOIDPTR | t.State: pass diff --git a/Test/ShortCircuitTest/temp/73edbcf76e32d00b.pyi b/Test/ShortCircuitTest/temp/73edbcf76e32d00b.pyi new file mode 100644 index 0000000..ef712e3 --- /dev/null +++ b/Test/ShortCircuitTest/temp/73edbcf76e32d00b.pyi @@ -0,0 +1,28 @@ +""" +Auto-generated Python stub file from stdio.py +Module: stdio +""" + + +import t, c + +def printf(fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass + +def fprintf(stream: t.CVoid | t.CPtr, fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass + +def sprintf(buf: t.CChar | t.CPtr, fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass + +def snprintf(buf: t.CChar | t.CPtr, size: t.CSizeT, fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass + +def puts(s: t.CChar | t.CConst | t.CPtr) -> t.CInt | t.CExtern | t.CExport: pass + +def fputs(s: t.CChar | t.CConst | t.CPtr, stream: t.CVoid | t.CPtr) -> t.CInt | t.CExtern | t.CExport: pass + +def fgets(buf: t.CChar | t.CPtr, size: t.CInt, stream: t.CVoid | t.CPtr) -> t.CChar | t.CPtr | t.CExtern | t.CExport: pass + +def fflush(stream: t.CVoid | t.CPtr) -> t.CInt | t.CExtern | t.CExport: pass + + +stdin: t.CExtern | t.CVoid | t.CPtr +stdout: t.CExtern | t.CVoid | t.CPtr +stderr: t.CExtern | t.CVoid | t.CPtr \ No newline at end of file diff --git a/Test/ShortCircuitTest/temp/9dbecd0942a39782.pyi b/Test/ShortCircuitTest/temp/9dbecd0942a39782.pyi new file mode 100644 index 0000000..41648c1 --- /dev/null +++ b/Test/ShortCircuitTest/temp/9dbecd0942a39782.pyi @@ -0,0 +1,25 @@ +""" +Auto-generated Python stub file from testcheck.py +Module: testcheck +""" + + +import t, c +import stdio + +_pass_count: t.CExtern | t.CInt +_fail_count: t.CExtern | t.CInt + +def begin(name: str) -> t.CInt: pass + +def section(name: str) -> t.CInt: pass + +def ok(msg: str) -> t.CInt: pass + +def fail(msg: str) -> t.CInt: pass + +def check(cond: t.CInt, ok_msg: str, fail_msg: str) -> t.CInt: pass + +def info(msg: str) -> t.CInt: pass + +def end() -> t.CInt: pass diff --git a/Test/ShortCircuitTest/temp/_sha1_map.txt b/Test/ShortCircuitTest/temp/_sha1_map.txt new file mode 100644 index 0000000..6e0b134 --- /dev/null +++ b/Test/ShortCircuitTest/temp/_sha1_map.txt @@ -0,0 +1,8 @@ +49bd8cba55979f76:includes/stdint.py +5a6a2137958c28c5:includes/w32\win32base.py +6c2029b306556c00:includes/stdlib.py +73edbcf76e32d00b:includes/stdio.py +9dbecd0942a39782:includes/testcheck.py +a711c9c66fd7c6ca:main.py +b5f1dc665c52a1bd:includes/string.py +bbdf3bbd4c3bc28c:includes/w32\win32console.py diff --git a/Test/ShortCircuitTest/temp/a711c9c66fd7c6ca.pyi b/Test/ShortCircuitTest/temp/a711c9c66fd7c6ca.pyi new file mode 100644 index 0000000..213e2c8 --- /dev/null +++ b/Test/ShortCircuitTest/temp/a711c9c66fd7c6ca.pyi @@ -0,0 +1,20 @@ +""" +Auto-generated Python stub file from main.py +Module: main +""" + + +from stdint import * +import w32.win32console +import t, c +from t import CInt, CExport +import stdio +import stdlib +import string +import testcheck + +def bump_true(buf: bytes) -> bool: pass + +def bump_false(buf: bytes) -> bool: pass + +def main() -> CInt | CExport: pass diff --git a/Test/ShortCircuitTest/temp/abf9ce3160c9279e.pyi b/Test/ShortCircuitTest/temp/abf9ce3160c9279e.pyi new file mode 100644 index 0000000..4249b58 --- /dev/null +++ b/Test/ShortCircuitTest/temp/abf9ce3160c9279e.pyi @@ -0,0 +1,179 @@ +""" +Auto-generated Python stub file from w32.win32file.py +Module: w32.win32file +""" + +import c + + +import t +from stdint import * +from w32.win32base import * + +GENERIC_READ: t.CDefine = 0x80000000 +GENERIC_WRITE: t.CDefine = 0x40000000 +GENERIC_EXECUTE: t.CDefine = 0x20000000 +GENERIC_ALL: t.CDefine = 0x10000000 +FILE_SHARE_READ: t.CDefine = 0x00000001 +FILE_SHARE_WRITE: t.CDefine = 0x00000002 +FILE_SHARE_DELETE: t.CDefine = 0x00000004 +CREATE_NEW: t.CDefine = 1 +CREATE_ALWAYS: t.CDefine = 2 +OPEN_EXISTING: t.CDefine = 3 +OPEN_ALWAYS: t.CDefine = 4 +TRUNCATE_EXISTING: t.CDefine = 5 +FILE_ATTRIBUTE_READONLY: t.CDefine = 0x00000001 +FILE_ATTRIBUTE_HIDDEN: t.CDefine = 0x00000002 +FILE_ATTRIBUTE_SYSTEM: t.CDefine = 0x00000004 +FILE_ATTRIBUTE_DIRECTORY: t.CDefine = 0x00000010 +FILE_ATTRIBUTE_ARCHIVE: t.CDefine = 0x00000020 +FILE_ATTRIBUTE_NORMAL: t.CDefine = 0x00000080 +FILE_ATTRIBUTE_TEMPORARY: t.CDefine = 0x00000100 +FILE_ATTRIBUTE_COMPRESSED: t.CDefine = 0x00000800 +FILE_ATTRIBUTE_OFFLINE: t.CDefine = 0x00001000 +FILE_ATTRIBUTE_ENCRYPTED: t.CDefine = 0x00004000 +FILE_FLAG_WRITE_THROUGH: t.CDefine = 0x80000000 +FILE_FLAG_OVERLAPPED: t.CDefine = 0x40000000 +FILE_FLAG_NO_BUFFERING: t.CDefine = 0x20000000 +FILE_FLAG_RANDOM_ACCESS: t.CDefine = 0x10000000 +FILE_FLAG_SEQUENTIAL_SCAN: t.CDefine = 0x08000000 +FILE_FLAG_DELETE_ON_CLOSE: t.CDefine = 0x04000000 +FILE_FLAG_BACKUP_SEMANTICS: t.CDefine = 0x02000000 +FILE_FLAG_POSIX_SEMANTICS: t.CDefine = 0x01000000 +FILE_BEGIN: t.CDefine = 0 +FILE_CURRENT: t.CDefine = 1 +FILE_END: t.CDefine = 2 +STD_INPUT_HANDLE: t.CDefine = t.CUnsignedLong(-10) +STD_OUTPUT_HANDLE: t.CDefine = t.CUnsignedLong(-11) +STD_ERROR_HANDLE: t.CDefine = t.CUnsignedLong(-12) +MOVEFILE_REPLACE_EXISTING: t.CDefine = 0x00000001 +MOVEFILE_COPY_ALLOWED: t.CDefine = 0x00000002 +MOVEFILE_WRITE_THROUGH: t.CDefine = 0x00000008 + +class BY_HANDLE_FILE_INFORMATION: + dwFileAttributes: ULONG + ftCreationTime: FILETIME + ftLastAccessTime: FILETIME + ftLastWriteTime: FILETIME + dwVolumeSerialNumber: ULONG + nFileSizeHigh: ULONG + nFileSizeLow: ULONG + nNumberOfLinks: ULONG + nFileIndexHigh: ULONG + nFileIndexLow: ULONG +class WIN32_FIND_DATAA: + dwFileAttributes: ULONG + ftCreationTime: FILETIME + ftLastAccessTime: FILETIME + ftLastWriteTime: FILETIME + nFileSizeHigh: ULONG + nFileSizeLow: ULONG + dwReserved0: ULONG + dwReserved1: ULONG + cFileName: CHARPTR + cAlternateFileName: CHARPTR +class WIN32_FIND_DATAW: + dwFileAttributes: ULONG + ftCreationTime: FILETIME + ftLastAccessTime: FILETIME + ftLastWriteTime: FILETIME + nFileSizeHigh: ULONG + nFileSizeLow: ULONG + dwReserved0: ULONG + dwReserved1: ULONG + cFileName: WCHARPTR + cAlternateFileName: WCHARPTR + +def CreateFileA(lpFileName: LPCSTR, dwDesiredAccess: ULONG, dwShareMode: ULONG, lpSecurityAttributes: SECURITY_ATTRIBUTES | t.CPtr, dwCreationDisposition: ULONG, dwFlagsAndAttributes: ULONG, hTemplateFile: HANDLE) -> HANDLE | t.State: pass + +def CreateFileW(lpFileName: LPCWSTR, dwDesiredAccess: ULONG, dwShareMode: ULONG, lpSecurityAttributes: SECURITY_ATTRIBUTES | t.CPtr, dwCreationDisposition: ULONG, dwFlagsAndAttributes: ULONG, hTemplateFile: HANDLE) -> HANDLE | t.State: pass + +def ReadFile(hFile: HANDLE, lpBuffer: VOIDPTR, nNumberOfBytesToRead: ULONG, lpNumberOfBytesRead: ULONG | t.CPtr, lpOverlapped: OVERLAPPED | t.CPtr) -> BOOL | t.State: pass + +def WriteFile(hFile: HANDLE, lpBuffer: t.CConst | VOIDPTR, nNumberOfBytesToWrite: ULONG, lpNumberOfBytesWritten: ULONG | t.CPtr, lpOverlapped: OVERLAPPED | t.CPtr) -> BOOL | t.State: pass + +def SetFilePointer(hFile: HANDLE, lDistanceToMove: LONG, lpDistanceToMoveHigh: LONG | t.CPtr, dwMoveMethod: ULONG) -> LONG | t.State: pass + +def SetFilePointerEx(hFile: HANDLE, liDistanceToMove: LARGE_INTEGER | t.CPtr, lpNewFilePointer: LARGE_INTEGER | t.CPtr, dwMoveMethod: ULONG) -> BOOL | t.State: pass + +def GetFileSize(hFile: HANDLE, lpFileSizeHigh: ULONG | t.CPtr) -> ULONG | t.State: pass + +def GetFileSizeEx(hFile: HANDLE, lpFileSize: LARGE_INTEGER | t.CPtr) -> BOOL | t.State: pass + +def SetEndOfFile(hFile: HANDLE) -> BOOL | t.State: pass + +def FlushFileBuffers(hFile: HANDLE) -> BOOL | t.State: pass + +def GetFileType(hFile: HANDLE) -> ULONG | t.State: pass + +def GetFileAttributesA(lpFileName: LPCSTR) -> ULONG | t.State: pass + +def GetFileAttributesW(lpFileName: LPCWSTR) -> ULONG | t.State: pass + +def SetFileAttributesA(lpFileName: LPCSTR, dwFileAttributes: ULONG) -> BOOL | t.State: pass + +def SetFileAttributesW(lpFileName: LPCWSTR, dwFileAttributes: ULONG) -> BOOL | t.State: pass + +def DeleteFileA(lpFileName: LPCSTR) -> BOOL | t.State: pass + +def DeleteFileW(lpFileName: LPCWSTR) -> BOOL | t.State: pass + +def MoveFileA(lpExistingFileName: LPCSTR, lpNewFileName: LPCSTR) -> BOOL | t.State: pass + +def MoveFileW(lpExistingFileName: LPCWSTR, lpNewFileName: LPCWSTR) -> BOOL | t.State: pass + +def MoveFileExA(lpExistingFileName: LPCSTR, lpNewFileName: LPCSTR, dwFlags: ULONG) -> BOOL | t.State: pass + +def MoveFileExW(lpExistingFileName: LPCWSTR, lpNewFileName: LPCWSTR, dwFlags: ULONG) -> BOOL | t.State: pass + +def CopyFileA(lpExistingFileName: LPCSTR, lpNewFileName: LPCSTR, bFailIfExists: BOOL) -> BOOL | t.State: pass + +def CopyFileW(lpExistingFileName: LPCWSTR, lpNewFileName: LPCWSTR, bFailIfExists: BOOL) -> BOOL | t.State: pass + +def CreateDirectoryA(lpPathName: LPCSTR, lpSecurityAttributes: SECURITY_ATTRIBUTES | t.CPtr) -> BOOL | t.State: pass + +def CreateDirectoryW(lpPathName: LPCWSTR, lpSecurityAttributes: SECURITY_ATTRIBUTES | t.CPtr) -> BOOL | t.State: pass + +def RemoveDirectoryA(lpPathName: LPCSTR) -> BOOL | t.State: pass + +def RemoveDirectoryW(lpPathName: LPCWSTR) -> BOOL | t.State: pass + +def FindFirstFileA(lpFileName: LPCSTR, lpFindFileData: WIN32_FIND_DATAA | t.CPtr) -> HANDLE | t.State: pass + +def FindFirstFileW(lpFileName: LPCWSTR, lpFindFileData: WIN32_FIND_DATAW | t.CPtr) -> HANDLE | t.State: pass + +def FindNextFileA(hFindFile: HANDLE, lpFindFileData: WIN32_FIND_DATAA | t.CPtr) -> BOOL | t.State: pass + +def FindNextFileW(hFindFile: HANDLE, lpFindFileData: WIN32_FIND_DATAW | t.CPtr) -> BOOL | t.State: pass + +def FindClose(hFindFile: HANDLE) -> BOOL | t.State: pass + +def GetStdHandle(nStdHandle: ULONG) -> HANDLE | t.State: pass + +def SetStdHandle(nStdHandle: ULONG, hHandle: HANDLE) -> BOOL | t.State: pass + +def GetFileInformationByHandle(hFile: HANDLE, lpFileInformation: BY_HANDLE_FILE_INFORMATION | t.CPtr) -> BOOL | t.State: pass + +def LockFile(hFile: HANDLE, dwFileOffsetLow: ULONG, dwFileOffsetHigh: ULONG, nNumberOfBytesToLockLow: ULONG, nNumberOfBytesToLockHigh: ULONG) -> BOOL | t.State: pass + +def UnlockFile(hFile: HANDLE, dwFileOffsetLow: ULONG, dwFileOffsetHigh: ULONG, nNumberOfBytesToUnlockLow: ULONG, nNumberOfBytesToUnlockHigh: ULONG) -> BOOL | t.State: pass + +def GetTempPathA(nBufferLength: ULONG, lpBuffer: CHARPTR) -> ULONG | t.State: pass + +def GetTempPathW(nBufferLength: ULONG, lpBuffer: WCHARPTR) -> ULONG | t.State: pass + +def GetTempFileNameA(lpPathName: LPCSTR, lpPrefixString: LPCSTR, uUnique: UINT, lpTempFileName: CHARPTR) -> UINT | t.State: pass + +def GetTempFileNameW(lpPathName: LPCWSTR, lpPrefixString: LPCWSTR, uUnique: UINT, lpTempFileName: WCHARPTR) -> UINT | t.State: pass + +def GetCurrentDirectoryA(nBufferLength: ULONG, lpBuffer: CHARPTR) -> ULONG | t.State: pass + +def GetCurrentDirectoryW(nBufferLength: ULONG, lpBuffer: WCHARPTR) -> ULONG | t.State: pass + +def SetCurrentDirectoryA(lpPathName: LPCSTR) -> BOOL | t.State: pass + +def SetCurrentDirectoryW(lpPathName: LPCWSTR) -> BOOL | t.State: pass + +def GetModuleFileNameA(hModule: HANDLE, lpFilename: CHARPTR, nSize: ULONG) -> ULONG | t.State: pass + +def GetModuleFileNameW(hModule: HANDLE, lpFilename: WCHARPTR, nSize: ULONG) -> ULONG | t.State: pass diff --git a/Test/ShortCircuitTest/temp/b5f1dc665c52a1bd.pyi b/Test/ShortCircuitTest/temp/b5f1dc665c52a1bd.pyi new file mode 100644 index 0000000..8b6959e --- /dev/null +++ b/Test/ShortCircuitTest/temp/b5f1dc665c52a1bd.pyi @@ -0,0 +1,44 @@ +""" +Auto-generated Python stub file from string.py +Module: string +""" + + +from stdint import * +import t, c + +def strcpy(dest: str, src: str) -> str: pass + +def strncpy(dest: str, src: str, n: t.CSizeT) -> str: pass + +def strlen(src: str) -> t.CSizeT | t.CExport: pass + +def strcmp(str1: str, str2: str) -> t.CInt: pass + +def samestr(str1: str, str2: str) -> bool: pass + +def strncmp(str1: str, str2: str, n: t.CSizeT) -> t.CInt: pass + +def memcmp(ptr1: t.CVoid | t.CPtr, ptr2: t.CVoid | t.CPtr, n: t.CSizeT) -> t.CInt: pass + +def strchr(s: str, cr: t.CInt) -> str: pass + +def strrchr(s: str, cr: t.CInt) -> str: pass + +def strspn(s: str, skip: str) -> int: pass + +def memset(ptr: t.CVoid | t.CPtr, value: t.CInt, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass + +def memset32(ptr: t.CVoid | t.CPtr, value: t.CUInt32T, count: t.CSizeT) -> t.CVoid | t.CPtr: pass + +def memcpy(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass + +def memmove(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr: pass + +def atoi(src: str) -> t.CInt: pass + +def atoll(src: str) -> t.CInt64T: pass + +def atof(src: str) -> t.CDouble: pass + +def split(s: str, delim: str, result: t.CArray[str]) -> int: pass diff --git a/Test/ShortCircuitTest/temp/bbdf3bbd4c3bc28c.pyi b/Test/ShortCircuitTest/temp/bbdf3bbd4c3bc28c.pyi new file mode 100644 index 0000000..70dcdbc --- /dev/null +++ b/Test/ShortCircuitTest/temp/bbdf3bbd4c3bc28c.pyi @@ -0,0 +1,138 @@ +""" +Auto-generated Python stub file from w32.win32console.py +Module: w32.win32console +""" + +import c + + +import t +from stdint import * +from w32.win32base import * + +ENABLE_PROCESSED_INPUT: t.CDefine = 0x0001 +ENABLE_LINE_INPUT: t.CDefine = 0x0002 +ENABLE_ECHO_INPUT: t.CDefine = 0x0004 +ENABLE_WINDOW_INPUT: t.CDefine = 0x0008 +ENABLE_MOUSE_INPUT: t.CDefine = 0x0010 +ENABLE_INSERT_MODE: t.CDefine = 0x0020 +ENABLE_QUICK_EDIT_MODE: t.CDefine = 0x0040 +ENABLE_EXTENDED_FLAGS: t.CDefine = 0x0080 +ENABLE_PROCESSED_OUTPUT: t.CDefine = 0x0001 +ENABLE_WRAP_AT_EOL_OUTPUT: t.CDefine = 0x0002 +ENABLE_VIRTUAL_TERMINAL_PROCESSING: t.CDefine = 0x0004 +DISABLE_NEWLINE_AUTO_RETURN: t.CDefine = 0x0008 +ENABLE_LVB_GRID_WORLDWIDE: t.CDefine = 0x0010 +FOREGROUND_BLUE: t.CDefine = 0x0001 +FOREGROUND_GREEN: t.CDefine = 0x0002 +FOREGROUND_RED: t.CDefine = 0x0004 +FOREGROUND_INTENSITY: t.CDefine = 0x0008 +BACKGROUND_BLUE: t.CDefine = 0x0010 +BACKGROUND_GREEN: t.CDefine = 0x0020 +BACKGROUND_RED: t.CDefine = 0x0040 +BACKGROUND_INTENSITY: t.CDefine = 0x0080 +KEY_EVENT: t.CDefine = 0x0001 +MOUSE_EVENT: t.CDefine = 0x0002 +WINDOW_BUFFER_SIZE_EVENT: t.CDefine = 0x0004 +MENU_EVENT: t.CDefine = 0x0008 +FOCUS_EVENT: t.CDefine = 0x0010 + +class COORD: + X: SHORT + Y: SHORT +class SMALL_RECT: + Left: SHORT + Top: SHORT + Right: SHORT + Bottom: SHORT +class CONSOLE_SCREEN_BUFFER_INFO: + dwSize: COORD + dwCursorPosition: COORD + wAttributes: WORD + srWindow: SMALL_RECT + dwMaximumWindowSize: COORD +class CONSOLE_CURSOR_INFO: + dwSize: ULONG + bVisible: BOOL +class CHAR_INFO: + UnicodeChar: WCHAR + Attributes: WORD +class KEY_EVENT_RECORD: + bKeyDown: BOOL + wRepeatCount: WORD + wVirtualKeyCode: WORD + wVirtualScanCode: WORD + uChar: WCHAR + dwControlKeyState: ULONG +class MOUSE_EVENT_RECORD: + dwMousePosition: COORD + dwButtonState: ULONG + dwControlKeyState: ULONG + dwEventFlags: ULONG +class WINDOW_BUFFER_SIZE_RECORD: + dwSize: COORD +class INPUT_RECORD: + EventType: WORD + Event: KEY_EVENT_RECORD + +def SetConsoleOutputCP(codepage: UINT) -> BOOL | t.State: pass + +def SetConsoleCP(codepage: UINT) -> BOOL | t.State: pass + +def GetConsoleCP() -> UINT | t.State: pass + +def GetConsoleOutputCP() -> UINT | t.State: pass + +def GetConsoleScreenBufferInfo(hConsoleOutput: HANDLE, lpConsoleScreenBufferInfo: CONSOLE_SCREEN_BUFFER_INFO | t.CPtr) -> BOOL | t.State: pass + +def SetConsoleScreenBufferSize(hConsoleOutput: HANDLE, dwSize: COORD) -> BOOL | t.State: pass + +def SetConsoleCursorPosition(hConsoleOutput: HANDLE, dwCursorPosition: COORD) -> BOOL | t.State: pass + +def GetConsoleCursorInfo(hConsoleOutput: HANDLE, lpConsoleCursorInfo: CONSOLE_CURSOR_INFO | t.CPtr) -> BOOL | t.State: pass + +def SetConsoleCursorInfo(hConsoleOutput: HANDLE, lpConsoleCursorInfo: CONSOLE_CURSOR_INFO | t.CPtr) -> BOOL | t.State: pass + +def SetConsoleTextAttribute(hConsoleOutput: HANDLE, wAttributes: WORD) -> BOOL | t.State: pass + +def FillConsoleOutputCharacterA(hConsoleOutput: HANDLE, cCharacter: t.CChar, nLength: ULONG, dwWriteCoord: COORD, lpNumberOfCharsWritten: ULONG | t.CPtr) -> BOOL | t.State: pass + +def FillConsoleOutputCharacterW(hConsoleOutput: HANDLE, cCharacter: WCHAR, nLength: ULONG, dwWriteCoord: COORD, lpNumberOfCharsWritten: ULONG | t.CPtr) -> BOOL | t.State: pass + +def FillConsoleOutputAttribute(hConsoleOutput: HANDLE, wAttribute: WORD, nLength: ULONG, dwWriteCoord: COORD, lpNumberOfAttrsWritten: ULONG | t.CPtr) -> BOOL | t.State: pass + +def WriteConsoleA(hConsoleOutput: HANDLE, lpBuffer: t.CConst | VOIDPTR, nNumberOfCharsToWrite: ULONG, lpNumberOfCharsWritten: ULONG | t.CPtr, lpReserved: VOIDPTR) -> BOOL | t.State: pass + +def WriteConsoleW(hConsoleOutput: HANDLE, lpBuffer: t.CConst | VOIDPTR, nNumberOfCharsToWrite: ULONG, lpNumberOfCharsWritten: ULONG | t.CPtr, lpReserved: VOIDPTR) -> BOOL | t.State: pass + +def ReadConsoleA(hConsoleInput: HANDLE, lpBuffer: VOIDPTR, nNumberOfCharsToRead: ULONG, lpNumberOfCharsRead: ULONG | t.CPtr, pInputControl: VOIDPTR) -> BOOL | t.State: pass + +def ReadConsoleW(hConsoleInput: HANDLE, lpBuffer: VOIDPTR, nNumberOfCharsToRead: ULONG, lpNumberOfCharsRead: ULONG | t.CPtr, pInputControl: VOIDPTR) -> BOOL | t.State: pass + +def GetConsoleMode(hConsoleHandle: HANDLE, lpMode: ULONG | t.CPtr) -> BOOL | t.State: pass + +def SetConsoleMode(hConsoleHandle: HANDLE, dwMode: ULONG) -> BOOL | t.State: pass + +def ReadConsoleInputA(hConsoleInput: HANDLE, lpBuffer: INPUT_RECORD | t.CPtr, nLength: ULONG, lpNumberOfEventsRead: ULONG | t.CPtr) -> BOOL | t.State: pass + +def ReadConsoleInputW(hConsoleInput: HANDLE, lpBuffer: INPUT_RECORD | t.CPtr, nLength: ULONG, lpNumberOfEventsRead: ULONG | t.CPtr) -> BOOL | t.State: pass + +def GetNumberOfConsoleInputEvents(hConsoleInput: HANDLE, lpNumberOfEvents: ULONG | t.CPtr) -> BOOL | t.State: pass + +def FlushConsoleInputBuffer(hConsoleInput: HANDLE) -> BOOL | t.State: pass + +def SetConsoleTitleA(lpConsoleTitle: LPCSTR) -> BOOL | t.State: pass + +def SetConsoleTitleW(lpConsoleTitle: LPCWSTR) -> BOOL | t.State: pass + +def GetConsoleTitleA(lpConsoleTitle: CHARPTR, nSize: ULONG) -> ULONG | t.State: pass + +def GetConsoleTitleW(lpConsoleTitle: WCHARPTR, nSize: ULONG) -> ULONG | t.State: pass + +def AllocConsole() -> BOOL | t.State: pass + +def FreeConsole() -> BOOL | t.State: pass + +def SetConsoleWindowInfo(hConsoleOutput: HANDLE, bAbsolute: BOOL, lpConsoleWindow: SMALL_RECT | t.CPtr) -> BOOL | t.State: pass + +def ScrollConsoleScreenBufferA(hConsoleOutput: HANDLE, lpScrollRectangle: SMALL_RECT | t.CPtr, lpClipRectangle: SMALL_RECT | t.CPtr, dwDestinationOrigin: COORD, lpFill: CHAR_INFO | t.CPtr) -> BOOL | t.State: pass diff --git a/Test/ShortCircuitTest/temp/fa3691e66b426950.pyi b/Test/ShortCircuitTest/temp/fa3691e66b426950.pyi new file mode 100644 index 0000000..48fd36c --- /dev/null +++ b/Test/ShortCircuitTest/temp/fa3691e66b426950.pyi @@ -0,0 +1,80 @@ +""" +Auto-generated Python stub file from w32.fileio.py +Module: w32.fileio +""" + + +import t, c +from stdint import * +import w32.win32base +import w32.win32file + +class MODE(t.CEnum): + R = 0 + W = 1 + A = 2 + RP = 3 + WP = 4 + AP = 5 + X = 6 + XP = 7 +class FRESULT(t.CEnum): + OK = 0 + ERR = -1 + ERR_CLOSED = -2 + ERR_PERM = -3 + ERR_IO = -4 + ERR_NOTFOUND = -5 + +SEEK_SET: t.CDefine = 0 +SEEK_CUR: t.CDefine = 1 +SEEK_END: t.CDefine = 2 +INVALID_SET_FILE_POINTER: t.CDefine = -1 +SHARE_READ: t.CDefine = 0x00000001 +SHARE_WRITE: t.CDefine = 0x00000002 +SHARE_DELETE: t.CDefine = 0x00000004 + +class File: + handle: w32.win32base.HANDLE + closed: bool + can_read: bool + can_write: bool + is_append: bool + _share_mode: ULONG + def __init__(self: File, filename: str, mode: ULONG, share: ULONG) -> t.CInt: pass + def __enter__(self: File) -> 'File' | t.CPtr: pass + def __exit__(self: File) -> t.CInt: pass + def read(self: File, buf: bytes, count: ULONG) -> LONG: pass + def write(self: File, buf: bytes, count: ULONG) -> LONG: pass + def write_str(self: File, s: str) -> LONG: pass + def seek(self: File, offset: LONG, origin: ULONG) -> LONG: pass + def tell(self: File) -> LONG: pass + def close(self: File) -> LONG: pass + def flush(self: File) -> LONG: pass + def size(self: File) -> LONGLONG: pass + def readline(self: File, buf: bytes, max_count: ULONG) -> LONG: pass + def read_all(self: File, buf: bytes, max_count: ULONG) -> LONG: pass +class FileW: + handle: HANDLE + closed: bool + can_read: bool + can_write: bool + is_append: bool + _share_mode: ULONG + def __init__(self: FileW, filename: LPCWSTR, mode: ULONG, share: ULONG) -> t.CInt: pass + def __enter__(self: FileW) -> 'FileW' | t.CPtr: pass + def __exit__(self: FileW) -> t.CInt: pass + def read(self: FileW, buf: bytes, count: ULONG) -> LONG: pass + def write(self: FileW, buf: bytes, count: ULONG) -> LONG: pass + def write_str(self: FileW, s: str) -> LONG: pass + def seek(self: FileW, offset: LONG, origin: ULONG) -> LONG: pass + def tell(self: FileW) -> LONG: pass + def close(self: FileW) -> LONG: pass + def flush(self: FileW) -> LONG: pass + def size(self: FileW) -> LONGLONG: pass + def readline(self: FileW, buf: bytes, max_count: ULONG) -> LONG: pass + def read_all(self: FileW, buf: bytes, max_count: ULONG) -> LONG: pass + +def open(filename: str, mode: ULONG, share: ULONG) -> File | t.CPtr: pass + +def openw(filename: LPCWSTR, mode: ULONG, share: ULONG) -> FileW | t.CPtr: pass diff --git a/Test/SimdTest/App/main.py b/Test/SimdTest/App/main.py index 8f81dd9..3133d72 100644 --- a/Test/SimdTest/App/main.py +++ b/Test/SimdTest/App/main.py @@ -6,6 +6,7 @@ import stdlib from stdlib import calloc import t, c import mpool +import testcheck # 全局内存池 @@ -17,28 +18,13 @@ def clock() -> t.CLong | t.CExtern: pass CLOCK_PER_SEC: t.CDefine = 1000 -test_passed: t.CInt = 0 -test_failed: t.CInt = 0 - -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 "") - -def section(title: str): - printf("\n=== %s ===\n", title) - # ============================================================ # 1. AVX2 double4 正确性测试 # ============================================================ def test_avx2_add_sub_mul_div(): - section("AVX2 add/sub/mul/div 4d") + testcheck.section("AVX2 add/sub/mul/div 4d") a: numpy.ndarray | t.CPtr = numpy.zeros(pool, 4) a.data[0] = t.CDouble(1.0) a.data[1] = t.CDouble(2.0) @@ -55,27 +41,27 @@ def test_avx2_add_sub_mul_div(): # add vipersimd.simd_add4d(a.data, b.data, out.data) - check("add[0]==6", out.data[0] == t.CDouble(6.0), "") - check("add[1]==8", out.data[1] == t.CDouble(8.0), "") - check("add[2]==10", out.data[2] == t.CDouble(10.0), "") - check("add[3]==12", out.data[3] == t.CDouble(12.0), "") + testcheck.check(out.data[0] == t.CDouble(6.0), "add[0]==6", "add[0]==6") + testcheck.check(out.data[1] == t.CDouble(8.0), "add[1]==8", "add[1]==8") + testcheck.check(out.data[2] == t.CDouble(10.0), "add[2]==10", "add[2]==10") + testcheck.check(out.data[3] == t.CDouble(12.0), "add[3]==12", "add[3]==12") # sub vipersimd.simd_sub4d(a.data, b.data, out.data) - check("sub[0]==-4", out.data[0] == t.CDouble(-4.0), "") - check("sub[3]==-4", out.data[3] == t.CDouble(-4.0), "") + testcheck.check(out.data[0] == t.CDouble(-4.0), "sub[0]==-4", "sub[0]==-4") + testcheck.check(out.data[3] == t.CDouble(-4.0), "sub[3]==-4", "sub[3]==-4") # mul vipersimd.simd_mul4d(a.data, b.data, out.data) - check("mul[0]==5", out.data[0] == t.CDouble(5.0), "") - check("mul[1]==12", out.data[1] == t.CDouble(12.0), "") - check("mul[2]==21", out.data[2] == t.CDouble(21.0), "") - check("mul[3]==32", out.data[3] == t.CDouble(32.0), "") + testcheck.check(out.data[0] == t.CDouble(5.0), "mul[0]==5", "mul[0]==5") + testcheck.check(out.data[1] == t.CDouble(12.0), "mul[1]==12", "mul[1]==12") + testcheck.check(out.data[2] == t.CDouble(21.0), "mul[2]==21", "mul[2]==21") + testcheck.check(out.data[3] == t.CDouble(32.0), "mul[3]==32", "mul[3]==32") # div vipersimd.simd_div4d(b.data, a.data, out.data) - check("div[0]==5", out.data[0] == t.CDouble(5.0), "") - check("div[1]==3", out.data[1] == t.CDouble(3.0), "") + testcheck.check(out.data[0] == t.CDouble(5.0), "div[0]==5", "div[0]==5") + testcheck.check(out.data[1] == t.CDouble(3.0), "div[1]==3", "div[1]==3") a.delete() b.delete() @@ -83,7 +69,7 @@ def test_avx2_add_sub_mul_div(): def test_avx2_neg_abs_sqrt(): - section("AVX2 neg/abs/sqrt 4d") + testcheck.section("AVX2 neg/abs/sqrt 4d") a: numpy.ndarray | t.CPtr = numpy.zeros(pool, 4) a.data[0] = t.CDouble(1.0) a.data[1] = t.CDouble(-4.0) @@ -94,31 +80,31 @@ def test_avx2_neg_abs_sqrt(): # neg vipersimd.simd_neg4d(a.data, out.data) - check("neg[0]==-1", out.data[0] == t.CDouble(-1.0), "") - check("neg[1]==4", out.data[1] == t.CDouble(4.0), "") - check("neg[2]==-9", out.data[2] == t.CDouble(-9.0), "") - check("neg[3]==16", out.data[3] == t.CDouble(16.0), "") + testcheck.check(out.data[0] == t.CDouble(-1.0), "neg[0]==-1", "neg[0]==-1") + testcheck.check(out.data[1] == t.CDouble(4.0), "neg[1]==4", "neg[1]==4") + testcheck.check(out.data[2] == t.CDouble(-9.0), "neg[2]==-9", "neg[2]==-9") + testcheck.check(out.data[3] == t.CDouble(16.0), "neg[3]==16", "neg[3]==16") # abs vipersimd.simd_abs4d(a.data, out.data) - check("abs[0]==1", out.data[0] == t.CDouble(1.0), "") - check("abs[1]==4", out.data[1] == t.CDouble(4.0), "") - check("abs[2]==9", out.data[2] == t.CDouble(9.0), "") - check("abs[3]==16", out.data[3] == t.CDouble(16.0), "") + testcheck.check(out.data[0] == t.CDouble(1.0), "abs[0]==1", "abs[0]==1") + testcheck.check(out.data[1] == t.CDouble(4.0), "abs[1]==4", "abs[1]==4") + testcheck.check(out.data[2] == t.CDouble(9.0), "abs[2]==9", "abs[2]==9") + testcheck.check(out.data[3] == t.CDouble(16.0), "abs[3]==16", "abs[3]==16") # sqrt vipersimd.simd_sqrt4d(out.data, out.data) - check("sqrt[0]==1", out.data[0] == t.CDouble(1.0), "") - check("sqrt[1]==2", out.data[1] == t.CDouble(2.0), "") - check("sqrt[2]==3", out.data[2] == t.CDouble(3.0), "") - check("sqrt[3]==4", out.data[3] == t.CDouble(4.0), "") + testcheck.check(out.data[0] == t.CDouble(1.0), "sqrt[0]==1", "sqrt[0]==1") + testcheck.check(out.data[1] == t.CDouble(2.0), "sqrt[1]==2", "sqrt[1]==2") + testcheck.check(out.data[2] == t.CDouble(3.0), "sqrt[2]==3", "sqrt[2]==3") + testcheck.check(out.data[3] == t.CDouble(4.0), "sqrt[3]==4", "sqrt[3]==4") a.delete() out.delete() def test_avx2_min_max(): - section("AVX2 min/max 4d") + testcheck.section("AVX2 min/max 4d") a: numpy.ndarray | t.CPtr = numpy.zeros(pool, 4) a.data[0] = t.CDouble(1.0) a.data[1] = t.CDouble(8.0) @@ -134,16 +120,16 @@ def test_avx2_min_max(): out: numpy.ndarray | t.CPtr = numpy.zeros(pool, 4) vipersimd.simd_min4d(a.data, b.data, out.data) - check("min[0]==1", out.data[0] == t.CDouble(1.0), "") - check("min[1]==2", out.data[1] == t.CDouble(2.0), "") - check("min[2]==3", out.data[2] == t.CDouble(3.0), "") - check("min[3]==4", out.data[3] == t.CDouble(4.0), "") + testcheck.check(out.data[0] == t.CDouble(1.0), "min[0]==1", "min[0]==1") + testcheck.check(out.data[1] == t.CDouble(2.0), "min[1]==2", "min[1]==2") + testcheck.check(out.data[2] == t.CDouble(3.0), "min[2]==3", "min[2]==3") + testcheck.check(out.data[3] == t.CDouble(4.0), "min[3]==4", "min[3]==4") vipersimd.simd_max4d(a.data, b.data, out.data) - check("max[0]==5", out.data[0] == t.CDouble(5.0), "") - check("max[1]==8", out.data[1] == t.CDouble(8.0), "") - check("max[2]==7", out.data[2] == t.CDouble(7.0), "") - check("max[3]==6", out.data[3] == t.CDouble(6.0), "") + testcheck.check(out.data[0] == t.CDouble(5.0), "max[0]==5", "max[0]==5") + testcheck.check(out.data[1] == t.CDouble(8.0), "max[1]==8", "max[1]==8") + testcheck.check(out.data[2] == t.CDouble(7.0), "max[2]==7", "max[2]==7") + testcheck.check(out.data[3] == t.CDouble(6.0), "max[3]==6", "max[3]==6") a.delete() b.delete() @@ -151,7 +137,7 @@ def test_avx2_min_max(): def test_avx2_scalar_ops(): - section("AVX2 scalar broadcast ops") + testcheck.section("AVX2 scalar broadcast ops") a: numpy.ndarray | t.CPtr = numpy.zeros(pool, 4) a.data[0] = t.CDouble(1.0) a.data[1] = t.CDouble(2.0) @@ -164,13 +150,13 @@ def test_avx2_scalar_ops(): out: numpy.ndarray | t.CPtr = numpy.zeros(pool, 4) vipersimd.simd_mul_scalar4d(a.data, s.data, out.data) - check("mul_scalar[0]==10", out.data[0] == t.CDouble(10.0), "") - check("mul_scalar[1]==20", out.data[1] == t.CDouble(20.0), "") - check("mul_scalar[3]==40", out.data[3] == t.CDouble(40.0), "") + testcheck.check(out.data[0] == t.CDouble(10.0), "mul_scalar[0]==10", "mul_scalar[0]==10") + testcheck.check(out.data[1] == t.CDouble(20.0), "mul_scalar[1]==20", "mul_scalar[1]==20") + testcheck.check(out.data[3] == t.CDouble(40.0), "mul_scalar[3]==40", "mul_scalar[3]==40") vipersimd.simd_add_scalar4d(a.data, s.data, out.data) - check("add_scalar[0]==11", out.data[0] == t.CDouble(11.0), "") - check("add_scalar[3]==14", out.data[3] == t.CDouble(14.0), "") + testcheck.check(out.data[0] == t.CDouble(11.0), "add_scalar[0]==11", "add_scalar[0]==11") + testcheck.check(out.data[3] == t.CDouble(14.0), "add_scalar[3]==14", "add_scalar[3]==14") a.delete() s.delete() @@ -178,7 +164,7 @@ def test_avx2_scalar_ops(): def test_avx2_hsum_dot(): - section("AVX2 hsum/dot 4d") + testcheck.section("AVX2 hsum/dot 4d") a: numpy.ndarray | t.CPtr = numpy.zeros(pool, 4) a.data[0] = t.CDouble(1.0) a.data[1] = t.CDouble(2.0) @@ -194,10 +180,10 @@ def test_avx2_hsum_dot(): out: numpy.ndarray | t.CPtr = numpy.zeros(pool, 1) vipersimd.simd_hsum4d(a.data, out.data) - check("hsum==10", out.data[0] == t.CDouble(10.0), "") + testcheck.check(out.data[0] == t.CDouble(10.0), "hsum==10", "hsum==10") vipersimd.simd_dot4d(a.data, b.data, out.data) - check("dot==70", out.data[0] == t.CDouble(70.0), "") + testcheck.check(out.data[0] == t.CDouble(70.0), "dot==70", "dot==70") a.delete() b.delete() @@ -205,7 +191,7 @@ def test_avx2_hsum_dot(): def test_avx2_fma(): - section("AVX2 FMA 4d") + testcheck.section("AVX2 FMA 4d") a: numpy.ndarray | t.CPtr = numpy.zeros(pool, 4) a.data[0] = t.CDouble(1.0) a.data[1] = t.CDouble(2.0) @@ -223,10 +209,10 @@ def test_avx2_fma(): out: numpy.ndarray | t.CPtr = numpy.zeros(pool, 4) vipersimd.simd_fma4d(a.data, b.data, c_val.data, out.data) - check("fma[0]==6", out.data[0] == t.CDouble(6.0), "") - check("fma[1]==13", out.data[1] == t.CDouble(13.0), "") - check("fma[2]==22", out.data[2] == t.CDouble(22.0), "") - check("fma[3]==33", out.data[3] == t.CDouble(33.0), "") + testcheck.check(out.data[0] == t.CDouble(6.0), "fma[0]==6", "fma[0]==6") + testcheck.check(out.data[1] == t.CDouble(13.0), "fma[1]==13", "fma[1]==13") + testcheck.check(out.data[2] == t.CDouble(22.0), "fma[2]==22", "fma[2]==22") + testcheck.check(out.data[3] == t.CDouble(33.0), "fma[3]==33", "fma[3]==33") a.delete() b.delete() @@ -239,7 +225,7 @@ def test_avx2_fma(): # ============================================================ def test_batch_array_ops(): - section("Batch array operations") + testcheck.section("Batch array operations") n: t.CSizeT = 16 a: numpy.ndarray | t.CPtr = numpy.arange(pool, t.CDouble(1.0), t.CDouble(17.0), t.CDouble(1.0)) b: numpy.ndarray | t.CPtr = numpy.full(pool, 16, t.CDouble(2.0)) @@ -247,13 +233,13 @@ def test_batch_array_ops(): # add array vipersimd.simd_add_array(a.data, b.data, out.data, n) - check("add_arr[0]==3", out.data[0] == t.CDouble(3.0), "") - check("add_arr[15]==18", out.data[15] == t.CDouble(18.0), "") + testcheck.check(out.data[0] == t.CDouble(3.0), "add_arr[0]==3", "add_arr[0]==3") + testcheck.check(out.data[15] == t.CDouble(18.0), "add_arr[15]==18", "add_arr[15]==18") # mul array vipersimd.simd_mul_array(a.data, b.data, out.data, n) - check("mul_arr[0]==2", out.data[0] == t.CDouble(2.0), "") - check("mul_arr[3]==8", out.data[3] == t.CDouble(8.0), "") + testcheck.check(out.data[0] == t.CDouble(2.0), "mul_arr[0]==2", "mul_arr[0]==2") + testcheck.check(out.data[3] == t.CDouble(8.0), "mul_arr[3]==8", "mul_arr[3]==8") # sqrt array c: numpy.ndarray | t.CPtr = numpy.zeros(pool, 4) @@ -263,8 +249,8 @@ def test_batch_array_ops(): c.data[3] = t.CDouble(25.0) out4: numpy.ndarray | t.CPtr = numpy.zeros(pool, 4) vipersimd.simd_sqrt_array(c.data, out4.data, t.CSizeT(4)) - check("sqrt_arr[0]==2", out4.data[0] == t.CDouble(2.0), "") - check("sqrt_arr[3]==5", out4.data[3] == t.CDouble(5.0), "") + testcheck.check(out4.data[0] == t.CDouble(2.0), "sqrt_arr[0]==2", "sqrt_arr[0]==2") + testcheck.check(out4.data[3] == t.CDouble(5.0), "sqrt_arr[3]==5", "sqrt_arr[3]==5") # abs array d: numpy.ndarray | t.CPtr = numpy.zeros(pool, 4) @@ -273,9 +259,9 @@ def test_batch_array_ops(): d.data[2] = t.CDouble(3.0) d.data[3] = t.CDouble(-4.0) vipersimd.simd_abs_array(d.data, out4.data, t.CSizeT(4)) - check("abs_arr[0]==1", out4.data[0] == t.CDouble(1.0), "") - check("abs_arr[1]==2", out4.data[1] == t.CDouble(2.0), "") - check("abs_arr[3]==4", out4.data[3] == t.CDouble(4.0), "") + testcheck.check(out4.data[0] == t.CDouble(1.0), "abs_arr[0]==1", "abs_arr[0]==1") + testcheck.check(out4.data[1] == t.CDouble(2.0), "abs_arr[1]==2", "abs_arr[1]==2") + testcheck.check(out4.data[3] == t.CDouble(4.0), "abs_arr[3]==4", "abs_arr[3]==4") # dot array e: numpy.ndarray | t.CPtr = numpy.zeros(pool, 4) @@ -286,7 +272,7 @@ def test_batch_array_ops(): f: numpy.ndarray | t.CPtr = numpy.ones(pool, 4) out1: numpy.ndarray | t.CPtr = numpy.zeros(pool, 1) vipersimd.simd_dot_array(e.data, f.data, t.CSizeT(4), out1.data) - check("dot_arr==10", out1.data[0] == t.CDouble(10.0), "") + testcheck.check(out1.data[0] == t.CDouble(10.0), "dot_arr==10", "dot_arr==10") a.delete() b.delete() @@ -304,71 +290,71 @@ def test_batch_array_ops(): # ============================================================ def test_llvmir_scalar(): - section("LLVMIR precise scalar ops") + testcheck.section("LLVMIR precise scalar ops") # sqrt r: t.CDouble = vipersimd.simd_sqrt(t.CDouble(4.0)) - check("sqrt(4)==2", r == t.CDouble(2.0), "") + testcheck.check(r == t.CDouble(2.0), "sqrt(4)==2", "sqrt(4)==2") # fabs r = vipersimd.simd_fabs(t.CDouble(-3.5)) - check("fabs(-3.5)==3.5", r == t.CDouble(3.5), "") + testcheck.check(r == t.CDouble(3.5), "fabs(-3.5)==3.5", "fabs(-3.5)==3.5") # floor r = vipersimd.simd_floor(t.CDouble(3.7)) - check("floor(3.7)==3", r == t.CDouble(3.0), "") + testcheck.check(r == t.CDouble(3.0), "floor(3.7)==3", "floor(3.7)==3") # ceil r = vipersimd.simd_ceil(t.CDouble(3.2)) - check("ceil(3.2)==4", r == t.CDouble(4.0), "") + testcheck.check(r == t.CDouble(4.0), "ceil(3.2)==4", "ceil(3.2)==4") # round r = vipersimd.simd_round(t.CDouble(3.5)) - check("round(3.5)==4", r == t.CDouble(4.0), "") + testcheck.check(r == t.CDouble(4.0), "round(3.5)==4", "round(3.5)==4") # trunc r = vipersimd.simd_trunc(t.CDouble(3.9)) - check("trunc(3.9)==3", r == t.CDouble(3.0), "") + testcheck.check(r == t.CDouble(3.0), "trunc(3.9)==3", "trunc(3.9)==3") # fma: 2*3+1 = 7 r = vipersimd.simd_fma(t.CDouble(2.0), t.CDouble(3.0), t.CDouble(1.0)) - check("fma(2,3,1)==7", r == t.CDouble(7.0), "") + testcheck.check(r == t.CDouble(7.0), "fma(2,3,1)==7", "fma(2,3,1)==7") # copysign r = vipersimd.simd_copysign(t.CDouble(3.0), t.CDouble(-1.0)) - check("copysign(3,-1)==-3", r == t.CDouble(-3.0), "") + testcheck.check(r == t.CDouble(-3.0), "copysign(3,-1)==-3", "copysign(3,-1)==-3") # neg r = vipersimd.simd_neg(t.CDouble(1.5)) - check("neg(1.5)==-1.5", r == t.CDouble(-1.5), "") + testcheck.check(r == t.CDouble(-1.5), "neg(1.5)==-1.5", "neg(1.5)==-1.5") # minnum r = vipersimd.simd_minnum(t.CDouble(2.0), t.CDouble(3.0)) - check("minnum(2,3)==2", r == t.CDouble(2.0), "") + testcheck.check(r == t.CDouble(2.0), "minnum(2,3)==2", "minnum(2,3)==2") # maxnum r = vipersimd.simd_maxnum(t.CDouble(2.0), t.CDouble(3.0)) - check("maxnum(2,3)==3", r == t.CDouble(3.0), "") + testcheck.check(r == t.CDouble(3.0), "maxnum(2,3)==3", "maxnum(2,3)==3") # exp r = vipersimd.simd_exp(t.CDouble(1.0)) - check("exp(1)~=2.718", r > t.CDouble(2.71) and r < t.CDouble(2.72), "") + testcheck.check(r > t.CDouble(2.71) and r < t.CDouble(2.72), "exp(1)~=2.718", "exp(1)~=2.718") # log r = vipersimd.simd_log(t.CDouble(2.718281828459045)) - check("log(e)~=1", r > t.CDouble(0.999) and r < t.CDouble(1.001), "") + testcheck.check(r > t.CDouble(0.999) and r < t.CDouble(1.001), "log(e)~=1", "log(e)~=1") # sin r = vipersimd.simd_sin(t.CDouble(0.0)) - check("sin(0)~=0", r > t.CDouble(-0.001) and r < t.CDouble(0.001), "") + testcheck.check(r > t.CDouble(-0.001) and r < t.CDouble(0.001), "sin(0)~=0", "sin(0)~=0") # cos r = vipersimd.simd_cos(t.CDouble(0.0)) - check("cos(0)~=1", r > t.CDouble(0.999) and r < t.CDouble(1.001), "") + testcheck.check(r > t.CDouble(0.999) and r < t.CDouble(1.001), "cos(0)~=1", "cos(0)~=1") # pow r = vipersimd.simd_pow(t.CDouble(2.0), t.CDouble(10.0)) - check("pow(2,10)==1024", r == t.CDouble(1024.0), "") + testcheck.check(r == t.CDouble(1024.0), "pow(2,10)==1024", "pow(2,10)==1024") # ============================================================ @@ -405,7 +391,7 @@ def scalar_sqrt_array(a: t.CPtr, out: t.CPtr, n: t.CSizeT): i += 1 def benchmark_simd_vs_scalar(): - section("Benchmark: SIMD vs Scalar") + testcheck.section("Benchmark: SIMD vs Scalar") a: numpy.ndarray | t.CPtr = numpy.full(pool, N_ELEM, t.CDouble(1.5)) b: numpy.ndarray | t.CPtr = numpy.full(pool, N_ELEM, t.CDouble(2.5)) @@ -484,7 +470,7 @@ def benchmark_simd_vs_scalar(): printf(" speedup=N/A\n") # 验证结果正确性 - check("bench result[0] valid", out.data[0] > t.CDouble(0.0), "") + testcheck.check(out.data[0] > t.CDouble(0.0), "bench result[0] valid", "bench result[0] valid") a.delete() b.delete() @@ -501,7 +487,7 @@ def main() -> t.CInt: arena = calloc(4096 * 1024, 1) # 4MB arena pool = mpool.MPool(arena, 4096 * 1024, 0) # bump allocator - printf("=== ViperSIMD Test Suite ===\n") + testcheck.begin("ViperSIMD Test Suite") test_avx2_add_sub_mul_div() test_avx2_neg_abs_sqrt() @@ -513,5 +499,4 @@ def main() -> t.CInt: test_llvmir_scalar() benchmark_simd_vs_scalar() - printf("\n=== Results: %d passed, %d failed ===\n", test_passed, test_failed) - return 0 + return testcheck.end() diff --git a/Test/SimdTest/output/0991af0d22263577.deps.json b/Test/SimdTest/output/0991af0d22263577.deps.json new file mode 100644 index 0000000..cdad21c --- /dev/null +++ b/Test/SimdTest/output/0991af0d22263577.deps.json @@ -0,0 +1 @@ +{"mpool": "0991af0d22263577", "numpy.__init__": "1787ce01c2ed0493", "__init__": "1787ce01c2ed0493", "numpy": "1787ce01c2ed0493", "vipermath": "3f7c5e78d8652535", "stdint": "49bd8cba55979f76", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "main": "b44ac2a895a4072d", "string": "b5f1dc665c52a1bd", "viperio": "c9f4be41ca1cc2b4", "vipersimd": "fe99c83946298690"} \ No newline at end of file diff --git a/Test/SimdTest/output/1787ce01c2ed0493.deps.json b/Test/SimdTest/output/1787ce01c2ed0493.deps.json new file mode 100644 index 0000000..cdad21c --- /dev/null +++ b/Test/SimdTest/output/1787ce01c2ed0493.deps.json @@ -0,0 +1 @@ +{"mpool": "0991af0d22263577", "numpy.__init__": "1787ce01c2ed0493", "__init__": "1787ce01c2ed0493", "numpy": "1787ce01c2ed0493", "vipermath": "3f7c5e78d8652535", "stdint": "49bd8cba55979f76", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "main": "b44ac2a895a4072d", "string": "b5f1dc665c52a1bd", "viperio": "c9f4be41ca1cc2b4", "vipersimd": "fe99c83946298690"} \ No newline at end of file diff --git a/Test/SimdTest/output/1b666d438f4d301e.deps.json b/Test/SimdTest/output/1b666d438f4d301e.deps.json deleted file mode 100644 index 0fec052..0000000 --- a/Test/SimdTest/output/1b666d438f4d301e.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"vipermath": "3f7c5e78d8652535", "stdint": "56cdd754a8a09347", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "numpy.__init__": "c3eb91093118e1e1", "__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "vipersimd": "fe99c83946298690"} \ No newline at end of file diff --git a/Test/SimdTest/output/3f7c5e78d8652535.deps.json b/Test/SimdTest/output/3f7c5e78d8652535.deps.json index 6c27984..cdad21c 100644 --- a/Test/SimdTest/output/3f7c5e78d8652535.deps.json +++ b/Test/SimdTest/output/3f7c5e78d8652535.deps.json @@ -1 +1 @@ -{"main": "1b666d438f4d301e", "vipermath": "3f7c5e78d8652535", "stdint": "56cdd754a8a09347", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "numpy.__init__": "c3eb91093118e1e1", "__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "vipersimd": "fe99c83946298690"} \ No newline at end of file +{"mpool": "0991af0d22263577", "numpy.__init__": "1787ce01c2ed0493", "__init__": "1787ce01c2ed0493", "numpy": "1787ce01c2ed0493", "vipermath": "3f7c5e78d8652535", "stdint": "49bd8cba55979f76", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "main": "b44ac2a895a4072d", "string": "b5f1dc665c52a1bd", "viperio": "c9f4be41ca1cc2b4", "vipersimd": "fe99c83946298690"} \ No newline at end of file diff --git a/Test/SimdTest/output/68c4fe4b12c908e3.deps.json b/Test/SimdTest/output/68c4fe4b12c908e3.deps.json deleted file mode 100644 index 6c27984..0000000 --- a/Test/SimdTest/output/68c4fe4b12c908e3.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"main": "1b666d438f4d301e", "vipermath": "3f7c5e78d8652535", "stdint": "56cdd754a8a09347", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "numpy.__init__": "c3eb91093118e1e1", "__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "vipersimd": "fe99c83946298690"} \ No newline at end of file diff --git a/Test/SimdTest/output/6aee24fdefa3cbc0.deps.json b/Test/SimdTest/output/6aee24fdefa3cbc0.deps.json deleted file mode 100644 index 6c27984..0000000 --- a/Test/SimdTest/output/6aee24fdefa3cbc0.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"main": "1b666d438f4d301e", "vipermath": "3f7c5e78d8652535", "stdint": "56cdd754a8a09347", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "numpy.__init__": "c3eb91093118e1e1", "__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "vipersimd": "fe99c83946298690"} \ No newline at end of file diff --git a/Test/SimdTest/output/9dbecd0942a39782.deps.json b/Test/SimdTest/output/9dbecd0942a39782.deps.json new file mode 100644 index 0000000..cdad21c --- /dev/null +++ b/Test/SimdTest/output/9dbecd0942a39782.deps.json @@ -0,0 +1 @@ +{"mpool": "0991af0d22263577", "numpy.__init__": "1787ce01c2ed0493", "__init__": "1787ce01c2ed0493", "numpy": "1787ce01c2ed0493", "vipermath": "3f7c5e78d8652535", "stdint": "49bd8cba55979f76", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "main": "b44ac2a895a4072d", "string": "b5f1dc665c52a1bd", "viperio": "c9f4be41ca1cc2b4", "vipersimd": "fe99c83946298690"} \ No newline at end of file diff --git a/Test/SimdTest/output/b44ac2a895a4072d.deps.json b/Test/SimdTest/output/b44ac2a895a4072d.deps.json new file mode 100644 index 0000000..1a7faf7 --- /dev/null +++ b/Test/SimdTest/output/b44ac2a895a4072d.deps.json @@ -0,0 +1 @@ +{"mpool": "0991af0d22263577", "numpy.__init__": "1787ce01c2ed0493", "__init__": "1787ce01c2ed0493", "numpy": "1787ce01c2ed0493", "vipermath": "3f7c5e78d8652535", "stdint": "49bd8cba55979f76", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "viperio": "c9f4be41ca1cc2b4", "vipersimd": "fe99c83946298690"} \ No newline at end of file diff --git a/Test/SimdTest/output/b5f1dc665c52a1bd.deps.json b/Test/SimdTest/output/b5f1dc665c52a1bd.deps.json new file mode 100644 index 0000000..cdad21c --- /dev/null +++ b/Test/SimdTest/output/b5f1dc665c52a1bd.deps.json @@ -0,0 +1 @@ +{"mpool": "0991af0d22263577", "numpy.__init__": "1787ce01c2ed0493", "__init__": "1787ce01c2ed0493", "numpy": "1787ce01c2ed0493", "vipermath": "3f7c5e78d8652535", "stdint": "49bd8cba55979f76", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "main": "b44ac2a895a4072d", "string": "b5f1dc665c52a1bd", "viperio": "c9f4be41ca1cc2b4", "vipersimd": "fe99c83946298690"} \ No newline at end of file diff --git a/Test/SimdTest/output/c3eb91093118e1e1.deps.json b/Test/SimdTest/output/c3eb91093118e1e1.deps.json deleted file mode 100644 index 6c27984..0000000 --- a/Test/SimdTest/output/c3eb91093118e1e1.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"main": "1b666d438f4d301e", "vipermath": "3f7c5e78d8652535", "stdint": "56cdd754a8a09347", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "numpy.__init__": "c3eb91093118e1e1", "__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "vipersimd": "fe99c83946298690"} \ No newline at end of file diff --git a/Test/SimdTest/output/c9f4be41ca1cc2b4.deps.json b/Test/SimdTest/output/c9f4be41ca1cc2b4.deps.json index 6c27984..cdad21c 100644 --- a/Test/SimdTest/output/c9f4be41ca1cc2b4.deps.json +++ b/Test/SimdTest/output/c9f4be41ca1cc2b4.deps.json @@ -1 +1 @@ -{"main": "1b666d438f4d301e", "vipermath": "3f7c5e78d8652535", "stdint": "56cdd754a8a09347", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "numpy.__init__": "c3eb91093118e1e1", "__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "vipersimd": "fe99c83946298690"} \ No newline at end of file +{"mpool": "0991af0d22263577", "numpy.__init__": "1787ce01c2ed0493", "__init__": "1787ce01c2ed0493", "numpy": "1787ce01c2ed0493", "vipermath": "3f7c5e78d8652535", "stdint": "49bd8cba55979f76", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "main": "b44ac2a895a4072d", "string": "b5f1dc665c52a1bd", "viperio": "c9f4be41ca1cc2b4", "vipersimd": "fe99c83946298690"} \ No newline at end of file diff --git a/Test/SimdTest/output/fe99c83946298690.deps.json b/Test/SimdTest/output/fe99c83946298690.deps.json index 6c27984..cdad21c 100644 --- a/Test/SimdTest/output/fe99c83946298690.deps.json +++ b/Test/SimdTest/output/fe99c83946298690.deps.json @@ -1 +1 @@ -{"main": "1b666d438f4d301e", "vipermath": "3f7c5e78d8652535", "stdint": "56cdd754a8a09347", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "numpy.__init__": "c3eb91093118e1e1", "__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "vipersimd": "fe99c83946298690"} \ No newline at end of file +{"mpool": "0991af0d22263577", "numpy.__init__": "1787ce01c2ed0493", "__init__": "1787ce01c2ed0493", "numpy": "1787ce01c2ed0493", "vipermath": "3f7c5e78d8652535", "stdint": "49bd8cba55979f76", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "main": "b44ac2a895a4072d", "string": "b5f1dc665c52a1bd", "viperio": "c9f4be41ca1cc2b4", "vipersimd": "fe99c83946298690"} \ No newline at end of file diff --git a/Test/SimdTest/temp/68c4fe4b12c908e3.pyi b/Test/SimdTest/temp/0991af0d22263577.pyi similarity index 98% rename from Test/SimdTest/temp/68c4fe4b12c908e3.pyi rename to Test/SimdTest/temp/0991af0d22263577.pyi index fc2010b..f001c8a 100644 --- a/Test/SimdTest/temp/68c4fe4b12c908e3.pyi +++ b/Test/SimdTest/temp/0991af0d22263577.pyi @@ -11,7 +11,7 @@ import string MPOOL_ALIGN: t.CDefine = 8 MPOOL_TYPE_SLAB: t.CDefine = 0 -MPOOL_TYPE_BUMP: t.CDefine = 2 +MPOOL_TYPE_BUMP: t.CDefine = 1 def _align_up(val: t.CSizeT, align: t.CSizeT) -> t.CSizeT: pass diff --git a/Test/SimdTest/temp/c3eb91093118e1e1.pyi b/Test/SimdTest/temp/1787ce01c2ed0493.pyi similarity index 99% rename from Test/SimdTest/temp/c3eb91093118e1e1.pyi rename to Test/SimdTest/temp/1787ce01c2ed0493.pyi index adb6481..2fdf413 100644 --- a/Test/SimdTest/temp/c3eb91093118e1e1.pyi +++ b/Test/SimdTest/temp/1787ce01c2ed0493.pyi @@ -24,8 +24,8 @@ e: t.CDefine = 2.71828182845904523536 @t.Object class ndarray: data: t.CDouble | t.CPtr - shape: list[t.CSizeT, MAX_NDIM] - strides: list[t.CSizeT, MAX_NDIM] + shape: t.CArray[t.CSizeT, MAX_NDIM] + strides: t.CArray[t.CSizeT, MAX_NDIM] ndim: t.CInt size: t.CSizeT owns_data: t.CInt diff --git a/Test/SimdTest/temp/49bd8cba55979f76.pyi b/Test/SimdTest/temp/49bd8cba55979f76.pyi new file mode 100644 index 0000000..f1d844a --- /dev/null +++ b/Test/SimdTest/temp/49bd8cba55979f76.pyi @@ -0,0 +1,75 @@ +""" +Auto-generated Python stub file from stdint.py +Module: stdint +""" + +import c + + +import t + +INT: t.CTypedef = t.CInt +INTPTR: t.CTypedef = t.CInt | t.CPtr +BOOL: t.CTypedef = t.CInt +UINT: t.CTypedef = t.CUnsignedInt +UINTPTR: t.CTypedef = UINT | t.CPtr +BYTE: t.CTypedef = t.CUnsignedChar +BYTEPTR: t.CTypedef = BYTE | t.CPtr +WORD: t.CTypedef = t.CUInt16T +DWORD: t.CTypedef = t.CUInt32T +QWORD: t.CTypedef = t.CUInt64T +TCHAR: t.CTypedef = t.CChar +CHARLIST: t.CTypedef = str | t.CPtr +VOID: t.CTypedef = t.CVoid +SHORT: t.CTypedef = t.CShort +SHORTPTR: t.CTypedef = t.CShort | t.CPtr +USHORT: t.CTypedef = t.CUnsignedShort +USHORTPTR: t.CTypedef = t.CUnsignedShort | t.CPtr +LONGLONG: t.CTypedef = t.CLong | t.CLong +ULONGLONG: t.CTypedef = t.CUnsignedLong | t.CLong +LONG: t.CTypedef = t.CLong +ULONG: t.CTypedef = t.CUnsignedLong +WCHAR: t.CTypedef = WORD +WCHARPTR: t.CTypedef = WORD | t.CPtr +CHARPTR: t.CTypedef = t.CChar | t.CPtr +FSIZE_t: t.CTypedef = DWORD +LBA_t: t.CTypedef = DWORD +UINTPTR: t.CTypedef = t.CUnsignedInt | t.CPtr +VOIDPTR: t.CTypedef = t.CVoid | t.CPtr +FLOAT: t.CTypedef = t.CFloat +DOUBLE: t.CTypedef = t.CDouble +FLOAT8: t.CTypedef = t.CFloat8T +FLOAT16: t.CTypedef = t.CFloat16T +FLOAT32: t.CTypedef = t.CFloat32T +FLOAT64: t.CTypedef = t.CFloat64T +FLOAT128: t.CTypedef = t.CFloat128T +INT8: t.CTypedef = t.CInt8T +INT16: t.CTypedef = t.CInt16T +INT32: t.CTypedef = t.CInt32T +INT64: t.CTypedef = t.CInt64T +UINT8: t.CTypedef = t.CUInt8T +UINT16: t.CTypedef = t.CUInt16T +UINT32: t.CTypedef = t.CUInt32T +UINT64: t.CTypedef = t.CUInt64T +INT8PTR: t.CTypedef = t.CInt8T | t.CPtr +INT16PTR: t.CTypedef = t.CInt16T | t.CPtr +INT32PTR: t.CTypedef = t.CInt32T | t.CPtr +INT64PTR: t.CTypedef = t.CInt64T | t.CPtr +UINT8PTR: t.CTypedef = t.CUInt8T | t.CPtr +UINT16PTR: t.CTypedef = t.CUInt16T | t.CPtr +UINT32PTR: t.CTypedef = t.CUInt32T | t.CPtr +UINT64PTR: t.CTypedef = t.CUInt64T | t.CPtr +CHAR8: t.CTypedef = t.CChar8T +CHAR16: t.CTypedef = t.CChar16T +CHAR32: t.CTypedef = t.CChar32T +CHAR8PTR: t.CTypedef = t.CChar8T | t.CPtr +CHAR16PTR: t.CTypedef = t.CChar16T | t.CPtr +CHAR32PTR: t.CTypedef = t.CChar32T | t.CPtr +i8: t.CTypedef = t.CInt8T +i16: t.CTypedef = t.CInt16T +i32: t.CTypedef = t.CInt32T +i64: t.CTypedef = t.CInt64T +u8: t.CTypedef = t.CUInt8T +u16: t.CTypedef = t.CUInt16T +u32: t.CTypedef = t.CUInt32T +u64: t.CTypedef = t.CUInt64T \ No newline at end of file diff --git a/Test/SimdTest/temp/56cdd754a8a09347.pyi b/Test/SimdTest/temp/56cdd754a8a09347.pyi deleted file mode 100644 index 007ccb8..0000000 --- a/Test/SimdTest/temp/56cdd754a8a09347.pyi +++ /dev/null @@ -1,67 +0,0 @@ -""" -Auto-generated Python stub file from stdint.py -Module: stdint -""" - -import c - - -import t - -INT: t.CTypedef = t.CInt -INTPTR: t.CTypedef = t.CInt | t.CPtr -BOOL: t.CTypedef = t.CInt -UINT: t.CTypedef = t.CUnsignedInt -UINTPTR: t.CTypedef = UINT | t.CPtr -BYTE: t.CTypedef = t.CUnsignedChar -BYTEPTR: t.CTypedef = BYTE | t.CPtr -WORD: t.CTypedef = t.CUInt16T -DWORD: t.CTypedef = t.CUInt32T -QWORD: t.CTypedef = t.CUInt64T -TCHAR: t.CTypedef = t.CChar -CHARLIST: t.CTypedef = str | t.CPtr -VOID: t.CTypedef = t.CVoid -SHORT: t.CTypedef = t.CShort -SHORTPTR: t.CTypedef = t.CShort | t.CPtr -USHORT: t.CTypedef = t.CUnsignedShort -USHORTPTR: t.CTypedef = t.CUnsignedShort | t.CPtr -LONGLONG: t.CTypedef = t.CLong | t.CLong -ULONGLONG: t.CTypedef = t.CUnsignedLong | t.CLong -LONG: t.CTypedef = t.CLong -ULONG: t.CTypedef = t.CUnsignedLong -WCHAR: t.CTypedef = WORD -WCHARPTR: t.CTypedef = WORD | t.CPtr -CHARPTR: t.CTypedef = t.CChar | t.CPtr -FSIZE_t: t.CTypedef = DWORD -LBA_t: t.CTypedef = DWORD -UINTPTR: t.CTypedef = t.CUnsignedInt | t.CPtr -VOIDPTR: t.CTypedef = t.CVoid | t.CPtr -FLOAT: t.CTypedef = t.CFloat -DOUBLE: t.CTypedef = t.CDouble -FLOAT8: t.CTypedef = t.CFloat8T -FLOAT16: t.CTypedef = t.CFloat16T -FLOAT32: t.CTypedef = t.CFloat32T -FLOAT64: t.CTypedef = t.CFloat64T -FLOAT128: t.CTypedef = t.CFloat128T -INT8: t.CTypedef = t.CInt8T -INT16: t.CTypedef = t.CInt16T -INT32: t.CTypedef = t.CInt32T -INT64: t.CTypedef = t.CInt64T -UINT8: t.CTypedef = t.CUInt8T -UINT16: t.CTypedef = t.CUInt16T -UINT32: t.CTypedef = t.CUInt32T -UINT64: t.CTypedef = t.CUInt64T -INT8PTR: t.CTypedef = t.CInt8T | t.CPtr -INT16PTR: t.CTypedef = t.CInt16T | t.CPtr -INT32PTR: t.CTypedef = t.CInt32T | t.CPtr -INT64PTR: t.CTypedef = t.CInt64T | t.CPtr -UINT8PTR: t.CTypedef = t.CUInt8T | t.CPtr -UINT16PTR: t.CTypedef = t.CUInt16T | t.CPtr -UINT32PTR: t.CTypedef = t.CUInt32T | t.CPtr -UINT64PTR: t.CTypedef = t.CUInt64T | t.CPtr -CHAR8: t.CTypedef = t.CChar8T -CHAR16: t.CTypedef = t.CChar16T -CHAR32: t.CTypedef = t.CChar32T -CHAR8PTR: t.CTypedef = t.CChar8T | t.CPtr -CHAR16PTR: t.CTypedef = t.CChar16T | t.CPtr -CHAR32PTR: t.CTypedef = t.CChar32T | t.CPtr \ No newline at end of file diff --git a/Test/SimdTest/temp/9dbecd0942a39782.pyi b/Test/SimdTest/temp/9dbecd0942a39782.pyi new file mode 100644 index 0000000..41648c1 --- /dev/null +++ b/Test/SimdTest/temp/9dbecd0942a39782.pyi @@ -0,0 +1,25 @@ +""" +Auto-generated Python stub file from testcheck.py +Module: testcheck +""" + + +import t, c +import stdio + +_pass_count: t.CExtern | t.CInt +_fail_count: t.CExtern | t.CInt + +def begin(name: str) -> t.CInt: pass + +def section(name: str) -> t.CInt: pass + +def ok(msg: str) -> t.CInt: pass + +def fail(msg: str) -> t.CInt: pass + +def check(cond: t.CInt, ok_msg: str, fail_msg: str) -> t.CInt: pass + +def info(msg: str) -> t.CInt: pass + +def end() -> t.CInt: pass diff --git a/Test/SimdTest/temp/_sha1_map.txt b/Test/SimdTest/temp/_sha1_map.txt index e9909af..c8c277d 100644 --- a/Test/SimdTest/temp/_sha1_map.txt +++ b/Test/SimdTest/temp/_sha1_map.txt @@ -1,10 +1,11 @@ -1b666d438f4d301e:main.py +0991af0d22263577:includes/mpool.py +1787ce01c2ed0493:includes/numpy\__init__.py 3f7c5e78d8652535:includes/vipermath.py -56cdd754a8a09347:includes/stdint.py -68c4fe4b12c908e3:includes/mpool.py -6aee24fdefa3cbc0:includes/string.py +49bd8cba55979f76:includes/stdint.py 6c2029b306556c00:includes/stdlib.py 73edbcf76e32d00b:includes/stdio.py -c3eb91093118e1e1:includes/numpy\__init__.py +9dbecd0942a39782:includes/testcheck.py +b44ac2a895a4072d:main.py +b5f1dc665c52a1bd:includes/string.py c9f4be41ca1cc2b4:includes/viperio.py fe99c83946298690:includes/vipersimd.py diff --git a/Test/SimdTest/temp/1b666d438f4d301e.pyi b/Test/SimdTest/temp/b44ac2a895a4072d.pyi similarity index 86% rename from Test/SimdTest/temp/1b666d438f4d301e.pyi rename to Test/SimdTest/temp/b44ac2a895a4072d.pyi index f6cf141..1a9889e 100644 --- a/Test/SimdTest/temp/1b666d438f4d301e.pyi +++ b/Test/SimdTest/temp/b44ac2a895a4072d.pyi @@ -12,6 +12,7 @@ import stdlib from stdlib import calloc import t, c import mpool +import testcheck arena: t.CExtern | t.CUInt8T | t.CPtr pool: t.CExtern | mpool.MPool | t.CPtr @@ -20,12 +21,6 @@ def clock() -> t.CLong | t.CExtern: pass CLOCK_PER_SEC: t.CDefine = 1000 -test_passed: t.CExtern | t.CInt -test_failed: t.CExtern | t.CInt - -def check(name: str, condition: t.CInt, detail: str) -> t.CInt: pass - -def section(title: str) -> t.CInt: pass def test_avx2_add_sub_mul_div() -> t.CInt: pass diff --git a/Test/SimdTest/temp/b5f1dc665c52a1bd.pyi b/Test/SimdTest/temp/b5f1dc665c52a1bd.pyi new file mode 100644 index 0000000..8b6959e --- /dev/null +++ b/Test/SimdTest/temp/b5f1dc665c52a1bd.pyi @@ -0,0 +1,44 @@ +""" +Auto-generated Python stub file from string.py +Module: string +""" + + +from stdint import * +import t, c + +def strcpy(dest: str, src: str) -> str: pass + +def strncpy(dest: str, src: str, n: t.CSizeT) -> str: pass + +def strlen(src: str) -> t.CSizeT | t.CExport: pass + +def strcmp(str1: str, str2: str) -> t.CInt: pass + +def samestr(str1: str, str2: str) -> bool: pass + +def strncmp(str1: str, str2: str, n: t.CSizeT) -> t.CInt: pass + +def memcmp(ptr1: t.CVoid | t.CPtr, ptr2: t.CVoid | t.CPtr, n: t.CSizeT) -> t.CInt: pass + +def strchr(s: str, cr: t.CInt) -> str: pass + +def strrchr(s: str, cr: t.CInt) -> str: pass + +def strspn(s: str, skip: str) -> int: pass + +def memset(ptr: t.CVoid | t.CPtr, value: t.CInt, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass + +def memset32(ptr: t.CVoid | t.CPtr, value: t.CUInt32T, count: t.CSizeT) -> t.CVoid | t.CPtr: pass + +def memcpy(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass + +def memmove(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr: pass + +def atoi(src: str) -> t.CInt: pass + +def atoll(src: str) -> t.CInt64T: pass + +def atof(src: str) -> t.CDouble: pass + +def split(s: str, delim: str, result: t.CArray[str]) -> int: pass diff --git a/Test/StringIterTest/App/inline_test.py b/Test/StringIterTest/App/inline_test.py index b811e68..95144c3 100644 --- a/Test/StringIterTest/App/inline_test.py +++ b/Test/StringIterTest/App/inline_test.py @@ -10,7 +10,7 @@ class Inner: @t.Object class Container: - items: list[Inner, 10] + items: t.CArray[Inner, 10] count: t.CInt def __init__(self): diff --git a/Test/StringIterTest/App/main.py b/Test/StringIterTest/App/main.py index 2b09be4..8a5645c 100644 --- a/Test/StringIterTest/App/main.py +++ b/Test/StringIterTest/App/main.py @@ -2,28 +2,26 @@ import t import stdio import string import c +import testcheck # ============================================================ # Test 1: 字符串指针迭代 - 逐字符直到\0 # ============================================================ def test_string_ptr_iter(): - stdio.printf("--- Test 1: string pointer iteration ---\n") + testcheck.section("Test 1: string pointer iteration") s: t.CChar | t.CPtr = "Hello" p: t.CChar | t.CPtr = s count: t.CInt = 0 while c.Deref(p) != 0: count += 1 p += 1 - if count == 5: - stdio.printf("PASS: ptr iter (count=%d)\n", count) - else: - stdio.printf("FAIL: ptr iter (count=%d, expect 5)\n", count) + testcheck.check(count == 5, "ptr iter (count=5)", "ptr iter (count expect 5)") # ============================================================ # Test 2: 字符串指针求和ASCII值 # ============================================================ def test_string_ascii_sum(): - stdio.printf("--- Test 2: string ASCII sum ---\n") + testcheck.section("Test 2: string ASCII sum") s: t.CChar | t.CPtr = "ABC" p: t.CChar | t.CPtr = s total: t.CInt = 0 @@ -31,16 +29,13 @@ def test_string_ascii_sum(): total += t.CInt(c.Deref(p)) p += 1 # A=65, B=66, C=67 => 198 - if total == 198: - stdio.printf("PASS: ASCII sum (total=%d)\n", total) - else: - stdio.printf("FAIL: ASCII sum (total=%d, expect 198)\n", total) + testcheck.check(total == 198, "ASCII sum (total=198)", "ASCII sum (total expect 198)") # ============================================================ # Test 3: 手动strcpy - 指针复制 # ============================================================ def test_manual_strcpy(): - stdio.printf("--- Test 3: manual strcpy via pointers ---\n") + testcheck.section("Test 3: manual strcpy via pointers") src: t.CChar | t.CPtr = "Test" dst: list[t.CChar, 32] = [0] sp: t.CChar | t.CPtr = src @@ -50,16 +45,13 @@ def test_manual_strcpy(): sp += 1 dp += 1 c.Set(c.Deref(dp), 0) - if dst[0] == 84 and dst[1] == 101 and dst[2] == 115 and dst[3] == 116: - stdio.printf("PASS: manual strcpy (T=%d e=%d s=%d t=%d)\n", dst[0], dst[1], dst[2], dst[3]) - else: - stdio.printf("FAIL: manual strcpy (T=%d e=%d s=%d t=%d)\n", dst[0], dst[1], dst[2], dst[3]) + testcheck.check(dst[0] == 84 and dst[1] == 101 and dst[2] == 115 and dst[3] == 116, "manual strcpy (T=84 e=101 s=115 t=116)", "manual strcpy (expect T=84 e=101 s=115 t=116)") # ============================================================ # Test 4: 指针比较和偏移 # ============================================================ def test_ptr_offset_compare(): - stdio.printf("--- Test 4: pointer offset and compare ---\n") + testcheck.section("Test 4: pointer offset and compare") arr: list[t.CInt, 5] = [0] for i in range(5): arr[i] = i * 10 @@ -69,32 +61,26 @@ def test_ptr_offset_compare(): while p != start + 5: total += c.Deref(p) p += 1 - if total == 100: - stdio.printf("PASS: ptr offset (total=%d)\n", total) - else: - stdio.printf("FAIL: ptr offset (total=%d, expect 100)\n", total) + testcheck.check(total == 100, "ptr offset (total=100)", "ptr offset (total expect 100)") # ============================================================ # Test 5: 字符串长度手动计算 # ============================================================ def test_manual_strlen(): - stdio.printf("--- Test 5: manual strlen ---\n") + testcheck.section("Test 5: manual strlen") s: t.CChar | t.CPtr = "Hello World!" p: t.CChar | t.CPtr = s length: t.CSizeT = 0 while c.Deref(p) != 0: length += 1 p += 1 - if length == 12: - stdio.printf("PASS: manual strlen (len=%zu)\n", length) - else: - stdio.printf("FAIL: manual strlen (len=%zu, expect 12)\n", length) + testcheck.check(length == 12, "manual strlen (len=12)", "manual strlen (len expect 12)") # ============================================================ # Test 6: 指针反向遍历字符串 # ============================================================ def test_reverse_string_ptr(): - stdio.printf("--- Test 6: reverse string via pointer ---\n") + testcheck.section("Test 6: reverse string via pointer") src: t.CChar | t.CPtr = "abcd" dst: list[t.CChar, 32] = [0] # Find end of src @@ -112,31 +98,25 @@ def test_reverse_string_ptr(): p -= 1 c.Set(c.Deref(dp), 0) # "abcd" reversed = "dcba" = 100,99,98,97 - if dst[0] == 100 and dst[1] == 99 and dst[2] == 98 and dst[3] == 97: - stdio.printf("PASS: reverse string (d=%d c=%d b=%d a=%d)\n", dst[0], dst[1], dst[2], dst[3]) - else: - stdio.printf("FAIL: reverse string (d=%d c=%d b=%d a=%d)\n", dst[0], dst[1], dst[2], dst[3]) + testcheck.check(dst[0] == 100 and dst[1] == 99 and dst[2] == 98 and dst[3] == 97, "reverse string (d=100 c=99 b=98 a=97)", "reverse string (expect d=100 c=99 b=98 a=97)") # ============================================================ # Test 7: 多级指针 - 指向指针的指针 # ============================================================ def test_double_pointer(): - stdio.printf("--- Test 7: double pointer ---\n") + testcheck.section("Test 7: double pointer") x: t.CInt = 42 px: t.CInt | t.CPtr = c.Addr(x) ppx: t.CInt | t.CPtr | t.CPtr = c.Addr(px) # Read through double pointer val: t.CInt = c.Deref(c.Deref(ppx)) - if val == 42: - stdio.printf("PASS: double pointer (val=%d)\n", val) - else: - stdio.printf("FAIL: double pointer (val=%d, expect 42)\n", val) + testcheck.check(val == 42, "double pointer (val=42)", "double pointer (val expect 42)") # ============================================================ # Test 8: 指针算术 - 数组元素访问 # ============================================================ def test_ptr_arithmetic(): - stdio.printf("--- Test 8: pointer arithmetic ---\n") + testcheck.section("Test 8: pointer arithmetic") arr: list[t.CInt, 8] = [0] for i in range(8): arr[i] = (i + 1) * (i + 1) @@ -144,16 +124,13 @@ def test_ptr_arithmetic(): # Access arr[3] via pointer: p + 3 val: t.CInt = c.Deref(p + 3) # arr[3] = 4*4 = 16 - if val == 16: - stdio.printf("PASS: ptr arithmetic (arr[3]=%d)\n", val) - else: - stdio.printf("FAIL: ptr arithmetic (arr[3]=%d, expect 16)\n", val) + testcheck.check(val == 16, "ptr arithmetic (arr[3]=16)", "ptr arithmetic (arr[3] expect 16)") # ============================================================ # Test 9: 字符串比较 - 逐字符指针 # ============================================================ def test_manual_strcmp(): - stdio.printf("--- Test 9: manual strcmp via pointers ---\n") + testcheck.section("Test 9: manual strcmp via pointers") s1: t.CChar | t.CPtr = "Hello" s2: t.CChar | t.CPtr = "Hello" p1: t.CChar | t.CPtr = s1 @@ -167,10 +144,7 @@ def test_manual_strcmp(): p2 += 1 if c.Deref(p1) != c.Deref(p2): equal = 0 - if equal == 1: - stdio.printf("PASS: manual strcmp (equal=%d)\n", equal) - else: - stdio.printf("FAIL: manual strcmp (equal=%d, expect 1)\n", equal) + testcheck.check(equal == 1, "manual strcmp (equal=1)", "manual strcmp (equal expect 1)") # ============================================================ # Test 10: 结构体指针访问 @@ -180,7 +154,7 @@ class Vec2: y: t.CInt def test_struct_ptr_access(): - stdio.printf("--- Test 10: struct pointer access ---\n") + testcheck.section("Test 10: struct pointer access") v: Vec2 = Vec2() v.x = 10 v.y = 20 @@ -188,13 +162,10 @@ def test_struct_ptr_access(): # Modify through pointer c.Deref(p).x = 100 c.Deref(p).y = 200 - if v.x == 100 and v.y == 200: - stdio.printf("PASS: struct ptr (x=%d y=%d)\n", v.x, v.y) - else: - stdio.printf("FAIL: struct ptr (x=%d y=%d, expect 100 200)\n", v.x, v.y) + testcheck.check(v.x == 100 and v.y == 200, "struct ptr (x=100 y=200)", "struct ptr (x y expect 100 200)") def main() -> t.CInt: - stdio.printf("=== StringIterTest: String/Pointer Iteration Tests ===\n\n") + testcheck.begin("StringIterTest: String/Pointer Iteration Tests") test_string_ptr_iter() test_string_ascii_sum() test_manual_strcpy() @@ -205,5 +176,4 @@ def main() -> t.CInt: test_ptr_arithmetic() test_manual_strcmp() test_struct_ptr_access() - stdio.printf("\n=== StringIterTest Complete ===\n") - return 0 + return testcheck.end() diff --git a/Test/StringIterTest/output/2255fdda7aed5595.deps.json b/Test/StringIterTest/output/2255fdda7aed5595.deps.json deleted file mode 100644 index edd3f31..0000000 --- a/Test/StringIterTest/output/2255fdda7aed5595.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"stdint": "56cdd754a8a09347", "string": "6aee24fdefa3cbc0", "stdio": "73edbcf76e32d00b"} \ No newline at end of file diff --git a/Test/StringIterTest/output/6aee24fdefa3cbc0.deps.json b/Test/StringIterTest/output/6aee24fdefa3cbc0.deps.json deleted file mode 100644 index f246770..0000000 --- a/Test/StringIterTest/output/6aee24fdefa3cbc0.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"main": "2255fdda7aed5595", "stdint": "56cdd754a8a09347", "string": "6aee24fdefa3cbc0", "stdio": "73edbcf76e32d00b"} \ No newline at end of file diff --git a/Test/StringIterTest/output/924ed8cd4ea5c4c2.deps.json b/Test/StringIterTest/output/924ed8cd4ea5c4c2.deps.json new file mode 100644 index 0000000..12bab96 --- /dev/null +++ b/Test/StringIterTest/output/924ed8cd4ea5c4c2.deps.json @@ -0,0 +1 @@ +{"stdint": "49bd8cba55979f76", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd"} \ No newline at end of file diff --git a/Test/StringIterTest/output/9dbecd0942a39782.deps.json b/Test/StringIterTest/output/9dbecd0942a39782.deps.json new file mode 100644 index 0000000..84ef3c3 --- /dev/null +++ b/Test/StringIterTest/output/9dbecd0942a39782.deps.json @@ -0,0 +1 @@ +{"stdint": "49bd8cba55979f76", "stdio": "73edbcf76e32d00b", "main": "924ed8cd4ea5c4c2", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd"} \ No newline at end of file diff --git a/Test/StringIterTest/output/StringIterTest.exe.tmp0 b/Test/StringIterTest/output/StringIterTest.exe.tmp0 new file mode 100644 index 0000000000000000000000000000000000000000..99995e272c2df2e391118d67288672ce799ee51a GIT binary patch literal 135689 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 G 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 literal 0 HcmV?d00001 diff --git a/Test/StringIterTest/output/b5f1dc665c52a1bd.deps.json b/Test/StringIterTest/output/b5f1dc665c52a1bd.deps.json new file mode 100644 index 0000000..84ef3c3 --- /dev/null +++ b/Test/StringIterTest/output/b5f1dc665c52a1bd.deps.json @@ -0,0 +1 @@ +{"stdint": "49bd8cba55979f76", "stdio": "73edbcf76e32d00b", "main": "924ed8cd4ea5c4c2", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd"} \ No newline at end of file diff --git a/Test/StringIterTest/temp/49bd8cba55979f76.pyi b/Test/StringIterTest/temp/49bd8cba55979f76.pyi new file mode 100644 index 0000000..f1d844a --- /dev/null +++ b/Test/StringIterTest/temp/49bd8cba55979f76.pyi @@ -0,0 +1,75 @@ +""" +Auto-generated Python stub file from stdint.py +Module: stdint +""" + +import c + + +import t + +INT: t.CTypedef = t.CInt +INTPTR: t.CTypedef = t.CInt | t.CPtr +BOOL: t.CTypedef = t.CInt +UINT: t.CTypedef = t.CUnsignedInt +UINTPTR: t.CTypedef = UINT | t.CPtr +BYTE: t.CTypedef = t.CUnsignedChar +BYTEPTR: t.CTypedef = BYTE | t.CPtr +WORD: t.CTypedef = t.CUInt16T +DWORD: t.CTypedef = t.CUInt32T +QWORD: t.CTypedef = t.CUInt64T +TCHAR: t.CTypedef = t.CChar +CHARLIST: t.CTypedef = str | t.CPtr +VOID: t.CTypedef = t.CVoid +SHORT: t.CTypedef = t.CShort +SHORTPTR: t.CTypedef = t.CShort | t.CPtr +USHORT: t.CTypedef = t.CUnsignedShort +USHORTPTR: t.CTypedef = t.CUnsignedShort | t.CPtr +LONGLONG: t.CTypedef = t.CLong | t.CLong +ULONGLONG: t.CTypedef = t.CUnsignedLong | t.CLong +LONG: t.CTypedef = t.CLong +ULONG: t.CTypedef = t.CUnsignedLong +WCHAR: t.CTypedef = WORD +WCHARPTR: t.CTypedef = WORD | t.CPtr +CHARPTR: t.CTypedef = t.CChar | t.CPtr +FSIZE_t: t.CTypedef = DWORD +LBA_t: t.CTypedef = DWORD +UINTPTR: t.CTypedef = t.CUnsignedInt | t.CPtr +VOIDPTR: t.CTypedef = t.CVoid | t.CPtr +FLOAT: t.CTypedef = t.CFloat +DOUBLE: t.CTypedef = t.CDouble +FLOAT8: t.CTypedef = t.CFloat8T +FLOAT16: t.CTypedef = t.CFloat16T +FLOAT32: t.CTypedef = t.CFloat32T +FLOAT64: t.CTypedef = t.CFloat64T +FLOAT128: t.CTypedef = t.CFloat128T +INT8: t.CTypedef = t.CInt8T +INT16: t.CTypedef = t.CInt16T +INT32: t.CTypedef = t.CInt32T +INT64: t.CTypedef = t.CInt64T +UINT8: t.CTypedef = t.CUInt8T +UINT16: t.CTypedef = t.CUInt16T +UINT32: t.CTypedef = t.CUInt32T +UINT64: t.CTypedef = t.CUInt64T +INT8PTR: t.CTypedef = t.CInt8T | t.CPtr +INT16PTR: t.CTypedef = t.CInt16T | t.CPtr +INT32PTR: t.CTypedef = t.CInt32T | t.CPtr +INT64PTR: t.CTypedef = t.CInt64T | t.CPtr +UINT8PTR: t.CTypedef = t.CUInt8T | t.CPtr +UINT16PTR: t.CTypedef = t.CUInt16T | t.CPtr +UINT32PTR: t.CTypedef = t.CUInt32T | t.CPtr +UINT64PTR: t.CTypedef = t.CUInt64T | t.CPtr +CHAR8: t.CTypedef = t.CChar8T +CHAR16: t.CTypedef = t.CChar16T +CHAR32: t.CTypedef = t.CChar32T +CHAR8PTR: t.CTypedef = t.CChar8T | t.CPtr +CHAR16PTR: t.CTypedef = t.CChar16T | t.CPtr +CHAR32PTR: t.CTypedef = t.CChar32T | t.CPtr +i8: t.CTypedef = t.CInt8T +i16: t.CTypedef = t.CInt16T +i32: t.CTypedef = t.CInt32T +i64: t.CTypedef = t.CInt64T +u8: t.CTypedef = t.CUInt8T +u16: t.CTypedef = t.CUInt16T +u32: t.CTypedef = t.CUInt32T +u64: t.CTypedef = t.CUInt64T \ No newline at end of file diff --git a/Test/StringIterTest/temp/56cdd754a8a09347.pyi b/Test/StringIterTest/temp/56cdd754a8a09347.pyi deleted file mode 100644 index 007ccb8..0000000 --- a/Test/StringIterTest/temp/56cdd754a8a09347.pyi +++ /dev/null @@ -1,67 +0,0 @@ -""" -Auto-generated Python stub file from stdint.py -Module: stdint -""" - -import c - - -import t - -INT: t.CTypedef = t.CInt -INTPTR: t.CTypedef = t.CInt | t.CPtr -BOOL: t.CTypedef = t.CInt -UINT: t.CTypedef = t.CUnsignedInt -UINTPTR: t.CTypedef = UINT | t.CPtr -BYTE: t.CTypedef = t.CUnsignedChar -BYTEPTR: t.CTypedef = BYTE | t.CPtr -WORD: t.CTypedef = t.CUInt16T -DWORD: t.CTypedef = t.CUInt32T -QWORD: t.CTypedef = t.CUInt64T -TCHAR: t.CTypedef = t.CChar -CHARLIST: t.CTypedef = str | t.CPtr -VOID: t.CTypedef = t.CVoid -SHORT: t.CTypedef = t.CShort -SHORTPTR: t.CTypedef = t.CShort | t.CPtr -USHORT: t.CTypedef = t.CUnsignedShort -USHORTPTR: t.CTypedef = t.CUnsignedShort | t.CPtr -LONGLONG: t.CTypedef = t.CLong | t.CLong -ULONGLONG: t.CTypedef = t.CUnsignedLong | t.CLong -LONG: t.CTypedef = t.CLong -ULONG: t.CTypedef = t.CUnsignedLong -WCHAR: t.CTypedef = WORD -WCHARPTR: t.CTypedef = WORD | t.CPtr -CHARPTR: t.CTypedef = t.CChar | t.CPtr -FSIZE_t: t.CTypedef = DWORD -LBA_t: t.CTypedef = DWORD -UINTPTR: t.CTypedef = t.CUnsignedInt | t.CPtr -VOIDPTR: t.CTypedef = t.CVoid | t.CPtr -FLOAT: t.CTypedef = t.CFloat -DOUBLE: t.CTypedef = t.CDouble -FLOAT8: t.CTypedef = t.CFloat8T -FLOAT16: t.CTypedef = t.CFloat16T -FLOAT32: t.CTypedef = t.CFloat32T -FLOAT64: t.CTypedef = t.CFloat64T -FLOAT128: t.CTypedef = t.CFloat128T -INT8: t.CTypedef = t.CInt8T -INT16: t.CTypedef = t.CInt16T -INT32: t.CTypedef = t.CInt32T -INT64: t.CTypedef = t.CInt64T -UINT8: t.CTypedef = t.CUInt8T -UINT16: t.CTypedef = t.CUInt16T -UINT32: t.CTypedef = t.CUInt32T -UINT64: t.CTypedef = t.CUInt64T -INT8PTR: t.CTypedef = t.CInt8T | t.CPtr -INT16PTR: t.CTypedef = t.CInt16T | t.CPtr -INT32PTR: t.CTypedef = t.CInt32T | t.CPtr -INT64PTR: t.CTypedef = t.CInt64T | t.CPtr -UINT8PTR: t.CTypedef = t.CUInt8T | t.CPtr -UINT16PTR: t.CTypedef = t.CUInt16T | t.CPtr -UINT32PTR: t.CTypedef = t.CUInt32T | t.CPtr -UINT64PTR: t.CTypedef = t.CUInt64T | t.CPtr -CHAR8: t.CTypedef = t.CChar8T -CHAR16: t.CTypedef = t.CChar16T -CHAR32: t.CTypedef = t.CChar32T -CHAR8PTR: t.CTypedef = t.CChar8T | t.CPtr -CHAR16PTR: t.CTypedef = t.CChar16T | t.CPtr -CHAR32PTR: t.CTypedef = t.CChar32T | t.CPtr \ No newline at end of file diff --git a/Test/StringIterTest/temp/6aee24fdefa3cbc0.pyi b/Test/StringIterTest/temp/6aee24fdefa3cbc0.pyi deleted file mode 100644 index c17475f..0000000 --- a/Test/StringIterTest/temp/6aee24fdefa3cbc0.pyi +++ /dev/null @@ -1,44 +0,0 @@ -""" -Auto-generated Python stub file from string.py -Module: string -""" - - -from stdint import * -import t, c - -def strcpy(dest: str, src: str) -> str: pass - -def strncpy(dest: str, src: str, n: t.CSizeT) -> str: pass - -def strlen(src: str) -> t.CSizeT | t.CExport: pass - -def strcmp(str1: str, str2: str) -> t.CInt: pass - -def samestr(str1: str, str2: str) -> bool: pass - -def strncmp(str1: str, str2: str, n: t.CSizeT) -> t.CInt: pass - -def memcmp(ptr1: t.CVoid | t.CPtr, ptr2: t.CVoid | t.CPtr, n: t.CSizeT) -> t.CInt: pass - -def strchr(s: str, cr: t.CInt) -> str: pass - -def strrchr(s: str, cr: t.CInt) -> str: pass - -def strspn(s: str, skip: str) -> int: pass - -def memset(ptr: t.CVoid | t.CPtr, value: t.CInt, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass - -def memset32(ptr: t.CVoid | t.CPtr, value: t.CUInt32T, count: t.CSizeT) -> t.CVoid | t.CPtr: pass - -def memcpy(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass - -def memmove(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr: pass - -def atoi(src: str) -> t.CInt: pass - -def atoll(src: str) -> t.CInt64T: pass - -def atof(src: str) -> t.CDouble: pass - -def split(s: str, delim: str, result: list[str]) -> int: pass diff --git a/Test/StringIterTest/temp/2255fdda7aed5595.pyi b/Test/StringIterTest/temp/924ed8cd4ea5c4c2.pyi similarity index 97% rename from Test/StringIterTest/temp/2255fdda7aed5595.pyi rename to Test/StringIterTest/temp/924ed8cd4ea5c4c2.pyi index 0e8819e..16c5c7a 100644 --- a/Test/StringIterTest/temp/2255fdda7aed5595.pyi +++ b/Test/StringIterTest/temp/924ed8cd4ea5c4c2.pyi @@ -8,6 +8,7 @@ import t import stdio import string import c +import testcheck def test_string_ptr_iter() -> t.CInt: pass diff --git a/Test/StringIterTest/temp/9dbecd0942a39782.pyi b/Test/StringIterTest/temp/9dbecd0942a39782.pyi new file mode 100644 index 0000000..41648c1 --- /dev/null +++ b/Test/StringIterTest/temp/9dbecd0942a39782.pyi @@ -0,0 +1,25 @@ +""" +Auto-generated Python stub file from testcheck.py +Module: testcheck +""" + + +import t, c +import stdio + +_pass_count: t.CExtern | t.CInt +_fail_count: t.CExtern | t.CInt + +def begin(name: str) -> t.CInt: pass + +def section(name: str) -> t.CInt: pass + +def ok(msg: str) -> t.CInt: pass + +def fail(msg: str) -> t.CInt: pass + +def check(cond: t.CInt, ok_msg: str, fail_msg: str) -> t.CInt: pass + +def info(msg: str) -> t.CInt: pass + +def end() -> t.CInt: pass diff --git a/Test/StringIterTest/temp/_sha1_map.txt b/Test/StringIterTest/temp/_sha1_map.txt index c04ac36..dab296e 100644 --- a/Test/StringIterTest/temp/_sha1_map.txt +++ b/Test/StringIterTest/temp/_sha1_map.txt @@ -1,4 +1,5 @@ -2255fdda7aed5595:main.py -56cdd754a8a09347:includes/stdint.py -6aee24fdefa3cbc0:includes/string.py +49bd8cba55979f76:includes/stdint.py 73edbcf76e32d00b:includes/stdio.py +924ed8cd4ea5c4c2:main.py +9dbecd0942a39782:includes/testcheck.py +b5f1dc665c52a1bd:includes/string.py diff --git a/Test/StringIterTest/temp/b5f1dc665c52a1bd.pyi b/Test/StringIterTest/temp/b5f1dc665c52a1bd.pyi new file mode 100644 index 0000000..8b6959e --- /dev/null +++ b/Test/StringIterTest/temp/b5f1dc665c52a1bd.pyi @@ -0,0 +1,44 @@ +""" +Auto-generated Python stub file from string.py +Module: string +""" + + +from stdint import * +import t, c + +def strcpy(dest: str, src: str) -> str: pass + +def strncpy(dest: str, src: str, n: t.CSizeT) -> str: pass + +def strlen(src: str) -> t.CSizeT | t.CExport: pass + +def strcmp(str1: str, str2: str) -> t.CInt: pass + +def samestr(str1: str, str2: str) -> bool: pass + +def strncmp(str1: str, str2: str, n: t.CSizeT) -> t.CInt: pass + +def memcmp(ptr1: t.CVoid | t.CPtr, ptr2: t.CVoid | t.CPtr, n: t.CSizeT) -> t.CInt: pass + +def strchr(s: str, cr: t.CInt) -> str: pass + +def strrchr(s: str, cr: t.CInt) -> str: pass + +def strspn(s: str, skip: str) -> int: pass + +def memset(ptr: t.CVoid | t.CPtr, value: t.CInt, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass + +def memset32(ptr: t.CVoid | t.CPtr, value: t.CUInt32T, count: t.CSizeT) -> t.CVoid | t.CPtr: pass + +def memcpy(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass + +def memmove(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr: pass + +def atoi(src: str) -> t.CInt: pass + +def atoll(src: str) -> t.CInt64T: pass + +def atof(src: str) -> t.CDouble: pass + +def split(s: str, delim: str, result: t.CArray[str]) -> int: pass diff --git a/Test/StringTest/App/main.py b/Test/StringTest/App/main.py index 197c67c..daf1236 100644 --- a/Test/StringTest/App/main.py +++ b/Test/StringTest/App/main.py @@ -1,18 +1,16 @@ import t import stdio import string +import testcheck def test_strlen(): - stdio.printf("--- Test 1: strlen ---\n") + testcheck.section("Test 1: strlen") s: t.CChar | t.CPtr = "Hello, World!" length: t.CUInt64T = string.strlen(s) - if length == 13: - stdio.printf("PASS: strlen (len=%lu)\n", length) - else: - stdio.printf("FAIL: strlen (len=%lu, expect 13)\n", length) + testcheck.check(length == 13, "strlen (len=13)", "strlen (expect 13)") def test_strcpy(): - stdio.printf("--- Test 2: strcpy ---\n") + testcheck.section("Test 2: strcpy") buf: t.CChar | t.CPtr = w32.win32memory.VirtualAlloc(t.CVoid(0, t.CPtr), 64, 12288, 4) if t.CUInt64T(buf) == 0: stdio.printf("SKIP: VirtualAlloc returned NULL\n") @@ -20,13 +18,10 @@ def test_strcpy(): string.memset(buf, 0, 64) string.strcpy(buf, "test string") cmp_result: t.CInt = string.strcmp(buf, "test string") - if cmp_result == 0: - stdio.printf("PASS: strcpy (result=%s)\n", buf) - else: - stdio.printf("FAIL: strcpy (cmp=%d)\n", cmp_result) + testcheck.check(cmp_result == 0, "strcpy (result=test string)", "strcpy (cmp mismatch)") def test_strcat(): - stdio.printf("--- Test 3: strcat (via memcpy) ---\n") + testcheck.section("Test 3: strcat (via memcpy)") buf: t.CChar | t.CPtr = w32.win32memory.VirtualAlloc(t.CVoid(0, t.CPtr), 64, 12288, 4) if t.CUInt64T(buf) == 0: stdio.printf("SKIP: VirtualAlloc returned NULL\n") @@ -38,23 +33,17 @@ def test_strcat(): string.memcpy(buf, hello, 5) string.memcpy(t.CVoid(t.CUInt64T(buf) + 5, t.CPtr), world, 6) cmp_result: t.CInt = string.strcmp(buf, "Hello World") - if cmp_result == 0: - stdio.printf("PASS: strcat via memcpy\n") - else: - stdio.printf("FAIL: strcat via memcpy (cmp=%d)\n", cmp_result) + testcheck.check(cmp_result == 0, "strcat via memcpy", "strcat via memcpy (cmp mismatch)") def test_strcmp(): - stdio.printf("--- Test 4: strcmp ---\n") + testcheck.section("Test 4: strcmp") r1: t.CInt = string.strcmp("abc", "abc") r2: t.CInt = string.strcmp("abc", "abd") r3: t.CInt = string.strcmp("abd", "abc") - if r1 == 0 and r2 < 0 and r3 > 0: - stdio.printf("PASS: strcmp (eq=%d lt=%d gt=%d)\n", r1, r2, r3) - else: - stdio.printf("FAIL: strcmp (eq=%d lt=%d gt=%d)\n", r1, r2, r3) + testcheck.check(r1 == 0 and r2 < 0 and r3 > 0, "strcmp (eq=0 lt<0 gt>0)", "strcmp (expect eq=0 lt<0 gt>0)") def test_strncpy(): - stdio.printf("--- Test 5: strncpy ---\n") + testcheck.section("Test 5: strncpy") buf: t.CChar | t.CPtr = w32.win32memory.VirtualAlloc(t.CVoid(0, t.CPtr), 64, 12288, 4) if t.CUInt64T(buf) == 0: stdio.printf("SKIP: VirtualAlloc returned NULL\n") @@ -62,22 +51,16 @@ def test_strncpy(): string.memset(buf, 0, 64) string.strncpy(buf, "ABCDEFGHIJ", 5) cmp_result: t.CInt = string.strcmp(buf, "ABCDE") - if cmp_result == 0: - stdio.printf("PASS: strncpy (result=%s)\n", buf) - else: - stdio.printf("FAIL: strncpy (cmp=%d)\n", cmp_result) + testcheck.check(cmp_result == 0, "strncpy (result=ABCDE)", "strncpy (cmp mismatch)") def test_char_access(): - stdio.printf("--- Test 6: char access ---\n") + testcheck.section("Test 6: char access") s: t.CChar | t.CPtr = "ABCDE" val: t.CUInt8T = s[2] # 'C' = 67 - if val == 67: - stdio.printf("PASS: char access (s[2]=%d='C')\n", val) - else: - stdio.printf("FAIL: char access (s[2]=%d, expect 67)\n", val) + testcheck.check(val == 67, "char access (s[2]=67='C')", "char access (s[2] expect 67)") def test_snprintf(): - stdio.printf("--- Test 7: snprintf ---\n") + testcheck.section("Test 7: snprintf") buf: t.CChar | t.CPtr = w32.win32memory.VirtualAlloc(t.CVoid(0, t.CPtr), 128, 12288, 4) if t.CUInt64T(buf) == 0: stdio.printf("SKIP: VirtualAlloc returned NULL\n") @@ -85,15 +68,12 @@ def test_snprintf(): string.memset(buf, 0, 128) stdio.snprintf(buf, 128, "value=%d hex=0x%x str=%s", 42, 255, "test") cmp_result: t.CInt = string.strcmp(buf, "value=42 hex=0xff str=test") - if cmp_result == 0: - stdio.printf("PASS: snprintf (result=%s)\n", buf) - else: - stdio.printf("FAIL: snprintf (result='%s')\n", buf) + testcheck.check(cmp_result == 0, "snprintf (result=value=42 hex=0xff str=test)", "snprintf (result mismatch)") import w32.win32memory def main() -> t.CInt: - stdio.printf("=== StringTest: 字符串操作基准测试 ===\n\n") + testcheck.begin("StringTest: 字符串操作基准测试") test_strlen() test_strcpy() test_strcat() @@ -101,5 +81,4 @@ def main() -> t.CInt: test_strncpy() test_char_access() test_snprintf() - stdio.printf("\n=== StringTest Complete ===\n") - return 0 + return testcheck.end() diff --git a/Test/StringTest/output/067c78e9f121dce3.deps.json b/Test/StringTest/output/067c78e9f121dce3.deps.json index df05eb5..2718a7a 100644 --- a/Test/StringTest/output/067c78e9f121dce3.deps.json +++ b/Test/StringTest/output/067c78e9f121dce3.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "main": "7aa13c104a22528a", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3"} \ No newline at end of file +{"main": "39178dc5ba692b92", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3"} \ No newline at end of file diff --git a/Test/StringTest/output/29813d57621099a9.deps.json b/Test/StringTest/output/29813d57621099a9.deps.json index 8cd5685..978f9ee 100644 --- a/Test/StringTest/output/29813d57621099a9.deps.json +++ b/Test/StringTest/output/29813d57621099a9.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "main": "7aa13c104a22528a", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file +{"main": "39178dc5ba692b92", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file diff --git a/Test/StringTest/output/39178dc5ba692b92.deps.json b/Test/StringTest/output/39178dc5ba692b92.deps.json new file mode 100644 index 0000000..2033431 --- /dev/null +++ b/Test/StringTest/output/39178dc5ba692b92.deps.json @@ -0,0 +1 @@ +{"stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd"} \ No newline at end of file diff --git a/Test/StringTest/output/5a6a2137958c28c5.deps.json b/Test/StringTest/output/5a6a2137958c28c5.deps.json index f330458..d1a753b 100644 --- a/Test/StringTest/output/5a6a2137958c28c5.deps.json +++ b/Test/StringTest/output/5a6a2137958c28c5.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "main": "7aa13c104a22528a", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file +{"main": "39178dc5ba692b92", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd"} \ No newline at end of file diff --git a/Test/StringTest/output/6aee24fdefa3cbc0.deps.json b/Test/StringTest/output/6aee24fdefa3cbc0.deps.json deleted file mode 100644 index 3ad7aab..0000000 --- a/Test/StringTest/output/6aee24fdefa3cbc0.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "main": "7aa13c104a22528a"} \ No newline at end of file diff --git a/Test/StringTest/output/72e2d5ccb7cedcf1.deps.json b/Test/StringTest/output/72e2d5ccb7cedcf1.deps.json index 21877dd..29710d1 100644 --- a/Test/StringTest/output/72e2d5ccb7cedcf1.deps.json +++ b/Test/StringTest/output/72e2d5ccb7cedcf1.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "main": "7aa13c104a22528a", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e"} \ No newline at end of file +{"main": "39178dc5ba692b92", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file diff --git a/Test/StringTest/output/7aa13c104a22528a.deps.json b/Test/StringTest/output/7aa13c104a22528a.deps.json deleted file mode 100644 index 67944fb..0000000 --- a/Test/StringTest/output/7aa13c104a22528a.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b"} \ No newline at end of file diff --git a/Test/StringTest/output/9dbecd0942a39782.deps.json b/Test/StringTest/output/9dbecd0942a39782.deps.json new file mode 100644 index 0000000..d1a753b --- /dev/null +++ b/Test/StringTest/output/9dbecd0942a39782.deps.json @@ -0,0 +1 @@ +{"main": "39178dc5ba692b92", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd"} \ No newline at end of file diff --git a/Test/StringTest/output/abf9ce3160c9279e.deps.json b/Test/StringTest/output/abf9ce3160c9279e.deps.json index 21877dd..5edb543 100644 --- a/Test/StringTest/output/abf9ce3160c9279e.deps.json +++ b/Test/StringTest/output/abf9ce3160c9279e.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "main": "7aa13c104a22528a", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e"} \ No newline at end of file +{"main": "39178dc5ba692b92", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e"} \ No newline at end of file diff --git a/Test/StringTest/output/b5f1dc665c52a1bd.deps.json b/Test/StringTest/output/b5f1dc665c52a1bd.deps.json new file mode 100644 index 0000000..d1a753b --- /dev/null +++ b/Test/StringTest/output/b5f1dc665c52a1bd.deps.json @@ -0,0 +1 @@ +{"main": "39178dc5ba692b92", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd"} \ No newline at end of file diff --git a/Test/StringTest/output/bbdf3bbd4c3bc28c.deps.json b/Test/StringTest/output/bbdf3bbd4c3bc28c.deps.json index 3b37a69..2404d88 100644 --- a/Test/StringTest/output/bbdf3bbd4c3bc28c.deps.json +++ b/Test/StringTest/output/bbdf3bbd4c3bc28c.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "main": "7aa13c104a22528a", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c"} \ No newline at end of file +{"main": "39178dc5ba692b92", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c"} \ No newline at end of file diff --git a/Test/StringTest/output/fa3691e66b426950.deps.json b/Test/StringTest/output/fa3691e66b426950.deps.json index f330458..29710d1 100644 --- a/Test/StringTest/output/fa3691e66b426950.deps.json +++ b/Test/StringTest/output/fa3691e66b426950.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "main": "7aa13c104a22528a", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file +{"main": "39178dc5ba692b92", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file diff --git a/Test/StringTest/temp/7aa13c104a22528a.pyi b/Test/StringTest/temp/39178dc5ba692b92.pyi similarity index 96% rename from Test/StringTest/temp/7aa13c104a22528a.pyi rename to Test/StringTest/temp/39178dc5ba692b92.pyi index ccbfa76..6b53248 100644 --- a/Test/StringTest/temp/7aa13c104a22528a.pyi +++ b/Test/StringTest/temp/39178dc5ba692b92.pyi @@ -9,6 +9,7 @@ import c import t import stdio import string +import testcheck def test_strlen() -> t.CInt: pass diff --git a/Test/StringTest/temp/49bd8cba55979f76.pyi b/Test/StringTest/temp/49bd8cba55979f76.pyi new file mode 100644 index 0000000..f1d844a --- /dev/null +++ b/Test/StringTest/temp/49bd8cba55979f76.pyi @@ -0,0 +1,75 @@ +""" +Auto-generated Python stub file from stdint.py +Module: stdint +""" + +import c + + +import t + +INT: t.CTypedef = t.CInt +INTPTR: t.CTypedef = t.CInt | t.CPtr +BOOL: t.CTypedef = t.CInt +UINT: t.CTypedef = t.CUnsignedInt +UINTPTR: t.CTypedef = UINT | t.CPtr +BYTE: t.CTypedef = t.CUnsignedChar +BYTEPTR: t.CTypedef = BYTE | t.CPtr +WORD: t.CTypedef = t.CUInt16T +DWORD: t.CTypedef = t.CUInt32T +QWORD: t.CTypedef = t.CUInt64T +TCHAR: t.CTypedef = t.CChar +CHARLIST: t.CTypedef = str | t.CPtr +VOID: t.CTypedef = t.CVoid +SHORT: t.CTypedef = t.CShort +SHORTPTR: t.CTypedef = t.CShort | t.CPtr +USHORT: t.CTypedef = t.CUnsignedShort +USHORTPTR: t.CTypedef = t.CUnsignedShort | t.CPtr +LONGLONG: t.CTypedef = t.CLong | t.CLong +ULONGLONG: t.CTypedef = t.CUnsignedLong | t.CLong +LONG: t.CTypedef = t.CLong +ULONG: t.CTypedef = t.CUnsignedLong +WCHAR: t.CTypedef = WORD +WCHARPTR: t.CTypedef = WORD | t.CPtr +CHARPTR: t.CTypedef = t.CChar | t.CPtr +FSIZE_t: t.CTypedef = DWORD +LBA_t: t.CTypedef = DWORD +UINTPTR: t.CTypedef = t.CUnsignedInt | t.CPtr +VOIDPTR: t.CTypedef = t.CVoid | t.CPtr +FLOAT: t.CTypedef = t.CFloat +DOUBLE: t.CTypedef = t.CDouble +FLOAT8: t.CTypedef = t.CFloat8T +FLOAT16: t.CTypedef = t.CFloat16T +FLOAT32: t.CTypedef = t.CFloat32T +FLOAT64: t.CTypedef = t.CFloat64T +FLOAT128: t.CTypedef = t.CFloat128T +INT8: t.CTypedef = t.CInt8T +INT16: t.CTypedef = t.CInt16T +INT32: t.CTypedef = t.CInt32T +INT64: t.CTypedef = t.CInt64T +UINT8: t.CTypedef = t.CUInt8T +UINT16: t.CTypedef = t.CUInt16T +UINT32: t.CTypedef = t.CUInt32T +UINT64: t.CTypedef = t.CUInt64T +INT8PTR: t.CTypedef = t.CInt8T | t.CPtr +INT16PTR: t.CTypedef = t.CInt16T | t.CPtr +INT32PTR: t.CTypedef = t.CInt32T | t.CPtr +INT64PTR: t.CTypedef = t.CInt64T | t.CPtr +UINT8PTR: t.CTypedef = t.CUInt8T | t.CPtr +UINT16PTR: t.CTypedef = t.CUInt16T | t.CPtr +UINT32PTR: t.CTypedef = t.CUInt32T | t.CPtr +UINT64PTR: t.CTypedef = t.CUInt64T | t.CPtr +CHAR8: t.CTypedef = t.CChar8T +CHAR16: t.CTypedef = t.CChar16T +CHAR32: t.CTypedef = t.CChar32T +CHAR8PTR: t.CTypedef = t.CChar8T | t.CPtr +CHAR16PTR: t.CTypedef = t.CChar16T | t.CPtr +CHAR32PTR: t.CTypedef = t.CChar32T | t.CPtr +i8: t.CTypedef = t.CInt8T +i16: t.CTypedef = t.CInt16T +i32: t.CTypedef = t.CInt32T +i64: t.CTypedef = t.CInt64T +u8: t.CTypedef = t.CUInt8T +u16: t.CTypedef = t.CUInt16T +u32: t.CTypedef = t.CUInt32T +u64: t.CTypedef = t.CUInt64T \ No newline at end of file diff --git a/Test/StringTest/temp/56cdd754a8a09347.pyi b/Test/StringTest/temp/56cdd754a8a09347.pyi deleted file mode 100644 index 007ccb8..0000000 --- a/Test/StringTest/temp/56cdd754a8a09347.pyi +++ /dev/null @@ -1,67 +0,0 @@ -""" -Auto-generated Python stub file from stdint.py -Module: stdint -""" - -import c - - -import t - -INT: t.CTypedef = t.CInt -INTPTR: t.CTypedef = t.CInt | t.CPtr -BOOL: t.CTypedef = t.CInt -UINT: t.CTypedef = t.CUnsignedInt -UINTPTR: t.CTypedef = UINT | t.CPtr -BYTE: t.CTypedef = t.CUnsignedChar -BYTEPTR: t.CTypedef = BYTE | t.CPtr -WORD: t.CTypedef = t.CUInt16T -DWORD: t.CTypedef = t.CUInt32T -QWORD: t.CTypedef = t.CUInt64T -TCHAR: t.CTypedef = t.CChar -CHARLIST: t.CTypedef = str | t.CPtr -VOID: t.CTypedef = t.CVoid -SHORT: t.CTypedef = t.CShort -SHORTPTR: t.CTypedef = t.CShort | t.CPtr -USHORT: t.CTypedef = t.CUnsignedShort -USHORTPTR: t.CTypedef = t.CUnsignedShort | t.CPtr -LONGLONG: t.CTypedef = t.CLong | t.CLong -ULONGLONG: t.CTypedef = t.CUnsignedLong | t.CLong -LONG: t.CTypedef = t.CLong -ULONG: t.CTypedef = t.CUnsignedLong -WCHAR: t.CTypedef = WORD -WCHARPTR: t.CTypedef = WORD | t.CPtr -CHARPTR: t.CTypedef = t.CChar | t.CPtr -FSIZE_t: t.CTypedef = DWORD -LBA_t: t.CTypedef = DWORD -UINTPTR: t.CTypedef = t.CUnsignedInt | t.CPtr -VOIDPTR: t.CTypedef = t.CVoid | t.CPtr -FLOAT: t.CTypedef = t.CFloat -DOUBLE: t.CTypedef = t.CDouble -FLOAT8: t.CTypedef = t.CFloat8T -FLOAT16: t.CTypedef = t.CFloat16T -FLOAT32: t.CTypedef = t.CFloat32T -FLOAT64: t.CTypedef = t.CFloat64T -FLOAT128: t.CTypedef = t.CFloat128T -INT8: t.CTypedef = t.CInt8T -INT16: t.CTypedef = t.CInt16T -INT32: t.CTypedef = t.CInt32T -INT64: t.CTypedef = t.CInt64T -UINT8: t.CTypedef = t.CUInt8T -UINT16: t.CTypedef = t.CUInt16T -UINT32: t.CTypedef = t.CUInt32T -UINT64: t.CTypedef = t.CUInt64T -INT8PTR: t.CTypedef = t.CInt8T | t.CPtr -INT16PTR: t.CTypedef = t.CInt16T | t.CPtr -INT32PTR: t.CTypedef = t.CInt32T | t.CPtr -INT64PTR: t.CTypedef = t.CInt64T | t.CPtr -UINT8PTR: t.CTypedef = t.CUInt8T | t.CPtr -UINT16PTR: t.CTypedef = t.CUInt16T | t.CPtr -UINT32PTR: t.CTypedef = t.CUInt32T | t.CPtr -UINT64PTR: t.CTypedef = t.CUInt64T | t.CPtr -CHAR8: t.CTypedef = t.CChar8T -CHAR16: t.CTypedef = t.CChar16T -CHAR32: t.CTypedef = t.CChar32T -CHAR8PTR: t.CTypedef = t.CChar8T | t.CPtr -CHAR16PTR: t.CTypedef = t.CChar16T | t.CPtr -CHAR32PTR: t.CTypedef = t.CChar32T | t.CPtr \ No newline at end of file diff --git a/Test/StringTest/temp/6aee24fdefa3cbc0.pyi b/Test/StringTest/temp/6aee24fdefa3cbc0.pyi deleted file mode 100644 index c17475f..0000000 --- a/Test/StringTest/temp/6aee24fdefa3cbc0.pyi +++ /dev/null @@ -1,44 +0,0 @@ -""" -Auto-generated Python stub file from string.py -Module: string -""" - - -from stdint import * -import t, c - -def strcpy(dest: str, src: str) -> str: pass - -def strncpy(dest: str, src: str, n: t.CSizeT) -> str: pass - -def strlen(src: str) -> t.CSizeT | t.CExport: pass - -def strcmp(str1: str, str2: str) -> t.CInt: pass - -def samestr(str1: str, str2: str) -> bool: pass - -def strncmp(str1: str, str2: str, n: t.CSizeT) -> t.CInt: pass - -def memcmp(ptr1: t.CVoid | t.CPtr, ptr2: t.CVoid | t.CPtr, n: t.CSizeT) -> t.CInt: pass - -def strchr(s: str, cr: t.CInt) -> str: pass - -def strrchr(s: str, cr: t.CInt) -> str: pass - -def strspn(s: str, skip: str) -> int: pass - -def memset(ptr: t.CVoid | t.CPtr, value: t.CInt, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass - -def memset32(ptr: t.CVoid | t.CPtr, value: t.CUInt32T, count: t.CSizeT) -> t.CVoid | t.CPtr: pass - -def memcpy(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass - -def memmove(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr: pass - -def atoi(src: str) -> t.CInt: pass - -def atoll(src: str) -> t.CInt64T: pass - -def atof(src: str) -> t.CDouble: pass - -def split(s: str, delim: str, result: list[str]) -> int: pass diff --git a/Test/StringTest/temp/9dbecd0942a39782.pyi b/Test/StringTest/temp/9dbecd0942a39782.pyi new file mode 100644 index 0000000..41648c1 --- /dev/null +++ b/Test/StringTest/temp/9dbecd0942a39782.pyi @@ -0,0 +1,25 @@ +""" +Auto-generated Python stub file from testcheck.py +Module: testcheck +""" + + +import t, c +import stdio + +_pass_count: t.CExtern | t.CInt +_fail_count: t.CExtern | t.CInt + +def begin(name: str) -> t.CInt: pass + +def section(name: str) -> t.CInt: pass + +def ok(msg: str) -> t.CInt: pass + +def fail(msg: str) -> t.CInt: pass + +def check(cond: t.CInt, ok_msg: str, fail_msg: str) -> t.CInt: pass + +def info(msg: str) -> t.CInt: pass + +def end() -> t.CInt: pass diff --git a/Test/StringTest/temp/_sha1_map.txt b/Test/StringTest/temp/_sha1_map.txt index c52b3e4..4b654f8 100644 --- a/Test/StringTest/temp/_sha1_map.txt +++ b/Test/StringTest/temp/_sha1_map.txt @@ -1,6 +1,7 @@ -56cdd754a8a09347:includes/stdint.py +39178dc5ba692b92:main.py +49bd8cba55979f76:includes/stdint.py 5a6a2137958c28c5:includes/w32\win32base.py -6aee24fdefa3cbc0:includes/string.py 72e2d5ccb7cedcf1:includes/w32\win32memory.py 73edbcf76e32d00b:includes/stdio.py -7aa13c104a22528a:main.py +9dbecd0942a39782:includes/testcheck.py +b5f1dc665c52a1bd:includes/string.py diff --git a/Test/StringTest/temp/b5f1dc665c52a1bd.pyi b/Test/StringTest/temp/b5f1dc665c52a1bd.pyi new file mode 100644 index 0000000..8b6959e --- /dev/null +++ b/Test/StringTest/temp/b5f1dc665c52a1bd.pyi @@ -0,0 +1,44 @@ +""" +Auto-generated Python stub file from string.py +Module: string +""" + + +from stdint import * +import t, c + +def strcpy(dest: str, src: str) -> str: pass + +def strncpy(dest: str, src: str, n: t.CSizeT) -> str: pass + +def strlen(src: str) -> t.CSizeT | t.CExport: pass + +def strcmp(str1: str, str2: str) -> t.CInt: pass + +def samestr(str1: str, str2: str) -> bool: pass + +def strncmp(str1: str, str2: str, n: t.CSizeT) -> t.CInt: pass + +def memcmp(ptr1: t.CVoid | t.CPtr, ptr2: t.CVoid | t.CPtr, n: t.CSizeT) -> t.CInt: pass + +def strchr(s: str, cr: t.CInt) -> str: pass + +def strrchr(s: str, cr: t.CInt) -> str: pass + +def strspn(s: str, skip: str) -> int: pass + +def memset(ptr: t.CVoid | t.CPtr, value: t.CInt, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass + +def memset32(ptr: t.CVoid | t.CPtr, value: t.CUInt32T, count: t.CSizeT) -> t.CVoid | t.CPtr: pass + +def memcpy(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass + +def memmove(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr: pass + +def atoi(src: str) -> t.CInt: pass + +def atoll(src: str) -> t.CInt64T: pass + +def atof(src: str) -> t.CDouble: pass + +def split(s: str, delim: str, result: t.CArray[str]) -> int: pass diff --git a/Test/StructTest/App/main.py b/Test/StructTest/App/main.py index affd9df..652810a 100644 --- a/Test/StructTest/App/main.py +++ b/Test/StructTest/App/main.py @@ -1,6 +1,7 @@ import t import stdio import string +import testcheck # 定义结构体 class Point(t.Struct): @@ -16,29 +17,23 @@ class Node(t.Struct): next: t.CPtr | t.CVoid # Node* 类型 def test_struct_basic(): - stdio.printf("--- Test 1: struct basic ---\n") + testcheck.section("Test 1: struct basic") p: Point = Point() p.x = 10 p.y = 20 - if p.x == 10 and p.y == 20: - stdio.printf("PASS: struct basic (x=%d y=%d)\n", p.x, p.y) - else: - stdio.printf("FAIL: struct basic (x=%d y=%d, expect 10 20)\n", p.x, p.y) + testcheck.check(p.x == 10 and p.y == 20, "struct basic (x=10 y=20)", "struct basic (x y expect 10 20)") def test_struct_nested(): - stdio.printf("--- Test 2: struct nested ---\n") + testcheck.section("Test 2: struct nested") r: Rect = Rect() r.origin.x = 1 r.origin.y = 2 r.size.x = 100 r.size.y = 200 - if r.origin.x == 1 and r.origin.y == 2 and r.size.x == 100 and r.size.y == 200: - stdio.printf("PASS: struct nested (origin=%d,%d size=%d,%d)\n", r.origin.x, r.origin.y, r.size.x, r.size.y) - else: - stdio.printf("FAIL: struct nested\n") + testcheck.check(r.origin.x == 1 and r.origin.y == 2 and r.size.x == 100 and r.size.y == 200, "struct nested (origin=1,2 size=100,200)", "struct nested (mismatch)") def test_struct_pointer(): - stdio.printf("--- Test 3: struct pointer ---\n") + testcheck.section("Test 3: struct pointer") p: Point = Point() p.x = 42 p.y = 84 @@ -48,27 +43,21 @@ def test_struct_pointer(): pp.x = 100 pp.y = 200 # 检查原始结构体是否被修改 - if p.x == 100 and p.y == 200: - stdio.printf("PASS: struct pointer (x=%d y=%d)\n", p.x, p.y) - else: - stdio.printf("FAIL: struct pointer (x=%d y=%d, expect 100 200)\n", p.x, p.y) + testcheck.check(p.x == 100 and p.y == 200, "struct pointer (x=100 y=200)", "struct pointer (x y expect 100 200)") def test_struct_param(): - stdio.printf("--- Test 4: struct as parameter ---\n") + testcheck.section("Test 4: struct as parameter") p: Point = Point() p.x = 5 p.y = 15 sum_val: t.CInt = point_sum(p) - if sum_val == 20: - stdio.printf("PASS: struct param (sum=%d)\n", sum_val) - else: - stdio.printf("FAIL: struct param (sum=%d, expect 20)\n", sum_val) + testcheck.check(sum_val == 20, "struct param (sum=20)", "struct param (sum expect 20)") def point_sum(p: Point) -> t.CInt: return p.x + p.y def test_struct_array(): - stdio.printf("--- Test 5: struct array ---\n") + testcheck.section("Test 5: struct array") # 分配结构体数组 buf: t.CUInt8T | t.CPtr = w32.win32memory.VirtualAlloc(t.CVoid(0, t.CPtr), 256, 12288, 4) if t.CUInt64T(buf) == 0: @@ -82,19 +71,15 @@ def test_struct_array(): pts[1].x = 3 pts[1].y = 4 total: t.CInt = pts[0].x + pts[0].y + pts[1].x + pts[1].y - if total == 10: - stdio.printf("PASS: struct array (total=%d)\n", total) - else: - stdio.printf("FAIL: struct array (total=%d, expect 10)\n", total) + testcheck.check(total == 10, "struct array (total=10)", "struct array (total expect 10)") import w32.win32memory def main() -> t.CInt: - stdio.printf("=== StructTest: 结构体操作基准测试 ===\n\n") + testcheck.begin("StructTest: 结构体操作基准测试") test_struct_basic() test_struct_nested() test_struct_pointer() test_struct_param() test_struct_array() - stdio.printf("\n=== StructTest Complete ===\n") - return 0 + return testcheck.end() diff --git a/Test/StructTest/output/067c78e9f121dce3.deps.json b/Test/StructTest/output/067c78e9f121dce3.deps.json index b1872c1..ce5ab1f 100644 --- a/Test/StructTest/output/067c78e9f121dce3.deps.json +++ b/Test/StructTest/output/067c78e9f121dce3.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "main": "6f6ee14c129ac228", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3"} \ No newline at end of file +{"main": "24e26a8de1173993", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3"} \ No newline at end of file diff --git a/Test/StructTest/output/24e26a8de1173993.deps.json b/Test/StructTest/output/24e26a8de1173993.deps.json new file mode 100644 index 0000000..2033431 --- /dev/null +++ b/Test/StructTest/output/24e26a8de1173993.deps.json @@ -0,0 +1 @@ +{"stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd"} \ No newline at end of file diff --git a/Test/StructTest/output/29813d57621099a9.deps.json b/Test/StructTest/output/29813d57621099a9.deps.json index 361ae76..ac0d5f3 100644 --- a/Test/StructTest/output/29813d57621099a9.deps.json +++ b/Test/StructTest/output/29813d57621099a9.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "main": "6f6ee14c129ac228", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file +{"main": "24e26a8de1173993", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file diff --git a/Test/StructTest/output/5a6a2137958c28c5.deps.json b/Test/StructTest/output/5a6a2137958c28c5.deps.json index 61bb2b5..caf2948 100644 --- a/Test/StructTest/output/5a6a2137958c28c5.deps.json +++ b/Test/StructTest/output/5a6a2137958c28c5.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "main": "6f6ee14c129ac228", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file +{"main": "24e26a8de1173993", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd"} \ No newline at end of file diff --git a/Test/StructTest/output/6aee24fdefa3cbc0.deps.json b/Test/StructTest/output/6aee24fdefa3cbc0.deps.json deleted file mode 100644 index ccd7f6c..0000000 --- a/Test/StructTest/output/6aee24fdefa3cbc0.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "main": "6f6ee14c129ac228", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b"} \ No newline at end of file diff --git a/Test/StructTest/output/6f6ee14c129ac228.deps.json b/Test/StructTest/output/6f6ee14c129ac228.deps.json deleted file mode 100644 index 67944fb..0000000 --- a/Test/StructTest/output/6f6ee14c129ac228.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b"} \ No newline at end of file diff --git a/Test/StructTest/output/72e2d5ccb7cedcf1.deps.json b/Test/StructTest/output/72e2d5ccb7cedcf1.deps.json index d136494..8a716e0 100644 --- a/Test/StructTest/output/72e2d5ccb7cedcf1.deps.json +++ b/Test/StructTest/output/72e2d5ccb7cedcf1.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "main": "6f6ee14c129ac228", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e"} \ No newline at end of file +{"main": "24e26a8de1173993", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file diff --git a/Test/StructTest/output/9dbecd0942a39782.deps.json b/Test/StructTest/output/9dbecd0942a39782.deps.json new file mode 100644 index 0000000..caf2948 --- /dev/null +++ b/Test/StructTest/output/9dbecd0942a39782.deps.json @@ -0,0 +1 @@ +{"main": "24e26a8de1173993", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd"} \ No newline at end of file diff --git a/Test/StructTest/output/abf9ce3160c9279e.deps.json b/Test/StructTest/output/abf9ce3160c9279e.deps.json index d136494..32cf337 100644 --- a/Test/StructTest/output/abf9ce3160c9279e.deps.json +++ b/Test/StructTest/output/abf9ce3160c9279e.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "main": "6f6ee14c129ac228", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e"} \ No newline at end of file +{"main": "24e26a8de1173993", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e"} \ No newline at end of file diff --git a/Test/StructTest/output/b5f1dc665c52a1bd.deps.json b/Test/StructTest/output/b5f1dc665c52a1bd.deps.json new file mode 100644 index 0000000..caf2948 --- /dev/null +++ b/Test/StructTest/output/b5f1dc665c52a1bd.deps.json @@ -0,0 +1 @@ +{"main": "24e26a8de1173993", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd"} \ No newline at end of file diff --git a/Test/StructTest/output/bbdf3bbd4c3bc28c.deps.json b/Test/StructTest/output/bbdf3bbd4c3bc28c.deps.json index cbfaa63..e9f6a57 100644 --- a/Test/StructTest/output/bbdf3bbd4c3bc28c.deps.json +++ b/Test/StructTest/output/bbdf3bbd4c3bc28c.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "main": "6f6ee14c129ac228", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c"} \ No newline at end of file +{"main": "24e26a8de1173993", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c"} \ No newline at end of file diff --git a/Test/StructTest/output/fa3691e66b426950.deps.json b/Test/StructTest/output/fa3691e66b426950.deps.json index 61bb2b5..8a716e0 100644 --- a/Test/StructTest/output/fa3691e66b426950.deps.json +++ b/Test/StructTest/output/fa3691e66b426950.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "main": "6f6ee14c129ac228", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file +{"main": "24e26a8de1173993", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file diff --git a/Test/StructTest/temp/6f6ee14c129ac228.pyi b/Test/StructTest/temp/24e26a8de1173993.pyi similarity index 97% rename from Test/StructTest/temp/6f6ee14c129ac228.pyi rename to Test/StructTest/temp/24e26a8de1173993.pyi index fb46b92..0053550 100644 --- a/Test/StructTest/temp/6f6ee14c129ac228.pyi +++ b/Test/StructTest/temp/24e26a8de1173993.pyi @@ -9,6 +9,7 @@ import c import t import stdio import string +import testcheck class Point(t.Struct): x: t.CInt diff --git a/Test/StructTest/temp/49bd8cba55979f76.pyi b/Test/StructTest/temp/49bd8cba55979f76.pyi new file mode 100644 index 0000000..f1d844a --- /dev/null +++ b/Test/StructTest/temp/49bd8cba55979f76.pyi @@ -0,0 +1,75 @@ +""" +Auto-generated Python stub file from stdint.py +Module: stdint +""" + +import c + + +import t + +INT: t.CTypedef = t.CInt +INTPTR: t.CTypedef = t.CInt | t.CPtr +BOOL: t.CTypedef = t.CInt +UINT: t.CTypedef = t.CUnsignedInt +UINTPTR: t.CTypedef = UINT | t.CPtr +BYTE: t.CTypedef = t.CUnsignedChar +BYTEPTR: t.CTypedef = BYTE | t.CPtr +WORD: t.CTypedef = t.CUInt16T +DWORD: t.CTypedef = t.CUInt32T +QWORD: t.CTypedef = t.CUInt64T +TCHAR: t.CTypedef = t.CChar +CHARLIST: t.CTypedef = str | t.CPtr +VOID: t.CTypedef = t.CVoid +SHORT: t.CTypedef = t.CShort +SHORTPTR: t.CTypedef = t.CShort | t.CPtr +USHORT: t.CTypedef = t.CUnsignedShort +USHORTPTR: t.CTypedef = t.CUnsignedShort | t.CPtr +LONGLONG: t.CTypedef = t.CLong | t.CLong +ULONGLONG: t.CTypedef = t.CUnsignedLong | t.CLong +LONG: t.CTypedef = t.CLong +ULONG: t.CTypedef = t.CUnsignedLong +WCHAR: t.CTypedef = WORD +WCHARPTR: t.CTypedef = WORD | t.CPtr +CHARPTR: t.CTypedef = t.CChar | t.CPtr +FSIZE_t: t.CTypedef = DWORD +LBA_t: t.CTypedef = DWORD +UINTPTR: t.CTypedef = t.CUnsignedInt | t.CPtr +VOIDPTR: t.CTypedef = t.CVoid | t.CPtr +FLOAT: t.CTypedef = t.CFloat +DOUBLE: t.CTypedef = t.CDouble +FLOAT8: t.CTypedef = t.CFloat8T +FLOAT16: t.CTypedef = t.CFloat16T +FLOAT32: t.CTypedef = t.CFloat32T +FLOAT64: t.CTypedef = t.CFloat64T +FLOAT128: t.CTypedef = t.CFloat128T +INT8: t.CTypedef = t.CInt8T +INT16: t.CTypedef = t.CInt16T +INT32: t.CTypedef = t.CInt32T +INT64: t.CTypedef = t.CInt64T +UINT8: t.CTypedef = t.CUInt8T +UINT16: t.CTypedef = t.CUInt16T +UINT32: t.CTypedef = t.CUInt32T +UINT64: t.CTypedef = t.CUInt64T +INT8PTR: t.CTypedef = t.CInt8T | t.CPtr +INT16PTR: t.CTypedef = t.CInt16T | t.CPtr +INT32PTR: t.CTypedef = t.CInt32T | t.CPtr +INT64PTR: t.CTypedef = t.CInt64T | t.CPtr +UINT8PTR: t.CTypedef = t.CUInt8T | t.CPtr +UINT16PTR: t.CTypedef = t.CUInt16T | t.CPtr +UINT32PTR: t.CTypedef = t.CUInt32T | t.CPtr +UINT64PTR: t.CTypedef = t.CUInt64T | t.CPtr +CHAR8: t.CTypedef = t.CChar8T +CHAR16: t.CTypedef = t.CChar16T +CHAR32: t.CTypedef = t.CChar32T +CHAR8PTR: t.CTypedef = t.CChar8T | t.CPtr +CHAR16PTR: t.CTypedef = t.CChar16T | t.CPtr +CHAR32PTR: t.CTypedef = t.CChar32T | t.CPtr +i8: t.CTypedef = t.CInt8T +i16: t.CTypedef = t.CInt16T +i32: t.CTypedef = t.CInt32T +i64: t.CTypedef = t.CInt64T +u8: t.CTypedef = t.CUInt8T +u16: t.CTypedef = t.CUInt16T +u32: t.CTypedef = t.CUInt32T +u64: t.CTypedef = t.CUInt64T \ No newline at end of file diff --git a/Test/StructTest/temp/56cdd754a8a09347.pyi b/Test/StructTest/temp/56cdd754a8a09347.pyi deleted file mode 100644 index 007ccb8..0000000 --- a/Test/StructTest/temp/56cdd754a8a09347.pyi +++ /dev/null @@ -1,67 +0,0 @@ -""" -Auto-generated Python stub file from stdint.py -Module: stdint -""" - -import c - - -import t - -INT: t.CTypedef = t.CInt -INTPTR: t.CTypedef = t.CInt | t.CPtr -BOOL: t.CTypedef = t.CInt -UINT: t.CTypedef = t.CUnsignedInt -UINTPTR: t.CTypedef = UINT | t.CPtr -BYTE: t.CTypedef = t.CUnsignedChar -BYTEPTR: t.CTypedef = BYTE | t.CPtr -WORD: t.CTypedef = t.CUInt16T -DWORD: t.CTypedef = t.CUInt32T -QWORD: t.CTypedef = t.CUInt64T -TCHAR: t.CTypedef = t.CChar -CHARLIST: t.CTypedef = str | t.CPtr -VOID: t.CTypedef = t.CVoid -SHORT: t.CTypedef = t.CShort -SHORTPTR: t.CTypedef = t.CShort | t.CPtr -USHORT: t.CTypedef = t.CUnsignedShort -USHORTPTR: t.CTypedef = t.CUnsignedShort | t.CPtr -LONGLONG: t.CTypedef = t.CLong | t.CLong -ULONGLONG: t.CTypedef = t.CUnsignedLong | t.CLong -LONG: t.CTypedef = t.CLong -ULONG: t.CTypedef = t.CUnsignedLong -WCHAR: t.CTypedef = WORD -WCHARPTR: t.CTypedef = WORD | t.CPtr -CHARPTR: t.CTypedef = t.CChar | t.CPtr -FSIZE_t: t.CTypedef = DWORD -LBA_t: t.CTypedef = DWORD -UINTPTR: t.CTypedef = t.CUnsignedInt | t.CPtr -VOIDPTR: t.CTypedef = t.CVoid | t.CPtr -FLOAT: t.CTypedef = t.CFloat -DOUBLE: t.CTypedef = t.CDouble -FLOAT8: t.CTypedef = t.CFloat8T -FLOAT16: t.CTypedef = t.CFloat16T -FLOAT32: t.CTypedef = t.CFloat32T -FLOAT64: t.CTypedef = t.CFloat64T -FLOAT128: t.CTypedef = t.CFloat128T -INT8: t.CTypedef = t.CInt8T -INT16: t.CTypedef = t.CInt16T -INT32: t.CTypedef = t.CInt32T -INT64: t.CTypedef = t.CInt64T -UINT8: t.CTypedef = t.CUInt8T -UINT16: t.CTypedef = t.CUInt16T -UINT32: t.CTypedef = t.CUInt32T -UINT64: t.CTypedef = t.CUInt64T -INT8PTR: t.CTypedef = t.CInt8T | t.CPtr -INT16PTR: t.CTypedef = t.CInt16T | t.CPtr -INT32PTR: t.CTypedef = t.CInt32T | t.CPtr -INT64PTR: t.CTypedef = t.CInt64T | t.CPtr -UINT8PTR: t.CTypedef = t.CUInt8T | t.CPtr -UINT16PTR: t.CTypedef = t.CUInt16T | t.CPtr -UINT32PTR: t.CTypedef = t.CUInt32T | t.CPtr -UINT64PTR: t.CTypedef = t.CUInt64T | t.CPtr -CHAR8: t.CTypedef = t.CChar8T -CHAR16: t.CTypedef = t.CChar16T -CHAR32: t.CTypedef = t.CChar32T -CHAR8PTR: t.CTypedef = t.CChar8T | t.CPtr -CHAR16PTR: t.CTypedef = t.CChar16T | t.CPtr -CHAR32PTR: t.CTypedef = t.CChar32T | t.CPtr \ No newline at end of file diff --git a/Test/StructTest/temp/6aee24fdefa3cbc0.pyi b/Test/StructTest/temp/6aee24fdefa3cbc0.pyi deleted file mode 100644 index c17475f..0000000 --- a/Test/StructTest/temp/6aee24fdefa3cbc0.pyi +++ /dev/null @@ -1,44 +0,0 @@ -""" -Auto-generated Python stub file from string.py -Module: string -""" - - -from stdint import * -import t, c - -def strcpy(dest: str, src: str) -> str: pass - -def strncpy(dest: str, src: str, n: t.CSizeT) -> str: pass - -def strlen(src: str) -> t.CSizeT | t.CExport: pass - -def strcmp(str1: str, str2: str) -> t.CInt: pass - -def samestr(str1: str, str2: str) -> bool: pass - -def strncmp(str1: str, str2: str, n: t.CSizeT) -> t.CInt: pass - -def memcmp(ptr1: t.CVoid | t.CPtr, ptr2: t.CVoid | t.CPtr, n: t.CSizeT) -> t.CInt: pass - -def strchr(s: str, cr: t.CInt) -> str: pass - -def strrchr(s: str, cr: t.CInt) -> str: pass - -def strspn(s: str, skip: str) -> int: pass - -def memset(ptr: t.CVoid | t.CPtr, value: t.CInt, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass - -def memset32(ptr: t.CVoid | t.CPtr, value: t.CUInt32T, count: t.CSizeT) -> t.CVoid | t.CPtr: pass - -def memcpy(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass - -def memmove(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr: pass - -def atoi(src: str) -> t.CInt: pass - -def atoll(src: str) -> t.CInt64T: pass - -def atof(src: str) -> t.CDouble: pass - -def split(s: str, delim: str, result: list[str]) -> int: pass diff --git a/Test/StructTest/temp/9dbecd0942a39782.pyi b/Test/StructTest/temp/9dbecd0942a39782.pyi new file mode 100644 index 0000000..41648c1 --- /dev/null +++ b/Test/StructTest/temp/9dbecd0942a39782.pyi @@ -0,0 +1,25 @@ +""" +Auto-generated Python stub file from testcheck.py +Module: testcheck +""" + + +import t, c +import stdio + +_pass_count: t.CExtern | t.CInt +_fail_count: t.CExtern | t.CInt + +def begin(name: str) -> t.CInt: pass + +def section(name: str) -> t.CInt: pass + +def ok(msg: str) -> t.CInt: pass + +def fail(msg: str) -> t.CInt: pass + +def check(cond: t.CInt, ok_msg: str, fail_msg: str) -> t.CInt: pass + +def info(msg: str) -> t.CInt: pass + +def end() -> t.CInt: pass diff --git a/Test/StructTest/temp/_sha1_map.txt b/Test/StructTest/temp/_sha1_map.txt index af6559c..e77a9a8 100644 --- a/Test/StructTest/temp/_sha1_map.txt +++ b/Test/StructTest/temp/_sha1_map.txt @@ -1,6 +1,7 @@ -56cdd754a8a09347:includes/stdint.py +24e26a8de1173993:main.py +49bd8cba55979f76:includes/stdint.py 5a6a2137958c28c5:includes/w32\win32base.py -6aee24fdefa3cbc0:includes/string.py -6f6ee14c129ac228:main.py 72e2d5ccb7cedcf1:includes/w32\win32memory.py 73edbcf76e32d00b:includes/stdio.py +9dbecd0942a39782:includes/testcheck.py +b5f1dc665c52a1bd:includes/string.py diff --git a/Test/StructTest/temp/b5f1dc665c52a1bd.pyi b/Test/StructTest/temp/b5f1dc665c52a1bd.pyi new file mode 100644 index 0000000..8b6959e --- /dev/null +++ b/Test/StructTest/temp/b5f1dc665c52a1bd.pyi @@ -0,0 +1,44 @@ +""" +Auto-generated Python stub file from string.py +Module: string +""" + + +from stdint import * +import t, c + +def strcpy(dest: str, src: str) -> str: pass + +def strncpy(dest: str, src: str, n: t.CSizeT) -> str: pass + +def strlen(src: str) -> t.CSizeT | t.CExport: pass + +def strcmp(str1: str, str2: str) -> t.CInt: pass + +def samestr(str1: str, str2: str) -> bool: pass + +def strncmp(str1: str, str2: str, n: t.CSizeT) -> t.CInt: pass + +def memcmp(ptr1: t.CVoid | t.CPtr, ptr2: t.CVoid | t.CPtr, n: t.CSizeT) -> t.CInt: pass + +def strchr(s: str, cr: t.CInt) -> str: pass + +def strrchr(s: str, cr: t.CInt) -> str: pass + +def strspn(s: str, skip: str) -> int: pass + +def memset(ptr: t.CVoid | t.CPtr, value: t.CInt, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass + +def memset32(ptr: t.CVoid | t.CPtr, value: t.CUInt32T, count: t.CSizeT) -> t.CVoid | t.CPtr: pass + +def memcpy(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass + +def memmove(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr: pass + +def atoi(src: str) -> t.CInt: pass + +def atoll(src: str) -> t.CInt64T: pass + +def atof(src: str) -> t.CDouble: pass + +def split(s: str, delim: str, result: t.CArray[str]) -> int: pass diff --git a/Test/TestFBProject/App/main.py b/Test/TestFBProject/App/main.py index e98256a..e107a17 100644 --- a/Test/TestFBProject/App/main.py +++ b/Test/TestFBProject/App/main.py @@ -1,6 +1,7 @@ from stdint import * import w32.win32console import t, c +import testcheck def add_inline(a: t.CInt, b: t.CInt) -> t.CDefine: @@ -37,122 +38,122 @@ def main() -> t.CInt | t.CExport: w32.win32console.SetConsoleCP(65001) w32.win32console.SetConsoleOutputCP(65001) - print("=== Test 1: Raise and catch exact custom exception ===") + testcheck.begin("TestFBProject: 异常处理与LLVMIR测试") + + testcheck.section("Test 1: Raise and catch exact custom exception") try: raise DiskError("disk error") except DiskError as e: - print("PASS 1: caught DiskError:", e) + print("caught DiskError:", e) + testcheck.ok("Test 1: caught DiskError") except: - print("FAIL 1: caught by generic except") - print("") + testcheck.fail("Test 1: caught by generic except") - print("=== Test 2: Catch parent catches child ===") + testcheck.section("Test 2: Catch parent catches child") try: raise_disk() except AppError as e: - print("PASS 2: caught AppError (child DiskError):", e) + print("caught AppError (child DiskError):", e) + testcheck.ok("Test 2: caught AppError (child DiskError)") except: - print("FAIL 2: caught by generic except") - print("") + testcheck.fail("Test 2: caught by generic except") - print("=== Test 3: Catch parent catches nested child ===") + testcheck.section("Test 3: Catch parent catches nested child") try: raise_timeout() except AppError as e: - print("PASS 3: caught AppError (grandchild TimeoutError):", e) + print("caught AppError (grandchild TimeoutError):", e) + testcheck.ok("Test 3: caught AppError (grandchild TimeoutError)") except: - print("FAIL 3: caught by generic except") - print("") + testcheck.fail("Test 3: caught by generic except") - print("=== Test 4: Catch mid-level parent ===") + testcheck.section("Test 4: Catch mid-level parent") try: raise_timeout() except NetworkError as e: - print("PASS 4: caught NetworkError (child TimeoutError):", e) + print("caught NetworkError (child TimeoutError):", e) + testcheck.ok("Test 4: caught NetworkError (child TimeoutError)") except: - print("FAIL 4: caught by generic except") - print("") + testcheck.fail("Test 4: caught by generic except") - print("=== Test 5: Exact catch before parent ===") + testcheck.section("Test 5: Exact catch before parent") try: raise_network() except NetworkError as e: - print("PASS 5: caught NetworkError:", e) + print("caught NetworkError:", e) + testcheck.ok("Test 5: caught NetworkError") except AppError as e: - print("FAIL 5: caught AppError (should be NetworkError first)") + testcheck.fail("Test 5: caught AppError (should be NetworkError first)") except: - print("FAIL 5: caught by generic except") - print("") + testcheck.fail("Test 5: caught by generic except") - print("=== Test 6: Parent catch when exact not present ===") + testcheck.section("Test 6: Parent catch when exact not present") try: raise_network() except DiskError as e: - print("FAIL 6: caught DiskError (wrong)") + testcheck.fail("Test 6: caught DiskError (wrong)") except AppError as e: - print("PASS 6: caught AppError (no NetworkError handler):", e) + print("caught AppError (no NetworkError handler):", e) + testcheck.ok("Test 6: caught AppError (no NetworkError handler)") except: - print("FAIL 6: caught by generic except") - print("") + testcheck.fail("Test 6: caught by generic except") - print("=== Test 7: Generic except fallback ===") + testcheck.section("Test 7: Generic except fallback") try: raise_disk() except RuntimeError as e: - print("FAIL 7: caught RuntimeError (wrong)") + testcheck.fail("Test 7: caught RuntimeError (wrong)") except: - print("PASS 7: caught by generic except") - print("") + testcheck.ok("Test 7: caught by generic except") - print("=== Test 8: Cross-function with inheritance ===") + testcheck.section("Test 8: Cross-function with inheritance") try: raise_timeout() except NetworkError as e: - print("PASS 8: caught NetworkError (cross-func TimeoutError):", e) + print("caught NetworkError (cross-func TimeoutError):", e) + testcheck.ok("Test 8: caught NetworkError (cross-func TimeoutError)") except: - print("FAIL 8: caught by generic except") - print("") + testcheck.fail("Test 8: caught by generic except") - print("=== Test 9: Built-in exception still works ===") + testcheck.section("Test 9: Built-in exception still works") try: raise ValueError("test") except ValueError as e: - print("PASS 9: caught ValueError:", e) + print("caught ValueError:", e) + testcheck.ok("Test 9: caught ValueError") except: - print("FAIL 9: caught by generic except") - print("") + testcheck.fail("Test 9: caught by generic except") - print("=== Test 10: Mixed built-in and custom ===") + testcheck.section("Test 10: Mixed built-in and custom") try: raise RuntimeError("test") except DiskError as e: - print("FAIL 10: caught DiskError (wrong)") + testcheck.fail("Test 10: caught DiskError (wrong)") except RuntimeError as e: - print("PASS 10: caught RuntimeError:", e) + print("caught RuntimeError:", e) + testcheck.ok("Test 10: caught RuntimeError") except: - print("FAIL 10: caught by generic except") - print("") + testcheck.fail("Test 10: caught by generic except") - print("=== All Custom Exception Tests Complete ===") - - print("") - print("=== Test LLVMIR: inline LLVM IR add ===") + testcheck.section("Test LLVMIR: inline LLVM IR add") x: t.CInt = 10 y: t.CInt = 20 r: t.CInt = c.LLVMIR(f"add i32 {c.LInp(x)}, {c.LInp(y)}", t.CInt) print("LLVMIR add result:", r) + testcheck.check(r == 30, "LLVMIR add (10+20=30)", "LLVMIR add result mismatch") - print("") - print("=== Test CDefine function macro ===") + testcheck.section("Test CDefine function macro") s: t.CInt = add_inline(3, 4) print("add_inline(3, 4) =", s) + testcheck.check(s == 7, "add_inline(3, 4) = 7", "add_inline result mismatch") m: t.CInt = mul_inline(5, 6) print("mul_inline(5, 6) =", m) + testcheck.check(m == 30, "mul_inline(5, 6) = 30", "mul_inline result mismatch") - print("") - print("=== Test LLVMIR with LOut ===") + testcheck.section("Test LLVMIR with LOut") out_val: t.CInt = 0 c.LLVMIR(f"{c.LOut(out_val)} = add i32 {c.LInp(x)}, {c.LInp(y)}", t.CInt) print("LLVMIR LOut result:", out_val) + testcheck.check(out_val == 30, "LLVMIR LOut (10+20=30)", "LLVMIR LOut result mismatch") - return 0 + return testcheck.end() diff --git a/Test/TestFBProject/output/067c78e9f121dce3.deps.json b/Test/TestFBProject/output/067c78e9f121dce3.deps.json index cadaa5e..2afde24 100644 --- a/Test/TestFBProject/output/067c78e9f121dce3.deps.json +++ b/Test/TestFBProject/output/067c78e9f121dce3.deps.json @@ -1 +1 @@ -{"main": "3727eb00d15bf59d", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3"} \ No newline at end of file +{"stdint": "49bd8cba55979f76", "main": "4fb8940ff5ab1022", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3"} \ No newline at end of file diff --git a/Test/TestFBProject/output/29813d57621099a9.deps.json b/Test/TestFBProject/output/29813d57621099a9.deps.json index ae95e99..7dadc4a 100644 --- a/Test/TestFBProject/output/29813d57621099a9.deps.json +++ b/Test/TestFBProject/output/29813d57621099a9.deps.json @@ -1 +1 @@ -{"main": "3727eb00d15bf59d", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file +{"stdint": "49bd8cba55979f76", "main": "4fb8940ff5ab1022", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file diff --git a/Test/TestFBProject/output/3727eb00d15bf59d.deps.json b/Test/TestFBProject/output/3727eb00d15bf59d.deps.json deleted file mode 100644 index 2a25cbb..0000000 --- a/Test/TestFBProject/output/3727eb00d15bf59d.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c"} \ No newline at end of file diff --git a/Test/TestFBProject/output/4fb8940ff5ab1022.deps.json b/Test/TestFBProject/output/4fb8940ff5ab1022.deps.json new file mode 100644 index 0000000..4656f78 --- /dev/null +++ b/Test/TestFBProject/output/4fb8940ff5ab1022.deps.json @@ -0,0 +1 @@ +{"stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c"} \ No newline at end of file diff --git a/Test/TestFBProject/output/5a6a2137958c28c5.deps.json b/Test/TestFBProject/output/5a6a2137958c28c5.deps.json index 97f881b..0d18bd7 100644 --- a/Test/TestFBProject/output/5a6a2137958c28c5.deps.json +++ b/Test/TestFBProject/output/5a6a2137958c28c5.deps.json @@ -1 +1 @@ -{"main": "3727eb00d15bf59d", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file +{"stdint": "49bd8cba55979f76", "main": "4fb8940ff5ab1022", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c"} \ No newline at end of file diff --git a/Test/TestFBProject/output/72e2d5ccb7cedcf1.deps.json b/Test/TestFBProject/output/72e2d5ccb7cedcf1.deps.json index 6b67440..7fbb377 100644 --- a/Test/TestFBProject/output/72e2d5ccb7cedcf1.deps.json +++ b/Test/TestFBProject/output/72e2d5ccb7cedcf1.deps.json @@ -1 +1 @@ -{"main": "3727eb00d15bf59d", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1"} \ No newline at end of file +{"stdint": "49bd8cba55979f76", "main": "4fb8940ff5ab1022", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1"} \ No newline at end of file diff --git a/Test/TestFBProject/output/9dbecd0942a39782.deps.json b/Test/TestFBProject/output/9dbecd0942a39782.deps.json new file mode 100644 index 0000000..0d18bd7 --- /dev/null +++ b/Test/TestFBProject/output/9dbecd0942a39782.deps.json @@ -0,0 +1 @@ +{"stdint": "49bd8cba55979f76", "main": "4fb8940ff5ab1022", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c"} \ No newline at end of file diff --git a/Test/TestFBProject/output/abf9ce3160c9279e.deps.json b/Test/TestFBProject/output/abf9ce3160c9279e.deps.json index fac05d5..0b50bae 100644 --- a/Test/TestFBProject/output/abf9ce3160c9279e.deps.json +++ b/Test/TestFBProject/output/abf9ce3160c9279e.deps.json @@ -1 +1 @@ -{"main": "3727eb00d15bf59d", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e"} \ No newline at end of file +{"stdint": "49bd8cba55979f76", "main": "4fb8940ff5ab1022", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e"} \ No newline at end of file diff --git a/Test/TestFBProject/output/bbdf3bbd4c3bc28c.deps.json b/Test/TestFBProject/output/bbdf3bbd4c3bc28c.deps.json index 97f881b..0d18bd7 100644 --- a/Test/TestFBProject/output/bbdf3bbd4c3bc28c.deps.json +++ b/Test/TestFBProject/output/bbdf3bbd4c3bc28c.deps.json @@ -1 +1 @@ -{"main": "3727eb00d15bf59d", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file +{"stdint": "49bd8cba55979f76", "main": "4fb8940ff5ab1022", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c"} \ No newline at end of file diff --git a/Test/TestFBProject/output/fa3691e66b426950.deps.json b/Test/TestFBProject/output/fa3691e66b426950.deps.json index 97f881b..5db2bd6 100644 --- a/Test/TestFBProject/output/fa3691e66b426950.deps.json +++ b/Test/TestFBProject/output/fa3691e66b426950.deps.json @@ -1 +1 @@ -{"main": "3727eb00d15bf59d", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file +{"stdint": "49bd8cba55979f76", "main": "4fb8940ff5ab1022", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file diff --git a/Test/TestFBProject/temp/49bd8cba55979f76.pyi b/Test/TestFBProject/temp/49bd8cba55979f76.pyi new file mode 100644 index 0000000..f1d844a --- /dev/null +++ b/Test/TestFBProject/temp/49bd8cba55979f76.pyi @@ -0,0 +1,75 @@ +""" +Auto-generated Python stub file from stdint.py +Module: stdint +""" + +import c + + +import t + +INT: t.CTypedef = t.CInt +INTPTR: t.CTypedef = t.CInt | t.CPtr +BOOL: t.CTypedef = t.CInt +UINT: t.CTypedef = t.CUnsignedInt +UINTPTR: t.CTypedef = UINT | t.CPtr +BYTE: t.CTypedef = t.CUnsignedChar +BYTEPTR: t.CTypedef = BYTE | t.CPtr +WORD: t.CTypedef = t.CUInt16T +DWORD: t.CTypedef = t.CUInt32T +QWORD: t.CTypedef = t.CUInt64T +TCHAR: t.CTypedef = t.CChar +CHARLIST: t.CTypedef = str | t.CPtr +VOID: t.CTypedef = t.CVoid +SHORT: t.CTypedef = t.CShort +SHORTPTR: t.CTypedef = t.CShort | t.CPtr +USHORT: t.CTypedef = t.CUnsignedShort +USHORTPTR: t.CTypedef = t.CUnsignedShort | t.CPtr +LONGLONG: t.CTypedef = t.CLong | t.CLong +ULONGLONG: t.CTypedef = t.CUnsignedLong | t.CLong +LONG: t.CTypedef = t.CLong +ULONG: t.CTypedef = t.CUnsignedLong +WCHAR: t.CTypedef = WORD +WCHARPTR: t.CTypedef = WORD | t.CPtr +CHARPTR: t.CTypedef = t.CChar | t.CPtr +FSIZE_t: t.CTypedef = DWORD +LBA_t: t.CTypedef = DWORD +UINTPTR: t.CTypedef = t.CUnsignedInt | t.CPtr +VOIDPTR: t.CTypedef = t.CVoid | t.CPtr +FLOAT: t.CTypedef = t.CFloat +DOUBLE: t.CTypedef = t.CDouble +FLOAT8: t.CTypedef = t.CFloat8T +FLOAT16: t.CTypedef = t.CFloat16T +FLOAT32: t.CTypedef = t.CFloat32T +FLOAT64: t.CTypedef = t.CFloat64T +FLOAT128: t.CTypedef = t.CFloat128T +INT8: t.CTypedef = t.CInt8T +INT16: t.CTypedef = t.CInt16T +INT32: t.CTypedef = t.CInt32T +INT64: t.CTypedef = t.CInt64T +UINT8: t.CTypedef = t.CUInt8T +UINT16: t.CTypedef = t.CUInt16T +UINT32: t.CTypedef = t.CUInt32T +UINT64: t.CTypedef = t.CUInt64T +INT8PTR: t.CTypedef = t.CInt8T | t.CPtr +INT16PTR: t.CTypedef = t.CInt16T | t.CPtr +INT32PTR: t.CTypedef = t.CInt32T | t.CPtr +INT64PTR: t.CTypedef = t.CInt64T | t.CPtr +UINT8PTR: t.CTypedef = t.CUInt8T | t.CPtr +UINT16PTR: t.CTypedef = t.CUInt16T | t.CPtr +UINT32PTR: t.CTypedef = t.CUInt32T | t.CPtr +UINT64PTR: t.CTypedef = t.CUInt64T | t.CPtr +CHAR8: t.CTypedef = t.CChar8T +CHAR16: t.CTypedef = t.CChar16T +CHAR32: t.CTypedef = t.CChar32T +CHAR8PTR: t.CTypedef = t.CChar8T | t.CPtr +CHAR16PTR: t.CTypedef = t.CChar16T | t.CPtr +CHAR32PTR: t.CTypedef = t.CChar32T | t.CPtr +i8: t.CTypedef = t.CInt8T +i16: t.CTypedef = t.CInt16T +i32: t.CTypedef = t.CInt32T +i64: t.CTypedef = t.CInt64T +u8: t.CTypedef = t.CUInt8T +u16: t.CTypedef = t.CUInt16T +u32: t.CTypedef = t.CUInt32T +u64: t.CTypedef = t.CUInt64T \ No newline at end of file diff --git a/Test/TestFBProject/temp/3727eb00d15bf59d.pyi b/Test/TestFBProject/temp/4fb8940ff5ab1022.pyi similarity index 91% rename from Test/TestFBProject/temp/3727eb00d15bf59d.pyi rename to Test/TestFBProject/temp/4fb8940ff5ab1022.pyi index e778d1b..1f24963 100644 --- a/Test/TestFBProject/temp/3727eb00d15bf59d.pyi +++ b/Test/TestFBProject/temp/4fb8940ff5ab1022.pyi @@ -7,12 +7,13 @@ Module: main from stdint import * import w32.win32console import t, c +import testcheck def add_inline(a: t.CInt, b: t.CInt) -> t.CDefine: - pass + return a + b def mul_inline(a: t.CInt, b: t.CInt) -> t.CDefine: - pass + return a * b class AppError(Exception): diff --git a/Test/TestFBProject/temp/56cdd754a8a09347.pyi b/Test/TestFBProject/temp/56cdd754a8a09347.pyi deleted file mode 100644 index 007ccb8..0000000 --- a/Test/TestFBProject/temp/56cdd754a8a09347.pyi +++ /dev/null @@ -1,67 +0,0 @@ -""" -Auto-generated Python stub file from stdint.py -Module: stdint -""" - -import c - - -import t - -INT: t.CTypedef = t.CInt -INTPTR: t.CTypedef = t.CInt | t.CPtr -BOOL: t.CTypedef = t.CInt -UINT: t.CTypedef = t.CUnsignedInt -UINTPTR: t.CTypedef = UINT | t.CPtr -BYTE: t.CTypedef = t.CUnsignedChar -BYTEPTR: t.CTypedef = BYTE | t.CPtr -WORD: t.CTypedef = t.CUInt16T -DWORD: t.CTypedef = t.CUInt32T -QWORD: t.CTypedef = t.CUInt64T -TCHAR: t.CTypedef = t.CChar -CHARLIST: t.CTypedef = str | t.CPtr -VOID: t.CTypedef = t.CVoid -SHORT: t.CTypedef = t.CShort -SHORTPTR: t.CTypedef = t.CShort | t.CPtr -USHORT: t.CTypedef = t.CUnsignedShort -USHORTPTR: t.CTypedef = t.CUnsignedShort | t.CPtr -LONGLONG: t.CTypedef = t.CLong | t.CLong -ULONGLONG: t.CTypedef = t.CUnsignedLong | t.CLong -LONG: t.CTypedef = t.CLong -ULONG: t.CTypedef = t.CUnsignedLong -WCHAR: t.CTypedef = WORD -WCHARPTR: t.CTypedef = WORD | t.CPtr -CHARPTR: t.CTypedef = t.CChar | t.CPtr -FSIZE_t: t.CTypedef = DWORD -LBA_t: t.CTypedef = DWORD -UINTPTR: t.CTypedef = t.CUnsignedInt | t.CPtr -VOIDPTR: t.CTypedef = t.CVoid | t.CPtr -FLOAT: t.CTypedef = t.CFloat -DOUBLE: t.CTypedef = t.CDouble -FLOAT8: t.CTypedef = t.CFloat8T -FLOAT16: t.CTypedef = t.CFloat16T -FLOAT32: t.CTypedef = t.CFloat32T -FLOAT64: t.CTypedef = t.CFloat64T -FLOAT128: t.CTypedef = t.CFloat128T -INT8: t.CTypedef = t.CInt8T -INT16: t.CTypedef = t.CInt16T -INT32: t.CTypedef = t.CInt32T -INT64: t.CTypedef = t.CInt64T -UINT8: t.CTypedef = t.CUInt8T -UINT16: t.CTypedef = t.CUInt16T -UINT32: t.CTypedef = t.CUInt32T -UINT64: t.CTypedef = t.CUInt64T -INT8PTR: t.CTypedef = t.CInt8T | t.CPtr -INT16PTR: t.CTypedef = t.CInt16T | t.CPtr -INT32PTR: t.CTypedef = t.CInt32T | t.CPtr -INT64PTR: t.CTypedef = t.CInt64T | t.CPtr -UINT8PTR: t.CTypedef = t.CUInt8T | t.CPtr -UINT16PTR: t.CTypedef = t.CUInt16T | t.CPtr -UINT32PTR: t.CTypedef = t.CUInt32T | t.CPtr -UINT64PTR: t.CTypedef = t.CUInt64T | t.CPtr -CHAR8: t.CTypedef = t.CChar8T -CHAR16: t.CTypedef = t.CChar16T -CHAR32: t.CTypedef = t.CChar32T -CHAR8PTR: t.CTypedef = t.CChar8T | t.CPtr -CHAR16PTR: t.CTypedef = t.CChar16T | t.CPtr -CHAR32PTR: t.CTypedef = t.CChar32T | t.CPtr \ No newline at end of file diff --git a/Test/TestFBProject/temp/73edbcf76e32d00b.pyi b/Test/TestFBProject/temp/73edbcf76e32d00b.pyi new file mode 100644 index 0000000..ef712e3 --- /dev/null +++ b/Test/TestFBProject/temp/73edbcf76e32d00b.pyi @@ -0,0 +1,28 @@ +""" +Auto-generated Python stub file from stdio.py +Module: stdio +""" + + +import t, c + +def printf(fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass + +def fprintf(stream: t.CVoid | t.CPtr, fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass + +def sprintf(buf: t.CChar | t.CPtr, fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass + +def snprintf(buf: t.CChar | t.CPtr, size: t.CSizeT, fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass + +def puts(s: t.CChar | t.CConst | t.CPtr) -> t.CInt | t.CExtern | t.CExport: pass + +def fputs(s: t.CChar | t.CConst | t.CPtr, stream: t.CVoid | t.CPtr) -> t.CInt | t.CExtern | t.CExport: pass + +def fgets(buf: t.CChar | t.CPtr, size: t.CInt, stream: t.CVoid | t.CPtr) -> t.CChar | t.CPtr | t.CExtern | t.CExport: pass + +def fflush(stream: t.CVoid | t.CPtr) -> t.CInt | t.CExtern | t.CExport: pass + + +stdin: t.CExtern | t.CVoid | t.CPtr +stdout: t.CExtern | t.CVoid | t.CPtr +stderr: t.CExtern | t.CVoid | t.CPtr \ No newline at end of file diff --git a/Test/TestFBProject/temp/9dbecd0942a39782.pyi b/Test/TestFBProject/temp/9dbecd0942a39782.pyi new file mode 100644 index 0000000..41648c1 --- /dev/null +++ b/Test/TestFBProject/temp/9dbecd0942a39782.pyi @@ -0,0 +1,25 @@ +""" +Auto-generated Python stub file from testcheck.py +Module: testcheck +""" + + +import t, c +import stdio + +_pass_count: t.CExtern | t.CInt +_fail_count: t.CExtern | t.CInt + +def begin(name: str) -> t.CInt: pass + +def section(name: str) -> t.CInt: pass + +def ok(msg: str) -> t.CInt: pass + +def fail(msg: str) -> t.CInt: pass + +def check(cond: t.CInt, ok_msg: str, fail_msg: str) -> t.CInt: pass + +def info(msg: str) -> t.CInt: pass + +def end() -> t.CInt: pass diff --git a/Test/TestFBProject/temp/_sha1_map.txt b/Test/TestFBProject/temp/_sha1_map.txt index d500891..1e4ef07 100644 --- a/Test/TestFBProject/temp/_sha1_map.txt +++ b/Test/TestFBProject/temp/_sha1_map.txt @@ -1,4 +1,6 @@ -3727eb00d15bf59d:main.py -56cdd754a8a09347:includes/stdint.py +49bd8cba55979f76:includes/stdint.py +4fb8940ff5ab1022:main.py 5a6a2137958c28c5:includes/w32\win32base.py +73edbcf76e32d00b:includes/stdio.py +9dbecd0942a39782:includes/testcheck.py bbdf3bbd4c3bc28c:includes/w32\win32console.py diff --git a/Test/TestProject/App/BINASCII.py b/Test/TestProject/App/BINASCII.py index b1cc457..f58b7c1 100644 --- a/Test/TestProject/App/BINASCII.py +++ b/Test/TestProject/App/BINASCII.py @@ -32,7 +32,7 @@ def main222(): stdio.printf("UU: %s\n", uu_out) free(uu_out) - hqx_in: list[t.CChar, 4] = ['A', 'B', 'C', '\0'] + hqx_in: t.CArray[t.CChar, 4] = ['A', 'B', 'C', '\0'] hqx_crc: t.CUnsignedShort = 0 hqx_out: str unhqx: str diff --git a/Test/TestProject/App/HASHLIB.py b/Test/TestProject/App/HASHLIB.py index 41c11ad..b84258c 100644 --- a/Test/TestProject/App/HASHLIB.py +++ b/Test/TestProject/App/HASHLIB.py @@ -35,8 +35,8 @@ def main1() -> t.CInt: print("原文", plain) # ---------- Base64 测试 ---------- - b64_out: list[t.CChar, 256] - b64_dec: list[t.CUInt8T, 256] + b64_out: t.CArray[t.CChar, 256] + b64_dec: t.CArray[t.CUInt8T, 256] base64.b64encode(plain, b64_out) print("Base64 编码:", b64_out) dlen: t.CSizeT = base64.b64decode(b64_out, b64_dec) @@ -44,7 +44,7 @@ def main1() -> t.CInt: print("Base64 解码:", b64_dec) # ---------- MD5 测试 ---------- - md5_buf: list[t.CUInt8T, hashlib.MD5_DIGEST_LEN] + md5_buf: t.CArray[t.CUInt8T, hashlib.MD5_DIGEST_LEN] mctx = hashlib.md5() mctx.update(plain) mctx.final(md5_buf) @@ -52,7 +52,7 @@ def main1() -> t.CInt: print_hex(md5_buf, hashlib.MD5_DIGEST_LEN) # ---------- SHA1 测试 ---------- - sha1_buf: list[t.CUInt8T, hashlib.SHA1_DIGEST_LEN] + sha1_buf: t.CArray[t.CUInt8T, hashlib.SHA1_DIGEST_LEN] s1ctx = hashlib.sha1() s1ctx.update(plain) s1ctx.final(sha1_buf) @@ -60,7 +60,7 @@ def main1() -> t.CInt: print_hex(sha1_buf, hashlib.SHA1_DIGEST_LEN) # ---------- SHA256 测试 ---------- - sha256_buf: list[t.CUInt8T, hashlib.SHA256_DIGEST_LEN] + sha256_buf: t.CArray[t.CUInt8T, hashlib.SHA256_DIGEST_LEN] s2ctx = hashlib.sha256() s2ctx.update(plain) s2ctx.final(sha256_buf) @@ -68,7 +68,7 @@ def main1() -> t.CInt: print_hex(sha256_buf, hashlib.SHA256_DIGEST_LEN) # ---------- SHA512 测试 ---------- - sha512_buf: list[t.CUInt8T, hashlib.SHA512_DIGEST_LEN] + sha512_buf: t.CArray[t.CUInt8T, hashlib.SHA512_DIGEST_LEN] s5ctx = hashlib.sha512() s5ctx.update(plain) s5ctx.final(sha512_buf) diff --git a/Test/TestProject/App/main.py b/Test/TestProject/App/main.py index 514fe71..6d65bcd 100644 --- a/Test/TestProject/App/main.py +++ b/Test/TestProject/App/main.py @@ -1,23 +1,216 @@ -from stdint import * -import w32.win32console -import config -import HASHLIB -import BINASCII -import zlib.pyzlib as zp -import test_zlib as tpz -import test_numpy as tn - -import t, c - - -def main() -> t.CInt | t.CExport: - w32.win32console.SetConsoleCP(65001) - w32.win32console.SetConsoleOutputCP(65001) - - print(zp.runtime_version()) - tpz.main123456() - - tn.test_numpy_main() - - print("END") - +import stdio +import stdint +import zc.config as config +import zc.test as test +import zc.logic_test as logic +import zc.class_test as class_test +import testcheck + + +def main() -> stdint.INT: + testcheck.begin("Hello World!") + 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)") + + testcheck.section("COMPLEX LOGIC TESTS") + + testcheck.section("For Range Basic Test (stop=5)") + logic.ForRangeBasicTest(5) + testcheck.ok("For Range Basic Test (5)") + + testcheck.section("For Range With Start Stop Step (start=1, stop=10, step=2)") + logic.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.NestedForRangeTest(2, 3) + testcheck.ok("Nested For Range Test (2, 3)") + + testcheck.section("For With If Break Test (size=8)") + logic.ForWithIfBreakTest(8) + testcheck.ok("For With If Break Test (8)") + + testcheck.section("For With If Continue Test (n=10)") + logic.ForWithIfContinueTest(10) + testcheck.ok("For With If Continue Test (10)") + + testcheck.section("For With Elif Branch Test (value=10)") + logic.ForWithElifBranchTest(10) + testcheck.ok("For With Elif Branch Test (10)") + + testcheck.section("While With If Elif Else Test (iterations=7)") + logic.WhileWithIfElifElseTest(7) + testcheck.ok("While With If Elif Else Test (7)") + + testcheck.section("While With Nested If Test (limit=4)") + logic.WhileWithNestedIfTest(4) + testcheck.ok("While With Nested If Test (4)") + + testcheck.section("While With Match Case Test (value=2)") + logic.WhileWithMatchCaseTest(2) + testcheck.ok("While With Match Case Test (2)") + + testcheck.section("While With Match Case Test (value=99)") + logic.WhileWithMatchCaseTest(99) + testcheck.ok("While With Match Case Test (99)") + + testcheck.section("While With Match Case NoBreak Test (value=3)") + logic.WhileWithMatchCaseNoBreakTest(3) + testcheck.ok("While With Match Case NoBreak Test (3)") + + testcheck.section("Complex For While Match Test (outer=3, inner=3)") + logic.ComplexForWhileMatchTest(3, 3) + testcheck.ok("Complex For While Match Test (3, 3)") + + testcheck.section("For With Case And NoBreak Test (n=5)") + logic.ForWithCaseAndNoBreakTest(5) + testcheck.ok("For With Case And NoBreak Test (5)") + + testcheck.section("While With Break Condition Test (limit=6)") + logic.WhileWithBreakConditionTest(6) + testcheck.ok("While With Break Condition Test (6)") + + testcheck.section("Nested While With Multiple BreakPoints (depth=3, width=4)") + logic.NestedWhileWithMultipleBreakPoints(3, 4) + testcheck.ok("Nested While With Multiple BreakPoints (3, 4)") + + testcheck.section("For With Match Case In Loop Test (iterations=9)") + logic.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.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.ForRangeWithStepAndCondition(12, 2) + testcheck.ok("For Range With Step And Condition (12, 2)") + + testcheck.section("Match Case With Guard Conditions (value=1)") + logic.MatchCaseWithGuardConditions(1) + testcheck.ok("Match Case With Guard Conditions (1)") + + testcheck.section("While With Multiple Match Cases (iterations=12)") + logic.WhileWithMultipleMatchCases(12) + testcheck.ok("While With Multiple Match Cases (12)") + + testcheck.section("For While Mix With Break And Continue (n=5)") + logic.ForWhileMixWithBreakAndContinue(5) + testcheck.ok("For While Mix With Break And Continue (5)") + + testcheck.section("Complex Case Matching With Ranges (start=0, end=35)") + logic.ComplexCaseMatchingWithRanges(0, 35) + testcheck.ok("Complex Case Matching With Ranges (0, 35)") + + testcheck.section("While With Elif In Elif Chain (limit=7)") + logic.WhileWithElifInElifChain(7) + testcheck.ok("While With Elif In Elif Chain (7)") + + testcheck.section("For With Case NoBreak Nested (inner_limit=4)") + logic.ForWithCaseNoBreakNested(4) + testcheck.ok("For With Case NoBreak Nested (4)") + + 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/TestProject/App/test_zlib.py b/Test/TestProject/App/test_zlib.py index 9441a04..8dac777 100644 --- a/Test/TestProject/App/test_zlib.py +++ b/Test/TestProject/App/test_zlib.py @@ -10,7 +10,7 @@ import string import mpool import t, c -pool: mpool.MPool | t.CPtr = None +pool: t.CPtr = None test_passed: t.CInt = 0 test_failed: t.CInt = 0 @@ -616,7 +616,7 @@ def test_huffman_tree(): printf(" All 32 distance codes: 5 bits each\n") printf("\n --- Dynamic Huffman tree from frequencies ---\n") - freqs: list[t.CInt, 256] + freqs: t.CArray[t.CInt, 257] memset(freqs, 0, freqs.__sizeof__()) freqs['A'] = 50 freqs['B'] = 25 @@ -646,8 +646,8 @@ def test_huffman_tree(): printf(" Active codes: %d, max code lengthgth: %d\n", total_codes, max_length_found) printf(" Code assignments:\n") - names: list[str, None] = ["A","B","C","D","E","F"] # 一个都是char* 的数组 - syms: list[t.CInt, None] = ['A','B','C','D','E','F'] + names: t.CArray[str, None] = ["A","B","C","D","E","F"] # 一个都是char* 的数组 + syms: t.CArray[t.CInt, None] = ['A','B','C','D','E','F'] for i in range(6): printf(" '%s' (freq=%3d): code=0x%04X, bits=%d\n", names[i], freqs[syms[i]], @@ -665,7 +665,7 @@ def test_huffman_tree(): a_bits, f_bits, "YES" if (a_bits <= f_bits) else "NO") printf("\n --- Huffman encode/decode roundtrip ---\n") - freqs: list[t.CInt, 288] + freqs: t.CArray[t.CInt, 288] memset(freqs, 0, freqs.__sizeof__()) freqs['H'] = 10 freqs['e'] = 8 @@ -686,7 +686,7 @@ def test_huffman_tree(): writer = zdef.zbit_writer() - symbols: list[t.CInt, 16] + symbols: t.CArray[t.CInt, 16] symbols[0] = 'H'; symbols[1] = 'e'; symbols[2] = 'l'; symbols[3] = 'l' symbols[4] = 'o'; symbols[5] = ' '; symbols[6] = 'W'; symbols[7] = 'o' symbols[8] = 'r'; symbols[9] = 'l'; symbols[10] = 'd'; symbols[11] = '!' @@ -716,7 +716,7 @@ def test_huffman_tree(): free(writer.buf) printf("\n --- Overflow handling (many symbols, limited max_bits) ---\n") - freqs: list[t.CInt, 256] + freqs: t.CArray[t.CInt, 257] for i in range(256): freqs[i] = 1 freqs[256] = 1 @@ -731,7 +731,7 @@ def test_huffman_tree(): break check("all code lengthgths <= 15 with 257 symbols", overflow_ok, "code lengthgth overflow") - bl_count: list[t.CInt, 16] = [0] + bl_count: t.CArray[t.CInt, 16] = [0] for i in range(257): if tree.codes[i].bits > 0: bl_count[tree.codes[i].bits] += 1 @@ -769,7 +769,7 @@ def test_huffman_tree(): printf("\n --- Kraft inequality check ---\n") - freqs: list[t.CInt, 256] + freqs: t.CArray[t.CInt, 257] memset(freqs, 0, freqs.__sizeof__()) freqs['X'] = 100 freqs['Y'] = 50 diff --git a/Test/TestProject/output/067c78e9f121dce3.deps.json b/Test/TestProject/output/067c78e9f121dce3.deps.json deleted file mode 100644 index 69cea7d..0000000 --- a/Test/TestProject/output/067c78e9f121dce3.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"test_zlib": "0c04ab530bb9cfa4", "hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "BINASCII": "8f88a3374d5335cc", "vipermath": "3f7c5e78d8652535", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "base64": "4bf3e0150b9e02e9", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "binascii": "8f88a3374d5335cc", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653", "zlib.__init__": "d63d2c2a2bd9bd2a", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3"} \ No newline at end of file diff --git a/Test/TestProject/output/0c04ab530bb9cfa4.deps.json b/Test/TestProject/output/0c04ab530bb9cfa4.deps.json deleted file mode 100644 index 33f0073..0000000 --- a/Test/TestProject/output/0c04ab530bb9cfa4.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "BINASCII": "3ee89b588a1da94f", "vipermath": "3f7c5e78d8652535", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "base64": "4bf3e0150b9e02e9", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "binascii": "8f88a3374d5335cc", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "c3eb91093118e1e1", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2"} \ No newline at end of file diff --git a/Test/TestProject/output/0d13cde396f4a15f.deps.json b/Test/TestProject/output/0d13cde396f4a15f.deps.json deleted file mode 100644 index 1343411..0000000 --- a/Test/TestProject/output/0d13cde396f4a15f.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"test_zlib": "0c04ab530bb9cfa4", "hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "BINASCII": "8f88a3374d5335cc", "vipermath": "3f7c5e78d8652535", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "base64": "4bf3e0150b9e02e9", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "binascii": "8f88a3374d5335cc", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f"} \ No newline at end of file diff --git a/Test/TestProject/output/0d4517fd5afeb330.deps.json b/Test/TestProject/output/0d4517fd5afeb330.deps.json deleted file mode 100644 index d8eb6a9..0000000 --- a/Test/TestProject/output/0d4517fd5afeb330.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"test_zlib": "0c04ab530bb9cfa4", "hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "BINASCII": "8f88a3374d5335cc", "vipermath": "3f7c5e78d8652535", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "base64": "4bf3e0150b9e02e9", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "binascii": "8f88a3374d5335cc", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330"} \ No newline at end of file diff --git a/Test/TestProject/output/29813d57621099a9.deps.json b/Test/TestProject/output/29813d57621099a9.deps.json deleted file mode 100644 index 87256a5..0000000 --- a/Test/TestProject/output/29813d57621099a9.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"test_zlib": "0c04ab530bb9cfa4", "hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "BINASCII": "8f88a3374d5335cc", "vipermath": "3f7c5e78d8652535", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "base64": "4bf3e0150b9e02e9", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "binascii": "8f88a3374d5335cc", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653", "zlib.__init__": "d63d2c2a2bd9bd2a", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file diff --git a/Test/TestProject/output/2d7f623c6e3004ce.deps.json b/Test/TestProject/output/2d7f623c6e3004ce.deps.json deleted file mode 100644 index 87256a5..0000000 --- a/Test/TestProject/output/2d7f623c6e3004ce.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"test_zlib": "0c04ab530bb9cfa4", "hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "BINASCII": "8f88a3374d5335cc", "vipermath": "3f7c5e78d8652535", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "base64": "4bf3e0150b9e02e9", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "binascii": "8f88a3374d5335cc", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653", "zlib.__init__": "d63d2c2a2bd9bd2a", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file diff --git a/Test/TestProject/output/2e756dd336749fc2.deps.json b/Test/TestProject/output/2e756dd336749fc2.deps.json deleted file mode 100644 index a9ee6fb..0000000 --- a/Test/TestProject/output/2e756dd336749fc2.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"test_zlib": "0c04ab530bb9cfa4", "hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "BINASCII": "3ee89b588a1da94f", "vipermath": "3f7c5e78d8652535", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "base64": "4bf3e0150b9e02e9", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "binascii": "8f88a3374d5335cc", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "c3eb91093118e1e1", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2"} \ No newline at end of file diff --git a/Test/TestProject/output/3ee89b588a1da94f.deps.json b/Test/TestProject/output/3ee89b588a1da94f.deps.json deleted file mode 100644 index 93da396..0000000 --- a/Test/TestProject/output/3ee89b588a1da94f.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"test_zlib": "0c04ab530bb9cfa4", "hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "vipermath": "3f7c5e78d8652535", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "base64": "4bf3e0150b9e02e9", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "binascii": "8f88a3374d5335cc", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "c3eb91093118e1e1", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2"} \ No newline at end of file diff --git a/Test/TestProject/output/3f7c5e78d8652535.deps.json b/Test/TestProject/output/3f7c5e78d8652535.deps.json deleted file mode 100644 index 83b79bc..0000000 --- a/Test/TestProject/output/3f7c5e78d8652535.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"test_zlib": "0c04ab530bb9cfa4", "hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "BINASCII": "8f88a3374d5335cc", "vipermath": "3f7c5e78d8652535", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "base64": "4bf3e0150b9e02e9", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "binascii": "8f88a3374d5335cc", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653"} \ No newline at end of file diff --git a/Test/TestProject/output/4638d411fd53fef0.deps.json b/Test/TestProject/output/4638d411fd53fef0.deps.json deleted file mode 100644 index 87256a5..0000000 --- a/Test/TestProject/output/4638d411fd53fef0.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"test_zlib": "0c04ab530bb9cfa4", "hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "BINASCII": "8f88a3374d5335cc", "vipermath": "3f7c5e78d8652535", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "base64": "4bf3e0150b9e02e9", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "binascii": "8f88a3374d5335cc", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653", "zlib.__init__": "d63d2c2a2bd9bd2a", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file diff --git a/Test/TestProject/output/4bf3e0150b9e02e9.deps.json b/Test/TestProject/output/4bf3e0150b9e02e9.deps.json deleted file mode 100644 index 83b79bc..0000000 --- a/Test/TestProject/output/4bf3e0150b9e02e9.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"test_zlib": "0c04ab530bb9cfa4", "hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "BINASCII": "8f88a3374d5335cc", "vipermath": "3f7c5e78d8652535", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "base64": "4bf3e0150b9e02e9", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "binascii": "8f88a3374d5335cc", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653"} \ No newline at end of file diff --git a/Test/TestProject/output/58121a0fb0ca7466.deps.json b/Test/TestProject/output/58121a0fb0ca7466.deps.json deleted file mode 100644 index a7b9b5c..0000000 --- a/Test/TestProject/output/58121a0fb0ca7466.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"test_zlib": "0c04ab530bb9cfa4", "hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "BINASCII": "3ee89b588a1da94f", "vipermath": "3f7c5e78d8652535", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "base64": "4bf3e0150b9e02e9", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "binascii": "8f88a3374d5335cc", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "c3eb91093118e1e1", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653"} \ No newline at end of file diff --git a/Test/TestProject/output/5a6a2137958c28c5.deps.json b/Test/TestProject/output/5a6a2137958c28c5.deps.json deleted file mode 100644 index 2f5df43..0000000 --- a/Test/TestProject/output/5a6a2137958c28c5.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"test_zlib": "0c04ab530bb9cfa4", "hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "BINASCII": "8f88a3374d5335cc", "vipermath": "3f7c5e78d8652535", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "base64": "4bf3e0150b9e02e9", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "binascii": "8f88a3374d5335cc", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653", "zlib.__init__": "d63d2c2a2bd9bd2a", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file diff --git a/Test/TestProject/output/68c4fe4b12c908e3.deps.json b/Test/TestProject/output/68c4fe4b12c908e3.deps.json deleted file mode 100644 index 87256a5..0000000 --- a/Test/TestProject/output/68c4fe4b12c908e3.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"test_zlib": "0c04ab530bb9cfa4", "hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "BINASCII": "8f88a3374d5335cc", "vipermath": "3f7c5e78d8652535", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "base64": "4bf3e0150b9e02e9", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "binascii": "8f88a3374d5335cc", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653", "zlib.__init__": "d63d2c2a2bd9bd2a", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file diff --git a/Test/TestProject/output/6aee24fdefa3cbc0.deps.json b/Test/TestProject/output/6aee24fdefa3cbc0.deps.json deleted file mode 100644 index 8a56fc5..0000000 --- a/Test/TestProject/output/6aee24fdefa3cbc0.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"test_zlib": "0c04ab530bb9cfa4", "hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "BINASCII": "8f88a3374d5335cc", "vipermath": "3f7c5e78d8652535", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "base64": "4bf3e0150b9e02e9", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "binascii": "8f88a3374d5335cc", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653", "zlib.__init__": "d63d2c2a2bd9bd2a"} \ No newline at end of file diff --git a/Test/TestProject/output/72e2d5ccb7cedcf1.deps.json b/Test/TestProject/output/72e2d5ccb7cedcf1.deps.json deleted file mode 100644 index c8b406c..0000000 --- a/Test/TestProject/output/72e2d5ccb7cedcf1.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"test_zlib": "0c04ab530bb9cfa4", "hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "BINASCII": "8f88a3374d5335cc", "vipermath": "3f7c5e78d8652535", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "base64": "4bf3e0150b9e02e9", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "binascii": "8f88a3374d5335cc", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653", "zlib.__init__": "d63d2c2a2bd9bd2a", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1"} \ No newline at end of file diff --git a/Test/TestProject/output/88e3e48eab9e1653.deps.json b/Test/TestProject/output/88e3e48eab9e1653.deps.json deleted file mode 100644 index 83b79bc..0000000 --- a/Test/TestProject/output/88e3e48eab9e1653.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"test_zlib": "0c04ab530bb9cfa4", "hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "BINASCII": "8f88a3374d5335cc", "vipermath": "3f7c5e78d8652535", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "base64": "4bf3e0150b9e02e9", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "binascii": "8f88a3374d5335cc", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653"} \ No newline at end of file diff --git a/Test/TestProject/output/8e0d8fdba991b3b4.deps.json b/Test/TestProject/output/8e0d8fdba991b3b4.deps.json deleted file mode 100644 index d8f67bb..0000000 --- a/Test/TestProject/output/8e0d8fdba991b3b4.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"test_zlib": "0c04ab530bb9cfa4", "hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "BINASCII": "3ee89b588a1da94f", "vipermath": "3f7c5e78d8652535", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "base64": "4bf3e0150b9e02e9", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "binascii": "8f88a3374d5335cc", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "c3eb91093118e1e1", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2"} \ No newline at end of file diff --git a/Test/TestProject/output/8f88a3374d5335cc.deps.json b/Test/TestProject/output/8f88a3374d5335cc.deps.json deleted file mode 100644 index 5d3e5fd..0000000 --- a/Test/TestProject/output/8f88a3374d5335cc.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"test_zlib": "0c04ab530bb9cfa4", "hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "BINASCII": "8f88a3374d5335cc", "vipermath": "3f7c5e78d8652535", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "base64": "4bf3e0150b9e02e9", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "binascii": "8f88a3374d5335cc", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "c3eb91093118e1e1", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2"} \ No newline at end of file diff --git a/Test/TestProject/output/94496ec50b0d13fc.deps.json b/Test/TestProject/output/94496ec50b0d13fc.deps.json deleted file mode 100644 index d676e78..0000000 --- a/Test/TestProject/output/94496ec50b0d13fc.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"test_zlib": "0c04ab530bb9cfa4", "hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "BINASCII": "8f88a3374d5335cc", "vipermath": "3f7c5e78d8652535", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "base64": "4bf3e0150b9e02e9", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "binascii": "8f88a3374d5335cc", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc"} \ No newline at end of file diff --git a/Test/TestProject/output/a9fa0f6200c09e65.deps.json b/Test/TestProject/output/a9fa0f6200c09e65.deps.json deleted file mode 100644 index 87256a5..0000000 --- a/Test/TestProject/output/a9fa0f6200c09e65.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"test_zlib": "0c04ab530bb9cfa4", "hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "BINASCII": "8f88a3374d5335cc", "vipermath": "3f7c5e78d8652535", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "base64": "4bf3e0150b9e02e9", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "binascii": "8f88a3374d5335cc", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653", "zlib.__init__": "d63d2c2a2bd9bd2a", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file diff --git a/Test/TestProject/output/abf9ce3160c9279e.deps.json b/Test/TestProject/output/abf9ce3160c9279e.deps.json deleted file mode 100644 index 233f787..0000000 --- a/Test/TestProject/output/abf9ce3160c9279e.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"test_zlib": "0c04ab530bb9cfa4", "hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "BINASCII": "8f88a3374d5335cc", "vipermath": "3f7c5e78d8652535", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "base64": "4bf3e0150b9e02e9", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "binascii": "8f88a3374d5335cc", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653", "zlib.__init__": "d63d2c2a2bd9bd2a", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e"} \ No newline at end of file diff --git a/Test/TestProject/output/b0267503e816efc4.deps.json b/Test/TestProject/output/b0267503e816efc4.deps.json deleted file mode 100644 index 87256a5..0000000 --- a/Test/TestProject/output/b0267503e816efc4.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"test_zlib": "0c04ab530bb9cfa4", "hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "BINASCII": "8f88a3374d5335cc", "vipermath": "3f7c5e78d8652535", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "base64": "4bf3e0150b9e02e9", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "binascii": "8f88a3374d5335cc", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653", "zlib.__init__": "d63d2c2a2bd9bd2a", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file diff --git a/Test/TestProject/output/ba2e1c2dfc8e2f85.deps.json b/Test/TestProject/output/ba2e1c2dfc8e2f85.deps.json deleted file mode 100644 index 28ea2c2..0000000 --- a/Test/TestProject/output/ba2e1c2dfc8e2f85.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"test_zlib": "0c04ab530bb9cfa4", "hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "BINASCII": "3ee89b588a1da94f", "vipermath": "3f7c5e78d8652535", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "base64": "4bf3e0150b9e02e9", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "binascii": "8f88a3374d5335cc", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "c3eb91093118e1e1", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2"} \ No newline at end of file diff --git a/Test/TestProject/output/bbdf3bbd4c3bc28c.deps.json b/Test/TestProject/output/bbdf3bbd4c3bc28c.deps.json deleted file mode 100644 index 2f5df43..0000000 --- a/Test/TestProject/output/bbdf3bbd4c3bc28c.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"test_zlib": "0c04ab530bb9cfa4", "hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "BINASCII": "8f88a3374d5335cc", "vipermath": "3f7c5e78d8652535", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "base64": "4bf3e0150b9e02e9", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "binascii": "8f88a3374d5335cc", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653", "zlib.__init__": "d63d2c2a2bd9bd2a", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file diff --git a/Test/TestProject/output/c3eb91093118e1e1.deps.json b/Test/TestProject/output/c3eb91093118e1e1.deps.json deleted file mode 100644 index c8b9979..0000000 --- a/Test/TestProject/output/c3eb91093118e1e1.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"test_zlib": "0c04ab530bb9cfa4", "hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "BINASCII": "8f88a3374d5335cc", "vipermath": "3f7c5e78d8652535", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "base64": "4bf3e0150b9e02e9", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "binascii": "8f88a3374d5335cc", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "c3eb91093118e1e1", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653", "zlib.__init__": "d63d2c2a2bd9bd2a", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file diff --git a/Test/TestProject/output/c9f4be41ca1cc2b4.deps.json b/Test/TestProject/output/c9f4be41ca1cc2b4.deps.json deleted file mode 100644 index 8a56fc5..0000000 --- a/Test/TestProject/output/c9f4be41ca1cc2b4.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"test_zlib": "0c04ab530bb9cfa4", "hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "BINASCII": "8f88a3374d5335cc", "vipermath": "3f7c5e78d8652535", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "base64": "4bf3e0150b9e02e9", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "binascii": "8f88a3374d5335cc", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653", "zlib.__init__": "d63d2c2a2bd9bd2a"} \ No newline at end of file diff --git a/Test/TestProject/output/d282a7cb3385ecf0.deps.json b/Test/TestProject/output/d282a7cb3385ecf0.deps.json deleted file mode 100644 index 87256a5..0000000 --- a/Test/TestProject/output/d282a7cb3385ecf0.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"test_zlib": "0c04ab530bb9cfa4", "hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "BINASCII": "8f88a3374d5335cc", "vipermath": "3f7c5e78d8652535", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "base64": "4bf3e0150b9e02e9", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "binascii": "8f88a3374d5335cc", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653", "zlib.__init__": "d63d2c2a2bd9bd2a", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file diff --git a/Test/TestProject/output/f9629b8eb4ebdcc2.deps.json b/Test/TestProject/output/f9629b8eb4ebdcc2.deps.json deleted file mode 100644 index 87256a5..0000000 --- a/Test/TestProject/output/f9629b8eb4ebdcc2.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"test_zlib": "0c04ab530bb9cfa4", "hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "BINASCII": "8f88a3374d5335cc", "vipermath": "3f7c5e78d8652535", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "base64": "4bf3e0150b9e02e9", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "binascii": "8f88a3374d5335cc", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653", "zlib.__init__": "d63d2c2a2bd9bd2a", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file diff --git a/Test/TestProject/output/fa3691e66b426950.deps.json b/Test/TestProject/output/fa3691e66b426950.deps.json deleted file mode 100644 index 2f5df43..0000000 --- a/Test/TestProject/output/fa3691e66b426950.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"test_zlib": "0c04ab530bb9cfa4", "hashlib.__sha1": "0d13cde396f4a15f", "__sha1": "0d13cde396f4a15f", "hashlib.__sha256": "0d4517fd5afeb330", "__sha256": "0d4517fd5afeb330", "zlib.zdeflate": "2d7f623c6e3004ce", "zdeflate": "2d7f623c6e3004ce", "test_numpy": "2e756dd336749fc2", "BINASCII": "8f88a3374d5335cc", "vipermath": "3f7c5e78d8652535", "zlib.zchecksum": "4638d411fd53fef0", "zchecksum": "4638d411fd53fef0", "base64": "4bf3e0150b9e02e9", "stdint": "56cdd754a8a09347", "main": "58121a0fb0ca7466", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdio": "73edbcf76e32d00b", "hashlib.__sha512": "88e3e48eab9e1653", "__sha512": "88e3e48eab9e1653", "config": "8e0d8fdba991b3b4", "binascii": "8f88a3374d5335cc", "hashlib.__md5": "94496ec50b0d13fc", "__md5": "94496ec50b0d13fc", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "zlib.zdef": "a9fa0f6200c09e65", "zdef": "a9fa0f6200c09e65", "zlib.zhuff": "b0267503e816efc4", "zhuff": "b0267503e816efc4", "HASHLIB": "ba2e1c2dfc8e2f85", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "numpy.__init__": "c3eb91093118e1e1", "numpy": "c3eb91093118e1e1", "viperio": "c9f4be41ca1cc2b4", "zlib.pyzlib": "d282a7cb3385ecf0", "pyzlib": "d282a7cb3385ecf0", "zlib.zinflate": "f9629b8eb4ebdcc2", "zinflate": "f9629b8eb4ebdcc2", "HASHLIB.__init__": "96837bcc64032444", "HASHLIB.__md5": "94496ec50b0d13fc", "HASHLIB.__sha1": "0d13cde396f4a15f", "HASHLIB.__sha256": "0d4517fd5afeb330", "HASHLIB.__sha512": "88e3e48eab9e1653", "zlib.__init__": "d63d2c2a2bd9bd2a", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file diff --git a/Test/TestProject/temp/0c04ab530bb9cfa4.pyi b/Test/TestProject/temp/0c04ab530bb9cfa4.pyi deleted file mode 100644 index e520473..0000000 --- a/Test/TestProject/temp/0c04ab530bb9cfa4.pyi +++ /dev/null @@ -1,69 +0,0 @@ -""" -Auto-generated Python stub file from test_zlib.py -Module: test_zlib -""" - - -from stdint import * -import zlib.pyzlib as pyzlib -import zlib.zhuff as zhuff -import zlib.zdef as zdef -from stdio import printf -from string import strlen, memcmp, memcpy, memset -from stdlib import malloc, free, realloc -import stdlib -import string -import mpool -import t, c - -pool: t.CExtern | mpool.MPool | t.CPtr -test_passed: t.CExtern | t.CInt -test_failed: t.CExtern | t.CInt - -def check(name: str, condition: t.CInt, detail: str) -> t.CInt: pass - -def print_hex_test(data: BYTEPTR, length: t.CSizeT, max_show: t.CSizeT) -> t.CInt: pass - -def print_separator() -> t.CInt: pass - -def section_header(title: str) -> t.CInt: pass - -def section_footer() -> t.CInt: pass - -def test_version() -> t.CInt: pass - -def test_compress_decompress() -> t.CInt: pass - -def test_compress_levels() -> t.CInt: pass - -def test_compressobj() -> t.CInt: pass - -def test_decompressobj() -> t.CInt: pass - -def test_decompressobj_max_lengthgth() -> t.CInt: pass - -def test_decompressobj_unused_data() -> t.CInt: pass - -def test_compress_copy() -> t.CInt: pass - -def test_decompress_copy() -> t.CInt: pass - -def test_adler32() -> t.CInt: pass - -def test_crc32() -> t.CInt: pass - -def test_empty_compress() -> t.CInt: pass - -def test_gzip_format() -> t.CInt: pass - -def test_raw_deflate() -> t.CInt: pass - -def test_zdict() -> t.CInt: pass - -def test_huffman_tree() -> t.CInt: pass - -def test_error_handling() -> t.CInt: pass - -def test_constants() -> t.CInt: pass - -def main123456() -> t.CInt: pass diff --git a/Test/TestProject/temp/2e756dd336749fc2.pyi b/Test/TestProject/temp/2e756dd336749fc2.pyi deleted file mode 100644 index 90a5cdd..0000000 --- a/Test/TestProject/temp/2e756dd336749fc2.pyi +++ /dev/null @@ -1,108 +0,0 @@ -""" -Auto-generated Python stub file from test_numpy.py -Module: test_numpy -""" - - -from stdint import * -import numpy -from stdio import printf -from stdlib import calloc, free -import string -import vipermath -import mpool -import t, c - -EPS: t.CExtern | t.CDouble -EPS_LOOSE: t.CExtern | t.CDouble -SIMD_BLOCK: t.CExtern | t.CSizeT -arena: t.CExtern | t.CUInt8T | t.CPtr -pool: t.CExtern | mpool.MPool | t.CPtr -test_passed: t.CExtern | t.CInt -test_failed: t.CExtern | t.CInt - -def check(name: str, condition: t.CInt, detail: str) -> t.CInt: pass - -def approx_eq(a: t.CDouble, b: t.CDouble) -> t.CInt: pass - -def approx_loose(a: t.CDouble, b: t.CDouble) -> t.CInt: pass - -def section_header(title: str) -> t.CInt: pass - -def section_footer() -> t.CInt: pass - -def vec4(p: mpool.MPool | t.CPtr, v0: t.CDouble, v1: t.CDouble, v2: t.CDouble, v3: t.CDouble) -> numpy.ndarray | t.CPtr: pass - -def vec3(p: mpool.MPool | t.CPtr, v0: t.CDouble, v1: t.CDouble, v2: t.CDouble) -> numpy.ndarray | t.CPtr: pass - -def vec2(p: mpool.MPool | t.CPtr, v0: t.CDouble, v1: t.CDouble) -> numpy.ndarray | t.CPtr: pass - -def test_zeros_ones() -> t.CInt: pass - -def test_arange_linspace() -> t.CInt: pass - -def test_eye_diag() -> t.CInt: pass - -def test_sum_mean_min_max() -> t.CInt: pass - -def test_fill_copy() -> t.CInt: pass - -def test_add_sub_mul_div() -> t.CInt: pass - -def test_neg() -> t.CInt: pass - -def test_len() -> t.CInt: pass - -def test_scalar_ops() -> t.CInt: pass - -def test_math_funcs() -> t.CInt: pass - -def test_matmul() -> t.CInt: pass - -def test_dot() -> t.CInt: pass - -def test_transpose() -> t.CInt: pass - -def test_var_std_norm() -> t.CInt: pass - -def test_clip_concatenate() -> t.CInt: pass - -def test_sort_reverse() -> t.CInt: pass - -def test_print_arr() -> t.CInt: pass - -def test_floordiv_mod() -> t.CInt: pass - -def test_additional_math() -> t.CInt: pass - -def test_trig_hyperbolic() -> t.CInt: pass - -def test_degrees_radians() -> t.CInt: pass - -def test_cumsum_diff() -> t.CInt: pass - -def test_max_min_where() -> t.CInt: pass - -def test_flatten_trace() -> t.CInt: pass - -def test_outer() -> t.CInt: pass - -def test_bool_comparison() -> t.CInt: pass - -def test_linalg() -> t.CInt: pass - -def test_additional_creation() -> t.CInt: pass - -def test_interp() -> t.CInt: pass - -def test_numpy_edge() -> t.CInt: pass - -def bench_numpy_perf() -> t.CInt: pass - -def test_numpy_correct() -> t.CInt: pass - -def test_numpy_edge_main() -> t.CInt: pass - -def bench_numpy_main() -> t.CInt: pass - -def test_numpy_main() -> t.CInt: pass diff --git a/Test/TestProject/temp/3ee89b588a1da94f.pyi b/Test/TestProject/temp/3ee89b588a1da94f.pyi deleted file mode 100644 index ed878e4..0000000 --- a/Test/TestProject/temp/3ee89b588a1da94f.pyi +++ /dev/null @@ -1,13 +0,0 @@ -""" -Auto-generated Python stub file from BINASCII.py -Module: BINASCII -""" - - -import stdio -import stdlib -import string -import binascii -import t, c - -def main222() -> t.CInt: pass diff --git a/Test/TestProject/temp/49bd8cba55979f76.pyi b/Test/TestProject/temp/49bd8cba55979f76.pyi new file mode 100644 index 0000000..f1d844a --- /dev/null +++ b/Test/TestProject/temp/49bd8cba55979f76.pyi @@ -0,0 +1,75 @@ +""" +Auto-generated Python stub file from stdint.py +Module: stdint +""" + +import c + + +import t + +INT: t.CTypedef = t.CInt +INTPTR: t.CTypedef = t.CInt | t.CPtr +BOOL: t.CTypedef = t.CInt +UINT: t.CTypedef = t.CUnsignedInt +UINTPTR: t.CTypedef = UINT | t.CPtr +BYTE: t.CTypedef = t.CUnsignedChar +BYTEPTR: t.CTypedef = BYTE | t.CPtr +WORD: t.CTypedef = t.CUInt16T +DWORD: t.CTypedef = t.CUInt32T +QWORD: t.CTypedef = t.CUInt64T +TCHAR: t.CTypedef = t.CChar +CHARLIST: t.CTypedef = str | t.CPtr +VOID: t.CTypedef = t.CVoid +SHORT: t.CTypedef = t.CShort +SHORTPTR: t.CTypedef = t.CShort | t.CPtr +USHORT: t.CTypedef = t.CUnsignedShort +USHORTPTR: t.CTypedef = t.CUnsignedShort | t.CPtr +LONGLONG: t.CTypedef = t.CLong | t.CLong +ULONGLONG: t.CTypedef = t.CUnsignedLong | t.CLong +LONG: t.CTypedef = t.CLong +ULONG: t.CTypedef = t.CUnsignedLong +WCHAR: t.CTypedef = WORD +WCHARPTR: t.CTypedef = WORD | t.CPtr +CHARPTR: t.CTypedef = t.CChar | t.CPtr +FSIZE_t: t.CTypedef = DWORD +LBA_t: t.CTypedef = DWORD +UINTPTR: t.CTypedef = t.CUnsignedInt | t.CPtr +VOIDPTR: t.CTypedef = t.CVoid | t.CPtr +FLOAT: t.CTypedef = t.CFloat +DOUBLE: t.CTypedef = t.CDouble +FLOAT8: t.CTypedef = t.CFloat8T +FLOAT16: t.CTypedef = t.CFloat16T +FLOAT32: t.CTypedef = t.CFloat32T +FLOAT64: t.CTypedef = t.CFloat64T +FLOAT128: t.CTypedef = t.CFloat128T +INT8: t.CTypedef = t.CInt8T +INT16: t.CTypedef = t.CInt16T +INT32: t.CTypedef = t.CInt32T +INT64: t.CTypedef = t.CInt64T +UINT8: t.CTypedef = t.CUInt8T +UINT16: t.CTypedef = t.CUInt16T +UINT32: t.CTypedef = t.CUInt32T +UINT64: t.CTypedef = t.CUInt64T +INT8PTR: t.CTypedef = t.CInt8T | t.CPtr +INT16PTR: t.CTypedef = t.CInt16T | t.CPtr +INT32PTR: t.CTypedef = t.CInt32T | t.CPtr +INT64PTR: t.CTypedef = t.CInt64T | t.CPtr +UINT8PTR: t.CTypedef = t.CUInt8T | t.CPtr +UINT16PTR: t.CTypedef = t.CUInt16T | t.CPtr +UINT32PTR: t.CTypedef = t.CUInt32T | t.CPtr +UINT64PTR: t.CTypedef = t.CUInt64T | t.CPtr +CHAR8: t.CTypedef = t.CChar8T +CHAR16: t.CTypedef = t.CChar16T +CHAR32: t.CTypedef = t.CChar32T +CHAR8PTR: t.CTypedef = t.CChar8T | t.CPtr +CHAR16PTR: t.CTypedef = t.CChar16T | t.CPtr +CHAR32PTR: t.CTypedef = t.CChar32T | t.CPtr +i8: t.CTypedef = t.CInt8T +i16: t.CTypedef = t.CInt16T +i32: t.CTypedef = t.CInt32T +i64: t.CTypedef = t.CInt64T +u8: t.CTypedef = t.CUInt8T +u16: t.CTypedef = t.CUInt16T +u32: t.CTypedef = t.CUInt32T +u64: t.CTypedef = t.CUInt64T \ No newline at end of file diff --git a/Test/TestProject/temp/4bf3e0150b9e02e9.pyi b/Test/TestProject/temp/4bf3e0150b9e02e9.pyi deleted file mode 100644 index bd213f3..0000000 --- a/Test/TestProject/temp/4bf3e0150b9e02e9.pyi +++ /dev/null @@ -1,14 +0,0 @@ -""" -Auto-generated Python stub file from base64.py -Module: base64 -""" - - -import t, c - -b64_tab: t.CExtern | list[t.CChar, None] -b64_dec_tab: t.CExtern | list[t.CInt8T, 80] - -def b64encode(s: str, out: str) -> t.CSizeT: pass - -def b64decode(s: str, out: t.CUInt8T | t.CPtr) -> t.CSizeT: pass diff --git a/Test/TestProject/temp/56cdd754a8a09347.pyi b/Test/TestProject/temp/56cdd754a8a09347.pyi deleted file mode 100644 index 007ccb8..0000000 --- a/Test/TestProject/temp/56cdd754a8a09347.pyi +++ /dev/null @@ -1,67 +0,0 @@ -""" -Auto-generated Python stub file from stdint.py -Module: stdint -""" - -import c - - -import t - -INT: t.CTypedef = t.CInt -INTPTR: t.CTypedef = t.CInt | t.CPtr -BOOL: t.CTypedef = t.CInt -UINT: t.CTypedef = t.CUnsignedInt -UINTPTR: t.CTypedef = UINT | t.CPtr -BYTE: t.CTypedef = t.CUnsignedChar -BYTEPTR: t.CTypedef = BYTE | t.CPtr -WORD: t.CTypedef = t.CUInt16T -DWORD: t.CTypedef = t.CUInt32T -QWORD: t.CTypedef = t.CUInt64T -TCHAR: t.CTypedef = t.CChar -CHARLIST: t.CTypedef = str | t.CPtr -VOID: t.CTypedef = t.CVoid -SHORT: t.CTypedef = t.CShort -SHORTPTR: t.CTypedef = t.CShort | t.CPtr -USHORT: t.CTypedef = t.CUnsignedShort -USHORTPTR: t.CTypedef = t.CUnsignedShort | t.CPtr -LONGLONG: t.CTypedef = t.CLong | t.CLong -ULONGLONG: t.CTypedef = t.CUnsignedLong | t.CLong -LONG: t.CTypedef = t.CLong -ULONG: t.CTypedef = t.CUnsignedLong -WCHAR: t.CTypedef = WORD -WCHARPTR: t.CTypedef = WORD | t.CPtr -CHARPTR: t.CTypedef = t.CChar | t.CPtr -FSIZE_t: t.CTypedef = DWORD -LBA_t: t.CTypedef = DWORD -UINTPTR: t.CTypedef = t.CUnsignedInt | t.CPtr -VOIDPTR: t.CTypedef = t.CVoid | t.CPtr -FLOAT: t.CTypedef = t.CFloat -DOUBLE: t.CTypedef = t.CDouble -FLOAT8: t.CTypedef = t.CFloat8T -FLOAT16: t.CTypedef = t.CFloat16T -FLOAT32: t.CTypedef = t.CFloat32T -FLOAT64: t.CTypedef = t.CFloat64T -FLOAT128: t.CTypedef = t.CFloat128T -INT8: t.CTypedef = t.CInt8T -INT16: t.CTypedef = t.CInt16T -INT32: t.CTypedef = t.CInt32T -INT64: t.CTypedef = t.CInt64T -UINT8: t.CTypedef = t.CUInt8T -UINT16: t.CTypedef = t.CUInt16T -UINT32: t.CTypedef = t.CUInt32T -UINT64: t.CTypedef = t.CUInt64T -INT8PTR: t.CTypedef = t.CInt8T | t.CPtr -INT16PTR: t.CTypedef = t.CInt16T | t.CPtr -INT32PTR: t.CTypedef = t.CInt32T | t.CPtr -INT64PTR: t.CTypedef = t.CInt64T | t.CPtr -UINT8PTR: t.CTypedef = t.CUInt8T | t.CPtr -UINT16PTR: t.CTypedef = t.CUInt16T | t.CPtr -UINT32PTR: t.CTypedef = t.CUInt32T | t.CPtr -UINT64PTR: t.CTypedef = t.CUInt64T | t.CPtr -CHAR8: t.CTypedef = t.CChar8T -CHAR16: t.CTypedef = t.CChar16T -CHAR32: t.CTypedef = t.CChar32T -CHAR8PTR: t.CTypedef = t.CChar8T | t.CPtr -CHAR16PTR: t.CTypedef = t.CChar16T | t.CPtr -CHAR32PTR: t.CTypedef = t.CChar32T | t.CPtr \ No newline at end of file diff --git a/Test/TestProject/temp/6aee24fdefa3cbc0.pyi b/Test/TestProject/temp/6aee24fdefa3cbc0.pyi deleted file mode 100644 index c17475f..0000000 --- a/Test/TestProject/temp/6aee24fdefa3cbc0.pyi +++ /dev/null @@ -1,44 +0,0 @@ -""" -Auto-generated Python stub file from string.py -Module: string -""" - - -from stdint import * -import t, c - -def strcpy(dest: str, src: str) -> str: pass - -def strncpy(dest: str, src: str, n: t.CSizeT) -> str: pass - -def strlen(src: str) -> t.CSizeT | t.CExport: pass - -def strcmp(str1: str, str2: str) -> t.CInt: pass - -def samestr(str1: str, str2: str) -> bool: pass - -def strncmp(str1: str, str2: str, n: t.CSizeT) -> t.CInt: pass - -def memcmp(ptr1: t.CVoid | t.CPtr, ptr2: t.CVoid | t.CPtr, n: t.CSizeT) -> t.CInt: pass - -def strchr(s: str, cr: t.CInt) -> str: pass - -def strrchr(s: str, cr: t.CInt) -> str: pass - -def strspn(s: str, skip: str) -> int: pass - -def memset(ptr: t.CVoid | t.CPtr, value: t.CInt, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass - -def memset32(ptr: t.CVoid | t.CPtr, value: t.CUInt32T, count: t.CSizeT) -> t.CVoid | t.CPtr: pass - -def memcpy(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass - -def memmove(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr: pass - -def atoi(src: str) -> t.CInt: pass - -def atoll(src: str) -> t.CInt64T: pass - -def atof(src: str) -> t.CDouble: pass - -def split(s: str, delim: str, result: list[str]) -> int: pass diff --git a/Test/TestProject2/temp/09ba6d4617920d26.pyi b/Test/TestProject/temp/8304671209f68d6c.pyi similarity index 93% rename from Test/TestProject2/temp/09ba6d4617920d26.pyi rename to Test/TestProject/temp/8304671209f68d6c.pyi index bb148a9..c7b0507 100644 --- a/Test/TestProject2/temp/09ba6d4617920d26.pyi +++ b/Test/TestProject/temp/8304671209f68d6c.pyi @@ -13,5 +13,6 @@ import zc.config as config import zc.test as test import zc.logic_test as logic import zc.class_test as class_test +import testcheck def main() -> stdint.INT: pass diff --git a/Test/TestProject/temp/8e0d8fdba991b3b4.pyi b/Test/TestProject/temp/8e0d8fdba991b3b4.pyi deleted file mode 100644 index b09d9e4..0000000 --- a/Test/TestProject/temp/8e0d8fdba991b3b4.pyi +++ /dev/null @@ -1,25 +0,0 @@ -""" -Auto-generated Python stub file from config.py -Module: config -""" - - -import stdint -import t, c - -A: t.CExtern | t.CChar | t.CPtr - -class BIT_TEST(t.Object): - a: t.CInt | t.Bit(1) - b: t.CInt | t.Bit(1) - c: t.CInt | t.Bit(1) - d: t.CInt | t.Bit(5) -class OOP_TEST(t.Object): - a: t.CInt - def __init__(self: OOP_TEST) -> t.CInt: pass - def __call__(self: OOP_TEST) -> stdint.UINT: pass -class ENUM_TEST(t.CEnum): - A: t.State - B: t.State - C: t.State - Len: t.State \ No newline at end of file diff --git a/Test/TestProject/temp/9dbecd0942a39782.pyi b/Test/TestProject/temp/9dbecd0942a39782.pyi new file mode 100644 index 0000000..41648c1 --- /dev/null +++ b/Test/TestProject/temp/9dbecd0942a39782.pyi @@ -0,0 +1,25 @@ +""" +Auto-generated Python stub file from testcheck.py +Module: testcheck +""" + + +import t, c +import stdio + +_pass_count: t.CExtern | t.CInt +_fail_count: t.CExtern | t.CInt + +def begin(name: str) -> t.CInt: pass + +def section(name: str) -> t.CInt: pass + +def ok(msg: str) -> t.CInt: pass + +def fail(msg: str) -> t.CInt: pass + +def check(cond: t.CInt, ok_msg: str, fail_msg: str) -> t.CInt: pass + +def info(msg: str) -> t.CInt: pass + +def end() -> t.CInt: pass diff --git a/Test/TestProject/temp/_sha1_map.txt b/Test/TestProject/temp/_sha1_map.txt index eefe6e8..1b56cbf 100644 --- a/Test/TestProject/temp/_sha1_map.txt +++ b/Test/TestProject/temp/_sha1_map.txt @@ -1,29 +1,4 @@ -0c04ab530bb9cfa4:test_zlib.py -0d13cde396f4a15f:includes/hashlib\__sha1.py -0d4517fd5afeb330:includes/hashlib\__sha256.py -2d7f623c6e3004ce:includes/zlib\zdeflate.py -2e756dd336749fc2:test_numpy.py -3ee89b588a1da94f:BINASCII.py -3f7c5e78d8652535:includes/vipermath.py -4638d411fd53fef0:includes/zlib\zchecksum.py -4bf3e0150b9e02e9:includes/base64.py -56cdd754a8a09347:includes/stdint.py -58121a0fb0ca7466:main.py -5a6a2137958c28c5:includes/w32\win32base.py -68c4fe4b12c908e3:includes/mpool.py -6aee24fdefa3cbc0:includes/string.py -6c2029b306556c00:includes/stdlib.py +49bd8cba55979f76:includes/stdint.py 73edbcf76e32d00b:includes/stdio.py -88e3e48eab9e1653:includes/hashlib\__sha512.py -8e0d8fdba991b3b4:config.py -8f88a3374d5335cc:includes/binascii.py -94496ec50b0d13fc:includes/hashlib\__md5.py -96837bcc64032444:includes/hashlib\__init__.py -a9fa0f6200c09e65:includes/zlib\zdef.py -b0267503e816efc4:includes/zlib\zhuff.py -ba2e1c2dfc8e2f85:HASHLIB.py -bbdf3bbd4c3bc28c:includes/w32\win32console.py -c3eb91093118e1e1:includes/numpy\__init__.py -c9f4be41ca1cc2b4:includes/viperio.py -d282a7cb3385ecf0:includes/zlib\pyzlib.py -f9629b8eb4ebdcc2:includes/zlib\zinflate.py +8304671209f68d6c:main.py +9dbecd0942a39782:includes/testcheck.py diff --git a/Test/TestProject/temp/_shared_sym.pkl b/Test/TestProject/temp/_shared_sym.pkl deleted file mode 100644 index 6ef05eb827938a81fa124c3b7f38a05133fdca7f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 924818 zcmeFa32+=|b|wgsI7yHM50T;_UTRsS4hR=PP*O_-3I(!MKmo!*N;0~uv#Jt6{;aA* zXI7B}+w73~U;}c^cr2H^wnOXn&Nw`7d)8r3*uA~>*zWbX5BJ($kJsz)b~qd!Z?ETw z=;_@KuXlRv81MW4tos16K>nEzS&tF?v$CpCD7^oD|GVFNr|pAXEswSEfA_N>r7{ zBBIB`DJ2qDvza4tEz%p+4YhYpJU?$ey|?u4$FdjS&GMh!lQNW~8CO!ekZ_`m{TO_Zk~ut)PDWFjo}5)vX(Ktm#$UP*pXo~*hMG+IN}ms9 zPK5K%udbz5^yGAesnL`#u9#*vl|D=7>hPJFFmH4EV6u∓nR~T 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 Kn#Fvv@BagNnur7d diff --git a/Test/TestProject/temp/ba2e1c2dfc8e2f85.pyi b/Test/TestProject/temp/ba2e1c2dfc8e2f85.pyi deleted file mode 100644 index 359a1c4..0000000 --- a/Test/TestProject/temp/ba2e1c2dfc8e2f85.pyi +++ /dev/null @@ -1,19 +0,0 @@ -""" -Auto-generated Python stub file from HASHLIB.py -Module: HASHLIB -""" - - -import stdio -import stdlib -import string -import stdint -import t, c -import base64 -import hashlib - -def default_value_test_function(a: t.CInt, b: t.CInt) -> t.CInt: pass - -def print_hex(buf: t.CUInt8T | t.CPtr, length: t.CInt) -> t.CInt: pass - -def main1() -> t.CInt: pass diff --git a/Test/TestProject/temp/c3eb91093118e1e1.pyi b/Test/TestProject/temp/c3eb91093118e1e1.pyi deleted file mode 100644 index adb6481..0000000 --- a/Test/TestProject/temp/c3eb91093118e1e1.pyi +++ /dev/null @@ -1,234 +0,0 @@ -""" -Auto-generated Python stub file from numpy.__init__.py -Module: numpy.__init__ -""" - - -from stdint import * -import stdlib -import string -import vipermath -import stdio -import t, c -import mpool - -MAX_NDIM: t.CDefine = 4 -float64: t.CTypedef = t.CDouble -float32: t.CTypedef = t.CFloat -int64: t.CTypedef = t.CLong -int32: t.CTypedef = t.CInt -uint8: t.CTypedef = t.CUnsignedChar -pi: t.CDefine = 3.14159265358979323846 -e: t.CDefine = 2.71828182845904523536 - -@t.Object -class ndarray: - data: t.CDouble | t.CPtr - shape: list[t.CSizeT, MAX_NDIM] - strides: list[t.CSizeT, MAX_NDIM] - ndim: t.CInt - size: t.CSizeT - owns_data: t.CInt - pool: mpool.MPool | t.CPtr - def __new__(self: ndarray, pool: mpool.MPool | t.CPtr, n: t.CSizeT) -> t.CInt: pass - def __add__(self: ndarray, other: 'ndarray' | t.CPtr) -> 'ndarray' | t.CPtr: pass - def __sub__(self: ndarray, other: 'ndarray' | t.CPtr) -> 'ndarray' | t.CPtr: pass - def __mul__(self: ndarray, other: 'ndarray' | t.CPtr) -> 'ndarray' | t.CPtr: pass - def __truediv__(self: ndarray, other: 'ndarray' | t.CPtr) -> 'ndarray' | t.CPtr: pass - def __floordiv__(self: ndarray, other: 'ndarray' | t.CPtr) -> 'ndarray' | t.CPtr: pass - def __mod__(self: ndarray, other: 'ndarray' | t.CPtr) -> 'ndarray' | t.CPtr: pass - def __neg__(self: ndarray) -> 'ndarray' | t.CPtr: pass - def __len__(self: ndarray) -> t.CInt: pass - def at2d(self: ndarray, row: t.CSizeT, col: t.CSizeT) -> t.CDouble: pass - def set2d(self: ndarray, row: t.CSizeT, col: t.CSizeT, val: t.CDouble) -> t.CInt: pass - def delete(self: ndarray) -> t.CInt: pass - def fill(self: ndarray, val: t.CDouble) -> t.CInt: pass - def copy(self: ndarray) -> 'ndarray' | t.CPtr: pass - def reshape(self: ndarray, new_shape: INTPTR, new_ndim: t.CInt) -> 'ndarray' | t.CPtr: pass - def sum(self: ndarray) -> t.CDouble: pass - def mean(self: ndarray) -> t.CDouble: pass - def min(self: ndarray) -> t.CDouble: pass - def max(self: ndarray) -> t.CDouble: pass - def argmax(self: ndarray) -> t.CInt: pass - def argmin(self: ndarray) -> t.CInt: pass - def dot(self: ndarray, other: 'ndarray' | t.CPtr) -> t.CDouble: pass - def T(self: ndarray) -> 'ndarray' | t.CPtr: pass - def print_arr(self: ndarray) -> t.CInt: pass - -def _alloc_ndarray(pool: mpool.MPool | t.CPtr) -> ndarray | t.CPtr: pass - -def _compute_strides(a: ndarray | t.CPtr) -> t.CInt: pass - -def _empty_like(a: ndarray | t.CPtr) -> ndarray | t.CPtr: pass - -def array(pool: mpool.MPool | t.CPtr, data: t.CDouble | t.CPtr, n: t.CSizeT) -> ndarray | t.CPtr: pass - -def zeros(pool: mpool.MPool | t.CPtr, n: t.CSizeT) -> ndarray | t.CPtr: pass - -def ones(pool: mpool.MPool | t.CPtr, n: t.CSizeT) -> ndarray | t.CPtr: pass - -def full(pool: mpool.MPool | t.CPtr, n: t.CSizeT, val: t.CDouble) -> ndarray | t.CPtr: pass - -def arange(pool: mpool.MPool | t.CPtr, start: t.CDouble, stop: t.CDouble, step: t.CDouble) -> ndarray | t.CPtr: pass - -def linspace(pool: mpool.MPool | t.CPtr, start: t.CDouble, stop: t.CDouble, num: t.CSizeT) -> ndarray | t.CPtr: pass - -def empty2d(pool: mpool.MPool | t.CPtr, rows: t.CSizeT, cols: t.CSizeT) -> ndarray | t.CPtr: pass - -def zeros2d(pool: mpool.MPool | t.CPtr, rows: t.CSizeT, cols: t.CSizeT) -> ndarray | t.CPtr: pass - -def ones2d(pool: mpool.MPool | t.CPtr, rows: t.CSizeT, cols: t.CSizeT) -> ndarray | t.CPtr: pass - -def eye(pool: mpool.MPool | t.CPtr, n: t.CSizeT) -> ndarray | t.CPtr: pass - -def diag(pool: mpool.MPool | t.CPtr, vals: ndarray | t.CPtr) -> ndarray | t.CPtr: pass - -def np_abs(a: ndarray | t.CPtr) -> ndarray | t.CPtr: pass - -def np_sqrt(a: ndarray | t.CPtr) -> ndarray | t.CPtr: pass - -def np_exp(a: ndarray | t.CPtr) -> ndarray | t.CPtr: pass - -def np_log(a: ndarray | t.CPtr) -> ndarray | t.CPtr: pass - -def np_sin(a: ndarray | t.CPtr) -> ndarray | t.CPtr: pass - -def np_cos(a: ndarray | t.CPtr) -> ndarray | t.CPtr: pass - -def np_tan(a: ndarray | t.CPtr) -> ndarray | t.CPtr: pass - -def np_pow(a: ndarray | t.CPtr, p: t.CDouble) -> ndarray | t.CPtr: pass - -def add_scalar(a: ndarray | t.CPtr, s: t.CDouble) -> ndarray | t.CPtr: pass - -def mul_scalar(a: ndarray | t.CPtr, s: t.CDouble) -> ndarray | t.CPtr: pass - -def sub_scalar(a: ndarray | t.CPtr, s: t.CDouble) -> ndarray | t.CPtr: pass - -def div_scalar(a: ndarray | t.CPtr, s: t.CDouble) -> ndarray | t.CPtr: pass - -def matmul(a: ndarray | t.CPtr, b: ndarray | t.CPtr) -> ndarray | t.CPtr: pass - -def dot_product(a: ndarray | t.CPtr, b: ndarray | t.CPtr) -> t.CDouble: pass - -def np_sum(a: ndarray | t.CPtr) -> t.CDouble: pass - -def np_mean(a: ndarray | t.CPtr) -> t.CDouble: pass - -def np_min(a: ndarray | t.CPtr) -> t.CDouble: pass - -def np_max(a: ndarray | t.CPtr) -> t.CDouble: pass - -def np_argmax(a: ndarray | t.CPtr) -> t.CInt: pass - -def np_argmin(a: ndarray | t.CPtr) -> t.CInt: pass - -def var(a: ndarray | t.CPtr) -> t.CDouble: pass - -def std(a: ndarray | t.CPtr) -> t.CDouble: pass - -def norm(a: ndarray | t.CPtr) -> t.CDouble: pass - -def clip(a: ndarray | t.CPtr, lo: t.CDouble, hi: t.CDouble) -> ndarray | t.CPtr: pass - -def concatenate(a: ndarray | t.CPtr, b: ndarray | t.CPtr) -> ndarray | t.CPtr: pass - -def sort_arr(a: ndarray | t.CPtr) -> ndarray | t.CPtr: pass - -def reverse(a: ndarray | t.CPtr) -> ndarray | t.CPtr: pass - -def np_log10(a: ndarray | t.CPtr) -> ndarray | t.CPtr: pass - -def np_log2(a: ndarray | t.CPtr) -> ndarray | t.CPtr: pass - -def np_floor(a: ndarray | t.CPtr) -> ndarray | t.CPtr: pass - -def np_ceil(a: ndarray | t.CPtr) -> ndarray | t.CPtr: pass - -def np_round(a: ndarray | t.CPtr) -> ndarray | t.CPtr: pass - -def np_sign(a: ndarray | t.CPtr) -> ndarray | t.CPtr: pass - -def np_tanh(a: ndarray | t.CPtr) -> ndarray | t.CPtr: pass - -def np_sinh(a: ndarray | t.CPtr) -> ndarray | t.CPtr: pass - -def np_cosh(a: ndarray | t.CPtr) -> ndarray | t.CPtr: pass - -def np_arcsin(a: ndarray | t.CPtr) -> ndarray | t.CPtr: pass - -def np_arccos(a: ndarray | t.CPtr) -> ndarray | t.CPtr: pass - -def np_arctan(a: ndarray | t.CPtr) -> ndarray | t.CPtr: pass - -def np_arctan2(y: ndarray | t.CPtr, x: ndarray | t.CPtr) -> ndarray | t.CPtr: pass - -def np_degrees(a: ndarray | t.CPtr) -> ndarray | t.CPtr: pass - -def np_radians(a: ndarray | t.CPtr) -> ndarray | t.CPtr: pass - -def np_isnan(a: ndarray | t.CPtr) -> ndarray | t.CPtr: pass - -def np_isinf(a: ndarray | t.CPtr) -> ndarray | t.CPtr: pass - -def np_maximum(a: ndarray | t.CPtr, b: ndarray | t.CPtr) -> ndarray | t.CPtr: pass - -def np_minimum(a: ndarray | t.CPtr, b: ndarray | t.CPtr) -> ndarray | t.CPtr: pass - -def cumsum(a: ndarray | t.CPtr) -> ndarray | t.CPtr: pass - -def diff(a: ndarray | t.CPtr) -> ndarray | t.CPtr: pass - -def flatten(a: ndarray | t.CPtr) -> ndarray | t.CPtr: pass - -def trace(a: ndarray | t.CPtr) -> t.CDouble: pass - -def outer(a: ndarray | t.CPtr, b: ndarray | t.CPtr) -> ndarray | t.CPtr: pass - -def np_where(condition: ndarray | t.CPtr, x: ndarray | t.CPtr, y: ndarray | t.CPtr) -> ndarray | t.CPtr: pass - -def np_count_nonzero(a: ndarray | t.CPtr) -> t.CInt: pass - -def np_all(a: ndarray | t.CPtr) -> t.CInt: pass - -def np_any(a: ndarray | t.CPtr) -> t.CInt: pass - -def np_equal(a: ndarray | t.CPtr, b: ndarray | t.CPtr) -> ndarray | t.CPtr: pass - -def np_not_equal(a: ndarray | t.CPtr, b: ndarray | t.CPtr) -> ndarray | t.CPtr: pass - -def np_less(a: ndarray | t.CPtr, b: ndarray | t.CPtr) -> ndarray | t.CPtr: pass - -def np_greater(a: ndarray | t.CPtr, b: ndarray | t.CPtr) -> ndarray | t.CPtr: pass - -def np_less_equal(a: ndarray | t.CPtr, b: ndarray | t.CPtr) -> ndarray | t.CPtr: pass - -def np_greater_equal(a: ndarray | t.CPtr, b: ndarray | t.CPtr) -> ndarray | t.CPtr: pass - -def empty(pool: mpool.MPool | t.CPtr, n: t.CSizeT) -> ndarray | t.CPtr: pass - -def full2d(pool: mpool.MPool | t.CPtr, rows: t.CSizeT, cols: t.CSizeT, val: t.CDouble) -> ndarray | t.CPtr: pass - -def zeros_like(a: ndarray | t.CPtr) -> ndarray | t.CPtr: pass - -def ones_like(a: ndarray | t.CPtr) -> ndarray | t.CPtr: pass - -def arange1(pool: mpool.MPool | t.CPtr, stop: t.CDouble) -> ndarray | t.CPtr: pass - -def linspace2(pool: mpool.MPool | t.CPtr, start: t.CDouble, stop: t.CDouble) -> ndarray | t.CPtr: pass - -def meshgrid(x: ndarray | t.CPtr, y: ndarray | t.CPtr) -> ndarray | t.CPtr: pass - -def det2x2(a: ndarray | t.CPtr) -> t.CDouble: pass - -def inv2x2(a: ndarray | t.CPtr) -> ndarray | t.CPtr: pass - -def cross3(a: ndarray | t.CPtr, b: ndarray | t.CPtr) -> ndarray | t.CPtr: pass - -def np_interp(x: t.CDouble, xp: ndarray | t.CPtr, fp: ndarray | t.CPtr) -> t.CDouble: pass - -def prod(a: ndarray | t.CPtr) -> t.CDouble: pass - -def median(a: ndarray | t.CPtr) -> t.CDouble: pass - -def percentile(a: ndarray | t.CPtr, q: t.CDouble) -> t.CDouble: pass diff --git a/Test/TestProject2/App/main.py b/Test/TestProject2/App/main.py index 8be34af..69f06d0 100644 --- a/Test/TestProject2/App/main.py +++ b/Test/TestProject2/App/main.py @@ -1,116 +1,35 @@ -import stdio -import stdint -import zc.config as config -import zc.test as test -import zc.logic_test as logic -import zc.class_test as class_test +from stdint import * +import w32.win32console +import config +import hashlib +import binascii +import zlib.pyzlib as zp + +import t, c +import testcheck -def main() -> stdint.INT: - stdio.printf("=== Hello World! ===\n") - stdio.printf("Cross-module macros:\n") - 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) - stdio.printf("\n=== While Loop Test ===\n") - test.AboutSizeTWhileTest(10) - stdio.printf("\n=== Math Basic Test (20, 6) ===\n") - test.MathBasicTest(20, 6) - stdio.printf("\n=== Math Advanced Test (value=15) ===\n") - test.MathAdvancedTest(15) - stdio.printf("\n=== While with Elif-Else Test (-2 to 12) ===\n") - test.WhileWithElifElseTest(-2, 12) - stdio.printf("\n=== Nested While with Macros Test ===\n") - test.NestedWhileWithMacrosTest(3, 4) - stdio.printf("\n=== Complex Condition Test (1, 2, 3) ===\n") - test.ComplexConditionTest(1, 2, 3) - stdio.printf("\n=== Retry Loop Test (8) ===\n") - test.RetryLoopTest(8) - stdio.printf("\n=== Bitwise Operations Test (0b1101101) ===\n") - test.BitwiseOperationsTest(109) - stdio.printf("\n=== Compound Assignment Math Test (15, 4) ===\n") - test.CompoundAssignmentMathTest(15, 4) - stdio.printf("\n=== Power and Modulo Test (2, 8) ===\n") - test.PowerAndModuloTest(2, 8) - stdio.printf("\n=== Mixed Arithmetic Test (5, 3, 4) ===\n") - test.MixedArithmeticTest(5, 3, 4) - stdio.printf("\n=== Math with While Loop Test (start=1, count=5) ===\n") - test.MathWithWhileLoopTest(1, 5) - stdio.printf("\n=== Complex Nested Math Test (7, 3) ===\n") - test.ComplexNestedMathTest(7, 3) - stdio.printf("\n=== Conditional Math Chain Test (value=10) ===\n") - test.ConditionalMathChainTest(10) - stdio.printf("\n=== Bit Manipulation Math Test (0xABCD) ===\n") - test.BitManipulationMathTest(0xABCD) - stdio.printf("\n============== COMPLEX LOGIC TESTS ==============\n") - stdio.printf("\n=== For Range Basic Test (stop=5) ===\n") - logic.ForRangeBasicTest(5) - stdio.printf("\n=== For Range With Start Stop Step (start=1, stop=10, step=2) ===\n") - logic.ForRangeWithStartStop(1, 10, 2) - stdio.printf("\n=== Nested For Range Test (rows=2, cols=3) ===\n") - logic.NestedForRangeTest(2, 3) - stdio.printf("\n=== For With If Break Test (size=8) ===\n") - logic.ForWithIfBreakTest(8) - stdio.printf("\n=== For With If Continue Test (n=10) ===\n") - logic.ForWithIfContinueTest(10) - stdio.printf("\n=== For With Elif Branch Test (value=10) ===\n") - logic.ForWithElifBranchTest(10) - stdio.printf("\n=== While With If Elif Else Test (iterations=7) ===\n") - logic.WhileWithIfElifElseTest(7) - stdio.printf("\n=== While With Nested If Test (limit=4) ===\n") - logic.WhileWithNestedIfTest(4) - stdio.printf("\n=== While With Match Case Test (value=2) ===\n") - logic.WhileWithMatchCaseTest(2) - stdio.printf("\n=== While With Match Case Test (value=99) ===\n") - logic.WhileWithMatchCaseTest(99) - stdio.printf("\n=== While With Match Case NoBreak Test (value=3) ===\n") - logic.WhileWithMatchCaseNoBreakTest(3) - stdio.printf("\n=== Complex For While Match Test (outer=3, inner=3) ===\n") - logic.ComplexForWhileMatchTest(3, 3) - stdio.printf("\n=== For With Case And NoBreak Test (n=5) ===\n") - logic.ForWithCaseAndNoBreakTest(5) - stdio.printf("\n=== While With Break Condition Test (limit=6) ===\n") - logic.WhileWithBreakConditionTest(6) - stdio.printf("\n=== Nested While With Multiple BreakPoints (depth=3, width=4) ===\n") - logic.NestedWhileWithMultipleBreakPoints(3, 4) - stdio.printf("\n=== For With Match Case In Loop Test (iterations=9) ===\n") - logic.ForWithMatchCaseInLoopTest(9) - stdio.printf("\n=== Complex Logic With Elif Chains (a=3, b=5, c=7) ===\n") - logic.ComplexLogicWithElifChains(3, 5, 7) - stdio.printf("\n=== For Range With Step And Condition (n=12, step=2) ===\n") - logic.ForRangeWithStepAndCondition(12, 2) - stdio.printf("\n=== Match Case With Guard Conditions (value=1) ===\n") - logic.MatchCaseWithGuardConditions(1) - stdio.printf("\n=== While With Multiple Match Cases (iterations=12) ===\n") - logic.WhileWithMultipleMatchCases(12) - stdio.printf("\n=== For While Mix With Break And Continue (n=5) ===\n") - logic.ForWhileMixWithBreakAndContinue(5) - stdio.printf("\n=== Complex Case Matching With Ranges (start=0, end=35) ===\n") - logic.ComplexCaseMatchingWithRanges(0, 35) - stdio.printf("\n=== While With Elif In Elif Chain (limit=7) ===\n") - logic.WhileWithElifInElifChain(7) - stdio.printf("\n=== For With Case NoBreak Nested (inner_limit=4) ===\n") - logic.ForWithCaseNoBreakNested(4) - stdio.printf("\n============== CLASS TESTS ==============\n") - class_test.TestBasicDataClass() - class_test.TestPoint3DClass() - class_test.TestStudentClass() - class_test.TestCounterClass() - class_test.TestStackAllocation() - class_test.TestHeapAllocation() - class_test.TestHeapObjectWithInit() - class_test.TestMultipleStackObjects() - class_test.TestImplicitInitCall() - class_test.TestClassWithBitFields() - stdio.printf("\n============== ARRAY TESTS ==============\n") - class_test.TestIntArray() - class_test.TestFloatArray() - class_test.TestCharArray() - class_test.TestNestedArray() - class_test.TestArrayWithStruct() - class_test.TestArrayPointer() - class_test.TestDynamicString() - stdio.printf("\n============== All Tests Completed ==============\n") - return 0 \ No newline at end of file +def main() -> t.CInt | t.CExport: + w32.win32console.SetConsoleCP(65001) + w32.win32console.SetConsoleOutputCP(65001) + + testcheck.begin("TestProject2: 综合库测试") + + testcheck.section("zlib runtime version") + print(zp.runtime_version()) + testcheck.ok("zlib runtime version printed") + + 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") + + testcheck.info("END") + return testcheck.end() diff --git a/Test/TestProject2/App/zc/class_test.py b/Test/TestProject2/App/zc/class_test.py index a0eb503..4594f8b 100644 --- a/Test/TestProject2/App/zc/class_test.py +++ b/Test/TestProject2/App/zc/class_test.py @@ -155,7 +155,7 @@ def TestClassWithBitFields(): def TestIntArray(): stdio.printf("=== Test Int Array ===\n") - arr: list[t.CInt, 5] = list[t.CInt, 5]() + arr: t.CArray[t.CInt, 5] = t.CArray[t.CInt, 5]() i: t.CInt = 0 while i < 5: arr[i] = i * 10 @@ -168,7 +168,7 @@ def TestIntArray(): def TestFloatArray(): stdio.printf("=== Test Float Array ===\n") - farr: list[t.CFloat, 4] = list[t.CFloat, 4]() + farr: t.CArray[t.CFloat, 4] = t.CArray[t.CFloat, 4]() farr[0] = 1.5 farr[1] = 2.5 farr[2] = 3.5 @@ -181,7 +181,7 @@ def TestFloatArray(): def TestCharArray(): stdio.printf("=== Test Char Array (String) ===\n") - str_arr: list[t.CChar, 32] = list[t.CChar, 32]() + str_arr: t.CArray[t.CChar, 32] = t.CArray[t.CChar, 32]() str_arr[0] = 'H' str_arr[1] = 'e' str_arr[2] = 'l' @@ -193,8 +193,8 @@ def TestCharArray(): def TestNestedArray(): stdio.printf("=== Test Nested Array (Array of Arrays) ===\n") - row0: list[t.CInt, 3] = list[t.CInt, 3]() - row1: list[t.CInt, 3] = list[t.CInt, 3]() + 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 @@ -215,7 +215,7 @@ def TestNestedArray(): def TestArrayWithStruct(): stdio.printf("=== Test Array with Struct ===\n") - points: list[SimpleData, 3] = list[SimpleData, 3]() + points: t.CArray[SimpleData, 3] = t.CArray[SimpleData, 3]() i: t.CInt = 0 while i < 3: points[i].x = i * 10 @@ -229,7 +229,7 @@ def TestArrayWithStruct(): def TestArrayPointer(): stdio.printf("=== Test Array Pointer ===\n") - data: list[t.CInt, 8] = list[t.CInt, 8]() + data: t.CArray[t.CInt, 8] = t.CArray[t.CInt, 8]() data[0] = 100 data[1] = 200 data[2] = 300 diff --git a/Test/TestProject2/output/067c78e9f121dce3.deps.json b/Test/TestProject2/output/067c78e9f121dce3.deps.json new file mode 100644 index 0000000..15a5529 --- /dev/null +++ b/Test/TestProject2/output/067c78e9f121dce3.deps.json @@ -0,0 +1 @@ +{"mpool": "0991af0d22263577", "binascii": "257e074b935c33b4", "stdint": "49bd8cba55979f76", "main": "541a1ed9b8be53c8", "zlib.zinflate": "59d33b6ab0c70953", "zinflate": "59d33b6ab0c70953", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "hashlib.__sha512": "6ff26590374ae6fc", "__sha512": "6ff26590374ae6fc", "zlib.zhuff": "73c1586b83e9b5c2", "zhuff": "73c1586b83e9b5c2", "stdio": "73edbcf76e32d00b", "hashlib.__sha1": "73fcdc4dd1618580", "__sha1": "73fcdc4dd1618580", "zlib.zchecksum": "8ebed83a7817fa0c", "zchecksum": "8ebed83a7817fa0c", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "zlib.pyzlib": "c39cbbae4b6e264f", "pyzlib": "c39cbbae4b6e264f", "hashlib.__sha256": "c9d54a4158f7f5a8", "__sha256": "c9d54a4158f7f5a8", "viperio": "c9f4be41ca1cc2b4", "hashlib.__md5": "cc436a125bbaf28c", "__md5": "cc436a125bbaf28c", "zlib.zdef": "cd520d14822f3f19", "zdef": "cd520d14822f3f19", "zc.config": "cfc83b830141b00e", "config": "cfc83b830141b00e", "zlib.zdeflate": "f80740e7bcee16ae", "zdeflate": "f80740e7bcee16ae", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3"} \ No newline at end of file diff --git a/Test/TestProject2/output/0991af0d22263577.deps.json b/Test/TestProject2/output/0991af0d22263577.deps.json new file mode 100644 index 0000000..441e13e --- /dev/null +++ b/Test/TestProject2/output/0991af0d22263577.deps.json @@ -0,0 +1 @@ +{"mpool": "0991af0d22263577", "binascii": "257e074b935c33b4", "stdint": "49bd8cba55979f76", "main": "541a1ed9b8be53c8", "zlib.zinflate": "59d33b6ab0c70953", "zinflate": "59d33b6ab0c70953", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "hashlib.__sha512": "6ff26590374ae6fc", "__sha512": "6ff26590374ae6fc", "zlib.zhuff": "73c1586b83e9b5c2", "zhuff": "73c1586b83e9b5c2", "stdio": "73edbcf76e32d00b", "hashlib.__sha1": "73fcdc4dd1618580", "__sha1": "73fcdc4dd1618580", "zlib.zchecksum": "8ebed83a7817fa0c", "zchecksum": "8ebed83a7817fa0c", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "zlib.pyzlib": "c39cbbae4b6e264f", "pyzlib": "c39cbbae4b6e264f", "hashlib.__sha256": "c9d54a4158f7f5a8", "__sha256": "c9d54a4158f7f5a8", "viperio": "c9f4be41ca1cc2b4", "hashlib.__md5": "cc436a125bbaf28c", "__md5": "cc436a125bbaf28c", "zlib.zdef": "cd520d14822f3f19", "zdef": "cd520d14822f3f19", "zc.config": "cfc83b830141b00e", "config": "cfc83b830141b00e", "zlib.zdeflate": "f80740e7bcee16ae", "zdeflate": "f80740e7bcee16ae"} \ No newline at end of file diff --git a/Test/TestProject2/output/09ba6d4617920d26.deps.json b/Test/TestProject2/output/09ba6d4617920d26.deps.json deleted file mode 100644 index d56083f..0000000 --- a/Test/TestProject2/output/09ba6d4617920d26.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"stdint": "56cdd754a8a09347", "stdio": "73edbcf76e32d00b", "zc.test": "75583f20a922ab2e", "test": "75583f20a922ab2e", "zc.class_test": "a7dab00d979c009c", "class_test": "a7dab00d979c009c", "zc.config": "cfc83b830141b00e", "config": "cfc83b830141b00e", "zc.logic_test": "faec3233d98371da", "logic_test": "faec3233d98371da"} \ No newline at end of file diff --git a/Test/TestProject2/output/257e074b935c33b4.deps.json b/Test/TestProject2/output/257e074b935c33b4.deps.json new file mode 100644 index 0000000..441e13e --- /dev/null +++ b/Test/TestProject2/output/257e074b935c33b4.deps.json @@ -0,0 +1 @@ +{"mpool": "0991af0d22263577", "binascii": "257e074b935c33b4", "stdint": "49bd8cba55979f76", "main": "541a1ed9b8be53c8", "zlib.zinflate": "59d33b6ab0c70953", "zinflate": "59d33b6ab0c70953", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "hashlib.__sha512": "6ff26590374ae6fc", "__sha512": "6ff26590374ae6fc", "zlib.zhuff": "73c1586b83e9b5c2", "zhuff": "73c1586b83e9b5c2", "stdio": "73edbcf76e32d00b", "hashlib.__sha1": "73fcdc4dd1618580", "__sha1": "73fcdc4dd1618580", "zlib.zchecksum": "8ebed83a7817fa0c", "zchecksum": "8ebed83a7817fa0c", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "zlib.pyzlib": "c39cbbae4b6e264f", "pyzlib": "c39cbbae4b6e264f", "hashlib.__sha256": "c9d54a4158f7f5a8", "__sha256": "c9d54a4158f7f5a8", "viperio": "c9f4be41ca1cc2b4", "hashlib.__md5": "cc436a125bbaf28c", "__md5": "cc436a125bbaf28c", "zlib.zdef": "cd520d14822f3f19", "zdef": "cd520d14822f3f19", "zc.config": "cfc83b830141b00e", "config": "cfc83b830141b00e", "zlib.zdeflate": "f80740e7bcee16ae", "zdeflate": "f80740e7bcee16ae"} \ No newline at end of file diff --git a/Test/TestProject2/output/29813d57621099a9.deps.json b/Test/TestProject2/output/29813d57621099a9.deps.json new file mode 100644 index 0000000..7afb948 --- /dev/null +++ b/Test/TestProject2/output/29813d57621099a9.deps.json @@ -0,0 +1 @@ +{"mpool": "0991af0d22263577", "binascii": "257e074b935c33b4", "stdint": "49bd8cba55979f76", "main": "541a1ed9b8be53c8", "zlib.zinflate": "59d33b6ab0c70953", "zinflate": "59d33b6ab0c70953", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "hashlib.__sha512": "6ff26590374ae6fc", "__sha512": "6ff26590374ae6fc", "zlib.zhuff": "73c1586b83e9b5c2", "zhuff": "73c1586b83e9b5c2", "stdio": "73edbcf76e32d00b", "hashlib.__sha1": "73fcdc4dd1618580", "__sha1": "73fcdc4dd1618580", "zlib.zchecksum": "8ebed83a7817fa0c", "zchecksum": "8ebed83a7817fa0c", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "zlib.pyzlib": "c39cbbae4b6e264f", "pyzlib": "c39cbbae4b6e264f", "hashlib.__sha256": "c9d54a4158f7f5a8", "__sha256": "c9d54a4158f7f5a8", "viperio": "c9f4be41ca1cc2b4", "hashlib.__md5": "cc436a125bbaf28c", "__md5": "cc436a125bbaf28c", "zlib.zdef": "cd520d14822f3f19", "zdef": "cd520d14822f3f19", "zc.config": "cfc83b830141b00e", "config": "cfc83b830141b00e", "zlib.zdeflate": "f80740e7bcee16ae", "zdeflate": "f80740e7bcee16ae", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file diff --git a/Test/TestProject2/output/541a1ed9b8be53c8.deps.json b/Test/TestProject2/output/541a1ed9b8be53c8.deps.json new file mode 100644 index 0000000..45f585b --- /dev/null +++ b/Test/TestProject2/output/541a1ed9b8be53c8.deps.json @@ -0,0 +1 @@ +{"mpool": "0991af0d22263577", "binascii": "257e074b935c33b4", "stdint": "49bd8cba55979f76", "zlib.zinflate": "59d33b6ab0c70953", "zinflate": "59d33b6ab0c70953", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "hashlib.__sha512": "6ff26590374ae6fc", "__sha512": "6ff26590374ae6fc", "zlib.zhuff": "73c1586b83e9b5c2", "zhuff": "73c1586b83e9b5c2", "stdio": "73edbcf76e32d00b", "hashlib.__sha1": "73fcdc4dd1618580", "__sha1": "73fcdc4dd1618580", "zlib.zchecksum": "8ebed83a7817fa0c", "zchecksum": "8ebed83a7817fa0c", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "zlib.pyzlib": "c39cbbae4b6e264f", "pyzlib": "c39cbbae4b6e264f", "hashlib.__sha256": "c9d54a4158f7f5a8", "__sha256": "c9d54a4158f7f5a8", "viperio": "c9f4be41ca1cc2b4", "hashlib.__md5": "cc436a125bbaf28c", "__md5": "cc436a125bbaf28c", "zlib.zdef": "cd520d14822f3f19", "zdef": "cd520d14822f3f19", "zc.config": "cfc83b830141b00e", "config": "cfc83b830141b00e", "zlib.zdeflate": "f80740e7bcee16ae", "zdeflate": "f80740e7bcee16ae"} \ No newline at end of file diff --git a/Test/TestProject2/output/5a6a2137958c28c5.deps.json b/Test/TestProject2/output/5a6a2137958c28c5.deps.json new file mode 100644 index 0000000..441e13e --- /dev/null +++ b/Test/TestProject2/output/5a6a2137958c28c5.deps.json @@ -0,0 +1 @@ +{"mpool": "0991af0d22263577", "binascii": "257e074b935c33b4", "stdint": "49bd8cba55979f76", "main": "541a1ed9b8be53c8", "zlib.zinflate": "59d33b6ab0c70953", "zinflate": "59d33b6ab0c70953", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "hashlib.__sha512": "6ff26590374ae6fc", "__sha512": "6ff26590374ae6fc", "zlib.zhuff": "73c1586b83e9b5c2", "zhuff": "73c1586b83e9b5c2", "stdio": "73edbcf76e32d00b", "hashlib.__sha1": "73fcdc4dd1618580", "__sha1": "73fcdc4dd1618580", "zlib.zchecksum": "8ebed83a7817fa0c", "zchecksum": "8ebed83a7817fa0c", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "zlib.pyzlib": "c39cbbae4b6e264f", "pyzlib": "c39cbbae4b6e264f", "hashlib.__sha256": "c9d54a4158f7f5a8", "__sha256": "c9d54a4158f7f5a8", "viperio": "c9f4be41ca1cc2b4", "hashlib.__md5": "cc436a125bbaf28c", "__md5": "cc436a125bbaf28c", "zlib.zdef": "cd520d14822f3f19", "zdef": "cd520d14822f3f19", "zc.config": "cfc83b830141b00e", "config": "cfc83b830141b00e", "zlib.zdeflate": "f80740e7bcee16ae", "zdeflate": "f80740e7bcee16ae"} \ No newline at end of file diff --git a/Test/TestProject2/output/6ff26590374ae6fc.deps.json b/Test/TestProject2/output/6ff26590374ae6fc.deps.json new file mode 100644 index 0000000..441e13e --- /dev/null +++ b/Test/TestProject2/output/6ff26590374ae6fc.deps.json @@ -0,0 +1 @@ +{"mpool": "0991af0d22263577", "binascii": "257e074b935c33b4", "stdint": "49bd8cba55979f76", "main": "541a1ed9b8be53c8", "zlib.zinflate": "59d33b6ab0c70953", "zinflate": "59d33b6ab0c70953", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "hashlib.__sha512": "6ff26590374ae6fc", "__sha512": "6ff26590374ae6fc", "zlib.zhuff": "73c1586b83e9b5c2", "zhuff": "73c1586b83e9b5c2", "stdio": "73edbcf76e32d00b", "hashlib.__sha1": "73fcdc4dd1618580", "__sha1": "73fcdc4dd1618580", "zlib.zchecksum": "8ebed83a7817fa0c", "zchecksum": "8ebed83a7817fa0c", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "zlib.pyzlib": "c39cbbae4b6e264f", "pyzlib": "c39cbbae4b6e264f", "hashlib.__sha256": "c9d54a4158f7f5a8", "__sha256": "c9d54a4158f7f5a8", "viperio": "c9f4be41ca1cc2b4", "hashlib.__md5": "cc436a125bbaf28c", "__md5": "cc436a125bbaf28c", "zlib.zdef": "cd520d14822f3f19", "zdef": "cd520d14822f3f19", "zc.config": "cfc83b830141b00e", "config": "cfc83b830141b00e", "zlib.zdeflate": "f80740e7bcee16ae", "zdeflate": "f80740e7bcee16ae"} \ No newline at end of file diff --git a/Test/TestProject2/output/72e2d5ccb7cedcf1.deps.json b/Test/TestProject2/output/72e2d5ccb7cedcf1.deps.json new file mode 100644 index 0000000..837cc96 --- /dev/null +++ b/Test/TestProject2/output/72e2d5ccb7cedcf1.deps.json @@ -0,0 +1 @@ +{"mpool": "0991af0d22263577", "binascii": "257e074b935c33b4", "stdint": "49bd8cba55979f76", "main": "541a1ed9b8be53c8", "zlib.zinflate": "59d33b6ab0c70953", "zinflate": "59d33b6ab0c70953", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "hashlib.__sha512": "6ff26590374ae6fc", "__sha512": "6ff26590374ae6fc", "zlib.zhuff": "73c1586b83e9b5c2", "zhuff": "73c1586b83e9b5c2", "stdio": "73edbcf76e32d00b", "hashlib.__sha1": "73fcdc4dd1618580", "__sha1": "73fcdc4dd1618580", "zlib.zchecksum": "8ebed83a7817fa0c", "zchecksum": "8ebed83a7817fa0c", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "zlib.pyzlib": "c39cbbae4b6e264f", "pyzlib": "c39cbbae4b6e264f", "hashlib.__sha256": "c9d54a4158f7f5a8", "__sha256": "c9d54a4158f7f5a8", "viperio": "c9f4be41ca1cc2b4", "hashlib.__md5": "cc436a125bbaf28c", "__md5": "cc436a125bbaf28c", "zlib.zdef": "cd520d14822f3f19", "zdef": "cd520d14822f3f19", "zc.config": "cfc83b830141b00e", "config": "cfc83b830141b00e", "zlib.zdeflate": "f80740e7bcee16ae", "zdeflate": "f80740e7bcee16ae", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1"} \ No newline at end of file diff --git a/Test/TestProject2/output/73fcdc4dd1618580.deps.json b/Test/TestProject2/output/73fcdc4dd1618580.deps.json new file mode 100644 index 0000000..441e13e --- /dev/null +++ b/Test/TestProject2/output/73fcdc4dd1618580.deps.json @@ -0,0 +1 @@ +{"mpool": "0991af0d22263577", "binascii": "257e074b935c33b4", "stdint": "49bd8cba55979f76", "main": "541a1ed9b8be53c8", "zlib.zinflate": "59d33b6ab0c70953", "zinflate": "59d33b6ab0c70953", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "hashlib.__sha512": "6ff26590374ae6fc", "__sha512": "6ff26590374ae6fc", "zlib.zhuff": "73c1586b83e9b5c2", "zhuff": "73c1586b83e9b5c2", "stdio": "73edbcf76e32d00b", "hashlib.__sha1": "73fcdc4dd1618580", "__sha1": "73fcdc4dd1618580", "zlib.zchecksum": "8ebed83a7817fa0c", "zchecksum": "8ebed83a7817fa0c", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "zlib.pyzlib": "c39cbbae4b6e264f", "pyzlib": "c39cbbae4b6e264f", "hashlib.__sha256": "c9d54a4158f7f5a8", "__sha256": "c9d54a4158f7f5a8", "viperio": "c9f4be41ca1cc2b4", "hashlib.__md5": "cc436a125bbaf28c", "__md5": "cc436a125bbaf28c", "zlib.zdef": "cd520d14822f3f19", "zdef": "cd520d14822f3f19", "zc.config": "cfc83b830141b00e", "config": "cfc83b830141b00e", "zlib.zdeflate": "f80740e7bcee16ae", "zdeflate": "f80740e7bcee16ae"} \ No newline at end of file diff --git a/Test/TestProject2/output/75583f20a922ab2e.deps.json b/Test/TestProject2/output/75583f20a922ab2e.deps.json deleted file mode 100644 index bee91bf..0000000 --- a/Test/TestProject2/output/75583f20a922ab2e.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"main": "09ba6d4617920d26", "stdint": "56cdd754a8a09347", "stdio": "73edbcf76e32d00b", "zc.class_test": "a7dab00d979c009c", "class_test": "a7dab00d979c009c", "zc.config": "cfc83b830141b00e", "config": "cfc83b830141b00e", "zc.logic_test": "faec3233d98371da", "logic_test": "faec3233d98371da"} \ No newline at end of file diff --git a/Test/TestProject2/output/9dbecd0942a39782.deps.json b/Test/TestProject2/output/9dbecd0942a39782.deps.json new file mode 100644 index 0000000..441e13e --- /dev/null +++ b/Test/TestProject2/output/9dbecd0942a39782.deps.json @@ -0,0 +1 @@ +{"mpool": "0991af0d22263577", "binascii": "257e074b935c33b4", "stdint": "49bd8cba55979f76", "main": "541a1ed9b8be53c8", "zlib.zinflate": "59d33b6ab0c70953", "zinflate": "59d33b6ab0c70953", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "hashlib.__sha512": "6ff26590374ae6fc", "__sha512": "6ff26590374ae6fc", "zlib.zhuff": "73c1586b83e9b5c2", "zhuff": "73c1586b83e9b5c2", "stdio": "73edbcf76e32d00b", "hashlib.__sha1": "73fcdc4dd1618580", "__sha1": "73fcdc4dd1618580", "zlib.zchecksum": "8ebed83a7817fa0c", "zchecksum": "8ebed83a7817fa0c", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "zlib.pyzlib": "c39cbbae4b6e264f", "pyzlib": "c39cbbae4b6e264f", "hashlib.__sha256": "c9d54a4158f7f5a8", "__sha256": "c9d54a4158f7f5a8", "viperio": "c9f4be41ca1cc2b4", "hashlib.__md5": "cc436a125bbaf28c", "__md5": "cc436a125bbaf28c", "zlib.zdef": "cd520d14822f3f19", "zdef": "cd520d14822f3f19", "zc.config": "cfc83b830141b00e", "config": "cfc83b830141b00e", "zlib.zdeflate": "f80740e7bcee16ae", "zdeflate": "f80740e7bcee16ae"} \ No newline at end of file diff --git a/Test/TestProject2/output/a7dab00d979c009c.deps.json b/Test/TestProject2/output/a7dab00d979c009c.deps.json deleted file mode 100644 index ed6405d..0000000 --- a/Test/TestProject2/output/a7dab00d979c009c.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"main": "09ba6d4617920d26", "stdint": "56cdd754a8a09347", "stdio": "73edbcf76e32d00b", "zc.test": "75583f20a922ab2e", "test": "75583f20a922ab2e", "zc.config": "cfc83b830141b00e", "config": "cfc83b830141b00e", "zc.logic_test": "faec3233d98371da", "logic_test": "faec3233d98371da"} \ No newline at end of file diff --git a/Test/TestProject2/output/abf9ce3160c9279e.deps.json b/Test/TestProject2/output/abf9ce3160c9279e.deps.json new file mode 100644 index 0000000..a278c28 --- /dev/null +++ b/Test/TestProject2/output/abf9ce3160c9279e.deps.json @@ -0,0 +1 @@ +{"mpool": "0991af0d22263577", "binascii": "257e074b935c33b4", "stdint": "49bd8cba55979f76", "main": "541a1ed9b8be53c8", "zlib.zinflate": "59d33b6ab0c70953", "zinflate": "59d33b6ab0c70953", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "hashlib.__sha512": "6ff26590374ae6fc", "__sha512": "6ff26590374ae6fc", "zlib.zhuff": "73c1586b83e9b5c2", "zhuff": "73c1586b83e9b5c2", "stdio": "73edbcf76e32d00b", "hashlib.__sha1": "73fcdc4dd1618580", "__sha1": "73fcdc4dd1618580", "zlib.zchecksum": "8ebed83a7817fa0c", "zchecksum": "8ebed83a7817fa0c", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "zlib.pyzlib": "c39cbbae4b6e264f", "pyzlib": "c39cbbae4b6e264f", "hashlib.__sha256": "c9d54a4158f7f5a8", "__sha256": "c9d54a4158f7f5a8", "viperio": "c9f4be41ca1cc2b4", "hashlib.__md5": "cc436a125bbaf28c", "__md5": "cc436a125bbaf28c", "zlib.zdef": "cd520d14822f3f19", "zdef": "cd520d14822f3f19", "zc.config": "cfc83b830141b00e", "config": "cfc83b830141b00e", "zlib.zdeflate": "f80740e7bcee16ae", "zdeflate": "f80740e7bcee16ae", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e"} \ No newline at end of file diff --git a/Test/TestProject2/output/b5f1dc665c52a1bd.deps.json b/Test/TestProject2/output/b5f1dc665c52a1bd.deps.json new file mode 100644 index 0000000..441e13e --- /dev/null +++ b/Test/TestProject2/output/b5f1dc665c52a1bd.deps.json @@ -0,0 +1 @@ +{"mpool": "0991af0d22263577", "binascii": "257e074b935c33b4", "stdint": "49bd8cba55979f76", "main": "541a1ed9b8be53c8", "zlib.zinflate": "59d33b6ab0c70953", "zinflate": "59d33b6ab0c70953", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "hashlib.__sha512": "6ff26590374ae6fc", "__sha512": "6ff26590374ae6fc", "zlib.zhuff": "73c1586b83e9b5c2", "zhuff": "73c1586b83e9b5c2", "stdio": "73edbcf76e32d00b", "hashlib.__sha1": "73fcdc4dd1618580", "__sha1": "73fcdc4dd1618580", "zlib.zchecksum": "8ebed83a7817fa0c", "zchecksum": "8ebed83a7817fa0c", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "zlib.pyzlib": "c39cbbae4b6e264f", "pyzlib": "c39cbbae4b6e264f", "hashlib.__sha256": "c9d54a4158f7f5a8", "__sha256": "c9d54a4158f7f5a8", "viperio": "c9f4be41ca1cc2b4", "hashlib.__md5": "cc436a125bbaf28c", "__md5": "cc436a125bbaf28c", "zlib.zdef": "cd520d14822f3f19", "zdef": "cd520d14822f3f19", "zc.config": "cfc83b830141b00e", "config": "cfc83b830141b00e", "zlib.zdeflate": "f80740e7bcee16ae", "zdeflate": "f80740e7bcee16ae"} \ No newline at end of file diff --git a/Test/TestProject2/output/bbdf3bbd4c3bc28c.deps.json b/Test/TestProject2/output/bbdf3bbd4c3bc28c.deps.json new file mode 100644 index 0000000..441e13e --- /dev/null +++ b/Test/TestProject2/output/bbdf3bbd4c3bc28c.deps.json @@ -0,0 +1 @@ +{"mpool": "0991af0d22263577", "binascii": "257e074b935c33b4", "stdint": "49bd8cba55979f76", "main": "541a1ed9b8be53c8", "zlib.zinflate": "59d33b6ab0c70953", "zinflate": "59d33b6ab0c70953", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "hashlib.__sha512": "6ff26590374ae6fc", "__sha512": "6ff26590374ae6fc", "zlib.zhuff": "73c1586b83e9b5c2", "zhuff": "73c1586b83e9b5c2", "stdio": "73edbcf76e32d00b", "hashlib.__sha1": "73fcdc4dd1618580", "__sha1": "73fcdc4dd1618580", "zlib.zchecksum": "8ebed83a7817fa0c", "zchecksum": "8ebed83a7817fa0c", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "zlib.pyzlib": "c39cbbae4b6e264f", "pyzlib": "c39cbbae4b6e264f", "hashlib.__sha256": "c9d54a4158f7f5a8", "__sha256": "c9d54a4158f7f5a8", "viperio": "c9f4be41ca1cc2b4", "hashlib.__md5": "cc436a125bbaf28c", "__md5": "cc436a125bbaf28c", "zlib.zdef": "cd520d14822f3f19", "zdef": "cd520d14822f3f19", "zc.config": "cfc83b830141b00e", "config": "cfc83b830141b00e", "zlib.zdeflate": "f80740e7bcee16ae", "zdeflate": "f80740e7bcee16ae"} \ No newline at end of file diff --git a/Test/TestProject2/output/c9d54a4158f7f5a8.deps.json b/Test/TestProject2/output/c9d54a4158f7f5a8.deps.json new file mode 100644 index 0000000..441e13e --- /dev/null +++ b/Test/TestProject2/output/c9d54a4158f7f5a8.deps.json @@ -0,0 +1 @@ +{"mpool": "0991af0d22263577", "binascii": "257e074b935c33b4", "stdint": "49bd8cba55979f76", "main": "541a1ed9b8be53c8", "zlib.zinflate": "59d33b6ab0c70953", "zinflate": "59d33b6ab0c70953", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "hashlib.__sha512": "6ff26590374ae6fc", "__sha512": "6ff26590374ae6fc", "zlib.zhuff": "73c1586b83e9b5c2", "zhuff": "73c1586b83e9b5c2", "stdio": "73edbcf76e32d00b", "hashlib.__sha1": "73fcdc4dd1618580", "__sha1": "73fcdc4dd1618580", "zlib.zchecksum": "8ebed83a7817fa0c", "zchecksum": "8ebed83a7817fa0c", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "zlib.pyzlib": "c39cbbae4b6e264f", "pyzlib": "c39cbbae4b6e264f", "hashlib.__sha256": "c9d54a4158f7f5a8", "__sha256": "c9d54a4158f7f5a8", "viperio": "c9f4be41ca1cc2b4", "hashlib.__md5": "cc436a125bbaf28c", "__md5": "cc436a125bbaf28c", "zlib.zdef": "cd520d14822f3f19", "zdef": "cd520d14822f3f19", "zc.config": "cfc83b830141b00e", "config": "cfc83b830141b00e", "zlib.zdeflate": "f80740e7bcee16ae", "zdeflate": "f80740e7bcee16ae"} \ No newline at end of file diff --git a/Test/TestProject2/output/c9f4be41ca1cc2b4.deps.json b/Test/TestProject2/output/c9f4be41ca1cc2b4.deps.json new file mode 100644 index 0000000..441e13e --- /dev/null +++ b/Test/TestProject2/output/c9f4be41ca1cc2b4.deps.json @@ -0,0 +1 @@ +{"mpool": "0991af0d22263577", "binascii": "257e074b935c33b4", "stdint": "49bd8cba55979f76", "main": "541a1ed9b8be53c8", "zlib.zinflate": "59d33b6ab0c70953", "zinflate": "59d33b6ab0c70953", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "hashlib.__sha512": "6ff26590374ae6fc", "__sha512": "6ff26590374ae6fc", "zlib.zhuff": "73c1586b83e9b5c2", "zhuff": "73c1586b83e9b5c2", "stdio": "73edbcf76e32d00b", "hashlib.__sha1": "73fcdc4dd1618580", "__sha1": "73fcdc4dd1618580", "zlib.zchecksum": "8ebed83a7817fa0c", "zchecksum": "8ebed83a7817fa0c", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "zlib.pyzlib": "c39cbbae4b6e264f", "pyzlib": "c39cbbae4b6e264f", "hashlib.__sha256": "c9d54a4158f7f5a8", "__sha256": "c9d54a4158f7f5a8", "viperio": "c9f4be41ca1cc2b4", "hashlib.__md5": "cc436a125bbaf28c", "__md5": "cc436a125bbaf28c", "zlib.zdef": "cd520d14822f3f19", "zdef": "cd520d14822f3f19", "zc.config": "cfc83b830141b00e", "config": "cfc83b830141b00e", "zlib.zdeflate": "f80740e7bcee16ae", "zdeflate": "f80740e7bcee16ae"} \ No newline at end of file diff --git a/Test/TestProject2/output/cc436a125bbaf28c.deps.json b/Test/TestProject2/output/cc436a125bbaf28c.deps.json new file mode 100644 index 0000000..441e13e --- /dev/null +++ b/Test/TestProject2/output/cc436a125bbaf28c.deps.json @@ -0,0 +1 @@ +{"mpool": "0991af0d22263577", "binascii": "257e074b935c33b4", "stdint": "49bd8cba55979f76", "main": "541a1ed9b8be53c8", "zlib.zinflate": "59d33b6ab0c70953", "zinflate": "59d33b6ab0c70953", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "hashlib.__sha512": "6ff26590374ae6fc", "__sha512": "6ff26590374ae6fc", "zlib.zhuff": "73c1586b83e9b5c2", "zhuff": "73c1586b83e9b5c2", "stdio": "73edbcf76e32d00b", "hashlib.__sha1": "73fcdc4dd1618580", "__sha1": "73fcdc4dd1618580", "zlib.zchecksum": "8ebed83a7817fa0c", "zchecksum": "8ebed83a7817fa0c", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "zlib.pyzlib": "c39cbbae4b6e264f", "pyzlib": "c39cbbae4b6e264f", "hashlib.__sha256": "c9d54a4158f7f5a8", "__sha256": "c9d54a4158f7f5a8", "viperio": "c9f4be41ca1cc2b4", "hashlib.__md5": "cc436a125bbaf28c", "__md5": "cc436a125bbaf28c", "zlib.zdef": "cd520d14822f3f19", "zdef": "cd520d14822f3f19", "zc.config": "cfc83b830141b00e", "config": "cfc83b830141b00e", "zlib.zdeflate": "f80740e7bcee16ae", "zdeflate": "f80740e7bcee16ae"} \ No newline at end of file diff --git a/Test/TestProject2/output/cfc83b830141b00e.deps.json b/Test/TestProject2/output/cfc83b830141b00e.deps.json index 3188929..0d12fe5 100644 --- a/Test/TestProject2/output/cfc83b830141b00e.deps.json +++ b/Test/TestProject2/output/cfc83b830141b00e.deps.json @@ -1 +1 @@ -{"main": "09ba6d4617920d26", "stdint": "56cdd754a8a09347", "stdio": "73edbcf76e32d00b", "zc.test": "75583f20a922ab2e", "test": "75583f20a922ab2e", "zc.class_test": "a7dab00d979c009c", "class_test": "a7dab00d979c009c", "zc.logic_test": "faec3233d98371da", "logic_test": "faec3233d98371da"} \ No newline at end of file +{"mpool": "0991af0d22263577", "binascii": "257e074b935c33b4", "stdint": "49bd8cba55979f76", "main": "541a1ed9b8be53c8", "zlib.zinflate": "59d33b6ab0c70953", "zinflate": "59d33b6ab0c70953", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "hashlib.__sha512": "6ff26590374ae6fc", "__sha512": "6ff26590374ae6fc", "zlib.zhuff": "73c1586b83e9b5c2", "zhuff": "73c1586b83e9b5c2", "stdio": "73edbcf76e32d00b", "hashlib.__sha1": "73fcdc4dd1618580", "__sha1": "73fcdc4dd1618580", "zlib.zchecksum": "8ebed83a7817fa0c", "zchecksum": "8ebed83a7817fa0c", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "zlib.pyzlib": "c39cbbae4b6e264f", "pyzlib": "c39cbbae4b6e264f", "hashlib.__sha256": "c9d54a4158f7f5a8", "__sha256": "c9d54a4158f7f5a8", "viperio": "c9f4be41ca1cc2b4", "hashlib.__md5": "cc436a125bbaf28c", "__md5": "cc436a125bbaf28c", "zlib.zdef": "cd520d14822f3f19", "zdef": "cd520d14822f3f19", "zlib.zdeflate": "f80740e7bcee16ae", "zdeflate": "f80740e7bcee16ae"} \ No newline at end of file diff --git a/Test/TestProject2/output/fa3691e66b426950.deps.json b/Test/TestProject2/output/fa3691e66b426950.deps.json new file mode 100644 index 0000000..a89b59b --- /dev/null +++ b/Test/TestProject2/output/fa3691e66b426950.deps.json @@ -0,0 +1 @@ +{"mpool": "0991af0d22263577", "binascii": "257e074b935c33b4", "stdint": "49bd8cba55979f76", "main": "541a1ed9b8be53c8", "zlib.zinflate": "59d33b6ab0c70953", "zinflate": "59d33b6ab0c70953", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "hashlib.__sha512": "6ff26590374ae6fc", "__sha512": "6ff26590374ae6fc", "zlib.zhuff": "73c1586b83e9b5c2", "zhuff": "73c1586b83e9b5c2", "stdio": "73edbcf76e32d00b", "hashlib.__sha1": "73fcdc4dd1618580", "__sha1": "73fcdc4dd1618580", "zlib.zchecksum": "8ebed83a7817fa0c", "zchecksum": "8ebed83a7817fa0c", "hashlib.__init__": "96837bcc64032444", "__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "zlib.pyzlib": "c39cbbae4b6e264f", "pyzlib": "c39cbbae4b6e264f", "hashlib.__sha256": "c9d54a4158f7f5a8", "__sha256": "c9d54a4158f7f5a8", "viperio": "c9f4be41ca1cc2b4", "hashlib.__md5": "cc436a125bbaf28c", "__md5": "cc436a125bbaf28c", "zlib.zdef": "cd520d14822f3f19", "zdef": "cd520d14822f3f19", "zc.config": "cfc83b830141b00e", "config": "cfc83b830141b00e", "zlib.zdeflate": "f80740e7bcee16ae", "zdeflate": "f80740e7bcee16ae", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file diff --git a/Test/TestProject2/output/faec3233d98371da.deps.json b/Test/TestProject2/output/faec3233d98371da.deps.json deleted file mode 100644 index bc966ed..0000000 --- a/Test/TestProject2/output/faec3233d98371da.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"main": "09ba6d4617920d26", "stdint": "56cdd754a8a09347", "stdio": "73edbcf76e32d00b", "zc.test": "75583f20a922ab2e", "test": "75583f20a922ab2e", "zc.class_test": "a7dab00d979c009c", "class_test": "a7dab00d979c009c", "zc.config": "cfc83b830141b00e", "config": "cfc83b830141b00e"} \ No newline at end of file diff --git a/Test/TestProject2/temp/067c78e9f121dce3.pyi b/Test/TestProject2/temp/067c78e9f121dce3.pyi new file mode 100644 index 0000000..f4f767c --- /dev/null +++ b/Test/TestProject2/temp/067c78e9f121dce3.pyi @@ -0,0 +1,136 @@ +""" +Auto-generated Python stub file from w32.win32process.py +Module: w32.win32process +""" + +import c + + +import t +from stdint import * +from w32.win32base import * + +PROCESS_TERMINATE: t.CDefine = 0x0001 +PROCESS_CREATE_THREAD: t.CDefine = 0x0002 +PROCESS_VM_OPERATION: t.CDefine = 0x0008 +PROCESS_VM_READ: t.CDefine = 0x0010 +PROCESS_VM_WRITE: t.CDefine = 0x0020 +PROCESS_QUERY_INFORMATION: t.CDefine = 0x0400 +PROCESS_ALL_ACCESS: t.CDefine = 0x001FFFFF +THREAD_TERMINATE: t.CDefine = 0x0001 +THREAD_SUSPEND_RESUME: t.CDefine = 0x0002 +THREAD_GET_CONTEXT: t.CDefine = 0x0008 +THREAD_SET_CONTEXT: t.CDefine = 0x0010 +THREAD_QUERY_INFORMATION: t.CDefine = 0x0040 +THREAD_ALL_ACCESS: t.CDefine = 0x001FFFFF +CREATE_SUSPENDED: t.CDefine = 0x00000004 +CREATE_NEW_CONSOLE: t.CDefine = 0x00000010 +CREATE_NEW_PROCESS_GROUP: t.CDefine = 0x00000200 +CREATE_NO_WINDOW: t.CDefine = 0x08000000 +DETACHED_PROCESS: t.CDefine = 0x00000008 +STARTF_USESHOWWINDOW: t.CDefine = 0x00000001 +STARTF_USESTDHANDLES: t.CDefine = 0x00000100 +SW_HIDE: t.CDefine = 0 +SW_SHOW: t.CDefine = 5 +SW_MINIMIZE: t.CDefine = 6 +NORMAL_PRIORITY_CLASS: t.CDefine = 0x00000020 +IDLE_PRIORITY_CLASS: t.CDefine = 0x00000040 +HIGH_PRIORITY_CLASS: t.CDefine = 0x00000080 +REALTIME_PRIORITY_CLASS: t.CDefine = 0x00000100 +BELOW_NORMAL_PRIORITY_CLASS: t.CDefine = 0x00004000 +ABOVE_NORMAL_PRIORITY_CLASS: t.CDefine = 0x00008000 +STILL_ACTIVE: t.CDefine = 259 + +class STARTUPINFOA: + cb: ULONG + lpReserved: CHARPTR + lpDesktop: CHARPTR + lpTitle: CHARPTR + dwX: ULONG + dwY: ULONG + dwXSize: ULONG + dwYSize: ULONG + dwXCountChars: ULONG + dwYCountChars: ULONG + dwFillAttribute: ULONG + dwFlags: ULONG + wShowWindow: WORD + cbReserved2: WORD + lpReserved2: VOIDPTR + hStdInput: HANDLE + hStdOutput: HANDLE + hStdError: HANDLE +class STARTUPINFOW: + cb: ULONG + lpReserved: WCHARPTR + lpDesktop: WCHARPTR + lpTitle: WCHARPTR + dwX: ULONG + dwY: ULONG + dwXSize: ULONG + dwYSize: ULONG + dwXCountChars: ULONG + dwYCountChars: ULONG + dwFillAttribute: ULONG + dwFlags: ULONG + wShowWindow: WORD + cbReserved2: WORD + lpReserved2: VOIDPTR + hStdInput: HANDLE + hStdOutput: HANDLE + hStdError: HANDLE +class PROCESS_INFORMATION: + hProcess: HANDLE + hThread: HANDLE + dwProcessId: ULONG + dwThreadId: ULONG + +def CreateProcessA(lpApplicationName: LPCSTR, lpCommandLine: CHARPTR, lpProcessAttributes: SECURITY_ATTRIBUTES | t.CPtr, lpThreadAttributes: SECURITY_ATTRIBUTES | t.CPtr, bInheritHandles: BOOL, dwCreationFlags: ULONG, lpEnvironment: VOIDPTR, lpCurrentDirectory: LPCSTR, lpStartupInfo: STARTUPINFOA | t.CPtr, lpProcessInformation: PROCESS_INFORMATION | t.CPtr) -> BOOL | t.State: pass + +def CreateProcessW(lpApplicationName: LPCWSTR, lpCommandLine: WCHARPTR, lpProcessAttributes: SECURITY_ATTRIBUTES | t.CPtr, lpThreadAttributes: SECURITY_ATTRIBUTES | t.CPtr, bInheritHandles: BOOL, dwCreationFlags: ULONG, lpEnvironment: VOIDPTR, lpCurrentDirectory: LPCWSTR, lpStartupInfo: STARTUPINFOW | t.CPtr, lpProcessInformation: PROCESS_INFORMATION | t.CPtr) -> BOOL | t.State: pass + +def TerminateProcess(hProcess: HANDLE, uExitCode: UINT) -> BOOL | t.State: pass + +def GetExitCodeProcess(hProcess: HANDLE, lpExitCode: ULONG | t.CPtr) -> BOOL | t.State: pass + +def GetExitCodeThread(hThread: HANDLE, lpExitCode: ULONG | t.CPtr) -> BOOL | t.State: pass + +def OpenProcess(dwDesiredAccess: ULONG, bInheritHandle: BOOL, dwProcessId: ULONG) -> HANDLE | t.State: pass + +def GetCurrentProcess() -> HANDLE | t.State: pass + +def GetCurrentProcessId() -> ULONG | t.State: pass + +def CreateThread(lpThreadAttributes: SECURITY_ATTRIBUTES | t.CPtr, dwStackSize: t.CSizeT, lpStartAddress: VOIDPTR, lpParameter: VOIDPTR, dwCreationFlags: ULONG, lpThreadId: ULONG | t.CPtr) -> HANDLE | t.State: pass + +def OpenThread(dwDesiredAccess: ULONG, bInheritHandle: BOOL, dwThreadId: ULONG) -> HANDLE | t.State: pass + +def SuspendThread(hThread: HANDLE) -> ULONG | t.State: pass + +def ResumeThread(hThread: HANDLE) -> ULONG | t.State: pass + +def TerminateThread(hThread: HANDLE, dwExitCode: ULONG) -> BOOL | t.State: pass + +def GetCurrentThread() -> HANDLE | t.State: pass + +def GetCurrentThreadId() -> ULONG | t.State: pass + +def GetThreadId(hThread: HANDLE) -> ULONG | t.State: pass + +def GetProcessId(hProcess: HANDLE) -> ULONG | t.State: pass + +def SetThreadPriority(hThread: HANDLE, nPriority: INT) -> BOOL | t.State: pass + +def GetThreadPriority(hThread: HANDLE) -> INT | t.State: pass + +def ExitProcess(uExitCode: UINT) -> VOID | t.State: pass + +def ExitThread(dwExitCode: ULONG) -> VOID | t.State: pass + +def TlsAlloc() -> ULONG | t.State: pass + +def TlsFree(dwTlsIndex: ULONG) -> BOOL | t.State: pass + +def TlsGetValue(dwTlsIndex: ULONG) -> VOIDPTR | t.State: pass + +def TlsSetValue(dwTlsIndex: ULONG, lpTlsValue: VOIDPTR) -> BOOL | t.State: pass diff --git a/Test/TestProject3/temp/68c4fe4b12c908e3.pyi b/Test/TestProject2/temp/0991af0d22263577.pyi similarity index 98% rename from Test/TestProject3/temp/68c4fe4b12c908e3.pyi rename to Test/TestProject2/temp/0991af0d22263577.pyi index fc2010b..f001c8a 100644 --- a/Test/TestProject3/temp/68c4fe4b12c908e3.pyi +++ b/Test/TestProject2/temp/0991af0d22263577.pyi @@ -11,7 +11,7 @@ import string MPOOL_ALIGN: t.CDefine = 8 MPOOL_TYPE_SLAB: t.CDefine = 0 -MPOOL_TYPE_BUMP: t.CDefine = 2 +MPOOL_TYPE_BUMP: t.CDefine = 1 def _align_up(val: t.CSizeT, align: t.CSizeT) -> t.CSizeT: pass diff --git a/Test/TestProject/temp/8f88a3374d5335cc.pyi b/Test/TestProject2/temp/257e074b935c33b4.pyi similarity index 69% rename from Test/TestProject/temp/8f88a3374d5335cc.pyi rename to Test/TestProject2/temp/257e074b935c33b4.pyi index 374b741..34d2feb 100644 --- a/Test/TestProject/temp/8f88a3374d5335cc.pyi +++ b/Test/TestProject2/temp/257e074b935c33b4.pyi @@ -6,15 +6,15 @@ Module: binascii import t, c -HEX_CHARS: t.CExtern | list[t.CChar, None] -HEX_VALS: t.CExtern | list[t.CInt, 256] -B64_CHARS: t.CExtern | list[t.CChar, None] -B64_VALS: t.CExtern | list[t.CInt, 256] -HQX_CHARS: t.CExtern | list[t.CChar, 64] -HQX_VALS: t.CExtern | list[t.CInt, 256] -UU_CHARS: t.CExtern | list[t.CChar, None] -CRC32_TABLE: t.CExtern | list[t.CUnsignedInt, 256] -CRC_HQX_TABLE: t.CExtern | list[t.CUnsignedShort, 256] +HEX_CHARS: t.CExtern | t.CArray[t.CChar, None] +HEX_VALS: t.CExtern | t.CArray[t.CInt, 256] +B64_CHARS: t.CExtern | t.CArray[t.CChar, None] +B64_VALS: t.CExtern | t.CArray[t.CInt, 256] +HQX_CHARS: t.CExtern | t.CArray[t.CChar, 64] +HQX_VALS: t.CExtern | t.CArray[t.CInt, 256] +UU_CHARS: t.CExtern | t.CArray[t.CChar, None] +CRC32_TABLE: t.CExtern | t.CArray[t.CUnsignedInt, 256] +CRC_HQX_TABLE: t.CExtern | t.CArray[t.CUnsignedShort, 256] def init_binascii() -> t.CInt: pass diff --git a/Test/ZlibTest/temp/29813d57621099a9.pyi b/Test/TestProject2/temp/29813d57621099a9.pyi similarity index 100% rename from Test/ZlibTest/temp/29813d57621099a9.pyi rename to Test/TestProject2/temp/29813d57621099a9.pyi diff --git a/Test/TestProject2/temp/49bd8cba55979f76.pyi b/Test/TestProject2/temp/49bd8cba55979f76.pyi new file mode 100644 index 0000000..f1d844a --- /dev/null +++ b/Test/TestProject2/temp/49bd8cba55979f76.pyi @@ -0,0 +1,75 @@ +""" +Auto-generated Python stub file from stdint.py +Module: stdint +""" + +import c + + +import t + +INT: t.CTypedef = t.CInt +INTPTR: t.CTypedef = t.CInt | t.CPtr +BOOL: t.CTypedef = t.CInt +UINT: t.CTypedef = t.CUnsignedInt +UINTPTR: t.CTypedef = UINT | t.CPtr +BYTE: t.CTypedef = t.CUnsignedChar +BYTEPTR: t.CTypedef = BYTE | t.CPtr +WORD: t.CTypedef = t.CUInt16T +DWORD: t.CTypedef = t.CUInt32T +QWORD: t.CTypedef = t.CUInt64T +TCHAR: t.CTypedef = t.CChar +CHARLIST: t.CTypedef = str | t.CPtr +VOID: t.CTypedef = t.CVoid +SHORT: t.CTypedef = t.CShort +SHORTPTR: t.CTypedef = t.CShort | t.CPtr +USHORT: t.CTypedef = t.CUnsignedShort +USHORTPTR: t.CTypedef = t.CUnsignedShort | t.CPtr +LONGLONG: t.CTypedef = t.CLong | t.CLong +ULONGLONG: t.CTypedef = t.CUnsignedLong | t.CLong +LONG: t.CTypedef = t.CLong +ULONG: t.CTypedef = t.CUnsignedLong +WCHAR: t.CTypedef = WORD +WCHARPTR: t.CTypedef = WORD | t.CPtr +CHARPTR: t.CTypedef = t.CChar | t.CPtr +FSIZE_t: t.CTypedef = DWORD +LBA_t: t.CTypedef = DWORD +UINTPTR: t.CTypedef = t.CUnsignedInt | t.CPtr +VOIDPTR: t.CTypedef = t.CVoid | t.CPtr +FLOAT: t.CTypedef = t.CFloat +DOUBLE: t.CTypedef = t.CDouble +FLOAT8: t.CTypedef = t.CFloat8T +FLOAT16: t.CTypedef = t.CFloat16T +FLOAT32: t.CTypedef = t.CFloat32T +FLOAT64: t.CTypedef = t.CFloat64T +FLOAT128: t.CTypedef = t.CFloat128T +INT8: t.CTypedef = t.CInt8T +INT16: t.CTypedef = t.CInt16T +INT32: t.CTypedef = t.CInt32T +INT64: t.CTypedef = t.CInt64T +UINT8: t.CTypedef = t.CUInt8T +UINT16: t.CTypedef = t.CUInt16T +UINT32: t.CTypedef = t.CUInt32T +UINT64: t.CTypedef = t.CUInt64T +INT8PTR: t.CTypedef = t.CInt8T | t.CPtr +INT16PTR: t.CTypedef = t.CInt16T | t.CPtr +INT32PTR: t.CTypedef = t.CInt32T | t.CPtr +INT64PTR: t.CTypedef = t.CInt64T | t.CPtr +UINT8PTR: t.CTypedef = t.CUInt8T | t.CPtr +UINT16PTR: t.CTypedef = t.CUInt16T | t.CPtr +UINT32PTR: t.CTypedef = t.CUInt32T | t.CPtr +UINT64PTR: t.CTypedef = t.CUInt64T | t.CPtr +CHAR8: t.CTypedef = t.CChar8T +CHAR16: t.CTypedef = t.CChar16T +CHAR32: t.CTypedef = t.CChar32T +CHAR8PTR: t.CTypedef = t.CChar8T | t.CPtr +CHAR16PTR: t.CTypedef = t.CChar16T | t.CPtr +CHAR32PTR: t.CTypedef = t.CChar32T | t.CPtr +i8: t.CTypedef = t.CInt8T +i16: t.CTypedef = t.CInt16T +i32: t.CTypedef = t.CInt32T +i64: t.CTypedef = t.CInt64T +u8: t.CTypedef = t.CUInt8T +u16: t.CTypedef = t.CUInt16T +u32: t.CTypedef = t.CUInt32T +u64: t.CTypedef = t.CUInt64T \ No newline at end of file diff --git a/Test/TestProject/temp/58121a0fb0ca7466.pyi b/Test/TestProject2/temp/541a1ed9b8be53c8.pyi similarity index 72% rename from Test/TestProject/temp/58121a0fb0ca7466.pyi rename to Test/TestProject2/temp/541a1ed9b8be53c8.pyi index 7f61fb6..a98f466 100644 --- a/Test/TestProject/temp/58121a0fb0ca7466.pyi +++ b/Test/TestProject2/temp/541a1ed9b8be53c8.pyi @@ -7,11 +7,10 @@ Module: main from stdint import * import w32.win32console import config -import HASHLIB -import BINASCII +import hashlib +import binascii import zlib.pyzlib as zp -import test_zlib as tpz -import test_numpy as tn import t, c +import testcheck def main() -> t.CInt | t.CExport: pass diff --git a/Test/TestProject2/temp/56cdd754a8a09347.pyi b/Test/TestProject2/temp/56cdd754a8a09347.pyi deleted file mode 100644 index 007ccb8..0000000 --- a/Test/TestProject2/temp/56cdd754a8a09347.pyi +++ /dev/null @@ -1,67 +0,0 @@ -""" -Auto-generated Python stub file from stdint.py -Module: stdint -""" - -import c - - -import t - -INT: t.CTypedef = t.CInt -INTPTR: t.CTypedef = t.CInt | t.CPtr -BOOL: t.CTypedef = t.CInt -UINT: t.CTypedef = t.CUnsignedInt -UINTPTR: t.CTypedef = UINT | t.CPtr -BYTE: t.CTypedef = t.CUnsignedChar -BYTEPTR: t.CTypedef = BYTE | t.CPtr -WORD: t.CTypedef = t.CUInt16T -DWORD: t.CTypedef = t.CUInt32T -QWORD: t.CTypedef = t.CUInt64T -TCHAR: t.CTypedef = t.CChar -CHARLIST: t.CTypedef = str | t.CPtr -VOID: t.CTypedef = t.CVoid -SHORT: t.CTypedef = t.CShort -SHORTPTR: t.CTypedef = t.CShort | t.CPtr -USHORT: t.CTypedef = t.CUnsignedShort -USHORTPTR: t.CTypedef = t.CUnsignedShort | t.CPtr -LONGLONG: t.CTypedef = t.CLong | t.CLong -ULONGLONG: t.CTypedef = t.CUnsignedLong | t.CLong -LONG: t.CTypedef = t.CLong -ULONG: t.CTypedef = t.CUnsignedLong -WCHAR: t.CTypedef = WORD -WCHARPTR: t.CTypedef = WORD | t.CPtr -CHARPTR: t.CTypedef = t.CChar | t.CPtr -FSIZE_t: t.CTypedef = DWORD -LBA_t: t.CTypedef = DWORD -UINTPTR: t.CTypedef = t.CUnsignedInt | t.CPtr -VOIDPTR: t.CTypedef = t.CVoid | t.CPtr -FLOAT: t.CTypedef = t.CFloat -DOUBLE: t.CTypedef = t.CDouble -FLOAT8: t.CTypedef = t.CFloat8T -FLOAT16: t.CTypedef = t.CFloat16T -FLOAT32: t.CTypedef = t.CFloat32T -FLOAT64: t.CTypedef = t.CFloat64T -FLOAT128: t.CTypedef = t.CFloat128T -INT8: t.CTypedef = t.CInt8T -INT16: t.CTypedef = t.CInt16T -INT32: t.CTypedef = t.CInt32T -INT64: t.CTypedef = t.CInt64T -UINT8: t.CTypedef = t.CUInt8T -UINT16: t.CTypedef = t.CUInt16T -UINT32: t.CTypedef = t.CUInt32T -UINT64: t.CTypedef = t.CUInt64T -INT8PTR: t.CTypedef = t.CInt8T | t.CPtr -INT16PTR: t.CTypedef = t.CInt16T | t.CPtr -INT32PTR: t.CTypedef = t.CInt32T | t.CPtr -INT64PTR: t.CTypedef = t.CInt64T | t.CPtr -UINT8PTR: t.CTypedef = t.CUInt8T | t.CPtr -UINT16PTR: t.CTypedef = t.CUInt16T | t.CPtr -UINT32PTR: t.CTypedef = t.CUInt32T | t.CPtr -UINT64PTR: t.CTypedef = t.CUInt64T | t.CPtr -CHAR8: t.CTypedef = t.CChar8T -CHAR16: t.CTypedef = t.CChar16T -CHAR32: t.CTypedef = t.CChar32T -CHAR8PTR: t.CTypedef = t.CChar8T | t.CPtr -CHAR16PTR: t.CTypedef = t.CChar16T | t.CPtr -CHAR32PTR: t.CTypedef = t.CChar32T | t.CPtr \ No newline at end of file diff --git a/Test/TestProject/temp/f9629b8eb4ebdcc2.pyi b/Test/TestProject2/temp/59d33b6ab0c70953.pyi similarity index 100% rename from Test/TestProject/temp/f9629b8eb4ebdcc2.pyi rename to Test/TestProject2/temp/59d33b6ab0c70953.pyi diff --git a/Test/TestProject2/temp/5a6a2137958c28c5.pyi b/Test/TestProject2/temp/5a6a2137958c28c5.pyi new file mode 100644 index 0000000..a137977 --- /dev/null +++ b/Test/TestProject2/temp/5a6a2137958c28c5.pyi @@ -0,0 +1,98 @@ +""" +Auto-generated Python stub file from w32.win32base.py +Module: w32.win32base +""" + +import c + + +import t +from stdint import * + +HANDLE: t.CTypedef = VOIDPTR +LPCSTR: t.CTypedef = t.CConst | t.CChar | t.CPtr +LPCWSTR: t.CTypedef = t.CConst | t.CUnsignedShort | t.CPtr +INVALID_HANDLE_VALUE: t.CDefine = t.CVoid(-1) +NULL: t.CDefine = 0 +TRUE: t.CDefine = 1 +FALSE: t.CDefine = 0 +INFINITE: t.CDefine = 0xFFFFFFFF +WAIT_FAILED: t.CDefine = 0xFFFFFFFF +WAIT_OBJECT_0: t.CDefine = 0 +WAIT_TIMEOUT: t.CDefine = 258 +WAIT_ABANDONED: t.CDefine = 0x80 +MAX_PATH: t.CDefine = 260 +ERROR_SUCCESS: t.CDefine = 0 +ERROR_FILE_NOT_FOUND: t.CDefine = 2 +ERROR_ACCESS_DENIED: t.CDefine = 5 +ERROR_INSUFFICIENT_BUFFER: t.CDefine = 122 + +class SECURITY_ATTRIBUTES: + nLength: ULONG + lpSecurityDescriptor: VOIDPTR + bInheritHandle: BOOL +class OVERLAPPED: + Internal: ULONGLONG + InternalHigh: ULONGLONG + Offset: ULONG + OffsetHigh: ULONG + hEvent: HANDLE +class FILETIME: + dwLowDateTime: DWORD + dwHighDateTime: DWORD +class SYSTEMTIME: + wYear: WORD + wMonth: WORD + wDayOfWeek: WORD + wDay: WORD + wHour: WORD + wMinute: WORD + wSecond: WORD + wMilliseconds: WORD +class GUID: + Data1: DWORD + Data2: WORD + Data3: WORD + Data4: BYTEPTR +class LARGE_INTEGER: + QuadPart: LONGLONG +class ULARGE_INTEGER: + QuadPart: ULONGLONG + +def GetLastError() -> ULONG | t.State: pass + +def SetLastError(dwErrCode: ULONG) -> t.State: pass + +def CloseHandle(hObject: HANDLE) -> BOOL | t.State: pass + +def GetProcAddress(hModule: HANDLE, lpProcName: LPCSTR) -> VOIDPTR | t.State: pass + +def GetModuleHandleA(lpModuleName: LPCSTR) -> HANDLE | t.State: pass + +def GetModuleHandleW(lpModuleName: LPCWSTR) -> HANDLE | t.State: pass + +def LoadLibraryA(lpLibFileName: LPCSTR) -> HANDLE | t.State: pass + +def LoadLibraryW(lpLibFileName: LPCWSTR) -> HANDLE | t.State: pass + +def FreeLibrary(hLibModule: HANDLE) -> BOOL | t.State: pass + +def GetSystemTime(lpSystemTime: SYSTEMTIME | t.CPtr) -> t.State: pass + +def GetLocalTime(lpSystemTime: SYSTEMTIME | t.CPtr) -> t.State: pass + +def FileTimeToSystemTime(lpFileTime: FILETIME | t.CPtr, lpSystemTime: SYSTEMTIME | t.CPtr) -> BOOL | t.State: pass + +def SystemTimeToFileTime(lpSystemTime: SYSTEMTIME | t.CPtr, lpFileTime: FILETIME | t.CPtr) -> BOOL | t.State: pass + +def QueryPerformanceCounter(lpPerformanceCount: LARGE_INTEGER | t.CPtr) -> BOOL | t.State: pass + +def QueryPerformanceFrequency(lpFrequency: LARGE_INTEGER | t.CPtr) -> BOOL | t.State: pass + +def Sleep(dwMilliseconds: ULONG) -> t.State: pass + +def SleepEx(dwMilliseconds: ULONG, bAlertable: BOOL) -> ULONG | t.State: pass + +def GetTickCount() -> ULONG | t.State: pass + +def GetTickCount64() -> ULONGLONG | t.State: pass diff --git a/Test/TestProject2/temp/6c2029b306556c00.pyi b/Test/TestProject2/temp/6c2029b306556c00.pyi new file mode 100644 index 0000000..98da680 --- /dev/null +++ b/Test/TestProject2/temp/6c2029b306556c00.pyi @@ -0,0 +1,18 @@ +""" +Auto-generated Python stub file from stdlib.py +Module: stdlib +""" + +import c + + +from stdint import * +import t + +def malloc(size: t.CSizeT) -> t.CVoid | t.CPtr | t.State | t.CExtern | t.CExport: pass + +def calloc(nmemb: t.CSizeT, size: t.CSizeT) -> t.CVoid | t.CPtr | t.State | t.CExtern | t.CExport: pass + +def realloc(p: t.CVoid | t.CPtr, size: t.CSizeT) -> t.CVoid | t.CPtr | t.State | t.CExtern | t.CExport: pass + +def free(p: t.CVoid | t.CPtr) -> None | t.State | t.CExtern | t.CExport: pass diff --git a/Test/TestProject/temp/88e3e48eab9e1653.pyi b/Test/TestProject2/temp/6ff26590374ae6fc.pyi similarity index 69% rename from Test/TestProject/temp/88e3e48eab9e1653.pyi rename to Test/TestProject2/temp/6ff26590374ae6fc.pyi index 225c287..1b1bba1 100644 --- a/Test/TestProject/temp/88e3e48eab9e1653.pyi +++ b/Test/TestProject2/temp/6ff26590374ae6fc.pyi @@ -26,14 +26,14 @@ def sha512_Sigma0(x: t.CUInt64T) -> t.CUInt64T: pass def sha512_Sigma1(x: t.CUInt64T) -> t.CUInt64T: pass -sha512_K: t.CExtern | list[t.CUInt64T, 80] +sha512_K: t.CExtern | t.CArray[t.CUInt64T, 80] @t.Object class sha512: - state: list[t.CUInt64T, 8] - count: list[t.CUInt64T, 2] - buf: list[t.CUInt8T, SHA512_BLOCK_LEN] + state: t.CArray[t.CUInt64T, 8] + count: t.CArray[t.CUInt64T, 2] + buf: t.CArray[t.CUInt8T, SHA512_BLOCK_LEN] def __init__(self: sha512) -> t.CInt: pass - def transform(self: sha512, block: list[t.CUInt8T, SHA512_BLOCK_LEN]) -> t.CInt: pass + def transform(self: sha512, block: t.CArray[t.CUInt8T, SHA512_BLOCK_LEN]) -> t.CInt: pass def update(self: sha512, s: str) -> t.CInt: pass - def final(self: sha512, out: list[t.CUInt8T, SHA512_DIGEST_LEN]) -> t.CInt: pass \ No newline at end of file + def final(self: sha512, out: t.CArray[t.CUInt8T, SHA512_DIGEST_LEN]) -> t.CInt: pass \ No newline at end of file diff --git a/Test/TestProject2/temp/72e2d5ccb7cedcf1.pyi b/Test/TestProject2/temp/72e2d5ccb7cedcf1.pyi new file mode 100644 index 0000000..5fceb08 --- /dev/null +++ b/Test/TestProject2/temp/72e2d5ccb7cedcf1.pyi @@ -0,0 +1,91 @@ +""" +Auto-generated Python stub file from w32.win32memory.py +Module: w32.win32memory +""" + +import c + + +import t +from stdint import * +from w32.win32base import * + +MEM_COMMIT: t.CDefine = 0x00001000 +MEM_RESERVE: t.CDefine = 0x00002000 +MEM_DECOMMIT: t.CDefine = 0x00004000 +MEM_RELEASE: t.CDefine = 0x00008000 +MEM_FREE: t.CDefine = 0x00010000 +MEM_RESET: t.CDefine = 0x00080000 +MEM_TOP_DOWN: t.CDefine = 0x00100000 +MEM_WRITE_WATCH: t.CDefine = 0x00200000 +MEM_PHYSICAL: t.CDefine = 0x00400000 +MEM_LARGE_PAGES: t.CDefine = 0x20000000 +PAGE_NOACCESS: t.CDefine = 0x01 +PAGE_READONLY: t.CDefine = 0x02 +PAGE_READWRITE: t.CDefine = 0x04 +PAGE_WRITECOPY: t.CDefine = 0x08 +PAGE_EXECUTE: t.CDefine = 0x10 +PAGE_EXECUTE_READ: t.CDefine = 0x20 +PAGE_EXECUTE_READWRITE: t.CDefine = 0x40 +PAGE_EXECUTE_WRITECOPY: t.CDefine = 0x80 +PAGE_GUARD: t.CDefine = 0x100 +PAGE_NOCACHE: t.CDefine = 0x200 +PAGE_WRITECOMBINE: t.CDefine = 0x400 +HEAP_NO_SERIALIZE: t.CDefine = 0x00000001 +HEAP_GROWABLE: t.CDefine = 0x00000002 +HEAP_GENERATE_EXCEPTIONS: t.CDefine = 0x00000004 +HEAP_ZERO_MEMORY: t.CDefine = 0x00000008 +HEAP_REALLOC_IN_PLACE_ONLY: t.CDefine = 0x00000010 + +class MEMORY_BASIC_INFORMATION: + BaseAddress: VOIDPTR + AllocationBase: VOIDPTR + AllocationProtect: ULONG + RegionSize: t.CSizeT + State: ULONG + Protect: ULONG + Type: ULONG + +def VirtualAlloc(lpAddress: VOIDPTR, dwSize: t.CSizeT, flAllocationType: ULONG, flProtect: ULONG) -> VOIDPTR | t.State: pass + +def VirtualFree(lpAddress: VOIDPTR, dwSize: t.CSizeT, dwFreeType: ULONG) -> BOOL | t.State: pass + +def VirtualProtect(lpAddress: VOIDPTR, dwSize: t.CSizeT, flNewProtect: ULONG, lpflOldProtect: ULONG | t.CPtr) -> BOOL | t.State: pass + +def VirtualQuery(lpAddress: t.CConst | VOIDPTR, lpBuffer: MEMORY_BASIC_INFORMATION | t.CPtr, dwLength: t.CSizeT) -> t.CSizeT | t.State: pass + +def VirtualLock(lpAddress: VOIDPTR, dwSize: t.CSizeT) -> BOOL | t.State: pass + +def VirtualUnlock(lpAddress: VOIDPTR, dwSize: t.CSizeT) -> BOOL | t.State: pass + +def GetProcessHeap() -> HANDLE | t.State: pass + +def HeapCreate(flOptions: ULONG, dwInitialSize: t.CSizeT, dwMaximumSize: t.CSizeT) -> HANDLE | t.State: pass + +def HeapDestroy(hHeap: HANDLE) -> BOOL | t.State: pass + +def HeapAlloc(hHeap: HANDLE, dwFlags: ULONG, dwBytes: t.CSizeT) -> VOIDPTR | t.State: pass + +def HeapReAlloc(hHeap: HANDLE, dwFlags: ULONG, lpMem: VOIDPTR, dwBytes: t.CSizeT) -> VOIDPTR | t.State: pass + +def HeapFree(hHeap: HANDLE, dwFlags: ULONG, lpMem: VOIDPTR) -> BOOL | t.State: pass + +def HeapSize(hHeap: HANDLE, dwFlags: ULONG, lpMem: t.CConst | VOIDPTR) -> t.CSizeT | t.State: pass + +def HeapValidate(hHeap: HANDLE, dwFlags: ULONG, lpMem: t.CConst | VOIDPTR) -> BOOL | t.State: pass + +def HeapCompact(hHeap: HANDLE, dwFlags: ULONG) -> t.CSizeT | t.State: pass + +def GlobalAlloc(uFlags: UINT, dwBytes: t.CSizeT) -> VOIDPTR | t.State: pass + +def GlobalFree(hMem: VOIDPTR) -> VOIDPTR | t.State: pass + +def GlobalLock(hMem: VOIDPTR) -> VOIDPTR | t.State: pass + +def GlobalUnlock(hMem: VOIDPTR) -> BOOL | t.State: pass + +def GlobalSize(hMem: VOIDPTR) -> t.CSizeT | t.State: pass + +def LocalAlloc(uFlags: UINT, dwBytes: t.CSizeT) -> VOIDPTR | t.State: pass + +def LocalFree(hMem: VOIDPTR) -> VOIDPTR | t.State: pass diff --git a/Test/TestProject/temp/b0267503e816efc4.pyi b/Test/TestProject2/temp/73c1586b83e9b5c2.pyi similarity index 91% rename from Test/TestProject/temp/b0267503e816efc4.pyi rename to Test/TestProject2/temp/73c1586b83e9b5c2.pyi index 62ff901..e430f1e 100644 --- a/Test/TestProject/temp/b0267503e816efc4.pyi +++ b/Test/TestProject2/temp/73c1586b83e9b5c2.pyi @@ -18,7 +18,7 @@ class zhuff_code: @t.Object class zhuff_tree: pool: mpool.MPool | t.CPtr - codes: list[zhuff_code, ZHUFF_MAX_CODES] + codes: t.CArray[zhuff_code, ZHUFF_MAX_CODES] count: t.CInt max_bits: t.CInt def __init__(self: zhuff_tree) -> t.CInt: pass @@ -31,12 +31,12 @@ class zhuff_tree: def get_fixed_dist_lengths(self: zhuff_tree, lengths: INTPTR) -> t.CInt: pass def build_tree_from_lengths(self: zhuff_tree, lengths: INTPTR, count: t.CInt, max_bits: t.CInt) -> t.CInt: pass class zhuff_decode_node: - children: list[t.CInt, 2] + children: t.CArray[t.CInt, 2] symbol: t.CInt @t.Object class zhuff_decode_tree: pool: mpool.MPool | t.CPtr - nodes: list[zhuff_decode_node, 2 * ZHUFF_MAX_CODES] + nodes: t.CArray[zhuff_decode_node, 2 * ZHUFF_MAX_CODES] node_count: t.CInt root: t.CInt def __init__(self: zhuff_decode_tree) -> t.CInt: pass diff --git a/Test/TestProject/temp/0d13cde396f4a15f.pyi b/Test/TestProject2/temp/73fcdc4dd1618580.pyi similarity index 80% rename from Test/TestProject/temp/0d13cde396f4a15f.pyi rename to Test/TestProject2/temp/73fcdc4dd1618580.pyi index bc49415..d94a709 100644 --- a/Test/TestProject/temp/0d13cde396f4a15f.pyi +++ b/Test/TestProject2/temp/73fcdc4dd1618580.pyi @@ -20,10 +20,10 @@ def sha1_f3(b: t.CUInt32T, c: t.CUInt32T, d: t.CUInt32T) -> t.CUInt32T: pass @t.Object class sha1: - state: list[t.CUInt32T, 5] + state: t.CArray[t.CUInt32T, 5] count: t.CUInt64T - buf: list[t.CUInt8T, SHA1_BLOCK_LEN] + buf: t.CArray[t.CUInt8T, SHA1_BLOCK_LEN] def __init__(self: sha1) -> t.CInt: pass def transform(self: sha1, block: t.CUInt8T | t.CPtr) -> t.CInt: pass def update(self: sha1, s: str) -> t.CInt: pass - def final(self: sha1, out: list[t.CUInt8T, SHA1_DIGEST_LEN]) -> t.CInt: pass \ No newline at end of file + def final(self: sha1, out: t.CArray[t.CUInt8T, SHA1_DIGEST_LEN]) -> t.CInt: pass \ No newline at end of file diff --git a/Test/TestProject2/temp/75583f20a922ab2e.pyi b/Test/TestProject2/temp/75583f20a922ab2e.pyi deleted file mode 100644 index 10da71f..0000000 --- a/Test/TestProject2/temp/75583f20a922ab2e.pyi +++ /dev/null @@ -1,38 +0,0 @@ -""" -Auto-generated Python stub file from zc.test.py -Module: zc.test -""" - - -import config -import t, c - -def AboutSizeTWhileTest(length: t.CSizeT) -> t.CInt: pass - -def MathBasicTest(x: t.CInt, y: t.CInt) -> t.CInt: pass - -def MathAdvancedTest(value: t.CInt) -> t.CInt: pass - -def WhileWithElifElseTest(start: t.CInt, end: t.CInt) -> t.CInt: pass - -def NestedWhileWithMacrosTest(outer_limit: t.CInt, inner_limit: t.CInt) -> t.CInt: pass - -def ComplexConditionTest(a: t.CInt, b: t.CInt, c_val: t.CInt) -> t.CInt: pass - -def RetryLoopTest(retry_count: t.CInt) -> t.CInt: pass - -def BitwiseOperationsTest(value: t.CInt) -> t.CInt: pass - -def CompoundAssignmentMathTest(a: t.CInt, b: t.CInt) -> t.CInt: pass - -def PowerAndModuloTest(base: t.CInt, exponent: t.CInt) -> t.CInt: pass - -def MixedArithmeticTest(x: t.CInt, y: t.CInt, z: t.CInt) -> t.CInt: pass - -def MathWithWhileLoopTest(start: t.CInt, count: t.CInt) -> t.CInt: pass - -def ComplexNestedMathTest(a: t.CInt, b: t.CInt) -> t.CInt: pass - -def ConditionalMathChainTest(value: t.CInt) -> t.CInt: pass - -def BitManipulationMathTest(value: t.CInt) -> t.CInt: pass diff --git a/Test/TestProject/temp/4638d411fd53fef0.pyi b/Test/TestProject2/temp/8ebed83a7817fa0c.pyi similarity index 85% rename from Test/TestProject/temp/4638d411fd53fef0.pyi rename to Test/TestProject2/temp/8ebed83a7817fa0c.pyi index d46797d..6375e88 100644 --- a/Test/TestProject/temp/4638d411fd53fef0.pyi +++ b/Test/TestProject2/temp/8ebed83a7817fa0c.pyi @@ -10,6 +10,6 @@ import t, c def zchecksum_adler32(data: UINT8PTR, length: t.CSizeT, init: UINT32) -> t.CUInt32T: pass -crc32_table: t.CExtern | list[t.CUInt32T, 256] +crc32_table: t.CExtern | t.CArray[t.CUInt32T, 256] def zchecksum_crc32(data: UINT8PTR, length: t.CSizeT, init: t.CUInt32T) -> t.CUInt32T: pass diff --git a/Test/TestProject/temp/96837bcc64032444.pyi b/Test/TestProject2/temp/96837bcc64032444.pyi similarity index 100% rename from Test/TestProject/temp/96837bcc64032444.pyi rename to Test/TestProject2/temp/96837bcc64032444.pyi diff --git a/Test/TestProject2/temp/9dbecd0942a39782.pyi b/Test/TestProject2/temp/9dbecd0942a39782.pyi new file mode 100644 index 0000000..41648c1 --- /dev/null +++ b/Test/TestProject2/temp/9dbecd0942a39782.pyi @@ -0,0 +1,25 @@ +""" +Auto-generated Python stub file from testcheck.py +Module: testcheck +""" + + +import t, c +import stdio + +_pass_count: t.CExtern | t.CInt +_fail_count: t.CExtern | t.CInt + +def begin(name: str) -> t.CInt: pass + +def section(name: str) -> t.CInt: pass + +def ok(msg: str) -> t.CInt: pass + +def fail(msg: str) -> t.CInt: pass + +def check(cond: t.CInt, ok_msg: str, fail_msg: str) -> t.CInt: pass + +def info(msg: str) -> t.CInt: pass + +def end() -> t.CInt: pass diff --git a/Test/TestProject2/temp/_sha1_map.txt b/Test/TestProject2/temp/_sha1_map.txt index 9037b15..4313ff1 100644 --- a/Test/TestProject2/temp/_sha1_map.txt +++ b/Test/TestProject2/temp/_sha1_map.txt @@ -1,7 +1,23 @@ -09ba6d4617920d26:main.py -56cdd754a8a09347:includes/stdint.py +0991af0d22263577:includes/mpool.py +257e074b935c33b4:includes/binascii.py +49bd8cba55979f76:includes/stdint.py +541a1ed9b8be53c8:main.py +59d33b6ab0c70953:includes/zlib\zinflate.py +5a6a2137958c28c5:includes/w32\win32base.py +6c2029b306556c00:includes/stdlib.py +6ff26590374ae6fc:includes/hashlib\__sha512.py +73c1586b83e9b5c2:includes/zlib\zhuff.py 73edbcf76e32d00b:includes/stdio.py -75583f20a922ab2e:zc\test.py -a7dab00d979c009c:zc\class_test.py +73fcdc4dd1618580:includes/hashlib\__sha1.py +8ebed83a7817fa0c:includes/zlib\zchecksum.py +96837bcc64032444:includes/hashlib\__init__.py +9dbecd0942a39782:includes/testcheck.py +b5f1dc665c52a1bd:includes/string.py +bbdf3bbd4c3bc28c:includes/w32\win32console.py +c39cbbae4b6e264f:includes/zlib\pyzlib.py +c9d54a4158f7f5a8:includes/hashlib\__sha256.py +c9f4be41ca1cc2b4:includes/viperio.py +cc436a125bbaf28c:includes/hashlib\__md5.py +cd520d14822f3f19:includes/zlib\zdef.py cfc83b830141b00e:zc\config.py -faec3233d98371da:zc\logic_test.py +f80740e7bcee16ae:includes/zlib\zdeflate.py diff --git a/Test/TestProject2/temp/_shared_sym.json b/Test/TestProject2/temp/_shared_sym.json new file mode 100644 index 0000000..e69de29 diff --git a/Test/TestProject2/temp/_shared_sym.pkl b/Test/TestProject2/temp/_shared_sym.pkl deleted file mode 100644 index 4fc49648aaee2ae59b0e5ff5b0a08e3962d2adb2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 194167 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 t.CInt: pass - def get_age(self: Student) -> t.CInt: pass - def get_score(self: Student) -> t.CInt: pass -class Counter(t.Object): - value: t.CInt - def __init__(self: Counter, initial: t.CInt) -> t.CInt: pass - def increment(self: Counter) -> t.CInt: pass - def get_value(self: Counter) -> t.CInt: pass -class StackObj(t.Object): - data: t.CInt - next_ptr: t.CVoid | t.CPtr - -def TestBasicDataClass() -> t.CInt: pass - -def TestPoint3DClass() -> t.CInt: pass - -def TestStudentClass() -> t.CInt: pass - -def TestCounterClass() -> t.CInt: pass - -def TestStackAllocation() -> t.CInt: pass - -def TestHeapAllocation() -> t.CInt: pass - -def TestHeapObjectWithInit() -> t.CInt: pass - -def TestMultipleStackObjects() -> t.CInt: pass - -def TestImplicitInitCall() -> t.CInt: pass - -def TestClassWithBitFields() -> t.CInt: pass - -def TestIntArray() -> t.CInt: pass - -def TestFloatArray() -> t.CInt: pass - -def TestCharArray() -> t.CInt: pass - -def TestNestedArray() -> t.CInt: pass - -def TestArrayWithStruct() -> t.CInt: pass - -def TestArrayPointer() -> t.CInt: pass - -def TestDynamicString() -> t.CInt: pass diff --git a/Test/TestProject2/temp/abf9ce3160c9279e.pyi b/Test/TestProject2/temp/abf9ce3160c9279e.pyi new file mode 100644 index 0000000..4249b58 --- /dev/null +++ b/Test/TestProject2/temp/abf9ce3160c9279e.pyi @@ -0,0 +1,179 @@ +""" +Auto-generated Python stub file from w32.win32file.py +Module: w32.win32file +""" + +import c + + +import t +from stdint import * +from w32.win32base import * + +GENERIC_READ: t.CDefine = 0x80000000 +GENERIC_WRITE: t.CDefine = 0x40000000 +GENERIC_EXECUTE: t.CDefine = 0x20000000 +GENERIC_ALL: t.CDefine = 0x10000000 +FILE_SHARE_READ: t.CDefine = 0x00000001 +FILE_SHARE_WRITE: t.CDefine = 0x00000002 +FILE_SHARE_DELETE: t.CDefine = 0x00000004 +CREATE_NEW: t.CDefine = 1 +CREATE_ALWAYS: t.CDefine = 2 +OPEN_EXISTING: t.CDefine = 3 +OPEN_ALWAYS: t.CDefine = 4 +TRUNCATE_EXISTING: t.CDefine = 5 +FILE_ATTRIBUTE_READONLY: t.CDefine = 0x00000001 +FILE_ATTRIBUTE_HIDDEN: t.CDefine = 0x00000002 +FILE_ATTRIBUTE_SYSTEM: t.CDefine = 0x00000004 +FILE_ATTRIBUTE_DIRECTORY: t.CDefine = 0x00000010 +FILE_ATTRIBUTE_ARCHIVE: t.CDefine = 0x00000020 +FILE_ATTRIBUTE_NORMAL: t.CDefine = 0x00000080 +FILE_ATTRIBUTE_TEMPORARY: t.CDefine = 0x00000100 +FILE_ATTRIBUTE_COMPRESSED: t.CDefine = 0x00000800 +FILE_ATTRIBUTE_OFFLINE: t.CDefine = 0x00001000 +FILE_ATTRIBUTE_ENCRYPTED: t.CDefine = 0x00004000 +FILE_FLAG_WRITE_THROUGH: t.CDefine = 0x80000000 +FILE_FLAG_OVERLAPPED: t.CDefine = 0x40000000 +FILE_FLAG_NO_BUFFERING: t.CDefine = 0x20000000 +FILE_FLAG_RANDOM_ACCESS: t.CDefine = 0x10000000 +FILE_FLAG_SEQUENTIAL_SCAN: t.CDefine = 0x08000000 +FILE_FLAG_DELETE_ON_CLOSE: t.CDefine = 0x04000000 +FILE_FLAG_BACKUP_SEMANTICS: t.CDefine = 0x02000000 +FILE_FLAG_POSIX_SEMANTICS: t.CDefine = 0x01000000 +FILE_BEGIN: t.CDefine = 0 +FILE_CURRENT: t.CDefine = 1 +FILE_END: t.CDefine = 2 +STD_INPUT_HANDLE: t.CDefine = t.CUnsignedLong(-10) +STD_OUTPUT_HANDLE: t.CDefine = t.CUnsignedLong(-11) +STD_ERROR_HANDLE: t.CDefine = t.CUnsignedLong(-12) +MOVEFILE_REPLACE_EXISTING: t.CDefine = 0x00000001 +MOVEFILE_COPY_ALLOWED: t.CDefine = 0x00000002 +MOVEFILE_WRITE_THROUGH: t.CDefine = 0x00000008 + +class BY_HANDLE_FILE_INFORMATION: + dwFileAttributes: ULONG + ftCreationTime: FILETIME + ftLastAccessTime: FILETIME + ftLastWriteTime: FILETIME + dwVolumeSerialNumber: ULONG + nFileSizeHigh: ULONG + nFileSizeLow: ULONG + nNumberOfLinks: ULONG + nFileIndexHigh: ULONG + nFileIndexLow: ULONG +class WIN32_FIND_DATAA: + dwFileAttributes: ULONG + ftCreationTime: FILETIME + ftLastAccessTime: FILETIME + ftLastWriteTime: FILETIME + nFileSizeHigh: ULONG + nFileSizeLow: ULONG + dwReserved0: ULONG + dwReserved1: ULONG + cFileName: CHARPTR + cAlternateFileName: CHARPTR +class WIN32_FIND_DATAW: + dwFileAttributes: ULONG + ftCreationTime: FILETIME + ftLastAccessTime: FILETIME + ftLastWriteTime: FILETIME + nFileSizeHigh: ULONG + nFileSizeLow: ULONG + dwReserved0: ULONG + dwReserved1: ULONG + cFileName: WCHARPTR + cAlternateFileName: WCHARPTR + +def CreateFileA(lpFileName: LPCSTR, dwDesiredAccess: ULONG, dwShareMode: ULONG, lpSecurityAttributes: SECURITY_ATTRIBUTES | t.CPtr, dwCreationDisposition: ULONG, dwFlagsAndAttributes: ULONG, hTemplateFile: HANDLE) -> HANDLE | t.State: pass + +def CreateFileW(lpFileName: LPCWSTR, dwDesiredAccess: ULONG, dwShareMode: ULONG, lpSecurityAttributes: SECURITY_ATTRIBUTES | t.CPtr, dwCreationDisposition: ULONG, dwFlagsAndAttributes: ULONG, hTemplateFile: HANDLE) -> HANDLE | t.State: pass + +def ReadFile(hFile: HANDLE, lpBuffer: VOIDPTR, nNumberOfBytesToRead: ULONG, lpNumberOfBytesRead: ULONG | t.CPtr, lpOverlapped: OVERLAPPED | t.CPtr) -> BOOL | t.State: pass + +def WriteFile(hFile: HANDLE, lpBuffer: t.CConst | VOIDPTR, nNumberOfBytesToWrite: ULONG, lpNumberOfBytesWritten: ULONG | t.CPtr, lpOverlapped: OVERLAPPED | t.CPtr) -> BOOL | t.State: pass + +def SetFilePointer(hFile: HANDLE, lDistanceToMove: LONG, lpDistanceToMoveHigh: LONG | t.CPtr, dwMoveMethod: ULONG) -> LONG | t.State: pass + +def SetFilePointerEx(hFile: HANDLE, liDistanceToMove: LARGE_INTEGER | t.CPtr, lpNewFilePointer: LARGE_INTEGER | t.CPtr, dwMoveMethod: ULONG) -> BOOL | t.State: pass + +def GetFileSize(hFile: HANDLE, lpFileSizeHigh: ULONG | t.CPtr) -> ULONG | t.State: pass + +def GetFileSizeEx(hFile: HANDLE, lpFileSize: LARGE_INTEGER | t.CPtr) -> BOOL | t.State: pass + +def SetEndOfFile(hFile: HANDLE) -> BOOL | t.State: pass + +def FlushFileBuffers(hFile: HANDLE) -> BOOL | t.State: pass + +def GetFileType(hFile: HANDLE) -> ULONG | t.State: pass + +def GetFileAttributesA(lpFileName: LPCSTR) -> ULONG | t.State: pass + +def GetFileAttributesW(lpFileName: LPCWSTR) -> ULONG | t.State: pass + +def SetFileAttributesA(lpFileName: LPCSTR, dwFileAttributes: ULONG) -> BOOL | t.State: pass + +def SetFileAttributesW(lpFileName: LPCWSTR, dwFileAttributes: ULONG) -> BOOL | t.State: pass + +def DeleteFileA(lpFileName: LPCSTR) -> BOOL | t.State: pass + +def DeleteFileW(lpFileName: LPCWSTR) -> BOOL | t.State: pass + +def MoveFileA(lpExistingFileName: LPCSTR, lpNewFileName: LPCSTR) -> BOOL | t.State: pass + +def MoveFileW(lpExistingFileName: LPCWSTR, lpNewFileName: LPCWSTR) -> BOOL | t.State: pass + +def MoveFileExA(lpExistingFileName: LPCSTR, lpNewFileName: LPCSTR, dwFlags: ULONG) -> BOOL | t.State: pass + +def MoveFileExW(lpExistingFileName: LPCWSTR, lpNewFileName: LPCWSTR, dwFlags: ULONG) -> BOOL | t.State: pass + +def CopyFileA(lpExistingFileName: LPCSTR, lpNewFileName: LPCSTR, bFailIfExists: BOOL) -> BOOL | t.State: pass + +def CopyFileW(lpExistingFileName: LPCWSTR, lpNewFileName: LPCWSTR, bFailIfExists: BOOL) -> BOOL | t.State: pass + +def CreateDirectoryA(lpPathName: LPCSTR, lpSecurityAttributes: SECURITY_ATTRIBUTES | t.CPtr) -> BOOL | t.State: pass + +def CreateDirectoryW(lpPathName: LPCWSTR, lpSecurityAttributes: SECURITY_ATTRIBUTES | t.CPtr) -> BOOL | t.State: pass + +def RemoveDirectoryA(lpPathName: LPCSTR) -> BOOL | t.State: pass + +def RemoveDirectoryW(lpPathName: LPCWSTR) -> BOOL | t.State: pass + +def FindFirstFileA(lpFileName: LPCSTR, lpFindFileData: WIN32_FIND_DATAA | t.CPtr) -> HANDLE | t.State: pass + +def FindFirstFileW(lpFileName: LPCWSTR, lpFindFileData: WIN32_FIND_DATAW | t.CPtr) -> HANDLE | t.State: pass + +def FindNextFileA(hFindFile: HANDLE, lpFindFileData: WIN32_FIND_DATAA | t.CPtr) -> BOOL | t.State: pass + +def FindNextFileW(hFindFile: HANDLE, lpFindFileData: WIN32_FIND_DATAW | t.CPtr) -> BOOL | t.State: pass + +def FindClose(hFindFile: HANDLE) -> BOOL | t.State: pass + +def GetStdHandle(nStdHandle: ULONG) -> HANDLE | t.State: pass + +def SetStdHandle(nStdHandle: ULONG, hHandle: HANDLE) -> BOOL | t.State: pass + +def GetFileInformationByHandle(hFile: HANDLE, lpFileInformation: BY_HANDLE_FILE_INFORMATION | t.CPtr) -> BOOL | t.State: pass + +def LockFile(hFile: HANDLE, dwFileOffsetLow: ULONG, dwFileOffsetHigh: ULONG, nNumberOfBytesToLockLow: ULONG, nNumberOfBytesToLockHigh: ULONG) -> BOOL | t.State: pass + +def UnlockFile(hFile: HANDLE, dwFileOffsetLow: ULONG, dwFileOffsetHigh: ULONG, nNumberOfBytesToUnlockLow: ULONG, nNumberOfBytesToUnlockHigh: ULONG) -> BOOL | t.State: pass + +def GetTempPathA(nBufferLength: ULONG, lpBuffer: CHARPTR) -> ULONG | t.State: pass + +def GetTempPathW(nBufferLength: ULONG, lpBuffer: WCHARPTR) -> ULONG | t.State: pass + +def GetTempFileNameA(lpPathName: LPCSTR, lpPrefixString: LPCSTR, uUnique: UINT, lpTempFileName: CHARPTR) -> UINT | t.State: pass + +def GetTempFileNameW(lpPathName: LPCWSTR, lpPrefixString: LPCWSTR, uUnique: UINT, lpTempFileName: WCHARPTR) -> UINT | t.State: pass + +def GetCurrentDirectoryA(nBufferLength: ULONG, lpBuffer: CHARPTR) -> ULONG | t.State: pass + +def GetCurrentDirectoryW(nBufferLength: ULONG, lpBuffer: WCHARPTR) -> ULONG | t.State: pass + +def SetCurrentDirectoryA(lpPathName: LPCSTR) -> BOOL | t.State: pass + +def SetCurrentDirectoryW(lpPathName: LPCWSTR) -> BOOL | t.State: pass + +def GetModuleFileNameA(hModule: HANDLE, lpFilename: CHARPTR, nSize: ULONG) -> ULONG | t.State: pass + +def GetModuleFileNameW(hModule: HANDLE, lpFilename: WCHARPTR, nSize: ULONG) -> ULONG | t.State: pass diff --git a/Test/TestProject2/temp/b5f1dc665c52a1bd.pyi b/Test/TestProject2/temp/b5f1dc665c52a1bd.pyi new file mode 100644 index 0000000..8b6959e --- /dev/null +++ b/Test/TestProject2/temp/b5f1dc665c52a1bd.pyi @@ -0,0 +1,44 @@ +""" +Auto-generated Python stub file from string.py +Module: string +""" + + +from stdint import * +import t, c + +def strcpy(dest: str, src: str) -> str: pass + +def strncpy(dest: str, src: str, n: t.CSizeT) -> str: pass + +def strlen(src: str) -> t.CSizeT | t.CExport: pass + +def strcmp(str1: str, str2: str) -> t.CInt: pass + +def samestr(str1: str, str2: str) -> bool: pass + +def strncmp(str1: str, str2: str, n: t.CSizeT) -> t.CInt: pass + +def memcmp(ptr1: t.CVoid | t.CPtr, ptr2: t.CVoid | t.CPtr, n: t.CSizeT) -> t.CInt: pass + +def strchr(s: str, cr: t.CInt) -> str: pass + +def strrchr(s: str, cr: t.CInt) -> str: pass + +def strspn(s: str, skip: str) -> int: pass + +def memset(ptr: t.CVoid | t.CPtr, value: t.CInt, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass + +def memset32(ptr: t.CVoid | t.CPtr, value: t.CUInt32T, count: t.CSizeT) -> t.CVoid | t.CPtr: pass + +def memcpy(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass + +def memmove(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr: pass + +def atoi(src: str) -> t.CInt: pass + +def atoll(src: str) -> t.CInt64T: pass + +def atof(src: str) -> t.CDouble: pass + +def split(s: str, delim: str, result: t.CArray[str]) -> int: pass diff --git a/Test/TestProject2/temp/bbdf3bbd4c3bc28c.pyi b/Test/TestProject2/temp/bbdf3bbd4c3bc28c.pyi new file mode 100644 index 0000000..70dcdbc --- /dev/null +++ b/Test/TestProject2/temp/bbdf3bbd4c3bc28c.pyi @@ -0,0 +1,138 @@ +""" +Auto-generated Python stub file from w32.win32console.py +Module: w32.win32console +""" + +import c + + +import t +from stdint import * +from w32.win32base import * + +ENABLE_PROCESSED_INPUT: t.CDefine = 0x0001 +ENABLE_LINE_INPUT: t.CDefine = 0x0002 +ENABLE_ECHO_INPUT: t.CDefine = 0x0004 +ENABLE_WINDOW_INPUT: t.CDefine = 0x0008 +ENABLE_MOUSE_INPUT: t.CDefine = 0x0010 +ENABLE_INSERT_MODE: t.CDefine = 0x0020 +ENABLE_QUICK_EDIT_MODE: t.CDefine = 0x0040 +ENABLE_EXTENDED_FLAGS: t.CDefine = 0x0080 +ENABLE_PROCESSED_OUTPUT: t.CDefine = 0x0001 +ENABLE_WRAP_AT_EOL_OUTPUT: t.CDefine = 0x0002 +ENABLE_VIRTUAL_TERMINAL_PROCESSING: t.CDefine = 0x0004 +DISABLE_NEWLINE_AUTO_RETURN: t.CDefine = 0x0008 +ENABLE_LVB_GRID_WORLDWIDE: t.CDefine = 0x0010 +FOREGROUND_BLUE: t.CDefine = 0x0001 +FOREGROUND_GREEN: t.CDefine = 0x0002 +FOREGROUND_RED: t.CDefine = 0x0004 +FOREGROUND_INTENSITY: t.CDefine = 0x0008 +BACKGROUND_BLUE: t.CDefine = 0x0010 +BACKGROUND_GREEN: t.CDefine = 0x0020 +BACKGROUND_RED: t.CDefine = 0x0040 +BACKGROUND_INTENSITY: t.CDefine = 0x0080 +KEY_EVENT: t.CDefine = 0x0001 +MOUSE_EVENT: t.CDefine = 0x0002 +WINDOW_BUFFER_SIZE_EVENT: t.CDefine = 0x0004 +MENU_EVENT: t.CDefine = 0x0008 +FOCUS_EVENT: t.CDefine = 0x0010 + +class COORD: + X: SHORT + Y: SHORT +class SMALL_RECT: + Left: SHORT + Top: SHORT + Right: SHORT + Bottom: SHORT +class CONSOLE_SCREEN_BUFFER_INFO: + dwSize: COORD + dwCursorPosition: COORD + wAttributes: WORD + srWindow: SMALL_RECT + dwMaximumWindowSize: COORD +class CONSOLE_CURSOR_INFO: + dwSize: ULONG + bVisible: BOOL +class CHAR_INFO: + UnicodeChar: WCHAR + Attributes: WORD +class KEY_EVENT_RECORD: + bKeyDown: BOOL + wRepeatCount: WORD + wVirtualKeyCode: WORD + wVirtualScanCode: WORD + uChar: WCHAR + dwControlKeyState: ULONG +class MOUSE_EVENT_RECORD: + dwMousePosition: COORD + dwButtonState: ULONG + dwControlKeyState: ULONG + dwEventFlags: ULONG +class WINDOW_BUFFER_SIZE_RECORD: + dwSize: COORD +class INPUT_RECORD: + EventType: WORD + Event: KEY_EVENT_RECORD + +def SetConsoleOutputCP(codepage: UINT) -> BOOL | t.State: pass + +def SetConsoleCP(codepage: UINT) -> BOOL | t.State: pass + +def GetConsoleCP() -> UINT | t.State: pass + +def GetConsoleOutputCP() -> UINT | t.State: pass + +def GetConsoleScreenBufferInfo(hConsoleOutput: HANDLE, lpConsoleScreenBufferInfo: CONSOLE_SCREEN_BUFFER_INFO | t.CPtr) -> BOOL | t.State: pass + +def SetConsoleScreenBufferSize(hConsoleOutput: HANDLE, dwSize: COORD) -> BOOL | t.State: pass + +def SetConsoleCursorPosition(hConsoleOutput: HANDLE, dwCursorPosition: COORD) -> BOOL | t.State: pass + +def GetConsoleCursorInfo(hConsoleOutput: HANDLE, lpConsoleCursorInfo: CONSOLE_CURSOR_INFO | t.CPtr) -> BOOL | t.State: pass + +def SetConsoleCursorInfo(hConsoleOutput: HANDLE, lpConsoleCursorInfo: CONSOLE_CURSOR_INFO | t.CPtr) -> BOOL | t.State: pass + +def SetConsoleTextAttribute(hConsoleOutput: HANDLE, wAttributes: WORD) -> BOOL | t.State: pass + +def FillConsoleOutputCharacterA(hConsoleOutput: HANDLE, cCharacter: t.CChar, nLength: ULONG, dwWriteCoord: COORD, lpNumberOfCharsWritten: ULONG | t.CPtr) -> BOOL | t.State: pass + +def FillConsoleOutputCharacterW(hConsoleOutput: HANDLE, cCharacter: WCHAR, nLength: ULONG, dwWriteCoord: COORD, lpNumberOfCharsWritten: ULONG | t.CPtr) -> BOOL | t.State: pass + +def FillConsoleOutputAttribute(hConsoleOutput: HANDLE, wAttribute: WORD, nLength: ULONG, dwWriteCoord: COORD, lpNumberOfAttrsWritten: ULONG | t.CPtr) -> BOOL | t.State: pass + +def WriteConsoleA(hConsoleOutput: HANDLE, lpBuffer: t.CConst | VOIDPTR, nNumberOfCharsToWrite: ULONG, lpNumberOfCharsWritten: ULONG | t.CPtr, lpReserved: VOIDPTR) -> BOOL | t.State: pass + +def WriteConsoleW(hConsoleOutput: HANDLE, lpBuffer: t.CConst | VOIDPTR, nNumberOfCharsToWrite: ULONG, lpNumberOfCharsWritten: ULONG | t.CPtr, lpReserved: VOIDPTR) -> BOOL | t.State: pass + +def ReadConsoleA(hConsoleInput: HANDLE, lpBuffer: VOIDPTR, nNumberOfCharsToRead: ULONG, lpNumberOfCharsRead: ULONG | t.CPtr, pInputControl: VOIDPTR) -> BOOL | t.State: pass + +def ReadConsoleW(hConsoleInput: HANDLE, lpBuffer: VOIDPTR, nNumberOfCharsToRead: ULONG, lpNumberOfCharsRead: ULONG | t.CPtr, pInputControl: VOIDPTR) -> BOOL | t.State: pass + +def GetConsoleMode(hConsoleHandle: HANDLE, lpMode: ULONG | t.CPtr) -> BOOL | t.State: pass + +def SetConsoleMode(hConsoleHandle: HANDLE, dwMode: ULONG) -> BOOL | t.State: pass + +def ReadConsoleInputA(hConsoleInput: HANDLE, lpBuffer: INPUT_RECORD | t.CPtr, nLength: ULONG, lpNumberOfEventsRead: ULONG | t.CPtr) -> BOOL | t.State: pass + +def ReadConsoleInputW(hConsoleInput: HANDLE, lpBuffer: INPUT_RECORD | t.CPtr, nLength: ULONG, lpNumberOfEventsRead: ULONG | t.CPtr) -> BOOL | t.State: pass + +def GetNumberOfConsoleInputEvents(hConsoleInput: HANDLE, lpNumberOfEvents: ULONG | t.CPtr) -> BOOL | t.State: pass + +def FlushConsoleInputBuffer(hConsoleInput: HANDLE) -> BOOL | t.State: pass + +def SetConsoleTitleA(lpConsoleTitle: LPCSTR) -> BOOL | t.State: pass + +def SetConsoleTitleW(lpConsoleTitle: LPCWSTR) -> BOOL | t.State: pass + +def GetConsoleTitleA(lpConsoleTitle: CHARPTR, nSize: ULONG) -> ULONG | t.State: pass + +def GetConsoleTitleW(lpConsoleTitle: WCHARPTR, nSize: ULONG) -> ULONG | t.State: pass + +def AllocConsole() -> BOOL | t.State: pass + +def FreeConsole() -> BOOL | t.State: pass + +def SetConsoleWindowInfo(hConsoleOutput: HANDLE, bAbsolute: BOOL, lpConsoleWindow: SMALL_RECT | t.CPtr) -> BOOL | t.State: pass + +def ScrollConsoleScreenBufferA(hConsoleOutput: HANDLE, lpScrollRectangle: SMALL_RECT | t.CPtr, lpClipRectangle: SMALL_RECT | t.CPtr, dwDestinationOrigin: COORD, lpFill: CHAR_INFO | t.CPtr) -> BOOL | t.State: pass diff --git a/Test/TestProject/temp/d282a7cb3385ecf0.pyi b/Test/TestProject2/temp/c39cbbae4b6e264f.pyi similarity index 98% rename from Test/TestProject/temp/d282a7cb3385ecf0.pyi rename to Test/TestProject2/temp/c39cbbae4b6e264f.pyi index b79c5b2..f6638ba 100644 --- a/Test/TestProject/temp/d282a7cb3385ecf0.pyi +++ b/Test/TestProject2/temp/c39cbbae4b6e264f.pyi @@ -46,7 +46,7 @@ MAX_WBITS: t.CDefine = 15 DEF_BUF_SIZE: t.CDefine = 16384 DEF_MEM_LEVEL: t.CDefine = 8 ZLIB_VERSION: t.CDefine = "1.3.2" -pyzlib_error_msg: t.CExtern | list[t.CChar, 512] +pyzlib_error_msg: t.CExtern | t.CArray[t.CChar, 512] pyzlib_error_code_val: t.CExtern | t.CInt @t.Object diff --git a/Test/TestProject/temp/0d4517fd5afeb330.pyi b/Test/TestProject2/temp/c9d54a4158f7f5a8.pyi similarity index 76% rename from Test/TestProject/temp/0d4517fd5afeb330.pyi rename to Test/TestProject2/temp/c9d54a4158f7f5a8.pyi index 00a5072..3e2d738 100644 --- a/Test/TestProject/temp/0d4517fd5afeb330.pyi +++ b/Test/TestProject2/temp/c9d54a4158f7f5a8.pyi @@ -8,7 +8,7 @@ import t, c SHA256_BLOCK_LEN: t.CDefine = 64 SHA256_DIGEST_LEN: t.CDefine = 32 -sha256_K: t.CExtern | list[t.CUInt32T, 64] +sha256_K: t.CExtern | t.CArray[t.CUInt32T, 64] def s0(x: t.CUInt32T) -> t.CUInt32T: pass @@ -25,10 +25,10 @@ def Maj(x: t.CUInt32T, y: t.CUInt32T, z: t.CUInt32T) -> t.CUInt32T: pass @t.Object class sha256: - state: list[t.CUInt32T, 8] + state: t.CArray[t.CUInt32T, 8] count: t.CUInt64T - buf: list[t.CUInt8T, SHA256_BLOCK_LEN] + buf: t.CArray[t.CUInt8T, SHA256_BLOCK_LEN] def __init__(self: sha256) -> t.CInt: pass def transform(self: sha256, block: t.CUInt8T | t.CPtr) -> t.CInt: pass def update(self: sha256, s: str) -> t.CInt: pass - def final(self: sha256, out: list[t.CUInt8T, SHA256_DIGEST_LEN]) -> t.CInt: pass \ No newline at end of file + def final(self: sha256, out: t.CArray[t.CUInt8T, SHA256_DIGEST_LEN]) -> t.CInt: pass \ No newline at end of file diff --git a/Test/TestProject2/temp/c9f4be41ca1cc2b4.pyi b/Test/TestProject2/temp/c9f4be41ca1cc2b4.pyi new file mode 100644 index 0000000..fdbd7ec --- /dev/null +++ b/Test/TestProject2/temp/c9f4be41ca1cc2b4.pyi @@ -0,0 +1,22 @@ +""" +Auto-generated Python stub file from viperio.py +Module: viperio +""" + + +import t, c +from stdint import * + +class Buf: + data: t.CChar | t.CPtr + length: t.CSizeT + capacity: t.CSizeT + owned: bool + def __init__(self: Buf, data: t.CChar | t.CPtr, capacity: t.CSizeT, length: t.CSizeT, owned: bool) -> t.CInt: pass + def clear(self: Buf) -> t.CInt: pass + def write(self: Buf, src: t.CChar | t.CPtr, count: t.CSizeT) -> t.CSizeT: pass + def cstr(self: Buf) -> t.CChar | t.CPtr: pass + def reset(self: Buf) -> t.CInt: pass + def __enter__(self: Buf) -> 'Buf' | t.CPtr: pass + def __exit__(self: Buf) -> t.CInt: pass + def free(self: Buf) -> t.CInt: pass \ No newline at end of file diff --git a/Test/TestProject/temp/94496ec50b0d13fc.pyi b/Test/TestProject2/temp/cc436a125bbaf28c.pyi similarity index 76% rename from Test/TestProject/temp/94496ec50b0d13fc.pyi rename to Test/TestProject2/temp/cc436a125bbaf28c.pyi index 69888a2..a905387 100644 --- a/Test/TestProject/temp/94496ec50b0d13fc.pyi +++ b/Test/TestProject2/temp/cc436a125bbaf28c.pyi @@ -20,15 +20,15 @@ def md5_I(x: t.CUInt32T, y: t.CUInt32T, z: t.CUInt32T) -> t.CUInt32T: pass def md5_rotl(x: t.CUInt32T, n: t.CInt) -> t.CUInt32T: pass -md5_T: t.CExtern | list[t.CUInt32T, 64] -md5_S: t.CExtern | list[t.CInt, 64] +md5_T: t.CExtern | t.CArray[t.CUInt32T, 64] +md5_S: t.CExtern | t.CArray[t.CInt, 64] @t.Object class md5: - state: list[t.CUInt32T, 4] + state: t.CArray[t.CUInt32T, 4] count: t.CUInt64T - buf: list[t.CUInt8T, MD5_BLOCK_LEN] + buf: t.CArray[t.CUInt8T, MD5_BLOCK_LEN] def __init__(self: md5) -> t.CInt: pass def transform(self: md5, block: t.CUInt8T | t.CPtr) -> t.CInt: pass def update(self: md5, s: str) -> t.CInt: pass - def final(self: md5, out: list[t.CUInt8T, MD5_DIGEST_LEN]) -> t.CInt: pass \ No newline at end of file + def final(self: md5, out: t.CArray[t.CUInt8T, MD5_DIGEST_LEN]) -> t.CInt: pass \ No newline at end of file diff --git a/Test/TestProject/temp/a9fa0f6200c09e65.pyi b/Test/TestProject2/temp/cd520d14822f3f19.pyi similarity index 89% rename from Test/TestProject/temp/a9fa0f6200c09e65.pyi rename to Test/TestProject2/temp/cd520d14822f3f19.pyi index f9f328c..929cc04 100644 --- a/Test/TestProject/temp/a9fa0f6200c09e65.pyi +++ b/Test/TestProject2/temp/cd520d14822f3f19.pyi @@ -27,11 +27,11 @@ ZDEFLATE_LIT_COUNT: t.CDefine = 286 ZDEFLATE_DIST_COUNT: t.CDefine = 30 ZDEFLATE_LEN_SYMBOLS_BASE: t.CDefine = 257 ZDEFLATE_END_OF_BLOCK: t.CDefine = 256 -zdeflate_len_extra_bits: t.CExtern | list[t.CInt, 29] -zdeflate_len_base: t.CExtern | list[t.CInt, 29] -zdeflate_dist_extra_bits: t.CExtern | list[t.CInt, 30] -zdeflate_dist_base: t.CExtern | list[t.CInt, 30] -zdeflate_codelen_order: t.CExtern | list[int, 19] +zdeflate_len_extra_bits: t.CExtern | t.CArray[t.CInt, 29] +zdeflate_len_base: t.CExtern | t.CArray[t.CInt, 29] +zdeflate_dist_extra_bits: t.CExtern | t.CArray[t.CInt, 30] +zdeflate_dist_base: t.CExtern | t.CArray[t.CInt, 30] +zdeflate_codelen_order: t.CExtern | t.CArray[int, 19] @t.Object class zbit_writer: diff --git a/Test/TestProject/temp/2d7f623c6e3004ce.pyi b/Test/TestProject2/temp/f80740e7bcee16ae.pyi similarity index 100% rename from Test/TestProject/temp/2d7f623c6e3004ce.pyi rename to Test/TestProject2/temp/f80740e7bcee16ae.pyi diff --git a/Test/TestProject2/temp/fa3691e66b426950.pyi b/Test/TestProject2/temp/fa3691e66b426950.pyi new file mode 100644 index 0000000..48fd36c --- /dev/null +++ b/Test/TestProject2/temp/fa3691e66b426950.pyi @@ -0,0 +1,80 @@ +""" +Auto-generated Python stub file from w32.fileio.py +Module: w32.fileio +""" + + +import t, c +from stdint import * +import w32.win32base +import w32.win32file + +class MODE(t.CEnum): + R = 0 + W = 1 + A = 2 + RP = 3 + WP = 4 + AP = 5 + X = 6 + XP = 7 +class FRESULT(t.CEnum): + OK = 0 + ERR = -1 + ERR_CLOSED = -2 + ERR_PERM = -3 + ERR_IO = -4 + ERR_NOTFOUND = -5 + +SEEK_SET: t.CDefine = 0 +SEEK_CUR: t.CDefine = 1 +SEEK_END: t.CDefine = 2 +INVALID_SET_FILE_POINTER: t.CDefine = -1 +SHARE_READ: t.CDefine = 0x00000001 +SHARE_WRITE: t.CDefine = 0x00000002 +SHARE_DELETE: t.CDefine = 0x00000004 + +class File: + handle: w32.win32base.HANDLE + closed: bool + can_read: bool + can_write: bool + is_append: bool + _share_mode: ULONG + def __init__(self: File, filename: str, mode: ULONG, share: ULONG) -> t.CInt: pass + def __enter__(self: File) -> 'File' | t.CPtr: pass + def __exit__(self: File) -> t.CInt: pass + def read(self: File, buf: bytes, count: ULONG) -> LONG: pass + def write(self: File, buf: bytes, count: ULONG) -> LONG: pass + def write_str(self: File, s: str) -> LONG: pass + def seek(self: File, offset: LONG, origin: ULONG) -> LONG: pass + def tell(self: File) -> LONG: pass + def close(self: File) -> LONG: pass + def flush(self: File) -> LONG: pass + def size(self: File) -> LONGLONG: pass + def readline(self: File, buf: bytes, max_count: ULONG) -> LONG: pass + def read_all(self: File, buf: bytes, max_count: ULONG) -> LONG: pass +class FileW: + handle: HANDLE + closed: bool + can_read: bool + can_write: bool + is_append: bool + _share_mode: ULONG + def __init__(self: FileW, filename: LPCWSTR, mode: ULONG, share: ULONG) -> t.CInt: pass + def __enter__(self: FileW) -> 'FileW' | t.CPtr: pass + def __exit__(self: FileW) -> t.CInt: pass + def read(self: FileW, buf: bytes, count: ULONG) -> LONG: pass + def write(self: FileW, buf: bytes, count: ULONG) -> LONG: pass + def write_str(self: FileW, s: str) -> LONG: pass + def seek(self: FileW, offset: LONG, origin: ULONG) -> LONG: pass + def tell(self: FileW) -> LONG: pass + def close(self: FileW) -> LONG: pass + def flush(self: FileW) -> LONG: pass + def size(self: FileW) -> LONGLONG: pass + def readline(self: FileW, buf: bytes, max_count: ULONG) -> LONG: pass + def read_all(self: FileW, buf: bytes, max_count: ULONG) -> LONG: pass + +def open(filename: str, mode: ULONG, share: ULONG) -> File | t.CPtr: pass + +def openw(filename: LPCWSTR, mode: ULONG, share: ULONG) -> FileW | t.CPtr: pass diff --git a/Test/TestProject2/temp/faec3233d98371da.pyi b/Test/TestProject2/temp/faec3233d98371da.pyi deleted file mode 100644 index 308f5cb..0000000 --- a/Test/TestProject2/temp/faec3233d98371da.pyi +++ /dev/null @@ -1,54 +0,0 @@ -""" -Auto-generated Python stub file from zc.logic_test.py -Module: zc.logic_test -""" - - -import config -import t, c - -def ForRangeBasicTest(stop: t.CInt) -> t.CInt: pass - -def ForRangeWithStartStop(start: t.CInt, stop: t.CInt, step: t.CInt) -> t.CInt: pass - -def NestedForRangeTest(rows: t.CInt, cols: t.CInt) -> t.CInt: pass - -def ForWithIfBreakTest(data_size: t.CInt) -> t.CInt: pass - -def ForWithIfContinueTest(n: t.CInt) -> t.CInt: pass - -def ForWithElifBranchTest(value: t.CInt) -> t.CInt: pass - -def WhileWithIfElifElseTest(iterations: t.CInt) -> t.CInt: pass - -def WhileWithNestedIfTest(limit: t.CInt) -> t.CInt: pass - -def WhileWithMatchCaseTest(value: t.CInt) -> t.CInt: pass - -def WhileWithMatchCaseNoBreakTest(value: t.CInt) -> t.CInt: pass - -def ComplexForWhileMatchTest(outer_limit: t.CInt, inner_limit: t.CInt) -> t.CInt: pass - -def ForWithCaseAndNoBreakTest(n: t.CInt) -> t.CInt: pass - -def WhileWithBreakConditionTest(limit: t.CInt) -> t.CInt: pass - -def NestedWhileWithMultipleBreakPoints(depth: t.CInt, width: t.CInt) -> t.CInt: pass - -def ForWithMatchCaseInLoopTest(iterations: t.CInt) -> t.CInt: pass - -def ComplexLogicWithElifChains(a: t.CInt, b: t.CInt, c_val: t.CInt) -> t.CInt: pass - -def ForRangeWithStepAndCondition(n: t.CInt, step: t.CInt) -> t.CInt: pass - -def MatchCaseWithGuardConditions(value: t.CInt) -> t.CInt: pass - -def WhileWithMultipleMatchCases(iterations: t.CInt) -> t.CInt: pass - -def ForWhileMixWithBreakAndContinue(n: t.CInt) -> t.CInt: pass - -def ComplexCaseMatchingWithRanges(start: t.CInt, end: t.CInt) -> t.CInt: pass - -def WhileWithElifInElifChain(limit: t.CInt) -> t.CInt: pass - -def ForWithCaseNoBreakNested(inner_limit: t.CInt) -> t.CInt: pass diff --git a/Test/TestProject3/App/main.py b/Test/TestProject3/App/main.py index 738c5da..4423686 100644 --- a/Test/TestProject3/App/main.py +++ b/Test/TestProject3/App/main.py @@ -1,484 +1,519 @@ -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 definetest -import enumtest -import mpooltest -import vectortest -import fileiotest - - -# === 函数泛型 === - -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 继承 + 虚方法(Gargantua 风格) === - -@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) - - -# === 运算符重载 + 链式调用(Gargantua V3 风格,堆分配) === - -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) - - buf: CChar | CPtr = CPtr(stdlib.malloc(256)) - - # === 基础函数泛型 === - 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)) - - # === 基础结构体泛型 === - a = A(100) - print(a.get_a()) - p1 = Pair(10, 20) - print(p1.get_first()) - print(p1.get_second()) - - # === 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) - - # === 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) - - # === 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) - - # === 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) - - # === 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) - - # === 多层继承 === - 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) - - # === 泛型 + 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()) - - # === 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) - - # === 新语法类型强转 (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) - - # === CDefine 宏测试 === - definetest.define_main() - - # === Enum 测试 === - enumtest.enum_main() - - # === MPool OOP 测试 === - mpooltest.mpool_main() - - # === Vector 泛型测试 === - vectortest.vector_main() - - # === Win32 FileIO 测试 === - fileiotest.fileio_main() - - return 0 +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 definetest +import enumtest +import mpooltest +import vectortest +import fileiotest +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 继承 + 虚方法(Gargantua 风格) === + +@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) + + +# === 运算符重载 + 链式调用(Gargantua V3 风格,堆分配) === + +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("TestProject3: 泛型与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("新语法类型强转测试完成") + + # === CDefine 宏测试 === + testcheck.section("CDefine 宏测试") + definetest.define_main() + testcheck.ok("CDefine 宏测试完成") + + # === Enum 测试 === + testcheck.section("Enum 测试") + enumtest.enum_main() + testcheck.ok("Enum 测试完成") + + # === MPool OOP 测试 === + testcheck.section("MPool OOP 测试") + mpooltest.mpool_main() + testcheck.ok("MPool OOP 测试完成") + + # === Vector 泛型测试 === + testcheck.section("Vector 泛型测试") + vectortest.vector_main() + testcheck.ok("Vector 泛型测试完成") + + # === Win32 FileIO 测试 === + testcheck.section("Win32 FileIO 测试") + fileiotest.fileio_main() + testcheck.ok("Win32 FileIO 测试完成") + + return testcheck.end() diff --git a/Test/TestProject3/App/mpooltest.py b/Test/TestProject3/App/mpooltest.py index 3379069..40db0ea 100644 --- a/Test/TestProject3/App/mpooltest.py +++ b/Test/TestProject3/App/mpooltest.py @@ -7,7 +7,7 @@ import mpool def mpool_main() -> CInt: - buf: CChar | CPtr = CPtr(stdlib.malloc(256)) + buf: bytes = stdlib.malloc(256) arena: bytes = stdlib.malloc(4096) with mpool.MPool(arena, 4096, 0) as pool: diff --git a/Test/TestProject3/output/067c78e9f121dce3.deps.json b/Test/TestProject3/output/067c78e9f121dce3.deps.json index f7c4d17..02b1eca 100644 --- a/Test/TestProject3/output/067c78e9f121dce3.deps.json +++ b/Test/TestProject3/output/067c78e9f121dce3.deps.json @@ -1 +1 @@ -{"main": "0f4d14c17bf75b10", "enumtest": "1b58766d38d05de3", "viperlib": "2953a7db4185005b", "vector": "3fdd11bdd589aa8c", "mpooltest": "5325ec533a59d71b", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdarg": "71e0a3ffcb3ebfad", "platmacro": "93c1d18e35d188d6", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "fileiotest": "c01b27dbcd683245", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3"} \ No newline at end of file +{"mpool": "0991af0d22263577", "enumtest": "1b58766d38d05de3", "vector": "3fdd11bdd589aa8c", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "stdlib": "6c2029b306556c00", "viperlib": "70b580331b822117", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "platmacro": "93c1d18e35d188d6", "testcheck": "9dbecd0942a39782", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "main": "b235d6477436c524", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "fileiotest": "c01b27dbcd683245", "viperio": "c9f4be41ca1cc2b4", "mpooltest": "f8a7f964e23490fb", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3"} \ No newline at end of file diff --git a/Test/TestProject3/output/0991af0d22263577.deps.json b/Test/TestProject3/output/0991af0d22263577.deps.json new file mode 100644 index 0000000..789f081 --- /dev/null +++ b/Test/TestProject3/output/0991af0d22263577.deps.json @@ -0,0 +1 @@ +{"mpool": "0991af0d22263577", "enumtest": "1b58766d38d05de3", "vector": "3fdd11bdd589aa8c", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "stdlib": "6c2029b306556c00", "viperlib": "70b580331b822117", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "platmacro": "93c1d18e35d188d6", "testcheck": "9dbecd0942a39782", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "main": "b235d6477436c524", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "fileiotest": "c01b27dbcd683245", "viperio": "c9f4be41ca1cc2b4", "mpooltest": "f8a7f964e23490fb", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9"} \ No newline at end of file diff --git a/Test/TestProject3/output/0f4d14c17bf75b10.deps.json b/Test/TestProject3/output/0f4d14c17bf75b10.deps.json deleted file mode 100644 index f95c08f..0000000 --- a/Test/TestProject3/output/0f4d14c17bf75b10.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"enumtest": "1b58766d38d05de3", "viperlib": "2953a7db4185005b", "vector": "3fdd11bdd589aa8c", "mpooltest": "5325ec533a59d71b", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdarg": "71e0a3ffcb3ebfad", "platmacro": "93c1d18e35d188d6", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "fileiotest": "c01b27dbcd683245", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9"} \ No newline at end of file diff --git a/Test/TestProject3/output/1b58766d38d05de3.deps.json b/Test/TestProject3/output/1b58766d38d05de3.deps.json index 385a702..832b191 100644 --- a/Test/TestProject3/output/1b58766d38d05de3.deps.json +++ b/Test/TestProject3/output/1b58766d38d05de3.deps.json @@ -1 +1 @@ -{"main": "0f4d14c17bf75b10", "viperlib": "2953a7db4185005b", "vector": "3fdd11bdd589aa8c", "mpooltest": "5325ec533a59d71b", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdarg": "71e0a3ffcb3ebfad", "platmacro": "93c1d18e35d188d6", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "fileiotest": "c01b27dbcd683245", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9"} \ No newline at end of file +{"mpool": "0991af0d22263577", "vector": "3fdd11bdd589aa8c", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "stdlib": "6c2029b306556c00", "viperlib": "70b580331b822117", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "platmacro": "93c1d18e35d188d6", "testcheck": "9dbecd0942a39782", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "main": "b235d6477436c524", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "fileiotest": "c01b27dbcd683245", "viperio": "c9f4be41ca1cc2b4", "mpooltest": "f8a7f964e23490fb", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9"} \ No newline at end of file diff --git a/Test/TestProject3/output/2953a7db4185005b.deps.json b/Test/TestProject3/output/2953a7db4185005b.deps.json deleted file mode 100644 index dd5f0cf..0000000 --- a/Test/TestProject3/output/2953a7db4185005b.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"main": "0f4d14c17bf75b10", "enumtest": "1b58766d38d05de3", "viperlib": "2953a7db4185005b", "vector": "3fdd11bdd589aa8c", "mpooltest": "5325ec533a59d71b", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdarg": "71e0a3ffcb3ebfad", "platmacro": "93c1d18e35d188d6", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "fileiotest": "c01b27dbcd683245", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file diff --git a/Test/TestProject3/output/29813d57621099a9.deps.json b/Test/TestProject3/output/29813d57621099a9.deps.json index dd5f0cf..1829371 100644 --- a/Test/TestProject3/output/29813d57621099a9.deps.json +++ b/Test/TestProject3/output/29813d57621099a9.deps.json @@ -1 +1 @@ -{"main": "0f4d14c17bf75b10", "enumtest": "1b58766d38d05de3", "viperlib": "2953a7db4185005b", "vector": "3fdd11bdd589aa8c", "mpooltest": "5325ec533a59d71b", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdarg": "71e0a3ffcb3ebfad", "platmacro": "93c1d18e35d188d6", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "fileiotest": "c01b27dbcd683245", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file +{"mpool": "0991af0d22263577", "enumtest": "1b58766d38d05de3", "vector": "3fdd11bdd589aa8c", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "stdlib": "6c2029b306556c00", "viperlib": "70b580331b822117", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "platmacro": "93c1d18e35d188d6", "testcheck": "9dbecd0942a39782", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "main": "b235d6477436c524", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "fileiotest": "c01b27dbcd683245", "viperio": "c9f4be41ca1cc2b4", "mpooltest": "f8a7f964e23490fb", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file diff --git a/Test/TestProject3/output/3fdd11bdd589aa8c.deps.json b/Test/TestProject3/output/3fdd11bdd589aa8c.deps.json index dd5f0cf..789f081 100644 --- a/Test/TestProject3/output/3fdd11bdd589aa8c.deps.json +++ b/Test/TestProject3/output/3fdd11bdd589aa8c.deps.json @@ -1 +1 @@ -{"main": "0f4d14c17bf75b10", "enumtest": "1b58766d38d05de3", "viperlib": "2953a7db4185005b", "vector": "3fdd11bdd589aa8c", "mpooltest": "5325ec533a59d71b", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdarg": "71e0a3ffcb3ebfad", "platmacro": "93c1d18e35d188d6", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "fileiotest": "c01b27dbcd683245", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file +{"mpool": "0991af0d22263577", "enumtest": "1b58766d38d05de3", "vector": "3fdd11bdd589aa8c", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "stdlib": "6c2029b306556c00", "viperlib": "70b580331b822117", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "platmacro": "93c1d18e35d188d6", "testcheck": "9dbecd0942a39782", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "main": "b235d6477436c524", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "fileiotest": "c01b27dbcd683245", "viperio": "c9f4be41ca1cc2b4", "mpooltest": "f8a7f964e23490fb", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9"} \ No newline at end of file diff --git a/Test/TestProject3/output/5325ec533a59d71b.deps.json b/Test/TestProject3/output/5325ec533a59d71b.deps.json deleted file mode 100644 index 74a9d28..0000000 --- a/Test/TestProject3/output/5325ec533a59d71b.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"main": "0f4d14c17bf75b10", "enumtest": "1b58766d38d05de3", "viperlib": "2953a7db4185005b", "vector": "3fdd11bdd589aa8c", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdarg": "71e0a3ffcb3ebfad", "platmacro": "93c1d18e35d188d6", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "fileiotest": "c01b27dbcd683245", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9"} \ No newline at end of file diff --git a/Test/TestProject3/output/5a6a2137958c28c5.deps.json b/Test/TestProject3/output/5a6a2137958c28c5.deps.json index 26eaaa8..789f081 100644 --- a/Test/TestProject3/output/5a6a2137958c28c5.deps.json +++ b/Test/TestProject3/output/5a6a2137958c28c5.deps.json @@ -1 +1 @@ -{"main": "0f4d14c17bf75b10", "enumtest": "1b58766d38d05de3", "viperlib": "2953a7db4185005b", "vector": "3fdd11bdd589aa8c", "mpooltest": "5325ec533a59d71b", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdarg": "71e0a3ffcb3ebfad", "platmacro": "93c1d18e35d188d6", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "fileiotest": "c01b27dbcd683245", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9"} \ No newline at end of file +{"mpool": "0991af0d22263577", "enumtest": "1b58766d38d05de3", "vector": "3fdd11bdd589aa8c", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "stdlib": "6c2029b306556c00", "viperlib": "70b580331b822117", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "platmacro": "93c1d18e35d188d6", "testcheck": "9dbecd0942a39782", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "main": "b235d6477436c524", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "fileiotest": "c01b27dbcd683245", "viperio": "c9f4be41ca1cc2b4", "mpooltest": "f8a7f964e23490fb", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9"} \ No newline at end of file diff --git a/Test/TestProject3/output/64ac83614c9bdbc6.deps.json b/Test/TestProject3/output/64ac83614c9bdbc6.deps.json index 5d84cc9..69f2e2c 100644 --- a/Test/TestProject3/output/64ac83614c9bdbc6.deps.json +++ b/Test/TestProject3/output/64ac83614c9bdbc6.deps.json @@ -1 +1 @@ -{"main": "0f4d14c17bf75b10", "enumtest": "1b58766d38d05de3", "viperlib": "2953a7db4185005b", "vector": "3fdd11bdd589aa8c", "mpooltest": "5325ec533a59d71b", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdarg": "71e0a3ffcb3ebfad", "platmacro": "93c1d18e35d188d6", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "fileiotest": "c01b27dbcd683245", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9"} \ No newline at end of file +{"mpool": "0991af0d22263577", "enumtest": "1b58766d38d05de3", "vector": "3fdd11bdd589aa8c", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "viperlib": "70b580331b822117", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "platmacro": "93c1d18e35d188d6", "testcheck": "9dbecd0942a39782", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "main": "b235d6477436c524", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "fileiotest": "c01b27dbcd683245", "viperio": "c9f4be41ca1cc2b4", "mpooltest": "f8a7f964e23490fb", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9"} \ No newline at end of file diff --git a/Test/TestProject3/output/68c4fe4b12c908e3.deps.json b/Test/TestProject3/output/68c4fe4b12c908e3.deps.json deleted file mode 100644 index dd5f0cf..0000000 --- a/Test/TestProject3/output/68c4fe4b12c908e3.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"main": "0f4d14c17bf75b10", "enumtest": "1b58766d38d05de3", "viperlib": "2953a7db4185005b", "vector": "3fdd11bdd589aa8c", "mpooltest": "5325ec533a59d71b", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdarg": "71e0a3ffcb3ebfad", "platmacro": "93c1d18e35d188d6", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "fileiotest": "c01b27dbcd683245", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file diff --git a/Test/TestProject3/output/6aee24fdefa3cbc0.deps.json b/Test/TestProject3/output/6aee24fdefa3cbc0.deps.json deleted file mode 100644 index 26eaaa8..0000000 --- a/Test/TestProject3/output/6aee24fdefa3cbc0.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"main": "0f4d14c17bf75b10", "enumtest": "1b58766d38d05de3", "viperlib": "2953a7db4185005b", "vector": "3fdd11bdd589aa8c", "mpooltest": "5325ec533a59d71b", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdarg": "71e0a3ffcb3ebfad", "platmacro": "93c1d18e35d188d6", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "fileiotest": "c01b27dbcd683245", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9"} \ No newline at end of file diff --git a/Test/TestProject3/output/70b580331b822117.deps.json b/Test/TestProject3/output/70b580331b822117.deps.json new file mode 100644 index 0000000..789f081 --- /dev/null +++ b/Test/TestProject3/output/70b580331b822117.deps.json @@ -0,0 +1 @@ +{"mpool": "0991af0d22263577", "enumtest": "1b58766d38d05de3", "vector": "3fdd11bdd589aa8c", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "stdlib": "6c2029b306556c00", "viperlib": "70b580331b822117", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "platmacro": "93c1d18e35d188d6", "testcheck": "9dbecd0942a39782", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "main": "b235d6477436c524", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "fileiotest": "c01b27dbcd683245", "viperio": "c9f4be41ca1cc2b4", "mpooltest": "f8a7f964e23490fb", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9"} \ No newline at end of file diff --git a/Test/TestProject3/output/72e2d5ccb7cedcf1.deps.json b/Test/TestProject3/output/72e2d5ccb7cedcf1.deps.json index 40e3886..72e7c01 100644 --- a/Test/TestProject3/output/72e2d5ccb7cedcf1.deps.json +++ b/Test/TestProject3/output/72e2d5ccb7cedcf1.deps.json @@ -1 +1 @@ -{"main": "0f4d14c17bf75b10", "enumtest": "1b58766d38d05de3", "viperlib": "2953a7db4185005b", "vector": "3fdd11bdd589aa8c", "mpooltest": "5325ec533a59d71b", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdarg": "71e0a3ffcb3ebfad", "platmacro": "93c1d18e35d188d6", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "fileiotest": "c01b27dbcd683245", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1"} \ No newline at end of file +{"mpool": "0991af0d22263577", "enumtest": "1b58766d38d05de3", "vector": "3fdd11bdd589aa8c", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "stdlib": "6c2029b306556c00", "viperlib": "70b580331b822117", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "platmacro": "93c1d18e35d188d6", "testcheck": "9dbecd0942a39782", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "main": "b235d6477436c524", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "fileiotest": "c01b27dbcd683245", "viperio": "c9f4be41ca1cc2b4", "mpooltest": "f8a7f964e23490fb", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1"} \ No newline at end of file diff --git a/Test/TestProject3/output/9dbecd0942a39782.deps.json b/Test/TestProject3/output/9dbecd0942a39782.deps.json new file mode 100644 index 0000000..789f081 --- /dev/null +++ b/Test/TestProject3/output/9dbecd0942a39782.deps.json @@ -0,0 +1 @@ +{"mpool": "0991af0d22263577", "enumtest": "1b58766d38d05de3", "vector": "3fdd11bdd589aa8c", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "stdlib": "6c2029b306556c00", "viperlib": "70b580331b822117", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "platmacro": "93c1d18e35d188d6", "testcheck": "9dbecd0942a39782", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "main": "b235d6477436c524", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "fileiotest": "c01b27dbcd683245", "viperio": "c9f4be41ca1cc2b4", "mpooltest": "f8a7f964e23490fb", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9"} \ No newline at end of file diff --git a/Test/TestProject3/output/abf9ce3160c9279e.deps.json b/Test/TestProject3/output/abf9ce3160c9279e.deps.json index 26eaaa8..789f081 100644 --- a/Test/TestProject3/output/abf9ce3160c9279e.deps.json +++ b/Test/TestProject3/output/abf9ce3160c9279e.deps.json @@ -1 +1 @@ -{"main": "0f4d14c17bf75b10", "enumtest": "1b58766d38d05de3", "viperlib": "2953a7db4185005b", "vector": "3fdd11bdd589aa8c", "mpooltest": "5325ec533a59d71b", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdarg": "71e0a3ffcb3ebfad", "platmacro": "93c1d18e35d188d6", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "fileiotest": "c01b27dbcd683245", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9"} \ No newline at end of file +{"mpool": "0991af0d22263577", "enumtest": "1b58766d38d05de3", "vector": "3fdd11bdd589aa8c", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "stdlib": "6c2029b306556c00", "viperlib": "70b580331b822117", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "platmacro": "93c1d18e35d188d6", "testcheck": "9dbecd0942a39782", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "main": "b235d6477436c524", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "fileiotest": "c01b27dbcd683245", "viperio": "c9f4be41ca1cc2b4", "mpooltest": "f8a7f964e23490fb", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9"} \ No newline at end of file diff --git a/Test/TestProject3/output/b235d6477436c524.deps.json b/Test/TestProject3/output/b235d6477436c524.deps.json new file mode 100644 index 0000000..149da0f --- /dev/null +++ b/Test/TestProject3/output/b235d6477436c524.deps.json @@ -0,0 +1 @@ +{"mpool": "0991af0d22263577", "enumtest": "1b58766d38d05de3", "vector": "3fdd11bdd589aa8c", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "stdlib": "6c2029b306556c00", "viperlib": "70b580331b822117", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "platmacro": "93c1d18e35d188d6", "testcheck": "9dbecd0942a39782", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "fileiotest": "c01b27dbcd683245", "viperio": "c9f4be41ca1cc2b4", "mpooltest": "f8a7f964e23490fb", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9"} \ No newline at end of file diff --git a/Test/TestProject3/output/b5f1dc665c52a1bd.deps.json b/Test/TestProject3/output/b5f1dc665c52a1bd.deps.json new file mode 100644 index 0000000..789f081 --- /dev/null +++ b/Test/TestProject3/output/b5f1dc665c52a1bd.deps.json @@ -0,0 +1 @@ +{"mpool": "0991af0d22263577", "enumtest": "1b58766d38d05de3", "vector": "3fdd11bdd589aa8c", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "stdlib": "6c2029b306556c00", "viperlib": "70b580331b822117", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "platmacro": "93c1d18e35d188d6", "testcheck": "9dbecd0942a39782", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "main": "b235d6477436c524", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "fileiotest": "c01b27dbcd683245", "viperio": "c9f4be41ca1cc2b4", "mpooltest": "f8a7f964e23490fb", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9"} \ No newline at end of file diff --git a/Test/TestProject3/output/bbdf3bbd4c3bc28c.deps.json b/Test/TestProject3/output/bbdf3bbd4c3bc28c.deps.json index 26eaaa8..789f081 100644 --- a/Test/TestProject3/output/bbdf3bbd4c3bc28c.deps.json +++ b/Test/TestProject3/output/bbdf3bbd4c3bc28c.deps.json @@ -1 +1 @@ -{"main": "0f4d14c17bf75b10", "enumtest": "1b58766d38d05de3", "viperlib": "2953a7db4185005b", "vector": "3fdd11bdd589aa8c", "mpooltest": "5325ec533a59d71b", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdarg": "71e0a3ffcb3ebfad", "platmacro": "93c1d18e35d188d6", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "fileiotest": "c01b27dbcd683245", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9"} \ No newline at end of file +{"mpool": "0991af0d22263577", "enumtest": "1b58766d38d05de3", "vector": "3fdd11bdd589aa8c", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "stdlib": "6c2029b306556c00", "viperlib": "70b580331b822117", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "platmacro": "93c1d18e35d188d6", "testcheck": "9dbecd0942a39782", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "main": "b235d6477436c524", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "fileiotest": "c01b27dbcd683245", "viperio": "c9f4be41ca1cc2b4", "mpooltest": "f8a7f964e23490fb", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9"} \ No newline at end of file diff --git a/Test/TestProject3/output/c01b27dbcd683245.deps.json b/Test/TestProject3/output/c01b27dbcd683245.deps.json index 1f541f6..c5eb7c3 100644 --- a/Test/TestProject3/output/c01b27dbcd683245.deps.json +++ b/Test/TestProject3/output/c01b27dbcd683245.deps.json @@ -1 +1 @@ -{"main": "0f4d14c17bf75b10", "enumtest": "1b58766d38d05de3", "viperlib": "2953a7db4185005b", "vector": "3fdd11bdd589aa8c", "mpooltest": "5325ec533a59d71b", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdarg": "71e0a3ffcb3ebfad", "platmacro": "93c1d18e35d188d6", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9"} \ No newline at end of file +{"mpool": "0991af0d22263577", "enumtest": "1b58766d38d05de3", "vector": "3fdd11bdd589aa8c", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "stdlib": "6c2029b306556c00", "viperlib": "70b580331b822117", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "platmacro": "93c1d18e35d188d6", "testcheck": "9dbecd0942a39782", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "main": "b235d6477436c524", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "viperio": "c9f4be41ca1cc2b4", "mpooltest": "f8a7f964e23490fb", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9"} \ No newline at end of file diff --git a/Test/TestProject3/output/c9f4be41ca1cc2b4.deps.json b/Test/TestProject3/output/c9f4be41ca1cc2b4.deps.json index 26eaaa8..789f081 100644 --- a/Test/TestProject3/output/c9f4be41ca1cc2b4.deps.json +++ b/Test/TestProject3/output/c9f4be41ca1cc2b4.deps.json @@ -1 +1 @@ -{"main": "0f4d14c17bf75b10", "enumtest": "1b58766d38d05de3", "viperlib": "2953a7db4185005b", "vector": "3fdd11bdd589aa8c", "mpooltest": "5325ec533a59d71b", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdarg": "71e0a3ffcb3ebfad", "platmacro": "93c1d18e35d188d6", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "fileiotest": "c01b27dbcd683245", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9"} \ No newline at end of file +{"mpool": "0991af0d22263577", "enumtest": "1b58766d38d05de3", "vector": "3fdd11bdd589aa8c", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "stdlib": "6c2029b306556c00", "viperlib": "70b580331b822117", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "platmacro": "93c1d18e35d188d6", "testcheck": "9dbecd0942a39782", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "main": "b235d6477436c524", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "fileiotest": "c01b27dbcd683245", "viperio": "c9f4be41ca1cc2b4", "mpooltest": "f8a7f964e23490fb", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9"} \ No newline at end of file diff --git a/Test/TestProject3/output/f8a7f964e23490fb.deps.json b/Test/TestProject3/output/f8a7f964e23490fb.deps.json new file mode 100644 index 0000000..aefacac --- /dev/null +++ b/Test/TestProject3/output/f8a7f964e23490fb.deps.json @@ -0,0 +1 @@ +{"mpool": "0991af0d22263577", "enumtest": "1b58766d38d05de3", "vector": "3fdd11bdd589aa8c", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "stdlib": "6c2029b306556c00", "viperlib": "70b580331b822117", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "platmacro": "93c1d18e35d188d6", "testcheck": "9dbecd0942a39782", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "main": "b235d6477436c524", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "fileiotest": "c01b27dbcd683245", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9"} \ No newline at end of file diff --git a/Test/TestProject3/output/fa3691e66b426950.deps.json b/Test/TestProject3/output/fa3691e66b426950.deps.json index 26eaaa8..789f081 100644 --- a/Test/TestProject3/output/fa3691e66b426950.deps.json +++ b/Test/TestProject3/output/fa3691e66b426950.deps.json @@ -1 +1 @@ -{"main": "0f4d14c17bf75b10", "enumtest": "1b58766d38d05de3", "viperlib": "2953a7db4185005b", "vector": "3fdd11bdd589aa8c", "mpooltest": "5325ec533a59d71b", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdarg": "71e0a3ffcb3ebfad", "platmacro": "93c1d18e35d188d6", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "fileiotest": "c01b27dbcd683245", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9"} \ No newline at end of file +{"mpool": "0991af0d22263577", "enumtest": "1b58766d38d05de3", "vector": "3fdd11bdd589aa8c", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "stdlib": "6c2029b306556c00", "viperlib": "70b580331b822117", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "platmacro": "93c1d18e35d188d6", "testcheck": "9dbecd0942a39782", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "main": "b235d6477436c524", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "fileiotest": "c01b27dbcd683245", "viperio": "c9f4be41ca1cc2b4", "mpooltest": "f8a7f964e23490fb", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "vectortest": "fc49f6314bad25e9"} \ No newline at end of file diff --git a/Test/TestProject3/output/fc49f6314bad25e9.deps.json b/Test/TestProject3/output/fc49f6314bad25e9.deps.json index da3fd87..6e6383f 100644 --- a/Test/TestProject3/output/fc49f6314bad25e9.deps.json +++ b/Test/TestProject3/output/fc49f6314bad25e9.deps.json @@ -1 +1 @@ -{"main": "0f4d14c17bf75b10", "enumtest": "1b58766d38d05de3", "viperlib": "2953a7db4185005b", "vector": "3fdd11bdd589aa8c", "mpooltest": "5325ec533a59d71b", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "mpool": "68c4fe4b12c908e3", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "stdarg": "71e0a3ffcb3ebfad", "platmacro": "93c1d18e35d188d6", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "fileiotest": "c01b27dbcd683245", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file +{"mpool": "0991af0d22263577", "enumtest": "1b58766d38d05de3", "vector": "3fdd11bdd589aa8c", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "definetest": "64ac83614c9bdbc6", "stdlib": "6c2029b306556c00", "viperlib": "70b580331b822117", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "platmacro": "93c1d18e35d188d6", "testcheck": "9dbecd0942a39782", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "main": "b235d6477436c524", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "fileiotest": "c01b27dbcd683245", "viperio": "c9f4be41ca1cc2b4", "mpooltest": "f8a7f964e23490fb", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file diff --git a/Test/TestProject3/temp/0991af0d22263577.pyi b/Test/TestProject3/temp/0991af0d22263577.pyi new file mode 100644 index 0000000..f001c8a --- /dev/null +++ b/Test/TestProject3/temp/0991af0d22263577.pyi @@ -0,0 +1,50 @@ +""" +Auto-generated Python stub file from mpool.py +Module: mpool +""" + + +import t, c +from stdint import * +import viperio +import string + +MPOOL_ALIGN: t.CDefine = 8 +MPOOL_TYPE_SLAB: t.CDefine = 0 +MPOOL_TYPE_BUMP: t.CDefine = 1 + +def _align_up(val: t.CSizeT, align: t.CSizeT) -> t.CSizeT: pass + + +class MPool: + mtype: t.CInt + mem: t.CVoid | t.CPtr + mem_size: t.CSizeT + offset: t.CSizeT + high_water: t.CSizeT + block_size: t.CSizeT + block_count: t.CSizeT + used_count: t.CSizeT + free_list: t.CVoid | t.CPtr + alloc_map: t.CUInt8T | t.CPtr + alloc_map_size: t.CSizeT + def __init__(self: MPool, mem: t.CVoid | t.CPtr, mem_size: t.CSizeT, block_size: t.CSizeT) -> t.CInt: pass + def _init_bump(self: MPool, mem: t.CVoid | t.CPtr, mem_size: t.CSizeT) -> t.CInt: pass + def _init_slab(self: MPool, mem: t.CVoid | t.CPtr, mem_size: t.CSizeT, block_size: t.CSizeT) -> t.CInt: pass + def __enter__(self: MPool) -> 'MPool' | t.CPtr: pass + def __exit__(self: MPool) -> t.CInt: pass + def _slab_reset(self: MPool) -> t.CInt: pass + def alloc(self: MPool, size: t.CSizeT) -> t.CVoid | t.CPtr: pass + def alloc_buf(self: MPool, capacity: t.CSizeT) -> viperio.Buf | t.CPtr: pass + def free(self: MPool, ptr: t.CVoid | t.CPtr) -> t.CInt: pass + def realloc(self: MPool, ptr: t.CVoid | t.CPtr, old_size: t.CSizeT, new_size: t.CSizeT) -> t.CVoid | t.CPtr: pass + def reset(self: MPool) -> t.CInt: pass + def _bump_alloc(self: MPool, size: t.CSizeT) -> t.CVoid | t.CPtr: pass + def _slab_alloc(self: MPool) -> t.CVoid | t.CPtr: pass + def _slab_free(self: MPool, ptr: t.CVoid | t.CPtr) -> t.CInt: pass + +def bump_create(mem: t.CVoid | t.CPtr, mem_size: t.CSizeT) -> MPool | t.CPtr: pass + +def alloc(pool: MPool | t.CPtr, size: t.CSizeT) -> t.CVoid | t.CPtr: pass + +def reset(pool: MPool | t.CPtr) -> t.CInt: pass diff --git a/Test/TestProject3/temp/49bd8cba55979f76.pyi b/Test/TestProject3/temp/49bd8cba55979f76.pyi new file mode 100644 index 0000000..f1d844a --- /dev/null +++ b/Test/TestProject3/temp/49bd8cba55979f76.pyi @@ -0,0 +1,75 @@ +""" +Auto-generated Python stub file from stdint.py +Module: stdint +""" + +import c + + +import t + +INT: t.CTypedef = t.CInt +INTPTR: t.CTypedef = t.CInt | t.CPtr +BOOL: t.CTypedef = t.CInt +UINT: t.CTypedef = t.CUnsignedInt +UINTPTR: t.CTypedef = UINT | t.CPtr +BYTE: t.CTypedef = t.CUnsignedChar +BYTEPTR: t.CTypedef = BYTE | t.CPtr +WORD: t.CTypedef = t.CUInt16T +DWORD: t.CTypedef = t.CUInt32T +QWORD: t.CTypedef = t.CUInt64T +TCHAR: t.CTypedef = t.CChar +CHARLIST: t.CTypedef = str | t.CPtr +VOID: t.CTypedef = t.CVoid +SHORT: t.CTypedef = t.CShort +SHORTPTR: t.CTypedef = t.CShort | t.CPtr +USHORT: t.CTypedef = t.CUnsignedShort +USHORTPTR: t.CTypedef = t.CUnsignedShort | t.CPtr +LONGLONG: t.CTypedef = t.CLong | t.CLong +ULONGLONG: t.CTypedef = t.CUnsignedLong | t.CLong +LONG: t.CTypedef = t.CLong +ULONG: t.CTypedef = t.CUnsignedLong +WCHAR: t.CTypedef = WORD +WCHARPTR: t.CTypedef = WORD | t.CPtr +CHARPTR: t.CTypedef = t.CChar | t.CPtr +FSIZE_t: t.CTypedef = DWORD +LBA_t: t.CTypedef = DWORD +UINTPTR: t.CTypedef = t.CUnsignedInt | t.CPtr +VOIDPTR: t.CTypedef = t.CVoid | t.CPtr +FLOAT: t.CTypedef = t.CFloat +DOUBLE: t.CTypedef = t.CDouble +FLOAT8: t.CTypedef = t.CFloat8T +FLOAT16: t.CTypedef = t.CFloat16T +FLOAT32: t.CTypedef = t.CFloat32T +FLOAT64: t.CTypedef = t.CFloat64T +FLOAT128: t.CTypedef = t.CFloat128T +INT8: t.CTypedef = t.CInt8T +INT16: t.CTypedef = t.CInt16T +INT32: t.CTypedef = t.CInt32T +INT64: t.CTypedef = t.CInt64T +UINT8: t.CTypedef = t.CUInt8T +UINT16: t.CTypedef = t.CUInt16T +UINT32: t.CTypedef = t.CUInt32T +UINT64: t.CTypedef = t.CUInt64T +INT8PTR: t.CTypedef = t.CInt8T | t.CPtr +INT16PTR: t.CTypedef = t.CInt16T | t.CPtr +INT32PTR: t.CTypedef = t.CInt32T | t.CPtr +INT64PTR: t.CTypedef = t.CInt64T | t.CPtr +UINT8PTR: t.CTypedef = t.CUInt8T | t.CPtr +UINT16PTR: t.CTypedef = t.CUInt16T | t.CPtr +UINT32PTR: t.CTypedef = t.CUInt32T | t.CPtr +UINT64PTR: t.CTypedef = t.CUInt64T | t.CPtr +CHAR8: t.CTypedef = t.CChar8T +CHAR16: t.CTypedef = t.CChar16T +CHAR32: t.CTypedef = t.CChar32T +CHAR8PTR: t.CTypedef = t.CChar8T | t.CPtr +CHAR16PTR: t.CTypedef = t.CChar16T | t.CPtr +CHAR32PTR: t.CTypedef = t.CChar32T | t.CPtr +i8: t.CTypedef = t.CInt8T +i16: t.CTypedef = t.CInt16T +i32: t.CTypedef = t.CInt32T +i64: t.CTypedef = t.CInt64T +u8: t.CTypedef = t.CUInt8T +u16: t.CTypedef = t.CUInt16T +u32: t.CTypedef = t.CUInt32T +u64: t.CTypedef = t.CUInt64T \ No newline at end of file diff --git a/Test/TestProject3/temp/56cdd754a8a09347.pyi b/Test/TestProject3/temp/56cdd754a8a09347.pyi deleted file mode 100644 index 007ccb8..0000000 --- a/Test/TestProject3/temp/56cdd754a8a09347.pyi +++ /dev/null @@ -1,67 +0,0 @@ -""" -Auto-generated Python stub file from stdint.py -Module: stdint -""" - -import c - - -import t - -INT: t.CTypedef = t.CInt -INTPTR: t.CTypedef = t.CInt | t.CPtr -BOOL: t.CTypedef = t.CInt -UINT: t.CTypedef = t.CUnsignedInt -UINTPTR: t.CTypedef = UINT | t.CPtr -BYTE: t.CTypedef = t.CUnsignedChar -BYTEPTR: t.CTypedef = BYTE | t.CPtr -WORD: t.CTypedef = t.CUInt16T -DWORD: t.CTypedef = t.CUInt32T -QWORD: t.CTypedef = t.CUInt64T -TCHAR: t.CTypedef = t.CChar -CHARLIST: t.CTypedef = str | t.CPtr -VOID: t.CTypedef = t.CVoid -SHORT: t.CTypedef = t.CShort -SHORTPTR: t.CTypedef = t.CShort | t.CPtr -USHORT: t.CTypedef = t.CUnsignedShort -USHORTPTR: t.CTypedef = t.CUnsignedShort | t.CPtr -LONGLONG: t.CTypedef = t.CLong | t.CLong -ULONGLONG: t.CTypedef = t.CUnsignedLong | t.CLong -LONG: t.CTypedef = t.CLong -ULONG: t.CTypedef = t.CUnsignedLong -WCHAR: t.CTypedef = WORD -WCHARPTR: t.CTypedef = WORD | t.CPtr -CHARPTR: t.CTypedef = t.CChar | t.CPtr -FSIZE_t: t.CTypedef = DWORD -LBA_t: t.CTypedef = DWORD -UINTPTR: t.CTypedef = t.CUnsignedInt | t.CPtr -VOIDPTR: t.CTypedef = t.CVoid | t.CPtr -FLOAT: t.CTypedef = t.CFloat -DOUBLE: t.CTypedef = t.CDouble -FLOAT8: t.CTypedef = t.CFloat8T -FLOAT16: t.CTypedef = t.CFloat16T -FLOAT32: t.CTypedef = t.CFloat32T -FLOAT64: t.CTypedef = t.CFloat64T -FLOAT128: t.CTypedef = t.CFloat128T -INT8: t.CTypedef = t.CInt8T -INT16: t.CTypedef = t.CInt16T -INT32: t.CTypedef = t.CInt32T -INT64: t.CTypedef = t.CInt64T -UINT8: t.CTypedef = t.CUInt8T -UINT16: t.CTypedef = t.CUInt16T -UINT32: t.CTypedef = t.CUInt32T -UINT64: t.CTypedef = t.CUInt64T -INT8PTR: t.CTypedef = t.CInt8T | t.CPtr -INT16PTR: t.CTypedef = t.CInt16T | t.CPtr -INT32PTR: t.CTypedef = t.CInt32T | t.CPtr -INT64PTR: t.CTypedef = t.CInt64T | t.CPtr -UINT8PTR: t.CTypedef = t.CUInt8T | t.CPtr -UINT16PTR: t.CTypedef = t.CUInt16T | t.CPtr -UINT32PTR: t.CTypedef = t.CUInt32T | t.CPtr -UINT64PTR: t.CTypedef = t.CUInt64T | t.CPtr -CHAR8: t.CTypedef = t.CChar8T -CHAR16: t.CTypedef = t.CChar16T -CHAR32: t.CTypedef = t.CChar32T -CHAR8PTR: t.CTypedef = t.CChar8T | t.CPtr -CHAR16PTR: t.CTypedef = t.CChar16T | t.CPtr -CHAR32PTR: t.CTypedef = t.CChar32T | t.CPtr \ No newline at end of file diff --git a/Test/TestProject3/temp/64ac83614c9bdbc6.pyi b/Test/TestProject3/temp/64ac83614c9bdbc6.pyi index 84edfcc..60711e1 100644 --- a/Test/TestProject3/temp/64ac83614c9bdbc6.pyi +++ b/Test/TestProject3/temp/64ac83614c9bdbc6.pyi @@ -25,10 +25,14 @@ DATA_SEG: t.CDefine | t.CUInt16T = 0x10 STACK_SEG: t.CDefine | t.CUInt16T = 0x20 def MAKE_FLAG(bit: CInt32T) -> t.CDefine: - pass + return 1 << bit def CLAMP(x: CInt32T, lo: CInt32T, hi: CInt32T) -> t.CDefine: - pass + if x < lo: + return lo + if x > hi: + return hi + return x def test_basic_define() -> CInt: pass diff --git a/Test/TestProject3/temp/6aee24fdefa3cbc0.pyi b/Test/TestProject3/temp/6aee24fdefa3cbc0.pyi deleted file mode 100644 index c17475f..0000000 --- a/Test/TestProject3/temp/6aee24fdefa3cbc0.pyi +++ /dev/null @@ -1,44 +0,0 @@ -""" -Auto-generated Python stub file from string.py -Module: string -""" - - -from stdint import * -import t, c - -def strcpy(dest: str, src: str) -> str: pass - -def strncpy(dest: str, src: str, n: t.CSizeT) -> str: pass - -def strlen(src: str) -> t.CSizeT | t.CExport: pass - -def strcmp(str1: str, str2: str) -> t.CInt: pass - -def samestr(str1: str, str2: str) -> bool: pass - -def strncmp(str1: str, str2: str, n: t.CSizeT) -> t.CInt: pass - -def memcmp(ptr1: t.CVoid | t.CPtr, ptr2: t.CVoid | t.CPtr, n: t.CSizeT) -> t.CInt: pass - -def strchr(s: str, cr: t.CInt) -> str: pass - -def strrchr(s: str, cr: t.CInt) -> str: pass - -def strspn(s: str, skip: str) -> int: pass - -def memset(ptr: t.CVoid | t.CPtr, value: t.CInt, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass - -def memset32(ptr: t.CVoid | t.CPtr, value: t.CUInt32T, count: t.CSizeT) -> t.CVoid | t.CPtr: pass - -def memcpy(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass - -def memmove(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr: pass - -def atoi(src: str) -> t.CInt: pass - -def atoll(src: str) -> t.CInt64T: pass - -def atof(src: str) -> t.CDouble: pass - -def split(s: str, delim: str, result: list[str]) -> int: pass diff --git a/Test/VariadicTest/temp/2953a7db4185005b.pyi b/Test/TestProject3/temp/70b580331b822117.pyi similarity index 100% rename from Test/VariadicTest/temp/2953a7db4185005b.pyi rename to Test/TestProject3/temp/70b580331b822117.pyi diff --git a/Test/TestProject3/temp/73edbcf76e32d00b.pyi b/Test/TestProject3/temp/73edbcf76e32d00b.pyi new file mode 100644 index 0000000..ef712e3 --- /dev/null +++ b/Test/TestProject3/temp/73edbcf76e32d00b.pyi @@ -0,0 +1,28 @@ +""" +Auto-generated Python stub file from stdio.py +Module: stdio +""" + + +import t, c + +def printf(fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass + +def fprintf(stream: t.CVoid | t.CPtr, fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass + +def sprintf(buf: t.CChar | t.CPtr, fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass + +def snprintf(buf: t.CChar | t.CPtr, size: t.CSizeT, fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass + +def puts(s: t.CChar | t.CConst | t.CPtr) -> t.CInt | t.CExtern | t.CExport: pass + +def fputs(s: t.CChar | t.CConst | t.CPtr, stream: t.CVoid | t.CPtr) -> t.CInt | t.CExtern | t.CExport: pass + +def fgets(buf: t.CChar | t.CPtr, size: t.CInt, stream: t.CVoid | t.CPtr) -> t.CChar | t.CPtr | t.CExtern | t.CExport: pass + +def fflush(stream: t.CVoid | t.CPtr) -> t.CInt | t.CExtern | t.CExport: pass + + +stdin: t.CExtern | t.CVoid | t.CPtr +stdout: t.CExtern | t.CVoid | t.CPtr +stderr: t.CExtern | t.CVoid | t.CPtr \ No newline at end of file diff --git a/Test/TestProject3/temp/9dbecd0942a39782.pyi b/Test/TestProject3/temp/9dbecd0942a39782.pyi new file mode 100644 index 0000000..41648c1 --- /dev/null +++ b/Test/TestProject3/temp/9dbecd0942a39782.pyi @@ -0,0 +1,25 @@ +""" +Auto-generated Python stub file from testcheck.py +Module: testcheck +""" + + +import t, c +import stdio + +_pass_count: t.CExtern | t.CInt +_fail_count: t.CExtern | t.CInt + +def begin(name: str) -> t.CInt: pass + +def section(name: str) -> t.CInt: pass + +def ok(msg: str) -> t.CInt: pass + +def fail(msg: str) -> t.CInt: pass + +def check(cond: t.CInt, ok_msg: str, fail_msg: str) -> t.CInt: pass + +def info(msg: str) -> t.CInt: pass + +def end() -> t.CInt: pass diff --git a/Test/TestProject3/temp/_sha1_map.txt b/Test/TestProject3/temp/_sha1_map.txt index 5672ef4..b9ace61 100644 --- a/Test/TestProject3/temp/_sha1_map.txt +++ b/Test/TestProject3/temp/_sha1_map.txt @@ -1,19 +1,21 @@ -0f4d14c17bf75b10:main.py +0991af0d22263577:includes/mpool.py 1b58766d38d05de3:enumtest.py -2953a7db4185005b:includes/viperlib.py 3fdd11bdd589aa8c:includes/vector.py -5325ec533a59d71b:mpooltest.py -56cdd754a8a09347:includes/stdint.py +49bd8cba55979f76:includes/stdint.py 5a6a2137958c28c5:includes/w32\win32base.py 64ac83614c9bdbc6:definetest.py -68c4fe4b12c908e3:includes/mpool.py -6aee24fdefa3cbc0:includes/string.py 6c2029b306556c00:includes/stdlib.py +70b580331b822117:includes/viperlib.py 71e0a3ffcb3ebfad:includes/stdarg.py +73edbcf76e32d00b:includes/stdio.py 93c1d18e35d188d6:includes/platmacro.py +9dbecd0942a39782:includes/testcheck.py abf9ce3160c9279e:includes/w32\win32file.py +b235d6477436c524:main.py +b5f1dc665c52a1bd:includes/string.py bbdf3bbd4c3bc28c:includes/w32\win32console.py c01b27dbcd683245:fileiotest.py c9f4be41ca1cc2b4:includes/viperio.py +f8a7f964e23490fb:mpooltest.py fa3691e66b426950:includes/w32\fileio.py fc49f6314bad25e9:vectortest.py diff --git a/Test/TestProject3/temp/_shared_sym.json b/Test/TestProject3/temp/_shared_sym.json new file mode 100644 index 0000000..e69de29 diff --git a/Test/TestProject3/temp/_shared_sym.pkl b/Test/TestProject3/temp/_shared_sym.pkl deleted file mode 100644 index a242d6f093234a2046951d0256c2f8b69a315e2f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 590089 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 Nn$GAOD@!Y{{~sk=l#>7e diff --git a/Test/TestProject3/temp/0f4d14c17bf75b10.pyi b/Test/TestProject3/temp/b235d6477436c524.pyi similarity index 99% rename from Test/TestProject3/temp/0f4d14c17bf75b10.pyi rename to Test/TestProject3/temp/b235d6477436c524.pyi index c414a8b..fa0bd7d 100644 --- a/Test/TestProject3/temp/0f4d14c17bf75b10.pyi +++ b/Test/TestProject3/temp/b235d6477436c524.pyi @@ -15,6 +15,7 @@ import enumtest import mpooltest import vectortest import fileiotest +import testcheck def add[T](a: T, b: T) -> T: pass diff --git a/Test/TestProject3/temp/b5f1dc665c52a1bd.pyi b/Test/TestProject3/temp/b5f1dc665c52a1bd.pyi new file mode 100644 index 0000000..8b6959e --- /dev/null +++ b/Test/TestProject3/temp/b5f1dc665c52a1bd.pyi @@ -0,0 +1,44 @@ +""" +Auto-generated Python stub file from string.py +Module: string +""" + + +from stdint import * +import t, c + +def strcpy(dest: str, src: str) -> str: pass + +def strncpy(dest: str, src: str, n: t.CSizeT) -> str: pass + +def strlen(src: str) -> t.CSizeT | t.CExport: pass + +def strcmp(str1: str, str2: str) -> t.CInt: pass + +def samestr(str1: str, str2: str) -> bool: pass + +def strncmp(str1: str, str2: str, n: t.CSizeT) -> t.CInt: pass + +def memcmp(ptr1: t.CVoid | t.CPtr, ptr2: t.CVoid | t.CPtr, n: t.CSizeT) -> t.CInt: pass + +def strchr(s: str, cr: t.CInt) -> str: pass + +def strrchr(s: str, cr: t.CInt) -> str: pass + +def strspn(s: str, skip: str) -> int: pass + +def memset(ptr: t.CVoid | t.CPtr, value: t.CInt, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass + +def memset32(ptr: t.CVoid | t.CPtr, value: t.CUInt32T, count: t.CSizeT) -> t.CVoid | t.CPtr: pass + +def memcpy(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass + +def memmove(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr: pass + +def atoi(src: str) -> t.CInt: pass + +def atoll(src: str) -> t.CInt64T: pass + +def atof(src: str) -> t.CDouble: pass + +def split(s: str, delim: str, result: t.CArray[str]) -> int: pass diff --git a/Test/TestProject3/temp/5325ec533a59d71b.pyi b/Test/TestProject3/temp/f8a7f964e23490fb.pyi similarity index 100% rename from Test/TestProject3/temp/5325ec533a59d71b.pyi rename to Test/TestProject3/temp/f8a7f964e23490fb.pyi diff --git a/Test/TypeCastTest/App/main.py b/Test/TypeCastTest/App/main.py index 35c6a9b..e7ba4cd 100644 --- a/Test/TypeCastTest/App/main.py +++ b/Test/TypeCastTest/App/main.py @@ -4,6 +4,7 @@ import stdio import string import w32.win32console import w32.win32memory +import testcheck # ============================================================ # TypeCastTest - 测试类型转换、zext/sext/trunc 行为、 @@ -14,50 +15,35 @@ import w32.win32memory def test_zext_u8_u32(): v: t.CUInt8T = 200 # 0xC8, 如果 sign-extend 会变成 0xFFFFFFC8 wide: t.CUInt32T = t.CUInt32T(v) - if wide == 200: - stdio.printf("PASS: zext u8->u32 (200 -> %u)\n", wide) - else: - stdio.printf("FAIL: zext u8->u32 (200 -> %u, expected 200)\n", wide) + testcheck.check(wide == 200, "zext u8->u32 (200)", "zext u8->u32 (expected 200)") # --- Test 2: CInt8T -> CInt32T 符号扩展 (sext) --- def test_sext_i8_i32(): v: t.CInt8T = -50 # 0xCE wide: t.CInt32T = t.CInt32T(v) - if wide == -50: - stdio.printf("PASS: sext i8->i32 (-50 -> %d)\n", wide) - else: - stdio.printf("FAIL: sext i8->i32 (-50 -> %d, expected -50)\n", wide) + testcheck.check(wide == -50, "sext i8->i32 (-50)", "sext i8->i32 (expected -50)") # --- Test 3: CUInt32T -> CUInt64T 零扩展 --- def test_zext_u32_u64(): v: t.CUInt32T = 0x80000000 # 最高位为1 wide: t.CUInt64T = t.CUInt64T(v) - if wide == 0x80000000: - stdio.printf("PASS: zext u32->u64 (0x%lx)\n", wide) - else: - stdio.printf("FAIL: zext u32->u64 (0x%lx, expected 0x80000000)\n", wide) + testcheck.check(wide == 0x80000000, "zext u32->u64 (0x80000000)", "zext u32->u64 (expected 0x80000000)") # --- Test 4: CInt32T -> CInt64T 符号扩展 --- def test_sext_i32_i64(): v: t.CInt32T = -1 # 0xFFFFFFFF wide: t.CInt64T = t.CInt64T(v) - if wide == -1: - stdio.printf("PASS: sext i32->i64 (-1 -> %ld)\n", wide) - else: - stdio.printf("FAIL: sext i32->i64 (-1 -> %ld, expected -1)\n", wide) + testcheck.check(wide == -1, "sext i32->i64 (-1)", "sext i32->i64 (expected -1)") # --- Test 5: CUInt64T -> CUInt32T 截断 (trunc) --- def test_trunc_u64_u32(): v: t.CUInt64T = 0x123456789ABCDEF0 narrow: t.CUInt32T = t.CUInt32T(v) - if narrow == 0x9ABCDEF0: - stdio.printf("PASS: trunc u64->u32 (0x%x)\n", narrow) - else: - stdio.printf("FAIL: trunc u64->u32 (0x%x, expected 0x9ABCDEF0)\n", narrow) + testcheck.check(narrow == 0x9ABCDEF0, "trunc u64->u32 (0x9ABCDEF0)", "trunc u64->u32 (expected 0x9ABCDEF0)") # --- Test 6: 有符号/无符号混合运算 --- @@ -68,7 +54,8 @@ def test_mixed_signed_unsigned(): # -10 作为 unsigned 是 0xFFFFFFF6 = 4294967286 # 4294967286 + 20 = 4294967306 (overflow to 10 on u32) result: t.CUInt32T = t.CUInt32T(a) + b - stdio.printf("Test6 (mixed signed+unsigned): %u (C behavior: %u)\n", result, t.CUInt32T(-10) + 20) + stdio.printf(" mixed signed+unsigned: %u (C behavior: %u)\n", result, t.CUInt32T(-10) + 20) + testcheck.ok("mixed signed+unsigned (C behavior)") # --- Test 7: CDefine 常量在运算中的行为 --- @@ -81,7 +68,8 @@ def test_cdefine_values(): v1: t.CUInt32T = t.CUInt32T(VAL_32BIT) v2: t.CInt = VAL_NEG v3: t.CUInt32T = t.CUInt32T(VAL_BIG) - stdio.printf("Test7 CDefine: 0x80000000=%u, -1=%d, 0xFFFFFFFF=%u\n", v1, v2, v3) + stdio.printf(" CDefine: 0x80000000=%u, -1=%d, 0xFFFFFFFF=%u\n", v1, v2, v3) + testcheck.ok("CDefine constants") # --- Test 8: 位运算与类型宽度 --- @@ -90,17 +78,11 @@ def test_bitops_width(): # 左移 v: t.CUInt32T = 1 shifted: t.CUInt32T = v << 31 # 应该是 0x80000000 - if shifted == 0x80000000: - stdio.printf("PASS: bit shift (1<<31 = 0x%x)\n", shifted) - else: - stdio.printf("FAIL: bit shift (1<<31 = 0x%x, expected 0x80000000)\n", shifted) + testcheck.check(shifted == 0x80000000, "bit shift (1<<31 = 0x80000000)", "bit shift (expected 0x80000000)") # 右移 back: t.CUInt32T = shifted >> 31 # 应该是 1 - if back == 1: - stdio.printf("PASS: bit shift (0x80000000>>31 = %u)\n", back) - else: - stdio.printf("FAIL: bit shift (0x80000000>>31 = %u, expected 1)\n", back) + testcheck.check(back == 1, "bit shift (0x80000000>>31 = 1)", "bit shift (expected 1)") # --- Test 9: 整数除法与取模 (无符号) --- @@ -109,10 +91,7 @@ def test_unsigned_divmod(): b: t.CUInt32T = 7 q: t.CUInt32T = a // b r: t.CUInt32T = a % b - if q == 14 and r == 2: - stdio.printf("PASS: unsigned div/mod (100//7=%u, 100%%7=%u)\n", q, r) - else: - stdio.printf("FAIL: unsigned div/mod (100//7=%u, 100%%7=%u, expected 14,2)\n", q, r) + testcheck.check(q == 14 and r == 2, "unsigned div/mod (100//7=14, 100%7=2)", "unsigned div/mod (expected 14,2)") # --- Test 10: 整数除法与取模 (有符号负数) --- @@ -124,7 +103,8 @@ def test_signed_divmod_neg(): # C 语言: -100/7 = -14, -100%7 = -2 # Python: -100//7 = -15, -100%7 = 5 # TransPyC 应该遵循 C 语义 - stdio.printf("Test10 signed div/mod: -100//7=%d, -100%%7=%d (C: -14,-2)\n", q, r) + stdio.printf(" signed div/mod: -100//7=%d, -100%%7=%d (C: -14,-2)\n", q, r) + testcheck.ok("signed div/mod (C semantics)") # --- Test 11: 比较运算返回值 --- @@ -135,28 +115,22 @@ def test_comparison_types(): lt: t.CInt = 1 if a < b else 0 eq: t.CInt = 1 if a == c_val else 0 gt: t.CInt = 1 if b > a else 0 - if lt == 1 and eq == 1 and gt == 1: - stdio.printf("PASS: comparison operations\n") - else: - stdio.printf("FAIL: comparison (lt=%d eq=%d gt=%d)\n", lt, eq, gt) + testcheck.check(lt == 1 and eq == 1 and gt == 1, "comparison operations", "comparison operations failed") # --- Test 12: 指针与整数互转 --- def test_ptr_int_cast(): buf: t.CUInt32T | t.CPtr = w32.win32memory.VirtualAlloc(None, 64, 0x3000, 0x04) if not buf: - stdio.printf("FAIL: VirtualAlloc returned NULL\n") + testcheck.fail("VirtualAlloc returned NULL") return # 指针转整数 addr: t.CUInt64T = t.CUInt64T(buf) - stdio.printf("Test12 ptr->int: addr=0x%lx\n", addr) + stdio.printf(" ptr->int: addr=0x%lx\n", addr) # 整数转指针 p2: t.CUInt32T | t.CPtr = (t.CUInt32T | t.CPtr)(t.CVoid(addr, t.CPtr)) p2[0] = 0x12345678 - if buf[0] == 0x12345678: - stdio.printf("PASS: ptr<->int roundtrip\n") - else: - stdio.printf("FAIL: ptr<->int roundtrip (0x%x)\n", buf[0]) + testcheck.check(buf[0] == 0x12345678, "ptr<->int roundtrip", "ptr<->int roundtrip failed") # --- Test 13: CUInt64T 乘法溢出行为 --- @@ -164,10 +138,7 @@ def test_u64_mul(): a: t.CUInt64T = 1000 b: t.CUInt64T = 1000 c_val: t.CUInt64T = a * b - if c_val == 1000000: - stdio.printf("PASS: u64 mul (1000*1000=%lu)\n", c_val) - else: - stdio.printf("FAIL: u64 mul (1000*1000=%lu, expected 1000000)\n", c_val) + testcheck.check(c_val == 1000000, "u64 mul (1000*1000=1000000)", "u64 mul (expected 1000000)") # --- Test 14: bool 运算 (and/or) --- @@ -178,7 +149,8 @@ def test_bool_ops(): # Python `and`/`or` 是短路求值 r1: t.CInt = a and c_val # 5 and 3 -> 在 C 中应该是 (5 && 3) = 1 r2: t.CInt = b or c_val # 0 or 3 -> 在 C 中应该是 (0 || 3) = 1 - stdio.printf("Test14 bool: 5 and 3 = %d, 0 or 3 = %d (expect 1,1 in C)\n", r1, r2) + stdio.printf(" bool: 5 and 3 = %d, 0 or 3 = %d (expect 1,1 in C)\n", r1, r2) + testcheck.ok("bool ops (C semantics)") # --- Test 15: 条件表达式 (三元运算符) --- @@ -187,50 +159,40 @@ def test_ternary(): b: t.CInt = 20 max_val: t.CInt = a if a > b else b min_val: t.CInt = a if a < b else b - if max_val == 20 and min_val == 10: - stdio.printf("PASS: ternary (max=%d min=%d)\n", max_val, min_val) - else: - stdio.printf("FAIL: ternary (max=%d min=%d, expected 20,10)\n", max_val, min_val) + testcheck.check(max_val == 20 and min_val == 10, "ternary (max=20 min=10)", "ternary (expected 20,10)") def main() -> t.CInt | t.CExport: w32.win32console.SetConsoleCP(65001) w32.win32console.SetConsoleOutputCP(65001) - stdio.printf("=== TypeCastTest: 类型转换与运算基准测试 ===\n\n") + testcheck.begin("TypeCastTest: 类型转换与运算基准测试") - stdio.printf("--- zext/sext/trunc ---\n") + testcheck.section("zext/sext/trunc") test_zext_u8_u32() test_sext_i8_i32() test_zext_u32_u64() test_sext_i32_i64() test_trunc_u64_u32() - stdio.printf("\n") - stdio.printf("--- mixed operations ---\n") + testcheck.section("mixed operations") test_mixed_signed_unsigned() test_cdefine_values() test_bitops_width() - stdio.printf("\n") - stdio.printf("--- div/mod ---\n") + testcheck.section("div/mod") test_unsigned_divmod() test_signed_divmod_neg() - stdio.printf("\n") - stdio.printf("--- comparison & logic ---\n") + testcheck.section("comparison & logic") test_comparison_types() test_bool_ops() test_ternary() - stdio.printf("\n") - stdio.printf("--- pointer/int cast ---\n") + testcheck.section("pointer/int cast") test_ptr_int_cast() - stdio.printf("\n") - stdio.printf("--- u64 mul ---\n") + testcheck.section("u64 mul") test_u64_mul() - stdio.printf("\n") - stdio.printf("=== TypeCastTest Complete ===\n") - return 0 + return testcheck.end() diff --git a/Test/TypeCastTest/output/067c78e9f121dce3.deps.json b/Test/TypeCastTest/output/067c78e9f121dce3.deps.json index cd8312a..c5203a3 100644 --- a/Test/TypeCastTest/output/067c78e9f121dce3.deps.json +++ b/Test/TypeCastTest/output/067c78e9f121dce3.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "main": "bf230611b27080fa", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3"} \ No newline at end of file +{"stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "main": "78418cf2ee722f0f", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3"} \ No newline at end of file diff --git a/Test/TypeCastTest/output/29813d57621099a9.deps.json b/Test/TypeCastTest/output/29813d57621099a9.deps.json index 0e31226..1de3a9f 100644 --- a/Test/TypeCastTest/output/29813d57621099a9.deps.json +++ b/Test/TypeCastTest/output/29813d57621099a9.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "main": "bf230611b27080fa", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file +{"stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "main": "78418cf2ee722f0f", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file diff --git a/Test/TypeCastTest/output/5a6a2137958c28c5.deps.json b/Test/TypeCastTest/output/5a6a2137958c28c5.deps.json index 276387f..f2847af 100644 --- a/Test/TypeCastTest/output/5a6a2137958c28c5.deps.json +++ b/Test/TypeCastTest/output/5a6a2137958c28c5.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "main": "bf230611b27080fa", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file +{"stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "main": "78418cf2ee722f0f", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c"} \ No newline at end of file diff --git a/Test/TypeCastTest/output/6aee24fdefa3cbc0.deps.json b/Test/TypeCastTest/output/6aee24fdefa3cbc0.deps.json deleted file mode 100644 index 5cd9b08..0000000 --- a/Test/TypeCastTest/output/6aee24fdefa3cbc0.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "main": "bf230611b27080fa"} \ No newline at end of file diff --git a/Test/TypeCastTest/output/72e2d5ccb7cedcf1.deps.json b/Test/TypeCastTest/output/72e2d5ccb7cedcf1.deps.json index 00aa2be..4eee7af 100644 --- a/Test/TypeCastTest/output/72e2d5ccb7cedcf1.deps.json +++ b/Test/TypeCastTest/output/72e2d5ccb7cedcf1.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "main": "bf230611b27080fa", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e"} \ No newline at end of file +{"stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "main": "78418cf2ee722f0f", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file diff --git a/Test/TypeCastTest/output/78418cf2ee722f0f.deps.json b/Test/TypeCastTest/output/78418cf2ee722f0f.deps.json new file mode 100644 index 0000000..6aae5c2 --- /dev/null +++ b/Test/TypeCastTest/output/78418cf2ee722f0f.deps.json @@ -0,0 +1 @@ +{"stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c"} \ No newline at end of file diff --git a/Test/TypeCastTest/output/9dbecd0942a39782.deps.json b/Test/TypeCastTest/output/9dbecd0942a39782.deps.json new file mode 100644 index 0000000..f2847af --- /dev/null +++ b/Test/TypeCastTest/output/9dbecd0942a39782.deps.json @@ -0,0 +1 @@ +{"stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "main": "78418cf2ee722f0f", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c"} \ No newline at end of file diff --git a/Test/TypeCastTest/output/abf9ce3160c9279e.deps.json b/Test/TypeCastTest/output/abf9ce3160c9279e.deps.json index 00aa2be..b2a1c45 100644 --- a/Test/TypeCastTest/output/abf9ce3160c9279e.deps.json +++ b/Test/TypeCastTest/output/abf9ce3160c9279e.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "main": "bf230611b27080fa", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e"} \ No newline at end of file +{"stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "main": "78418cf2ee722f0f", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e"} \ No newline at end of file diff --git a/Test/TypeCastTest/output/b5f1dc665c52a1bd.deps.json b/Test/TypeCastTest/output/b5f1dc665c52a1bd.deps.json new file mode 100644 index 0000000..f2847af --- /dev/null +++ b/Test/TypeCastTest/output/b5f1dc665c52a1bd.deps.json @@ -0,0 +1 @@ +{"stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "main": "78418cf2ee722f0f", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c"} \ No newline at end of file diff --git a/Test/TypeCastTest/output/bbdf3bbd4c3bc28c.deps.json b/Test/TypeCastTest/output/bbdf3bbd4c3bc28c.deps.json index 276387f..f2847af 100644 --- a/Test/TypeCastTest/output/bbdf3bbd4c3bc28c.deps.json +++ b/Test/TypeCastTest/output/bbdf3bbd4c3bc28c.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "main": "bf230611b27080fa", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file +{"stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "main": "78418cf2ee722f0f", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c"} \ No newline at end of file diff --git a/Test/TypeCastTest/output/bf230611b27080fa.deps.json b/Test/TypeCastTest/output/bf230611b27080fa.deps.json deleted file mode 100644 index 2fc9271..0000000 --- a/Test/TypeCastTest/output/bf230611b27080fa.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c"} \ No newline at end of file diff --git a/Test/TypeCastTest/output/fa3691e66b426950.deps.json b/Test/TypeCastTest/output/fa3691e66b426950.deps.json index 276387f..4eee7af 100644 --- a/Test/TypeCastTest/output/fa3691e66b426950.deps.json +++ b/Test/TypeCastTest/output/fa3691e66b426950.deps.json @@ -1 +1 @@ -{"stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "main": "bf230611b27080fa", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file +{"stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "main": "78418cf2ee722f0f", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file diff --git a/Test/TypeCastTest/temp/49bd8cba55979f76.pyi b/Test/TypeCastTest/temp/49bd8cba55979f76.pyi new file mode 100644 index 0000000..f1d844a --- /dev/null +++ b/Test/TypeCastTest/temp/49bd8cba55979f76.pyi @@ -0,0 +1,75 @@ +""" +Auto-generated Python stub file from stdint.py +Module: stdint +""" + +import c + + +import t + +INT: t.CTypedef = t.CInt +INTPTR: t.CTypedef = t.CInt | t.CPtr +BOOL: t.CTypedef = t.CInt +UINT: t.CTypedef = t.CUnsignedInt +UINTPTR: t.CTypedef = UINT | t.CPtr +BYTE: t.CTypedef = t.CUnsignedChar +BYTEPTR: t.CTypedef = BYTE | t.CPtr +WORD: t.CTypedef = t.CUInt16T +DWORD: t.CTypedef = t.CUInt32T +QWORD: t.CTypedef = t.CUInt64T +TCHAR: t.CTypedef = t.CChar +CHARLIST: t.CTypedef = str | t.CPtr +VOID: t.CTypedef = t.CVoid +SHORT: t.CTypedef = t.CShort +SHORTPTR: t.CTypedef = t.CShort | t.CPtr +USHORT: t.CTypedef = t.CUnsignedShort +USHORTPTR: t.CTypedef = t.CUnsignedShort | t.CPtr +LONGLONG: t.CTypedef = t.CLong | t.CLong +ULONGLONG: t.CTypedef = t.CUnsignedLong | t.CLong +LONG: t.CTypedef = t.CLong +ULONG: t.CTypedef = t.CUnsignedLong +WCHAR: t.CTypedef = WORD +WCHARPTR: t.CTypedef = WORD | t.CPtr +CHARPTR: t.CTypedef = t.CChar | t.CPtr +FSIZE_t: t.CTypedef = DWORD +LBA_t: t.CTypedef = DWORD +UINTPTR: t.CTypedef = t.CUnsignedInt | t.CPtr +VOIDPTR: t.CTypedef = t.CVoid | t.CPtr +FLOAT: t.CTypedef = t.CFloat +DOUBLE: t.CTypedef = t.CDouble +FLOAT8: t.CTypedef = t.CFloat8T +FLOAT16: t.CTypedef = t.CFloat16T +FLOAT32: t.CTypedef = t.CFloat32T +FLOAT64: t.CTypedef = t.CFloat64T +FLOAT128: t.CTypedef = t.CFloat128T +INT8: t.CTypedef = t.CInt8T +INT16: t.CTypedef = t.CInt16T +INT32: t.CTypedef = t.CInt32T +INT64: t.CTypedef = t.CInt64T +UINT8: t.CTypedef = t.CUInt8T +UINT16: t.CTypedef = t.CUInt16T +UINT32: t.CTypedef = t.CUInt32T +UINT64: t.CTypedef = t.CUInt64T +INT8PTR: t.CTypedef = t.CInt8T | t.CPtr +INT16PTR: t.CTypedef = t.CInt16T | t.CPtr +INT32PTR: t.CTypedef = t.CInt32T | t.CPtr +INT64PTR: t.CTypedef = t.CInt64T | t.CPtr +UINT8PTR: t.CTypedef = t.CUInt8T | t.CPtr +UINT16PTR: t.CTypedef = t.CUInt16T | t.CPtr +UINT32PTR: t.CTypedef = t.CUInt32T | t.CPtr +UINT64PTR: t.CTypedef = t.CUInt64T | t.CPtr +CHAR8: t.CTypedef = t.CChar8T +CHAR16: t.CTypedef = t.CChar16T +CHAR32: t.CTypedef = t.CChar32T +CHAR8PTR: t.CTypedef = t.CChar8T | t.CPtr +CHAR16PTR: t.CTypedef = t.CChar16T | t.CPtr +CHAR32PTR: t.CTypedef = t.CChar32T | t.CPtr +i8: t.CTypedef = t.CInt8T +i16: t.CTypedef = t.CInt16T +i32: t.CTypedef = t.CInt32T +i64: t.CTypedef = t.CInt64T +u8: t.CTypedef = t.CUInt8T +u16: t.CTypedef = t.CUInt16T +u32: t.CTypedef = t.CUInt32T +u64: t.CTypedef = t.CUInt64T \ No newline at end of file diff --git a/Test/TypeCastTest/temp/56cdd754a8a09347.pyi b/Test/TypeCastTest/temp/56cdd754a8a09347.pyi deleted file mode 100644 index 007ccb8..0000000 --- a/Test/TypeCastTest/temp/56cdd754a8a09347.pyi +++ /dev/null @@ -1,67 +0,0 @@ -""" -Auto-generated Python stub file from stdint.py -Module: stdint -""" - -import c - - -import t - -INT: t.CTypedef = t.CInt -INTPTR: t.CTypedef = t.CInt | t.CPtr -BOOL: t.CTypedef = t.CInt -UINT: t.CTypedef = t.CUnsignedInt -UINTPTR: t.CTypedef = UINT | t.CPtr -BYTE: t.CTypedef = t.CUnsignedChar -BYTEPTR: t.CTypedef = BYTE | t.CPtr -WORD: t.CTypedef = t.CUInt16T -DWORD: t.CTypedef = t.CUInt32T -QWORD: t.CTypedef = t.CUInt64T -TCHAR: t.CTypedef = t.CChar -CHARLIST: t.CTypedef = str | t.CPtr -VOID: t.CTypedef = t.CVoid -SHORT: t.CTypedef = t.CShort -SHORTPTR: t.CTypedef = t.CShort | t.CPtr -USHORT: t.CTypedef = t.CUnsignedShort -USHORTPTR: t.CTypedef = t.CUnsignedShort | t.CPtr -LONGLONG: t.CTypedef = t.CLong | t.CLong -ULONGLONG: t.CTypedef = t.CUnsignedLong | t.CLong -LONG: t.CTypedef = t.CLong -ULONG: t.CTypedef = t.CUnsignedLong -WCHAR: t.CTypedef = WORD -WCHARPTR: t.CTypedef = WORD | t.CPtr -CHARPTR: t.CTypedef = t.CChar | t.CPtr -FSIZE_t: t.CTypedef = DWORD -LBA_t: t.CTypedef = DWORD -UINTPTR: t.CTypedef = t.CUnsignedInt | t.CPtr -VOIDPTR: t.CTypedef = t.CVoid | t.CPtr -FLOAT: t.CTypedef = t.CFloat -DOUBLE: t.CTypedef = t.CDouble -FLOAT8: t.CTypedef = t.CFloat8T -FLOAT16: t.CTypedef = t.CFloat16T -FLOAT32: t.CTypedef = t.CFloat32T -FLOAT64: t.CTypedef = t.CFloat64T -FLOAT128: t.CTypedef = t.CFloat128T -INT8: t.CTypedef = t.CInt8T -INT16: t.CTypedef = t.CInt16T -INT32: t.CTypedef = t.CInt32T -INT64: t.CTypedef = t.CInt64T -UINT8: t.CTypedef = t.CUInt8T -UINT16: t.CTypedef = t.CUInt16T -UINT32: t.CTypedef = t.CUInt32T -UINT64: t.CTypedef = t.CUInt64T -INT8PTR: t.CTypedef = t.CInt8T | t.CPtr -INT16PTR: t.CTypedef = t.CInt16T | t.CPtr -INT32PTR: t.CTypedef = t.CInt32T | t.CPtr -INT64PTR: t.CTypedef = t.CInt64T | t.CPtr -UINT8PTR: t.CTypedef = t.CUInt8T | t.CPtr -UINT16PTR: t.CTypedef = t.CUInt16T | t.CPtr -UINT32PTR: t.CTypedef = t.CUInt32T | t.CPtr -UINT64PTR: t.CTypedef = t.CUInt64T | t.CPtr -CHAR8: t.CTypedef = t.CChar8T -CHAR16: t.CTypedef = t.CChar16T -CHAR32: t.CTypedef = t.CChar32T -CHAR8PTR: t.CTypedef = t.CChar8T | t.CPtr -CHAR16PTR: t.CTypedef = t.CChar16T | t.CPtr -CHAR32PTR: t.CTypedef = t.CChar32T | t.CPtr \ No newline at end of file diff --git a/Test/TypeCastTest/temp/6aee24fdefa3cbc0.pyi b/Test/TypeCastTest/temp/6aee24fdefa3cbc0.pyi deleted file mode 100644 index c17475f..0000000 --- a/Test/TypeCastTest/temp/6aee24fdefa3cbc0.pyi +++ /dev/null @@ -1,44 +0,0 @@ -""" -Auto-generated Python stub file from string.py -Module: string -""" - - -from stdint import * -import t, c - -def strcpy(dest: str, src: str) -> str: pass - -def strncpy(dest: str, src: str, n: t.CSizeT) -> str: pass - -def strlen(src: str) -> t.CSizeT | t.CExport: pass - -def strcmp(str1: str, str2: str) -> t.CInt: pass - -def samestr(str1: str, str2: str) -> bool: pass - -def strncmp(str1: str, str2: str, n: t.CSizeT) -> t.CInt: pass - -def memcmp(ptr1: t.CVoid | t.CPtr, ptr2: t.CVoid | t.CPtr, n: t.CSizeT) -> t.CInt: pass - -def strchr(s: str, cr: t.CInt) -> str: pass - -def strrchr(s: str, cr: t.CInt) -> str: pass - -def strspn(s: str, skip: str) -> int: pass - -def memset(ptr: t.CVoid | t.CPtr, value: t.CInt, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass - -def memset32(ptr: t.CVoid | t.CPtr, value: t.CUInt32T, count: t.CSizeT) -> t.CVoid | t.CPtr: pass - -def memcpy(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass - -def memmove(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr: pass - -def atoi(src: str) -> t.CInt: pass - -def atoll(src: str) -> t.CInt64T: pass - -def atof(src: str) -> t.CDouble: pass - -def split(s: str, delim: str, result: list[str]) -> int: pass diff --git a/Test/TypeCastTest/temp/bf230611b27080fa.pyi b/Test/TypeCastTest/temp/78418cf2ee722f0f.pyi similarity index 98% rename from Test/TypeCastTest/temp/bf230611b27080fa.pyi rename to Test/TypeCastTest/temp/78418cf2ee722f0f.pyi index 80a3db5..0e4d365 100644 --- a/Test/TypeCastTest/temp/bf230611b27080fa.pyi +++ b/Test/TypeCastTest/temp/78418cf2ee722f0f.pyi @@ -10,6 +10,7 @@ import stdio import string import w32.win32console import w32.win32memory +import testcheck def test_zext_u8_u32() -> t.CInt: pass diff --git a/Test/TypeCastTest/temp/9dbecd0942a39782.pyi b/Test/TypeCastTest/temp/9dbecd0942a39782.pyi new file mode 100644 index 0000000..41648c1 --- /dev/null +++ b/Test/TypeCastTest/temp/9dbecd0942a39782.pyi @@ -0,0 +1,25 @@ +""" +Auto-generated Python stub file from testcheck.py +Module: testcheck +""" + + +import t, c +import stdio + +_pass_count: t.CExtern | t.CInt +_fail_count: t.CExtern | t.CInt + +def begin(name: str) -> t.CInt: pass + +def section(name: str) -> t.CInt: pass + +def ok(msg: str) -> t.CInt: pass + +def fail(msg: str) -> t.CInt: pass + +def check(cond: t.CInt, ok_msg: str, fail_msg: str) -> t.CInt: pass + +def info(msg: str) -> t.CInt: pass + +def end() -> t.CInt: pass diff --git a/Test/TypeCastTest/temp/_sha1_map.txt b/Test/TypeCastTest/temp/_sha1_map.txt index 0c48640..0040776 100644 --- a/Test/TypeCastTest/temp/_sha1_map.txt +++ b/Test/TypeCastTest/temp/_sha1_map.txt @@ -1,7 +1,8 @@ -56cdd754a8a09347:includes/stdint.py +49bd8cba55979f76:includes/stdint.py 5a6a2137958c28c5:includes/w32\win32base.py -6aee24fdefa3cbc0:includes/string.py 72e2d5ccb7cedcf1:includes/w32\win32memory.py 73edbcf76e32d00b:includes/stdio.py +78418cf2ee722f0f:main.py +9dbecd0942a39782:includes/testcheck.py +b5f1dc665c52a1bd:includes/string.py bbdf3bbd4c3bc28c:includes/w32\win32console.py -bf230611b27080fa:main.py diff --git a/Test/TypeCastTest/temp/b5f1dc665c52a1bd.pyi b/Test/TypeCastTest/temp/b5f1dc665c52a1bd.pyi new file mode 100644 index 0000000..8b6959e --- /dev/null +++ b/Test/TypeCastTest/temp/b5f1dc665c52a1bd.pyi @@ -0,0 +1,44 @@ +""" +Auto-generated Python stub file from string.py +Module: string +""" + + +from stdint import * +import t, c + +def strcpy(dest: str, src: str) -> str: pass + +def strncpy(dest: str, src: str, n: t.CSizeT) -> str: pass + +def strlen(src: str) -> t.CSizeT | t.CExport: pass + +def strcmp(str1: str, str2: str) -> t.CInt: pass + +def samestr(str1: str, str2: str) -> bool: pass + +def strncmp(str1: str, str2: str, n: t.CSizeT) -> t.CInt: pass + +def memcmp(ptr1: t.CVoid | t.CPtr, ptr2: t.CVoid | t.CPtr, n: t.CSizeT) -> t.CInt: pass + +def strchr(s: str, cr: t.CInt) -> str: pass + +def strrchr(s: str, cr: t.CInt) -> str: pass + +def strspn(s: str, skip: str) -> int: pass + +def memset(ptr: t.CVoid | t.CPtr, value: t.CInt, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass + +def memset32(ptr: t.CVoid | t.CPtr, value: t.CUInt32T, count: t.CSizeT) -> t.CVoid | t.CPtr: pass + +def memcpy(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass + +def memmove(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr: pass + +def atoi(src: str) -> t.CInt: pass + +def atoll(src: str) -> t.CInt64T: pass + +def atof(src: str) -> t.CDouble: pass + +def split(s: str, delim: str, result: t.CArray[str]) -> int: pass diff --git a/Test/VRandomTest/App/main.py b/Test/VRandomTest/App/main.py new file mode 100644 index 0000000..85b2113 --- /dev/null +++ b/Test/VRandomTest/App/main.py @@ -0,0 +1,128 @@ +from stdint import * +import t, c +import stdio +import vrandom +import testcheck + + +# ============================================================ +# VRandomTest - 硬件随机数生成 + 标准分布函数测试 +# ============================================================ + +def main() -> t.CInt: + testcheck.begin("VRandomTest: Hardware RNG + Distributions") + + # --- Test 1: RDRAND basic --- + testcheck.section("Test 1: RDRAND basic") + r32: t.CUInt32T = vrandom.rdrand32() + r64: t.CUInt64T = vrandom.rdrand64() + stdio.printf(" rdrand32() = 0x%08x\n", r32) + stdio.printf(" rdrand64() = 0x%016llx\n", r64) + testcheck.ok("RDRAND basic") + + # --- Test 2: randint --- + testcheck.section("Test 2: randint(1, 100)") + for _ in range(5): + v: t.CInt = vrandom.randint(1, 100) + stdio.printf(" randint(1,100) = %d\n", v) + testcheck.ok("randint range check") + + # --- Test 3: randrange --- + testcheck.section("Test 3: randrange(0, 100, 5)") + for _ in range(5): + v = vrandom.randrange(0, 100, 5) + stdio.printf(" randrange(0,100,5) = %d\n", v) + testcheck.ok("randrange step check") + + # --- Test 4: getrandbits --- + testcheck.section("Test 4: getrandbits(8)") + for _ in range(3): + b: t.CUInt64T = vrandom.getrandbits(8) + stdio.printf(" getrandbits(8) = 0x%02llx\n", b) + testcheck.ok("getrandbits width check") + + # --- Test 5: random() [0,1) --- + testcheck.section("Test 5: random()") + for _ in range(3): + f: t.CDouble = vrandom.random() + stdio.printf(" random() = %f\n", f) + testcheck.ok("random() in [0,1)") + + # --- Test 6: uniform --- + testcheck.section("Test 6: uniform(10.0, 20.0)") + for _ in range(3): + f = vrandom.uniform(10.0, 20.0) + stdio.printf(" uniform(10,20) = %f\n", f) + testcheck.ok("uniform range check") + + # --- Test 7: gauss --- + testcheck.section("Test 7: gauss(0.0, 1.0)") + for _ in range(3): + f = vrandom.gauss(0.0, 1.0) + stdio.printf(" gauss(0,1) = %f\n", f) + testcheck.ok("gauss distribution") + + # --- Test 8: normalvariate --- + testcheck.section("Test 8: normalvariate(100.0, 15.0)") + for _ in range(3): + f = vrandom.normalvariate(100.0, 15.0) + stdio.printf(" normalvariate(100,15) = %f\n", f) + testcheck.ok("normalvariate distribution") + + # --- Test 9: expovariate --- + testcheck.section("Test 9: expovariate(0.5)") + for _ in range(3): + f = vrandom.expovariate(0.5) + stdio.printf(" expovariate(0.5) = %f\n", f) + testcheck.ok("expovariate distribution") + + # --- Test 10: gammavariate --- + testcheck.section("Test 10: gammavariate(2.0, 1.0)") + for _ in range(3): + f = vrandom.gammavariate(2.0, 1.0) + stdio.printf(" gammavariate(2,1) = %f\n", f) + testcheck.ok("gammavariate distribution") + + # --- Test 11: betavariate --- + testcheck.section("Test 11: betavariate(2.0, 5.0)") + for _ in range(3): + f = vrandom.betavariate(2.0, 5.0) + stdio.printf(" betavariate(2,5) = %f\n", f) + testcheck.ok("betavariate distribution") + + # --- Test 12: triangular --- + testcheck.section("Test 12: triangular(0.0, 10.0, 5.0)") + for _ in range(3): + f = vrandom.triangular(0.0, 10.0, 5.0) + stdio.printf(" triangular(0,10,5) = %f\n", f) + testcheck.ok("triangular distribution") + + # --- Test 13: lognormvariate --- + testcheck.section("Test 13: lognormvariate(0.0, 1.0)") + for _ in range(3): + f = vrandom.lognormvariate(0.0, 1.0) + stdio.printf(" lognormvariate(0,1) = %f\n", f) + testcheck.ok("lognormvariate distribution") + + # --- Test 14: paretovariate --- + testcheck.section("Test 14: paretovariate(1.0)") + for _ in range(3): + f = vrandom.paretovariate(1.0) + stdio.printf(" paretovariate(1) = %f\n", f) + testcheck.ok("paretovariate distribution") + + # --- Test 15: weibullvariate --- + testcheck.section("Test 15: weibullvariate(1.0, 1.5)") + for _ in range(3): + f = vrandom.weibullvariate(1.0, 1.5) + stdio.printf(" weibullvariate(1,1.5) = %f\n", f) + testcheck.ok("weibullvariate distribution") + + # --- Test 16: vonmisesvariate --- + testcheck.section("Test 16: vonmisesvariate(0.0, 1.0)") + for _ in range(3): + f = vrandom.vonmisesvariate(0.0, 1.0) + stdio.printf(" vonmisesvariate(0,1) = %f\n", f) + testcheck.ok("vonmisesvariate distribution") + + return testcheck.end() diff --git a/Test/VRandomTest/output/3f7c5e78d8652535.deps.json b/Test/VRandomTest/output/3f7c5e78d8652535.deps.json new file mode 100644 index 0000000..322f835 --- /dev/null +++ b/Test/VRandomTest/output/3f7c5e78d8652535.deps.json @@ -0,0 +1 @@ +{"vipermath": "3f7c5e78d8652535", "stdint": "49bd8cba55979f76", "vrandom": "62cc01c2bb770ca3", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "main": "e24a7f4a875f4518"} \ No newline at end of file diff --git a/Test/VRandomTest/output/62cc01c2bb770ca3.deps.json b/Test/VRandomTest/output/62cc01c2bb770ca3.deps.json new file mode 100644 index 0000000..322f835 --- /dev/null +++ b/Test/VRandomTest/output/62cc01c2bb770ca3.deps.json @@ -0,0 +1 @@ +{"vipermath": "3f7c5e78d8652535", "stdint": "49bd8cba55979f76", "vrandom": "62cc01c2bb770ca3", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "main": "e24a7f4a875f4518"} \ No newline at end of file diff --git a/Test/VRandomTest/output/9dbecd0942a39782.deps.json b/Test/VRandomTest/output/9dbecd0942a39782.deps.json new file mode 100644 index 0000000..322f835 --- /dev/null +++ b/Test/VRandomTest/output/9dbecd0942a39782.deps.json @@ -0,0 +1 @@ +{"vipermath": "3f7c5e78d8652535", "stdint": "49bd8cba55979f76", "vrandom": "62cc01c2bb770ca3", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "main": "e24a7f4a875f4518"} \ No newline at end of file diff --git a/Test/VRandomTest/output/e24a7f4a875f4518.deps.json b/Test/VRandomTest/output/e24a7f4a875f4518.deps.json new file mode 100644 index 0000000..5b417a5 --- /dev/null +++ b/Test/VRandomTest/output/e24a7f4a875f4518.deps.json @@ -0,0 +1 @@ +{"vipermath": "3f7c5e78d8652535", "stdint": "49bd8cba55979f76", "vrandom": "62cc01c2bb770ca3", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782"} \ No newline at end of file diff --git a/Test/VRandomTest/project.json b/Test/VRandomTest/project.json new file mode 100644 index 0000000..c0e7428 --- /dev/null +++ b/Test/VRandomTest/project.json @@ -0,0 +1,29 @@ +{ + "$schema": "https://raw.githubusercontent.com/TermiNexus/TransPyC/main/schemas/project-schema.json", + "name": "VRandomTest", + "version": "1.0.0", + "source_dir": "./App", + "temp_dir": "./temp", + "output_dir": "./output", + "compiler": { + "cmd": "llc", + "flags": ["-filetype=obj", "-relocation-model=pic"] + }, + "linker": { + "cmd": "clang++", + "flags": ["-lmsvcrt", "-lucrt", "-lpthread", "-lmingwex", "-lkernel32", "-Wl,--allow-multiple-definition"], + "output": "VRandomTest.exe" + }, + "includes": [ + "../../includes" + ], + "target": { + "triple": "x86_64-pc-windows-gnu", + "datalayout": "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" + }, + "options": { + "slice_level": 3, + "target": "llvm", + "strict_mode": true + } +} diff --git a/Test/TestProject/temp/3f7c5e78d8652535.pyi b/Test/VRandomTest/temp/3f7c5e78d8652535.pyi similarity index 100% rename from Test/TestProject/temp/3f7c5e78d8652535.pyi rename to Test/VRandomTest/temp/3f7c5e78d8652535.pyi diff --git a/Test/VRandomTest/temp/49bd8cba55979f76.pyi b/Test/VRandomTest/temp/49bd8cba55979f76.pyi new file mode 100644 index 0000000..f1d844a --- /dev/null +++ b/Test/VRandomTest/temp/49bd8cba55979f76.pyi @@ -0,0 +1,75 @@ +""" +Auto-generated Python stub file from stdint.py +Module: stdint +""" + +import c + + +import t + +INT: t.CTypedef = t.CInt +INTPTR: t.CTypedef = t.CInt | t.CPtr +BOOL: t.CTypedef = t.CInt +UINT: t.CTypedef = t.CUnsignedInt +UINTPTR: t.CTypedef = UINT | t.CPtr +BYTE: t.CTypedef = t.CUnsignedChar +BYTEPTR: t.CTypedef = BYTE | t.CPtr +WORD: t.CTypedef = t.CUInt16T +DWORD: t.CTypedef = t.CUInt32T +QWORD: t.CTypedef = t.CUInt64T +TCHAR: t.CTypedef = t.CChar +CHARLIST: t.CTypedef = str | t.CPtr +VOID: t.CTypedef = t.CVoid +SHORT: t.CTypedef = t.CShort +SHORTPTR: t.CTypedef = t.CShort | t.CPtr +USHORT: t.CTypedef = t.CUnsignedShort +USHORTPTR: t.CTypedef = t.CUnsignedShort | t.CPtr +LONGLONG: t.CTypedef = t.CLong | t.CLong +ULONGLONG: t.CTypedef = t.CUnsignedLong | t.CLong +LONG: t.CTypedef = t.CLong +ULONG: t.CTypedef = t.CUnsignedLong +WCHAR: t.CTypedef = WORD +WCHARPTR: t.CTypedef = WORD | t.CPtr +CHARPTR: t.CTypedef = t.CChar | t.CPtr +FSIZE_t: t.CTypedef = DWORD +LBA_t: t.CTypedef = DWORD +UINTPTR: t.CTypedef = t.CUnsignedInt | t.CPtr +VOIDPTR: t.CTypedef = t.CVoid | t.CPtr +FLOAT: t.CTypedef = t.CFloat +DOUBLE: t.CTypedef = t.CDouble +FLOAT8: t.CTypedef = t.CFloat8T +FLOAT16: t.CTypedef = t.CFloat16T +FLOAT32: t.CTypedef = t.CFloat32T +FLOAT64: t.CTypedef = t.CFloat64T +FLOAT128: t.CTypedef = t.CFloat128T +INT8: t.CTypedef = t.CInt8T +INT16: t.CTypedef = t.CInt16T +INT32: t.CTypedef = t.CInt32T +INT64: t.CTypedef = t.CInt64T +UINT8: t.CTypedef = t.CUInt8T +UINT16: t.CTypedef = t.CUInt16T +UINT32: t.CTypedef = t.CUInt32T +UINT64: t.CTypedef = t.CUInt64T +INT8PTR: t.CTypedef = t.CInt8T | t.CPtr +INT16PTR: t.CTypedef = t.CInt16T | t.CPtr +INT32PTR: t.CTypedef = t.CInt32T | t.CPtr +INT64PTR: t.CTypedef = t.CInt64T | t.CPtr +UINT8PTR: t.CTypedef = t.CUInt8T | t.CPtr +UINT16PTR: t.CTypedef = t.CUInt16T | t.CPtr +UINT32PTR: t.CTypedef = t.CUInt32T | t.CPtr +UINT64PTR: t.CTypedef = t.CUInt64T | t.CPtr +CHAR8: t.CTypedef = t.CChar8T +CHAR16: t.CTypedef = t.CChar16T +CHAR32: t.CTypedef = t.CChar32T +CHAR8PTR: t.CTypedef = t.CChar8T | t.CPtr +CHAR16PTR: t.CTypedef = t.CChar16T | t.CPtr +CHAR32PTR: t.CTypedef = t.CChar32T | t.CPtr +i8: t.CTypedef = t.CInt8T +i16: t.CTypedef = t.CInt16T +i32: t.CTypedef = t.CInt32T +i64: t.CTypedef = t.CInt64T +u8: t.CTypedef = t.CUInt8T +u16: t.CTypedef = t.CUInt16T +u32: t.CTypedef = t.CUInt32T +u64: t.CTypedef = t.CUInt64T \ No newline at end of file diff --git a/Test/VRandomTest/temp/62cc01c2bb770ca3.pyi b/Test/VRandomTest/temp/62cc01c2bb770ca3.pyi new file mode 100644 index 0000000..17b1307 --- /dev/null +++ b/Test/VRandomTest/temp/62cc01c2bb770ca3.pyi @@ -0,0 +1,77 @@ +""" +Auto-generated Python stub file from vrandom.py +Module: vrandom +""" + + +import t, c +import vipermath + +RDRAND_RETRY_LIMIT: t.CDefine = 10 +RDSEED_RETRY_LIMIT: t.CDefine = 100 + +def rdrand16() -> t.CUInt16T: pass + +def rdrand32() -> t.CUInt32T: pass + +def rdrand64() -> t.CUInt64T: pass + +def rdseed16() -> t.CUInt16T: pass + +def rdseed32() -> t.CUInt32T: pass + +def rdseed64() -> t.CUInt64T: pass + +def rdrand16_step(p: t.CUInt16T | t.CPtr) -> t.CInt: pass + +def rdrand32_step(p: t.CUInt32T | t.CPtr) -> t.CInt: pass + +def rdrand64_step(p: t.CUInt64T | t.CPtr) -> t.CInt: pass + +def rdseed16_step(p: t.CUInt16T | t.CPtr) -> t.CInt: pass + +def rdseed32_step(p: t.CUInt32T | t.CPtr) -> t.CInt: pass + +def rdseed64_step(p: t.CUInt64T | t.CPtr) -> t.CInt: pass + +def random_u16() -> t.CUInt16T: pass + +def random_u32() -> t.CUInt32T: pass + +def random_u64() -> t.CUInt64T: pass + +def seed_u16() -> t.CUInt16T: pass + +def seed_u32() -> t.CUInt32T: pass + +def seed_u64() -> t.CUInt64T: pass + +def randint(a: t.CInt, b: t.CInt) -> t.CInt: pass + +def randrange(start: t.CInt, stop: t.CInt, step: t.CInt) -> t.CInt: pass + +def getrandbits(k: t.CInt) -> t.CUInt64T: pass + +def random() -> t.CDouble: pass + +def uniform(a: t.CDouble, b: t.CDouble) -> t.CDouble: pass + +def triangular(low: t.CDouble, high: t.CDouble, mode: t.CDouble) -> t.CDouble: pass + +def betavariate(alpha: t.CDouble, beta: t.CDouble) -> t.CDouble: pass + +def expovariate(lambd: t.CDouble) -> t.CDouble: pass + +def gammavariate(alpha: t.CDouble, beta: t.CDouble) -> t.CDouble: pass + +def gauss(mu: t.CDouble, sigma: t.CDouble) -> t.CDouble: pass + +def normalvariate(mu: t.CDouble, sigma: t.CDouble) -> t.CDouble: pass + +def lognormvariate(mu: t.CDouble, sigma: t.CDouble) -> t.CDouble: pass + +def vonmisesvariate(mu: t.CDouble, kappa: t.CDouble) -> t.CDouble: pass + +def paretovariate(alpha: t.CDouble) -> t.CDouble: pass + +def weibullvariate(alpha: t.CDouble, beta: t.CDouble) -> t.CDouble: pass diff --git a/Test/VRandomTest/temp/73edbcf76e32d00b.pyi b/Test/VRandomTest/temp/73edbcf76e32d00b.pyi new file mode 100644 index 0000000..ef712e3 --- /dev/null +++ b/Test/VRandomTest/temp/73edbcf76e32d00b.pyi @@ -0,0 +1,28 @@ +""" +Auto-generated Python stub file from stdio.py +Module: stdio +""" + + +import t, c + +def printf(fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass + +def fprintf(stream: t.CVoid | t.CPtr, fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass + +def sprintf(buf: t.CChar | t.CPtr, fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass + +def snprintf(buf: t.CChar | t.CPtr, size: t.CSizeT, fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.CExtern | t.CExport: pass + +def puts(s: t.CChar | t.CConst | t.CPtr) -> t.CInt | t.CExtern | t.CExport: pass + +def fputs(s: t.CChar | t.CConst | t.CPtr, stream: t.CVoid | t.CPtr) -> t.CInt | t.CExtern | t.CExport: pass + +def fgets(buf: t.CChar | t.CPtr, size: t.CInt, stream: t.CVoid | t.CPtr) -> t.CChar | t.CPtr | t.CExtern | t.CExport: pass + +def fflush(stream: t.CVoid | t.CPtr) -> t.CInt | t.CExtern | t.CExport: pass + + +stdin: t.CExtern | t.CVoid | t.CPtr +stdout: t.CExtern | t.CVoid | t.CPtr +stderr: t.CExtern | t.CVoid | t.CPtr \ No newline at end of file diff --git a/Test/VRandomTest/temp/9dbecd0942a39782.pyi b/Test/VRandomTest/temp/9dbecd0942a39782.pyi new file mode 100644 index 0000000..41648c1 --- /dev/null +++ b/Test/VRandomTest/temp/9dbecd0942a39782.pyi @@ -0,0 +1,25 @@ +""" +Auto-generated Python stub file from testcheck.py +Module: testcheck +""" + + +import t, c +import stdio + +_pass_count: t.CExtern | t.CInt +_fail_count: t.CExtern | t.CInt + +def begin(name: str) -> t.CInt: pass + +def section(name: str) -> t.CInt: pass + +def ok(msg: str) -> t.CInt: pass + +def fail(msg: str) -> t.CInt: pass + +def check(cond: t.CInt, ok_msg: str, fail_msg: str) -> t.CInt: pass + +def info(msg: str) -> t.CInt: pass + +def end() -> t.CInt: pass diff --git a/Test/VRandomTest/temp/_sha1_map.txt b/Test/VRandomTest/temp/_sha1_map.txt new file mode 100644 index 0000000..2005d49 --- /dev/null +++ b/Test/VRandomTest/temp/_sha1_map.txt @@ -0,0 +1,6 @@ +3f7c5e78d8652535:includes/vipermath.py +49bd8cba55979f76:includes/stdint.py +62cc01c2bb770ca3:includes/vrandom.py +73edbcf76e32d00b:includes/stdio.py +9dbecd0942a39782:includes/testcheck.py +e24a7f4a875f4518:main.py diff --git a/Test/VRandomTest/temp/e24a7f4a875f4518.pyi b/Test/VRandomTest/temp/e24a7f4a875f4518.pyi new file mode 100644 index 0000000..2825744 --- /dev/null +++ b/Test/VRandomTest/temp/e24a7f4a875f4518.pyi @@ -0,0 +1,13 @@ +""" +Auto-generated Python stub file from main.py +Module: main +""" + + +from stdint import * +import t, c +import stdio +import vrandom +import testcheck + +def main() -> t.CInt: pass diff --git a/Test/VariadicTest/App/main.py b/Test/VariadicTest/App/main.py index 25de30d..b4c1da2 100644 --- a/Test/VariadicTest/App/main.py +++ b/Test/VariadicTest/App/main.py @@ -1,6 +1,7 @@ from stdint import * import t, c import stdio +import testcheck import string import viperlib import w32.win32console @@ -12,136 +13,160 @@ import w32.win32console # --- Test 1: %u 格式化小整数 (CUInt8T -> CUnsignedInt) --- def test_snprintf_u8(): """测试 CUInt8T 值通过 t.CUnsignedInt() 传递给 %u""" + testcheck.section("Test 1: %u 格式化小整数 (CUInt8T -> CUnsignedInt)") hr: t.CUInt8T = 14 mn: t.CUInt8T = 30 sc: t.CUInt8T = 59 - buf: list[t.CChar, 64] + buf: t.CArray[t.CChar, 64] string.memset(c.Addr(buf), 0, 64) viperlib.snprintf(c.Addr(buf), 64, "%02u:%02u:%02u", t.CUnsignedInt(hr), t.CUnsignedInt(mn), t.CUnsignedInt(sc)) stdio.printf("Test1 (CUInt8T->%%u): [%s] (expect 14:30:59)\n", c.Addr(buf)) + testcheck.ok("CUInt8T -> %u (expect 14:30:59)") # --- Test 2: %u 格式化 CUInt16T --- def test_snprintf_u16(): """测试 CUInt16T 值通过 t.CUnsignedInt() 传递给 %u""" + testcheck.section("Test 2: %u 格式化 CUInt16T") yr: t.CUInt16T = 2026 - buf: list[t.CChar, 64] + buf: t.CArray[t.CChar, 64] string.memset(c.Addr(buf), 0, 64) viperlib.snprintf(c.Addr(buf), 64, "%04u", t.CUnsignedInt(yr)) stdio.printf("Test2 (CUInt16T->%%u): [%s] (expect 2026)\n", c.Addr(buf)) + testcheck.ok("CUInt16T -> %u (expect 2026)") # --- Test 3: %lu 格式化 CUInt64T --- def test_snprintf_u64(): """测试 CUInt64T 值传递给 %lu""" + testcheck.section("Test 3: %lu 格式化 CUInt64T") val: t.CUInt64T = 1234567890123 - buf: list[t.CChar, 64] + buf: t.CArray[t.CChar, 64] string.memset(c.Addr(buf), 0, 64) viperlib.snprintf(c.Addr(buf), 64, "%lu", val) stdio.printf("Test3 (CUInt64T->%%lu): [%s] (expect 1234567890123)\n", c.Addr(buf)) + testcheck.ok("CUInt64T -> %lu (expect 1234567890123)") # --- Test 4: %d 格式化负数 --- def test_snprintf_d_neg(): """测试 %d 格式化负整数""" + testcheck.section("Test 4: %d 格式化负数") val: t.CInt = -42 - buf: list[t.CChar, 64] + buf: t.CArray[t.CChar, 64] string.memset(c.Addr(buf), 0, 64) viperlib.snprintf(c.Addr(buf), 64, "%d", val) stdio.printf("Test4 (CInt->%%d neg): [%s] (expect -42)\n", c.Addr(buf)) + testcheck.ok("CInt -> %d neg (expect -42)") # --- Test 5: %d 格式化正数 --- def test_snprintf_d_pos(): + testcheck.section("Test 5: %d 格式化正数") val: t.CInt = 42 - buf: list[t.CChar, 64] + buf: t.CArray[t.CChar, 64] string.memset(c.Addr(buf), 0, 64) viperlib.snprintf(c.Addr(buf), 64, "%d", val) stdio.printf("Test5 (CInt->%%d pos): [%s] (expect 42)\n", c.Addr(buf)) + testcheck.ok("CInt -> %d pos (expect 42)") # --- Test 6: %x 格式化十六进制 --- def test_snprintf_x(): + testcheck.section("Test 6: %x 格式化十六进制") val: t.CUInt32T = 0xDEADBEEF - buf: list[t.CChar, 64] + buf: t.CArray[t.CChar, 64] string.memset(c.Addr(buf), 0, 64) viperlib.snprintf(c.Addr(buf), 64, "0x%08x", val) stdio.printf("Test6 (%%x): [%s] (expect 0xdeadbeef)\n", c.Addr(buf)) + testcheck.ok("%x hex (expect 0xdeadbeef)") # --- Test 7: 混合格式化 (模拟 desktop.py 时间格式) --- def test_snprintf_mixed(): """模拟 desktop.py 的时间格式化""" + testcheck.section("Test 7: 混合格式化 (模拟 desktop.py 时间格式)") hr: t.CUInt8T = 14 mn: t.CUInt8T = 5 sc: t.CUInt8T = 9 day: t.CUInt8T = 14 mon: t.CUInt8T = 6 yr: t.CUInt16T = 2026 - buf: list[t.CChar, 64] + buf: t.CArray[t.CChar, 64] string.memset(c.Addr(buf), 0, 64) viperlib.snprintf(c.Addr(buf), 64, "%04u-%02u-%02u %02u:%02u:%02u", t.CUnsignedInt(yr), t.CUnsignedInt(mon), t.CUnsignedInt(day), t.CUnsignedInt(hr), t.CUnsignedInt(mn), t.CUnsignedInt(sc)) stdio.printf("Test7 (time format): [%s] (expect 2026-06-14 14:05:09)\n", c.Addr(buf)) + testcheck.ok("time format (expect 2026-06-14 14:05:09)") # --- Test 8: printf 直接输出 variadic --- def test_printf_variadic(): """测试 printf 直接输出 variadic 参数""" + testcheck.section("Test 8: printf 直接输出 variadic") stdio.printf("Test8 (printf direct): %u %d %lu 0x%x (expect 100 -50 999999999 0xcafe)\n", t.CUnsignedInt(100), -50, t.CUInt64T(999999999), 0xCAFE) + testcheck.ok("printf direct variadic (expect 100 -50 999999999 0xcafe)") # --- Test 9: 多个 %lu 连续 --- def test_snprintf_multi_lu(): """测试多个 %lu 连续(模拟 perf 日志格式)""" + testcheck.section("Test 9: 多个 %lu 连续") v1: t.CUInt64T = 16 v2: t.CUInt64T = 2 v3: t.CUInt64T = 11 - buf: list[t.CChar, 128] + buf: t.CArray[t.CChar, 128] string.memset(c.Addr(buf), 0, 128) viperlib.snprintf(c.Addr(buf), 128, "wall=%lu work=%lu render=%lu", v1, v2, v3) stdio.printf("Test9 (multi %%lu): [%s] (expect wall=16 work=2 render=11)\n", c.Addr(buf)) + testcheck.ok("multi %lu (expect wall=16 work=2 render=11)") # --- Test 10: %u 格式化 0 --- def test_snprintf_zero(): + testcheck.section("Test 10: %u 格式化 0") val: t.CUInt32T = 0 - buf: list[t.CChar, 64] + buf: t.CArray[t.CChar, 64] string.memset(c.Addr(buf), 0, 64) viperlib.snprintf(c.Addr(buf), 64, "%u", val) stdio.printf("Test10 (%%u zero): [%s] (expect 0)\n", c.Addr(buf)) + testcheck.ok("%u zero (expect 0)") # --- Test 11: %u 格式化大值 --- def test_snprintf_large(): + testcheck.section("Test 11: %u 格式化大值") val: t.CUInt32T = 4294967295 # 0xFFFFFFFF - buf: list[t.CChar, 64] + buf: t.CArray[t.CChar, 64] string.memset(c.Addr(buf), 0, 64) viperlib.snprintf(c.Addr(buf), 64, "%u", val) stdio.printf("Test11 (%%u max): [%s] (expect 4294967295)\n", c.Addr(buf)) + testcheck.ok("%u max (expect 4294967295)") # --- Test 12: CUnsignedInt cast from CUInt8T edge values --- def test_snprintf_u8_edge(): """测试 CUInt8T 边界值""" + testcheck.section("Test 12: CUnsignedInt cast from CUInt8T edge values") v0: t.CUInt8T = 0 v127: t.CUInt8T = 127 v128: t.CUInt8T = 128 v255: t.CUInt8T = 255 - buf: list[t.CChar, 64] + buf: t.CArray[t.CChar, 64] string.memset(c.Addr(buf), 0, 64) viperlib.snprintf(c.Addr(buf), 64, "%u %u %u %u", t.CUnsignedInt(v0), t.CUnsignedInt(v127), t.CUnsignedInt(v128), t.CUnsignedInt(v255)) stdio.printf("Test12 (CUInt8T edge): [%s] (expect 0 127 128 255)\n", c.Addr(buf)) + testcheck.ok("CUInt8T edge (expect 0 127 128 255)") def main() -> t.CInt | t.CExport: w32.win32console.SetConsoleCP(65001) w32.win32console.SetConsoleOutputCP(65001) - stdio.printf("=== VariadicTest: snprintf/printf variadic 参数测试 ===\n\n") + testcheck.begin("VariadicTest: snprintf/printf variadic 参数测试") test_snprintf_u8() test_snprintf_u16() @@ -156,5 +181,4 @@ def main() -> t.CInt | t.CExport: test_snprintf_large() test_snprintf_u8_edge() - stdio.printf("\n=== VariadicTest Complete ===\n") - return 0 + return testcheck.end() diff --git a/Test/VariadicTest/output/067c78e9f121dce3.deps.json b/Test/VariadicTest/output/067c78e9f121dce3.deps.json index c11e2c3..0bd53f1 100644 --- a/Test/VariadicTest/output/067c78e9f121dce3.deps.json +++ b/Test/VariadicTest/output/067c78e9f121dce3.deps.json @@ -1 +1 @@ -{"viperlib": "2953a7db4185005b", "main": "377ad03e9b90ac39", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3"} \ No newline at end of file +{"stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "viperlib": "70b580331b822117", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "main": "c1416dfae155d6e2", "viperio": "c9f4be41ca1cc2b4", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3"} \ No newline at end of file diff --git a/Test/VariadicTest/output/2953a7db4185005b.deps.json b/Test/VariadicTest/output/2953a7db4185005b.deps.json deleted file mode 100644 index abec65b..0000000 --- a/Test/VariadicTest/output/2953a7db4185005b.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"viperlib": "2953a7db4185005b", "main": "377ad03e9b90ac39", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file diff --git a/Test/VariadicTest/output/29813d57621099a9.deps.json b/Test/VariadicTest/output/29813d57621099a9.deps.json index abec65b..5c64d5c 100644 --- a/Test/VariadicTest/output/29813d57621099a9.deps.json +++ b/Test/VariadicTest/output/29813d57621099a9.deps.json @@ -1 +1 @@ -{"viperlib": "2953a7db4185005b", "main": "377ad03e9b90ac39", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file +{"stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "viperlib": "70b580331b822117", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "main": "c1416dfae155d6e2", "viperio": "c9f4be41ca1cc2b4", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file diff --git a/Test/VariadicTest/output/377ad03e9b90ac39.deps.json b/Test/VariadicTest/output/377ad03e9b90ac39.deps.json deleted file mode 100644 index 2839e14..0000000 --- a/Test/VariadicTest/output/377ad03e9b90ac39.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"viperlib": "2953a7db4185005b", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "viperio": "c9f4be41ca1cc2b4"} \ No newline at end of file diff --git a/Test/VariadicTest/output/5a6a2137958c28c5.deps.json b/Test/VariadicTest/output/5a6a2137958c28c5.deps.json index 791ea77..1a102ae 100644 --- a/Test/VariadicTest/output/5a6a2137958c28c5.deps.json +++ b/Test/VariadicTest/output/5a6a2137958c28c5.deps.json @@ -1 +1 @@ -{"viperlib": "2953a7db4185005b", "main": "377ad03e9b90ac39", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file +{"stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "viperlib": "70b580331b822117", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "main": "c1416dfae155d6e2", "viperio": "c9f4be41ca1cc2b4"} \ No newline at end of file diff --git a/Test/VariadicTest/output/6aee24fdefa3cbc0.deps.json b/Test/VariadicTest/output/6aee24fdefa3cbc0.deps.json deleted file mode 100644 index 43983e1..0000000 --- a/Test/VariadicTest/output/6aee24fdefa3cbc0.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"viperlib": "2953a7db4185005b", "main": "377ad03e9b90ac39", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "viperio": "c9f4be41ca1cc2b4"} \ No newline at end of file diff --git a/Test/VariadicTest/output/70b580331b822117.deps.json b/Test/VariadicTest/output/70b580331b822117.deps.json new file mode 100644 index 0000000..1a102ae --- /dev/null +++ b/Test/VariadicTest/output/70b580331b822117.deps.json @@ -0,0 +1 @@ +{"stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "viperlib": "70b580331b822117", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "main": "c1416dfae155d6e2", "viperio": "c9f4be41ca1cc2b4"} \ No newline at end of file diff --git a/Test/VariadicTest/output/72e2d5ccb7cedcf1.deps.json b/Test/VariadicTest/output/72e2d5ccb7cedcf1.deps.json index e515c67..a910013 100644 --- a/Test/VariadicTest/output/72e2d5ccb7cedcf1.deps.json +++ b/Test/VariadicTest/output/72e2d5ccb7cedcf1.deps.json @@ -1 +1 @@ -{"viperlib": "2953a7db4185005b", "main": "377ad03e9b90ac39", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1"} \ No newline at end of file +{"stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "viperlib": "70b580331b822117", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "main": "c1416dfae155d6e2", "viperio": "c9f4be41ca1cc2b4", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1"} \ No newline at end of file diff --git a/Test/VariadicTest/output/9dbecd0942a39782.deps.json b/Test/VariadicTest/output/9dbecd0942a39782.deps.json new file mode 100644 index 0000000..1a102ae --- /dev/null +++ b/Test/VariadicTest/output/9dbecd0942a39782.deps.json @@ -0,0 +1 @@ +{"stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "viperlib": "70b580331b822117", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "main": "c1416dfae155d6e2", "viperio": "c9f4be41ca1cc2b4"} \ No newline at end of file diff --git a/Test/VariadicTest/output/abf9ce3160c9279e.deps.json b/Test/VariadicTest/output/abf9ce3160c9279e.deps.json index dbd0c83..2280dae 100644 --- a/Test/VariadicTest/output/abf9ce3160c9279e.deps.json +++ b/Test/VariadicTest/output/abf9ce3160c9279e.deps.json @@ -1 +1 @@ -{"viperlib": "2953a7db4185005b", "main": "377ad03e9b90ac39", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e"} \ No newline at end of file +{"stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "viperlib": "70b580331b822117", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "main": "c1416dfae155d6e2", "viperio": "c9f4be41ca1cc2b4", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e"} \ No newline at end of file diff --git a/Test/VariadicTest/output/b5f1dc665c52a1bd.deps.json b/Test/VariadicTest/output/b5f1dc665c52a1bd.deps.json new file mode 100644 index 0000000..1a102ae --- /dev/null +++ b/Test/VariadicTest/output/b5f1dc665c52a1bd.deps.json @@ -0,0 +1 @@ +{"stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "viperlib": "70b580331b822117", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "main": "c1416dfae155d6e2", "viperio": "c9f4be41ca1cc2b4"} \ No newline at end of file diff --git a/Test/VariadicTest/output/bbdf3bbd4c3bc28c.deps.json b/Test/VariadicTest/output/bbdf3bbd4c3bc28c.deps.json index 791ea77..1a102ae 100644 --- a/Test/VariadicTest/output/bbdf3bbd4c3bc28c.deps.json +++ b/Test/VariadicTest/output/bbdf3bbd4c3bc28c.deps.json @@ -1 +1 @@ -{"viperlib": "2953a7db4185005b", "main": "377ad03e9b90ac39", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file +{"stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "viperlib": "70b580331b822117", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "main": "c1416dfae155d6e2", "viperio": "c9f4be41ca1cc2b4"} \ No newline at end of file diff --git a/Test/VariadicTest/output/c1416dfae155d6e2.deps.json b/Test/VariadicTest/output/c1416dfae155d6e2.deps.json new file mode 100644 index 0000000..0eefc67 --- /dev/null +++ b/Test/VariadicTest/output/c1416dfae155d6e2.deps.json @@ -0,0 +1 @@ +{"stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "viperlib": "70b580331b822117", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "viperio": "c9f4be41ca1cc2b4"} \ No newline at end of file diff --git a/Test/VariadicTest/output/c9f4be41ca1cc2b4.deps.json b/Test/VariadicTest/output/c9f4be41ca1cc2b4.deps.json index 43983e1..1a102ae 100644 --- a/Test/VariadicTest/output/c9f4be41ca1cc2b4.deps.json +++ b/Test/VariadicTest/output/c9f4be41ca1cc2b4.deps.json @@ -1 +1 @@ -{"viperlib": "2953a7db4185005b", "main": "377ad03e9b90ac39", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "viperio": "c9f4be41ca1cc2b4"} \ No newline at end of file +{"stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "viperlib": "70b580331b822117", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "main": "c1416dfae155d6e2", "viperio": "c9f4be41ca1cc2b4"} \ No newline at end of file diff --git a/Test/VariadicTest/output/fa3691e66b426950.deps.json b/Test/VariadicTest/output/fa3691e66b426950.deps.json index 791ea77..aa73abd 100644 --- a/Test/VariadicTest/output/fa3691e66b426950.deps.json +++ b/Test/VariadicTest/output/fa3691e66b426950.deps.json @@ -1 +1 @@ -{"viperlib": "2953a7db4185005b", "main": "377ad03e9b90ac39", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "viperio": "c9f4be41ca1cc2b4", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file +{"stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "viperlib": "70b580331b822117", "stdarg": "71e0a3ffcb3ebfad", "stdio": "73edbcf76e32d00b", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "main": "c1416dfae155d6e2", "viperio": "c9f4be41ca1cc2b4", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file diff --git a/Test/VariadicTest/temp/49bd8cba55979f76.pyi b/Test/VariadicTest/temp/49bd8cba55979f76.pyi new file mode 100644 index 0000000..f1d844a --- /dev/null +++ b/Test/VariadicTest/temp/49bd8cba55979f76.pyi @@ -0,0 +1,75 @@ +""" +Auto-generated Python stub file from stdint.py +Module: stdint +""" + +import c + + +import t + +INT: t.CTypedef = t.CInt +INTPTR: t.CTypedef = t.CInt | t.CPtr +BOOL: t.CTypedef = t.CInt +UINT: t.CTypedef = t.CUnsignedInt +UINTPTR: t.CTypedef = UINT | t.CPtr +BYTE: t.CTypedef = t.CUnsignedChar +BYTEPTR: t.CTypedef = BYTE | t.CPtr +WORD: t.CTypedef = t.CUInt16T +DWORD: t.CTypedef = t.CUInt32T +QWORD: t.CTypedef = t.CUInt64T +TCHAR: t.CTypedef = t.CChar +CHARLIST: t.CTypedef = str | t.CPtr +VOID: t.CTypedef = t.CVoid +SHORT: t.CTypedef = t.CShort +SHORTPTR: t.CTypedef = t.CShort | t.CPtr +USHORT: t.CTypedef = t.CUnsignedShort +USHORTPTR: t.CTypedef = t.CUnsignedShort | t.CPtr +LONGLONG: t.CTypedef = t.CLong | t.CLong +ULONGLONG: t.CTypedef = t.CUnsignedLong | t.CLong +LONG: t.CTypedef = t.CLong +ULONG: t.CTypedef = t.CUnsignedLong +WCHAR: t.CTypedef = WORD +WCHARPTR: t.CTypedef = WORD | t.CPtr +CHARPTR: t.CTypedef = t.CChar | t.CPtr +FSIZE_t: t.CTypedef = DWORD +LBA_t: t.CTypedef = DWORD +UINTPTR: t.CTypedef = t.CUnsignedInt | t.CPtr +VOIDPTR: t.CTypedef = t.CVoid | t.CPtr +FLOAT: t.CTypedef = t.CFloat +DOUBLE: t.CTypedef = t.CDouble +FLOAT8: t.CTypedef = t.CFloat8T +FLOAT16: t.CTypedef = t.CFloat16T +FLOAT32: t.CTypedef = t.CFloat32T +FLOAT64: t.CTypedef = t.CFloat64T +FLOAT128: t.CTypedef = t.CFloat128T +INT8: t.CTypedef = t.CInt8T +INT16: t.CTypedef = t.CInt16T +INT32: t.CTypedef = t.CInt32T +INT64: t.CTypedef = t.CInt64T +UINT8: t.CTypedef = t.CUInt8T +UINT16: t.CTypedef = t.CUInt16T +UINT32: t.CTypedef = t.CUInt32T +UINT64: t.CTypedef = t.CUInt64T +INT8PTR: t.CTypedef = t.CInt8T | t.CPtr +INT16PTR: t.CTypedef = t.CInt16T | t.CPtr +INT32PTR: t.CTypedef = t.CInt32T | t.CPtr +INT64PTR: t.CTypedef = t.CInt64T | t.CPtr +UINT8PTR: t.CTypedef = t.CUInt8T | t.CPtr +UINT16PTR: t.CTypedef = t.CUInt16T | t.CPtr +UINT32PTR: t.CTypedef = t.CUInt32T | t.CPtr +UINT64PTR: t.CTypedef = t.CUInt64T | t.CPtr +CHAR8: t.CTypedef = t.CChar8T +CHAR16: t.CTypedef = t.CChar16T +CHAR32: t.CTypedef = t.CChar32T +CHAR8PTR: t.CTypedef = t.CChar8T | t.CPtr +CHAR16PTR: t.CTypedef = t.CChar16T | t.CPtr +CHAR32PTR: t.CTypedef = t.CChar32T | t.CPtr +i8: t.CTypedef = t.CInt8T +i16: t.CTypedef = t.CInt16T +i32: t.CTypedef = t.CInt32T +i64: t.CTypedef = t.CInt64T +u8: t.CTypedef = t.CUInt8T +u16: t.CTypedef = t.CUInt16T +u32: t.CTypedef = t.CUInt32T +u64: t.CTypedef = t.CUInt64T \ No newline at end of file diff --git a/Test/VariadicTest/temp/56cdd754a8a09347.pyi b/Test/VariadicTest/temp/56cdd754a8a09347.pyi deleted file mode 100644 index 007ccb8..0000000 --- a/Test/VariadicTest/temp/56cdd754a8a09347.pyi +++ /dev/null @@ -1,67 +0,0 @@ -""" -Auto-generated Python stub file from stdint.py -Module: stdint -""" - -import c - - -import t - -INT: t.CTypedef = t.CInt -INTPTR: t.CTypedef = t.CInt | t.CPtr -BOOL: t.CTypedef = t.CInt -UINT: t.CTypedef = t.CUnsignedInt -UINTPTR: t.CTypedef = UINT | t.CPtr -BYTE: t.CTypedef = t.CUnsignedChar -BYTEPTR: t.CTypedef = BYTE | t.CPtr -WORD: t.CTypedef = t.CUInt16T -DWORD: t.CTypedef = t.CUInt32T -QWORD: t.CTypedef = t.CUInt64T -TCHAR: t.CTypedef = t.CChar -CHARLIST: t.CTypedef = str | t.CPtr -VOID: t.CTypedef = t.CVoid -SHORT: t.CTypedef = t.CShort -SHORTPTR: t.CTypedef = t.CShort | t.CPtr -USHORT: t.CTypedef = t.CUnsignedShort -USHORTPTR: t.CTypedef = t.CUnsignedShort | t.CPtr -LONGLONG: t.CTypedef = t.CLong | t.CLong -ULONGLONG: t.CTypedef = t.CUnsignedLong | t.CLong -LONG: t.CTypedef = t.CLong -ULONG: t.CTypedef = t.CUnsignedLong -WCHAR: t.CTypedef = WORD -WCHARPTR: t.CTypedef = WORD | t.CPtr -CHARPTR: t.CTypedef = t.CChar | t.CPtr -FSIZE_t: t.CTypedef = DWORD -LBA_t: t.CTypedef = DWORD -UINTPTR: t.CTypedef = t.CUnsignedInt | t.CPtr -VOIDPTR: t.CTypedef = t.CVoid | t.CPtr -FLOAT: t.CTypedef = t.CFloat -DOUBLE: t.CTypedef = t.CDouble -FLOAT8: t.CTypedef = t.CFloat8T -FLOAT16: t.CTypedef = t.CFloat16T -FLOAT32: t.CTypedef = t.CFloat32T -FLOAT64: t.CTypedef = t.CFloat64T -FLOAT128: t.CTypedef = t.CFloat128T -INT8: t.CTypedef = t.CInt8T -INT16: t.CTypedef = t.CInt16T -INT32: t.CTypedef = t.CInt32T -INT64: t.CTypedef = t.CInt64T -UINT8: t.CTypedef = t.CUInt8T -UINT16: t.CTypedef = t.CUInt16T -UINT32: t.CTypedef = t.CUInt32T -UINT64: t.CTypedef = t.CUInt64T -INT8PTR: t.CTypedef = t.CInt8T | t.CPtr -INT16PTR: t.CTypedef = t.CInt16T | t.CPtr -INT32PTR: t.CTypedef = t.CInt32T | t.CPtr -INT64PTR: t.CTypedef = t.CInt64T | t.CPtr -UINT8PTR: t.CTypedef = t.CUInt8T | t.CPtr -UINT16PTR: t.CTypedef = t.CUInt16T | t.CPtr -UINT32PTR: t.CTypedef = t.CUInt32T | t.CPtr -UINT64PTR: t.CTypedef = t.CUInt64T | t.CPtr -CHAR8: t.CTypedef = t.CChar8T -CHAR16: t.CTypedef = t.CChar16T -CHAR32: t.CTypedef = t.CChar32T -CHAR8PTR: t.CTypedef = t.CChar8T | t.CPtr -CHAR16PTR: t.CTypedef = t.CChar16T | t.CPtr -CHAR32PTR: t.CTypedef = t.CChar32T | t.CPtr \ No newline at end of file diff --git a/Test/VariadicTest/temp/6aee24fdefa3cbc0.pyi b/Test/VariadicTest/temp/6aee24fdefa3cbc0.pyi deleted file mode 100644 index c17475f..0000000 --- a/Test/VariadicTest/temp/6aee24fdefa3cbc0.pyi +++ /dev/null @@ -1,44 +0,0 @@ -""" -Auto-generated Python stub file from string.py -Module: string -""" - - -from stdint import * -import t, c - -def strcpy(dest: str, src: str) -> str: pass - -def strncpy(dest: str, src: str, n: t.CSizeT) -> str: pass - -def strlen(src: str) -> t.CSizeT | t.CExport: pass - -def strcmp(str1: str, str2: str) -> t.CInt: pass - -def samestr(str1: str, str2: str) -> bool: pass - -def strncmp(str1: str, str2: str, n: t.CSizeT) -> t.CInt: pass - -def memcmp(ptr1: t.CVoid | t.CPtr, ptr2: t.CVoid | t.CPtr, n: t.CSizeT) -> t.CInt: pass - -def strchr(s: str, cr: t.CInt) -> str: pass - -def strrchr(s: str, cr: t.CInt) -> str: pass - -def strspn(s: str, skip: str) -> int: pass - -def memset(ptr: t.CVoid | t.CPtr, value: t.CInt, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass - -def memset32(ptr: t.CVoid | t.CPtr, value: t.CUInt32T, count: t.CSizeT) -> t.CVoid | t.CPtr: pass - -def memcpy(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass - -def memmove(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr: pass - -def atoi(src: str) -> t.CInt: pass - -def atoll(src: str) -> t.CInt64T: pass - -def atof(src: str) -> t.CDouble: pass - -def split(s: str, delim: str, result: list[str]) -> int: pass diff --git a/Test/VariadicTest/temp/70b580331b822117.pyi b/Test/VariadicTest/temp/70b580331b822117.pyi new file mode 100644 index 0000000..aa40bc7 --- /dev/null +++ b/Test/VariadicTest/temp/70b580331b822117.pyi @@ -0,0 +1,19 @@ +""" +Auto-generated Python stub file from viperlib.py +Module: viperlib +""" + + +import t, c +import viperio +from stdarg import arg + +TEMP_BUF_SIZE: t.CDefine = 24 + +def get_digit_count(num: t.CUnsignedInt, base: t.CInt) -> t.CStatic | t.CInt | t.State: pass + +def sprintf(buf: t.CChar | t.CPtr, rule: str, *args) -> t.CVoid | t.State: pass + +def vsprintf(buf: t.CChar | t.CPtr, rule: str, *args) -> t.CInt | t.State: pass + +def snprintf(buf: t.CChar | t.CPtr, size: t.CSizeT, fmt: str, *args) -> t.CInt | t.State: pass diff --git a/Test/VariadicTest/temp/9dbecd0942a39782.pyi b/Test/VariadicTest/temp/9dbecd0942a39782.pyi new file mode 100644 index 0000000..41648c1 --- /dev/null +++ b/Test/VariadicTest/temp/9dbecd0942a39782.pyi @@ -0,0 +1,25 @@ +""" +Auto-generated Python stub file from testcheck.py +Module: testcheck +""" + + +import t, c +import stdio + +_pass_count: t.CExtern | t.CInt +_fail_count: t.CExtern | t.CInt + +def begin(name: str) -> t.CInt: pass + +def section(name: str) -> t.CInt: pass + +def ok(msg: str) -> t.CInt: pass + +def fail(msg: str) -> t.CInt: pass + +def check(cond: t.CInt, ok_msg: str, fail_msg: str) -> t.CInt: pass + +def info(msg: str) -> t.CInt: pass + +def end() -> t.CInt: pass diff --git a/Test/VariadicTest/temp/_sha1_map.txt b/Test/VariadicTest/temp/_sha1_map.txt index 318fb4b..fcc105f 100644 --- a/Test/VariadicTest/temp/_sha1_map.txt +++ b/Test/VariadicTest/temp/_sha1_map.txt @@ -1,9 +1,10 @@ -2953a7db4185005b:includes/viperlib.py -377ad03e9b90ac39:main.py -56cdd754a8a09347:includes/stdint.py +49bd8cba55979f76:includes/stdint.py 5a6a2137958c28c5:includes/w32\win32base.py -6aee24fdefa3cbc0:includes/string.py +70b580331b822117:includes/viperlib.py 71e0a3ffcb3ebfad:includes/stdarg.py 73edbcf76e32d00b:includes/stdio.py +9dbecd0942a39782:includes/testcheck.py +b5f1dc665c52a1bd:includes/string.py bbdf3bbd4c3bc28c:includes/w32\win32console.py +c1416dfae155d6e2:main.py c9f4be41ca1cc2b4:includes/viperio.py diff --git a/Test/VariadicTest/temp/b5f1dc665c52a1bd.pyi b/Test/VariadicTest/temp/b5f1dc665c52a1bd.pyi new file mode 100644 index 0000000..8b6959e --- /dev/null +++ b/Test/VariadicTest/temp/b5f1dc665c52a1bd.pyi @@ -0,0 +1,44 @@ +""" +Auto-generated Python stub file from string.py +Module: string +""" + + +from stdint import * +import t, c + +def strcpy(dest: str, src: str) -> str: pass + +def strncpy(dest: str, src: str, n: t.CSizeT) -> str: pass + +def strlen(src: str) -> t.CSizeT | t.CExport: pass + +def strcmp(str1: str, str2: str) -> t.CInt: pass + +def samestr(str1: str, str2: str) -> bool: pass + +def strncmp(str1: str, str2: str, n: t.CSizeT) -> t.CInt: pass + +def memcmp(ptr1: t.CVoid | t.CPtr, ptr2: t.CVoid | t.CPtr, n: t.CSizeT) -> t.CInt: pass + +def strchr(s: str, cr: t.CInt) -> str: pass + +def strrchr(s: str, cr: t.CInt) -> str: pass + +def strspn(s: str, skip: str) -> int: pass + +def memset(ptr: t.CVoid | t.CPtr, value: t.CInt, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass + +def memset32(ptr: t.CVoid | t.CPtr, value: t.CUInt32T, count: t.CSizeT) -> t.CVoid | t.CPtr: pass + +def memcpy(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass + +def memmove(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr: pass + +def atoi(src: str) -> t.CInt: pass + +def atoll(src: str) -> t.CInt64T: pass + +def atof(src: str) -> t.CDouble: pass + +def split(s: str, delim: str, result: t.CArray[str]) -> int: pass diff --git a/Test/VariadicTest/temp/377ad03e9b90ac39.pyi b/Test/VariadicTest/temp/c1416dfae155d6e2.pyi similarity index 97% rename from Test/VariadicTest/temp/377ad03e9b90ac39.pyi rename to Test/VariadicTest/temp/c1416dfae155d6e2.pyi index a23a5ee..636e8b0 100644 --- a/Test/VariadicTest/temp/377ad03e9b90ac39.pyi +++ b/Test/VariadicTest/temp/c1416dfae155d6e2.pyi @@ -7,6 +7,7 @@ Module: main from stdint import * import t, c import stdio +import testcheck import string import viperlib import w32.win32console diff --git a/Test/ZlibTest/App/__zlib/pyzlib.py b/Test/ZlibTest/App/__zlib/pyzlib.py index 0bd0a84..e495e6d 100644 --- a/Test/ZlibTest/App/__zlib/pyzlib.py +++ b/Test/ZlibTest/App/__zlib/pyzlib.py @@ -57,7 +57,7 @@ DEF_MEM_LEVEL: t.CDefine = 8 # Version ZLIB_VERSION: t.CDefine = "1.3.2" -pyzlib_error_msg: list[t.CChar, 512] = "" +pyzlib_error_msg: t.CArray[t.CChar, 512] = "" pyzlib_error_code_val: t.CInt = 0 # ============================================================ diff --git a/Test/ZlibTest/App/__zlib/test_pyzlib.py b/Test/ZlibTest/App/__zlib/test_pyzlib.py index d3b5b89..8f5c221 100644 --- a/Test/ZlibTest/App/__zlib/test_pyzlib.py +++ b/Test/ZlibTest/App/__zlib/test_pyzlib.py @@ -611,7 +611,7 @@ def test_huffman_tree(): printf(" All 32 distance codes: 5 bits each\n") printf("\n --- Dynamic Huffman tree from frequencies ---\n") - freqs: list[t.CInt, 256] + freqs: t.CArray[t.CInt, 256] memset(freqs, 0, freqs.__sizeof__()) freqs['A'] = 50 freqs['B'] = 25 @@ -641,8 +641,8 @@ def test_huffman_tree(): printf(" Active codes: %d, max code lengthgth: %d\n", total_codes, max_length_found) printf(" Code assignments:\n") - names: list[str, None] = ["A","B","C","D","E","F"] # 一个都æ˜?char* 的数ç»? - syms: list[t.CInt, None] = ['A','B','C','D','E','F'] + names: t.CArray[str, None] = ["A","B","C","D","E","F"] # 一个都æ˜?char* 的数ç»? + syms: t.CArray[t.CInt, None] = ['A','B','C','D','E','F'] for i in range(6): printf(" '%s' (freq=%3d): code=0x%04X, bits=%d\n", names[i], freqs[syms[i]], @@ -660,7 +660,7 @@ def test_huffman_tree(): a_bits, f_bits, "YES" if (a_bits <= f_bits) else "NO") printf("\n --- Huffman encode/decode roundtrip ---\n") - freqs: list[t.CInt, 288] + freqs: t.CArray[t.CInt, 288] memset(freqs, 0, freqs.__sizeof__()) freqs['H'] = 10 freqs['e'] = 8 @@ -681,7 +681,7 @@ def test_huffman_tree(): writer = zdef.zbit_writer() - symbols: list[t.CInt, None] = ['H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '!', 256] + symbols: t.CArray[t.CInt, None] = ['H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '!', 256] num_symbols: t.CInt = 13 for i in range(num_symbols): @@ -707,7 +707,7 @@ def test_huffman_tree(): free(writer.buf) printf("\n --- Overflow handling (many symbols, limited max_bits) ---\n") - freqs: list[t.CInt, 256] + freqs: t.CArray[t.CInt, 256] for i in range(256): freqs[i] = 1 freqs[256] = 1 @@ -722,7 +722,7 @@ def test_huffman_tree(): break check("all code lengthgths <= 15 with 257 symbols", overflow_ok, "code lengthgth overflow") - bl_count: list[t.CInt, 16] = [0] + bl_count: t.CArray[t.CInt, 16] = [0] for i in range(257): if tree.codes[i].bits > 0: bl_count[tree.codes[i].bits] += 1 @@ -760,7 +760,7 @@ def test_huffman_tree(): printf("\n --- Kraft inequality check ---\n") - freqs: list[t.CInt, 256] + freqs: t.CArray[t.CInt, 256] memset(freqs, 0, freqs.__sizeof__()) freqs['X'] = 100 freqs['Y'] = 50 diff --git a/Test/ZlibTest/App/__zlib/zchecksum.py b/Test/ZlibTest/App/__zlib/zchecksum.py index 422bd5e..7c2d644 100644 --- a/Test/ZlibTest/App/__zlib/zchecksum.py +++ b/Test/ZlibTest/App/__zlib/zchecksum.py @@ -13,7 +13,7 @@ def zchecksum_adler32(data: UINT8PTR, length: t.CSizeT, init: UINT32) -> t.CUInt b = (b + a) % 65521 return (b << 16) | a -crc32_table: list[t.CUInt32T, 256] = [ +crc32_table: t.CArray[t.CUInt32T, 256] = [ 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, diff --git a/Test/ZlibTest/App/__zlib/zdef.py b/Test/ZlibTest/App/__zlib/zdef.py index 4f1918c..301a919 100644 --- a/Test/ZlibTest/App/__zlib/zdef.py +++ b/Test/ZlibTest/App/__zlib/zdef.py @@ -33,7 +33,7 @@ ZDEFLATE_END_OF_BLOCK: t.CDefine = 256 # ============================================================ # Length / Distance extra bits tables (RFC 1951) # ============================================================ -zdeflate_len_extra_bits: list[t.CInt, 29] = [ +zdeflate_len_extra_bits: t.CArray[t.CInt, 29] = [ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, @@ -43,7 +43,7 @@ zdeflate_len_extra_bits: list[t.CInt, 29] = [ 0 ] -zdeflate_len_base: list[t.CInt, 29] = [ +zdeflate_len_base: t.CArray[t.CInt, 29] = [ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, @@ -53,7 +53,7 @@ zdeflate_len_base: list[t.CInt, 29] = [ 258 ] -zdeflate_dist_extra_bits: list[t.CInt, 30] = [ +zdeflate_dist_extra_bits: t.CArray[t.CInt, 30] = [ 0, 0, 0, 0, 1, 1, 2, 2, @@ -70,7 +70,7 @@ zdeflate_dist_extra_bits: list[t.CInt, 30] = [ 13, 13 ] -zdeflate_dist_base: list[t.CInt, 30] = [ +zdeflate_dist_base: t.CArray[t.CInt, 30] = [ 1, 2, 3, 4, 5, 7, 9, 13, @@ -87,7 +87,7 @@ zdeflate_dist_base: list[t.CInt, 30] = [ 16385, 24577 ] -zdeflate_codelen_order: list[int, 19] = [ +zdeflate_codelen_order: t.CArray[int, 19] = [ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 ] diff --git a/Test/ZlibTest/App/__zlib/zdeflate.py b/Test/ZlibTest/App/__zlib/zdeflate.py index dbcf839..3fef08c 100644 --- a/Test/ZlibTest/App/__zlib/zdeflate.py +++ b/Test/ZlibTest/App/__zlib/zdeflate.py @@ -119,8 +119,8 @@ class zdeflate_stream: def write_dynamic_block(self, data: UINT8PTR, length: t.CSizeT, final: t.CInt): - lit_freqs: list[t.CInt, 288] - dist_freqs: list[t.CInt, 32] + lit_freqs: t.CArray[t.CInt, 288] + dist_freqs: t.CArray[t.CInt, 32] zdeflate_count_freqs(lit_freqs, dist_freqs, self, data, length) hlit: t.CInt = 286 while hlit > 257 and lit_freqs[hlit - 1] == 0: hlit -= 1 @@ -130,11 +130,11 @@ class zdeflate_stream: dist_tree = zhuff.zhuff_tree() lit_tree.build_codes(lit_freqs, hlit, zdef.ZDEFLATE_MAX_BITS) dist_tree.build_codes(dist_freqs, hdist, zdef.ZDEFLATE_MAX_BITS) - all_lengths: list[t.CInt, 288 + 32] + all_lengths: t.CArray[t.CInt, 288 + 32] for i in range(hlit): all_lengths[i] = lit_tree.codes[i].bits for i in range(hdist): all_lengths[hlit + i] = dist_tree.codes[i].bits total_lengths: t.CInt = hlit + hdist - cl_freqs: list[t.CInt, 19] + cl_freqs: t.CArray[t.CInt, 19] zdeflate_count_cl_freqs(all_lengths, total_lengths, cl_freqs) cl_tree = zhuff.zhuff_tree() cl_tree.build_codes(cl_freqs, 19, 7) diff --git a/Test/ZlibTest/App/__zlib/zhuff.py b/Test/ZlibTest/App/__zlib/zhuff.py index 71c4158..0b38426 100644 --- a/Test/ZlibTest/App/__zlib/zhuff.py +++ b/Test/ZlibTest/App/__zlib/zhuff.py @@ -13,7 +13,7 @@ class zhuff_code: @t.Object class zhuff_tree: - codes: list[zhuff_code, ZHUFF_MAX_CODES] + codes: t.CArray[zhuff_code, ZHUFF_MAX_CODES] count: t.CInt max_bits: t.CInt @@ -21,9 +21,9 @@ class zhuff_tree: pass def build_codes(self, freqs: INTPTR, count: t.CInt, max_bits: t.CInt): - lengths: list[t.CInt, ZHUFF_MAX_CODES] - bl_count: list[t.CInt, ZHUFF_MAX_BITS + 1] - next_code: list[UINT, ZHUFF_MAX_BITS + 1] + lengths: t.CArray[t.CInt, ZHUFF_MAX_CODES] + bl_count: t.CArray[t.CInt, ZHUFF_MAX_BITS + 1] + next_code: t.CArray[UINT, ZHUFF_MAX_BITS + 1] self.count = count self.max_bits = max_bits self.build_code_lengths(lengths, freqs, count, max_bits) @@ -45,9 +45,9 @@ class zhuff_tree: self.codes[i].code = 0 def build_fixed_lit_tree(self): - lengths: list[t.CInt, 288] - bl_count: list[t.CInt, 16] - next_code: list[t.CUnsignedInt, 16] + lengths: t.CArray[t.CInt, 288] + bl_count: t.CArray[t.CInt, 16] + next_code: t.CArray[t.CUnsignedInt, 16] self.get_fixed_lit_lengths(lengths) memset(bl_count, 0, bl_count.__sizeof__()) for i in range(288): @@ -69,9 +69,9 @@ class zhuff_tree: self.codes[i].code = 0 def build_fixed_dist_tree(self): - lengths: list[t.CInt, 32] - bl_count: list[t.CInt, 16] - next_code: list[t.CUnsignedInt, 16] + lengths: t.CArray[t.CInt, 32] + bl_count: t.CArray[t.CInt, 16] + next_code: t.CArray[t.CUnsignedInt, 16] self.get_fixed_dist_lengths(lengths) memset(bl_count, 0, bl_count.__sizeof__()) for i in range(32): @@ -101,7 +101,7 @@ class zhuff_tree: def build_code_lengths(self, lengths: t.CInt | t.CPtr, freqs: t.CInt | t.CPtr, count: t.CInt, max_bits: t.CInt): - bl_count: list[t.CInt, ZHUFF_MAX_BITS + 2] + bl_count: t.CArray[t.CInt, ZHUFF_MAX_BITS + 2] sort_count: t.CInt = 0 memset(bl_count, 0, bl_count.__sizeof__()) memset(lengths, 0, int.__sizeof__() * count) @@ -270,8 +270,8 @@ class zhuff_tree: lengths[i] = 5 def build_tree_from_lengths(self, lengths: INTPTR, count: t.CInt, max_bits: t.CInt): - bl_count: list[t.CInt, 16] - next_code: list[t.CUnsignedInt, 16] + bl_count: t.CArray[t.CInt, 16] + next_code: t.CArray[t.CUnsignedInt, 16] memset(bl_count, 0, bl_count.__sizeof__()) for i in range(count): @@ -296,13 +296,13 @@ class zhuff_tree: class zhuff_decode_node: - children: list[t.CInt, 2] + children: t.CArray[t.CInt, 2] symbol: t.CInt @t.Object class zhuff_decode_tree: - nodes: list[zhuff_decode_node, 2 * ZHUFF_MAX_CODES] + nodes: t.CArray[zhuff_decode_node, 2 * ZHUFF_MAX_CODES] node_count: t.CInt root: t.CInt diff --git a/Test/ZlibTest/App/__zlib/zinflate.py b/Test/ZlibTest/App/__zlib/zinflate.py index efdcded..985f63e 100644 --- a/Test/ZlibTest/App/__zlib/zinflate.py +++ b/Test/ZlibTest/App/__zlib/zinflate.py @@ -212,7 +212,7 @@ class zinflate_stream: hdist: t.CInt = t.CInt(hdist_val) + 1 hclen: t.CInt = t.CInt(hclen_val) + 4 - cl_lengths: list[t.CInt, 19] + cl_lengths: t.CArray[t.CInt, 19] memset(cl_lengths, 0, cl_lengths.__sizeof__()) for i in range(hclen): len_val: UINT @@ -282,13 +282,13 @@ class zinflate_stream: lit_tree = zhuff.zhuff_tree() dist_tree = zhuff.zhuff_tree() - lit_lengths: list[t.CInt, 288] + lit_lengths: t.CArray[t.CInt, 288] memset(lit_lengths, 0, lit_lengths.__sizeof__()) for i in range(hlit): lit_lengths[i] = all_lengths[i] lit_tree.build_tree_from_lengths(lit_lengths, hlit, zdef.ZDEFLATE_MAX_BITS) - dist_lengths: list[t.CInt, 32] + dist_lengths: t.CArray[t.CInt, 32] memset(dist_lengths, 0, dist_lengths.__sizeof__()) for i in range(hdist): dist_lengths[i] = all_lengths[hlit + i] diff --git a/Test/ZlibTest/App/main.py b/Test/ZlibTest/App/main.py index c32ad80..6575ead 100644 --- a/Test/ZlibTest/App/main.py +++ b/Test/ZlibTest/App/main.py @@ -10,7 +10,10 @@ import __zlib.zhuff as zhuff import __zlib.test_pyzlib as tpz import w32.win32memory import c +import testcheck def main() -> t.CInt: + testcheck.begin("ZlibTest: Zlib 压缩库测试") tpz.main123456() - return 0 + testcheck.ok("zlib test_pyzlib completed") + return testcheck.end() diff --git a/Test/ZlibTest/output/03b24bc1d9327958.deps.json b/Test/ZlibTest/output/03b24bc1d9327958.deps.json new file mode 100644 index 0000000..3c3a294 --- /dev/null +++ b/Test/ZlibTest/output/03b24bc1d9327958.deps.json @@ -0,0 +1 @@ +{"__zlib.pyzlib": "0f8134f67bdaba8f", "pyzlib": "0f8134f67bdaba8f", "__zlib.test_pyzlib": "26e23066e8c7208d", "test_pyzlib": "26e23066e8c7208d", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "__zlib.zdef": "5d8612e70097f0ba", "zdef": "5d8612e70097f0ba", "stdlib": "6c2029b306556c00", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "__zlib.zdeflate": "77deeee736684e3e", "zdeflate": "77deeee736684e3e", "__zlib.zhuff": "8407b4239b208bdb", "zhuff": "8407b4239b208bdb", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "__zlib.zchecksum": "cb151b297f4ea56d", "zchecksum": "cb151b297f4ea56d", "__zlib.zinflate": "e445a2bb299d1b7d", "zinflate": "e445a2bb299d1b7d"} \ No newline at end of file diff --git a/Test/ZlibTest/output/067c78e9f121dce3.deps.json b/Test/ZlibTest/output/067c78e9f121dce3.deps.json deleted file mode 100644 index 02e0914..0000000 --- a/Test/ZlibTest/output/067c78e9f121dce3.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"__zlib.zdeflate": "0af305ed4e5f787d", "zdeflate": "0af305ed4e5f787d", "__zlib.test_pyzlib": "53fa0c913947021f", "test_pyzlib": "53fa0c913947021f", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "__zlib.pyzlib": "7e9fab9c7b47c4db", "pyzlib": "7e9fab9c7b47c4db", "__zlib.zchecksum": "95e27d852b773ae8", "zchecksum": "95e27d852b773ae8", "__zlib.zhuff": "c9349bf1e8390dd5", "zhuff": "c9349bf1e8390dd5", "main": "dca7ef1d57347738", "__zlib.zinflate": "e00d9854a0d03f4f", "zinflate": "e00d9854a0d03f4f", "__zlib.zdef": "f9cd063200178785", "zdef": "f9cd063200178785", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3"} \ No newline at end of file diff --git a/Test/ZlibTest/output/0af305ed4e5f787d.deps.json b/Test/ZlibTest/output/0af305ed4e5f787d.deps.json deleted file mode 100644 index b87171f..0000000 --- a/Test/ZlibTest/output/0af305ed4e5f787d.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"__zlib.test_pyzlib": "53fa0c913947021f", "test_pyzlib": "53fa0c913947021f", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "__zlib.pyzlib": "7e9fab9c7b47c4db", "pyzlib": "7e9fab9c7b47c4db", "__zlib.zchecksum": "95e27d852b773ae8", "zchecksum": "95e27d852b773ae8", "__zlib.zhuff": "c9349bf1e8390dd5", "zhuff": "c9349bf1e8390dd5", "main": "dca7ef1d57347738", "__zlib.zinflate": "e00d9854a0d03f4f", "zinflate": "e00d9854a0d03f4f", "__zlib.zdef": "f9cd063200178785", "zdef": "f9cd063200178785"} \ No newline at end of file diff --git a/Test/ZlibTest/output/0f8134f67bdaba8f.deps.json b/Test/ZlibTest/output/0f8134f67bdaba8f.deps.json new file mode 100644 index 0000000..0864fae --- /dev/null +++ b/Test/ZlibTest/output/0f8134f67bdaba8f.deps.json @@ -0,0 +1 @@ +{"main": "03b24bc1d9327958", "__zlib.test_pyzlib": "26e23066e8c7208d", "test_pyzlib": "26e23066e8c7208d", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "__zlib.zdef": "5d8612e70097f0ba", "zdef": "5d8612e70097f0ba", "stdlib": "6c2029b306556c00", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "__zlib.zdeflate": "77deeee736684e3e", "zdeflate": "77deeee736684e3e", "__zlib.zhuff": "8407b4239b208bdb", "zhuff": "8407b4239b208bdb", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "__zlib.zchecksum": "cb151b297f4ea56d", "zchecksum": "cb151b297f4ea56d", "__zlib.zinflate": "e445a2bb299d1b7d", "zinflate": "e445a2bb299d1b7d"} \ No newline at end of file diff --git a/Test/ZlibTest/output/26e23066e8c7208d.deps.json b/Test/ZlibTest/output/26e23066e8c7208d.deps.json new file mode 100644 index 0000000..d7a8738 --- /dev/null +++ b/Test/ZlibTest/output/26e23066e8c7208d.deps.json @@ -0,0 +1 @@ +{"main": "03b24bc1d9327958", "__zlib.pyzlib": "0f8134f67bdaba8f", "pyzlib": "0f8134f67bdaba8f", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "__zlib.zdef": "5d8612e70097f0ba", "zdef": "5d8612e70097f0ba", "stdlib": "6c2029b306556c00", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "__zlib.zdeflate": "77deeee736684e3e", "zdeflate": "77deeee736684e3e", "__zlib.zhuff": "8407b4239b208bdb", "zhuff": "8407b4239b208bdb", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "__zlib.zchecksum": "cb151b297f4ea56d", "zchecksum": "cb151b297f4ea56d", "__zlib.zinflate": "e445a2bb299d1b7d", "zinflate": "e445a2bb299d1b7d"} \ No newline at end of file diff --git a/Test/ZlibTest/output/29813d57621099a9.deps.json b/Test/ZlibTest/output/29813d57621099a9.deps.json deleted file mode 100644 index c0ff589..0000000 --- a/Test/ZlibTest/output/29813d57621099a9.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"__zlib.zdeflate": "0af305ed4e5f787d", "zdeflate": "0af305ed4e5f787d", "__zlib.test_pyzlib": "53fa0c913947021f", "test_pyzlib": "53fa0c913947021f", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "__zlib.pyzlib": "7e9fab9c7b47c4db", "pyzlib": "7e9fab9c7b47c4db", "__zlib.zchecksum": "95e27d852b773ae8", "zchecksum": "95e27d852b773ae8", "__zlib.zhuff": "c9349bf1e8390dd5", "zhuff": "c9349bf1e8390dd5", "main": "dca7ef1d57347738", "__zlib.zinflate": "e00d9854a0d03f4f", "zinflate": "e00d9854a0d03f4f", "__zlib.zdef": "f9cd063200178785", "zdef": "f9cd063200178785", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e", "w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "29813d57621099a9", "win32sync": "29813d57621099a9"} \ No newline at end of file diff --git a/Test/ZlibTest/output/53fa0c913947021f.deps.json b/Test/ZlibTest/output/53fa0c913947021f.deps.json deleted file mode 100644 index b0c8785..0000000 --- a/Test/ZlibTest/output/53fa0c913947021f.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"__zlib.zdeflate": "0af305ed4e5f787d", "zdeflate": "0af305ed4e5f787d", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "__zlib.pyzlib": "7e9fab9c7b47c4db", "pyzlib": "7e9fab9c7b47c4db", "__zlib.zchecksum": "95e27d852b773ae8", "zchecksum": "95e27d852b773ae8", "__zlib.zhuff": "c9349bf1e8390dd5", "zhuff": "c9349bf1e8390dd5", "main": "dca7ef1d57347738", "__zlib.zinflate": "e00d9854a0d03f4f", "zinflate": "e00d9854a0d03f4f", "__zlib.zdef": "f9cd063200178785", "zdef": "f9cd063200178785"} \ No newline at end of file diff --git a/Test/ZlibTest/output/5a6a2137958c28c5.deps.json b/Test/ZlibTest/output/5a6a2137958c28c5.deps.json deleted file mode 100644 index f29b4ab..0000000 --- a/Test/ZlibTest/output/5a6a2137958c28c5.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"__zlib.zdeflate": "0af305ed4e5f787d", "zdeflate": "0af305ed4e5f787d", "__zlib.test_pyzlib": "53fa0c913947021f", "test_pyzlib": "53fa0c913947021f", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "__zlib.pyzlib": "7e9fab9c7b47c4db", "pyzlib": "7e9fab9c7b47c4db", "__zlib.zchecksum": "95e27d852b773ae8", "zchecksum": "95e27d852b773ae8", "__zlib.zhuff": "c9349bf1e8390dd5", "zhuff": "c9349bf1e8390dd5", "main": "dca7ef1d57347738", "__zlib.zinflate": "e00d9854a0d03f4f", "zinflate": "e00d9854a0d03f4f", "__zlib.zdef": "f9cd063200178785", "zdef": "f9cd063200178785", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file diff --git a/Test/ZlibTest/output/5d8612e70097f0ba.deps.json b/Test/ZlibTest/output/5d8612e70097f0ba.deps.json new file mode 100644 index 0000000..6dbd8db --- /dev/null +++ b/Test/ZlibTest/output/5d8612e70097f0ba.deps.json @@ -0,0 +1 @@ +{"main": "03b24bc1d9327958", "__zlib.pyzlib": "0f8134f67bdaba8f", "pyzlib": "0f8134f67bdaba8f", "__zlib.test_pyzlib": "26e23066e8c7208d", "test_pyzlib": "26e23066e8c7208d", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "stdlib": "6c2029b306556c00", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "__zlib.zdeflate": "77deeee736684e3e", "zdeflate": "77deeee736684e3e", "__zlib.zhuff": "8407b4239b208bdb", "zhuff": "8407b4239b208bdb", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "__zlib.zchecksum": "cb151b297f4ea56d", "zchecksum": "cb151b297f4ea56d", "__zlib.zinflate": "e445a2bb299d1b7d", "zinflate": "e445a2bb299d1b7d"} \ No newline at end of file diff --git a/Test/ZlibTest/output/6aee24fdefa3cbc0.deps.json b/Test/ZlibTest/output/6aee24fdefa3cbc0.deps.json deleted file mode 100644 index 6276ce6..0000000 --- a/Test/ZlibTest/output/6aee24fdefa3cbc0.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"__zlib.zdeflate": "0af305ed4e5f787d", "zdeflate": "0af305ed4e5f787d", "__zlib.test_pyzlib": "53fa0c913947021f", "test_pyzlib": "53fa0c913947021f", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "__zlib.pyzlib": "7e9fab9c7b47c4db", "pyzlib": "7e9fab9c7b47c4db", "__zlib.zchecksum": "95e27d852b773ae8", "zchecksum": "95e27d852b773ae8", "__zlib.zhuff": "c9349bf1e8390dd5", "zhuff": "c9349bf1e8390dd5", "main": "dca7ef1d57347738", "__zlib.zinflate": "e00d9854a0d03f4f", "zinflate": "e00d9854a0d03f4f", "__zlib.zdef": "f9cd063200178785", "zdef": "f9cd063200178785"} \ No newline at end of file diff --git a/Test/ZlibTest/output/72e2d5ccb7cedcf1.deps.json b/Test/ZlibTest/output/72e2d5ccb7cedcf1.deps.json deleted file mode 100644 index 7138317..0000000 --- a/Test/ZlibTest/output/72e2d5ccb7cedcf1.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"__zlib.zdeflate": "0af305ed4e5f787d", "zdeflate": "0af305ed4e5f787d", "__zlib.test_pyzlib": "53fa0c913947021f", "test_pyzlib": "53fa0c913947021f", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "__zlib.pyzlib": "7e9fab9c7b47c4db", "pyzlib": "7e9fab9c7b47c4db", "__zlib.zchecksum": "95e27d852b773ae8", "zchecksum": "95e27d852b773ae8", "__zlib.zhuff": "c9349bf1e8390dd5", "zhuff": "c9349bf1e8390dd5", "main": "dca7ef1d57347738", "__zlib.zinflate": "e00d9854a0d03f4f", "zinflate": "e00d9854a0d03f4f", "__zlib.zdef": "f9cd063200178785", "zdef": "f9cd063200178785", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e"} \ No newline at end of file diff --git a/Test/ZlibTest/output/7e9fab9c7b47c4db.deps.json b/Test/ZlibTest/output/7e9fab9c7b47c4db.deps.json deleted file mode 100644 index e18b0d6..0000000 --- a/Test/ZlibTest/output/7e9fab9c7b47c4db.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"__zlib.zdeflate": "0af305ed4e5f787d", "zdeflate": "0af305ed4e5f787d", "__zlib.test_pyzlib": "53fa0c913947021f", "test_pyzlib": "53fa0c913947021f", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "__zlib.zchecksum": "95e27d852b773ae8", "zchecksum": "95e27d852b773ae8", "__zlib.zhuff": "c9349bf1e8390dd5", "zhuff": "c9349bf1e8390dd5", "main": "dca7ef1d57347738", "__zlib.zinflate": "e00d9854a0d03f4f", "zinflate": "e00d9854a0d03f4f", "__zlib.zdef": "f9cd063200178785", "zdef": "f9cd063200178785"} \ No newline at end of file diff --git a/Test/ZlibTest/output/95e27d852b773ae8.deps.json b/Test/ZlibTest/output/95e27d852b773ae8.deps.json deleted file mode 100644 index b228098..0000000 --- a/Test/ZlibTest/output/95e27d852b773ae8.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"__zlib.zdeflate": "0af305ed4e5f787d", "zdeflate": "0af305ed4e5f787d", "__zlib.test_pyzlib": "53fa0c913947021f", "test_pyzlib": "53fa0c913947021f", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "__zlib.pyzlib": "7e9fab9c7b47c4db", "pyzlib": "7e9fab9c7b47c4db", "__zlib.zhuff": "c9349bf1e8390dd5", "zhuff": "c9349bf1e8390dd5", "main": "dca7ef1d57347738", "__zlib.zinflate": "e00d9854a0d03f4f", "zinflate": "e00d9854a0d03f4f", "__zlib.zdef": "f9cd063200178785", "zdef": "f9cd063200178785"} \ No newline at end of file diff --git a/Test/ZlibTest/output/abf9ce3160c9279e.deps.json b/Test/ZlibTest/output/abf9ce3160c9279e.deps.json deleted file mode 100644 index 7138317..0000000 --- a/Test/ZlibTest/output/abf9ce3160c9279e.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"__zlib.zdeflate": "0af305ed4e5f787d", "zdeflate": "0af305ed4e5f787d", "__zlib.test_pyzlib": "53fa0c913947021f", "test_pyzlib": "53fa0c913947021f", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "__zlib.pyzlib": "7e9fab9c7b47c4db", "pyzlib": "7e9fab9c7b47c4db", "__zlib.zchecksum": "95e27d852b773ae8", "zchecksum": "95e27d852b773ae8", "__zlib.zhuff": "c9349bf1e8390dd5", "zhuff": "c9349bf1e8390dd5", "main": "dca7ef1d57347738", "__zlib.zinflate": "e00d9854a0d03f4f", "zinflate": "e00d9854a0d03f4f", "__zlib.zdef": "f9cd063200178785", "zdef": "f9cd063200178785", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "w32.win32file": "abf9ce3160c9279e", "win32file": "abf9ce3160c9279e"} \ No newline at end of file diff --git a/Test/ZlibTest/output/bbdf3bbd4c3bc28c.deps.json b/Test/ZlibTest/output/bbdf3bbd4c3bc28c.deps.json deleted file mode 100644 index 39ce516..0000000 --- a/Test/ZlibTest/output/bbdf3bbd4c3bc28c.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"__zlib.zdeflate": "0af305ed4e5f787d", "zdeflate": "0af305ed4e5f787d", "__zlib.test_pyzlib": "53fa0c913947021f", "test_pyzlib": "53fa0c913947021f", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "__zlib.pyzlib": "7e9fab9c7b47c4db", "pyzlib": "7e9fab9c7b47c4db", "__zlib.zchecksum": "95e27d852b773ae8", "zchecksum": "95e27d852b773ae8", "__zlib.zhuff": "c9349bf1e8390dd5", "zhuff": "c9349bf1e8390dd5", "main": "dca7ef1d57347738", "__zlib.zinflate": "e00d9854a0d03f4f", "zinflate": "e00d9854a0d03f4f", "__zlib.zdef": "f9cd063200178785", "zdef": "f9cd063200178785", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c"} \ No newline at end of file diff --git a/Test/ZlibTest/output/c9349bf1e8390dd5.deps.json b/Test/ZlibTest/output/c9349bf1e8390dd5.deps.json deleted file mode 100644 index 273dcc1..0000000 --- a/Test/ZlibTest/output/c9349bf1e8390dd5.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"__zlib.zdeflate": "0af305ed4e5f787d", "zdeflate": "0af305ed4e5f787d", "__zlib.test_pyzlib": "53fa0c913947021f", "test_pyzlib": "53fa0c913947021f", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "__zlib.pyzlib": "7e9fab9c7b47c4db", "pyzlib": "7e9fab9c7b47c4db", "__zlib.zchecksum": "95e27d852b773ae8", "zchecksum": "95e27d852b773ae8", "main": "dca7ef1d57347738", "__zlib.zinflate": "e00d9854a0d03f4f", "zinflate": "e00d9854a0d03f4f", "__zlib.zdef": "f9cd063200178785", "zdef": "f9cd063200178785"} \ No newline at end of file diff --git a/Test/ZlibTest/output/dca7ef1d57347738.deps.json b/Test/ZlibTest/output/dca7ef1d57347738.deps.json deleted file mode 100644 index 6c2e844..0000000 --- a/Test/ZlibTest/output/dca7ef1d57347738.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"__zlib.zdeflate": "0af305ed4e5f787d", "zdeflate": "0af305ed4e5f787d", "__zlib.test_pyzlib": "53fa0c913947021f", "test_pyzlib": "53fa0c913947021f", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "__zlib.pyzlib": "7e9fab9c7b47c4db", "pyzlib": "7e9fab9c7b47c4db", "__zlib.zchecksum": "95e27d852b773ae8", "zchecksum": "95e27d852b773ae8", "__zlib.zhuff": "c9349bf1e8390dd5", "zhuff": "c9349bf1e8390dd5", "__zlib.zinflate": "e00d9854a0d03f4f", "zinflate": "e00d9854a0d03f4f", "__zlib.zdef": "f9cd063200178785", "zdef": "f9cd063200178785"} \ No newline at end of file diff --git a/Test/ZlibTest/output/e00d9854a0d03f4f.deps.json b/Test/ZlibTest/output/e00d9854a0d03f4f.deps.json deleted file mode 100644 index 8c2e8d1..0000000 --- a/Test/ZlibTest/output/e00d9854a0d03f4f.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"__zlib.zdeflate": "0af305ed4e5f787d", "zdeflate": "0af305ed4e5f787d", "__zlib.test_pyzlib": "53fa0c913947021f", "test_pyzlib": "53fa0c913947021f", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "__zlib.pyzlib": "7e9fab9c7b47c4db", "pyzlib": "7e9fab9c7b47c4db", "__zlib.zchecksum": "95e27d852b773ae8", "zchecksum": "95e27d852b773ae8", "__zlib.zhuff": "c9349bf1e8390dd5", "zhuff": "c9349bf1e8390dd5", "main": "dca7ef1d57347738", "__zlib.zdef": "f9cd063200178785", "zdef": "f9cd063200178785"} \ No newline at end of file diff --git a/Test/ZlibTest/output/e445a2bb299d1b7d.deps.json b/Test/ZlibTest/output/e445a2bb299d1b7d.deps.json new file mode 100644 index 0000000..2071831 --- /dev/null +++ b/Test/ZlibTest/output/e445a2bb299d1b7d.deps.json @@ -0,0 +1 @@ +{"main": "03b24bc1d9327958", "__zlib.pyzlib": "0f8134f67bdaba8f", "pyzlib": "0f8134f67bdaba8f", "__zlib.test_pyzlib": "26e23066e8c7208d", "test_pyzlib": "26e23066e8c7208d", "stdint": "49bd8cba55979f76", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "__zlib.zdef": "5d8612e70097f0ba", "zdef": "5d8612e70097f0ba", "stdlib": "6c2029b306556c00", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "__zlib.zdeflate": "77deeee736684e3e", "zdeflate": "77deeee736684e3e", "__zlib.zhuff": "8407b4239b208bdb", "zhuff": "8407b4239b208bdb", "testcheck": "9dbecd0942a39782", "string": "b5f1dc665c52a1bd", "__zlib.zchecksum": "cb151b297f4ea56d", "zchecksum": "cb151b297f4ea56d"} \ No newline at end of file diff --git a/Test/ZlibTest/output/f9cd063200178785.deps.json b/Test/ZlibTest/output/f9cd063200178785.deps.json deleted file mode 100644 index bc04c95..0000000 --- a/Test/ZlibTest/output/f9cd063200178785.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"__zlib.zdeflate": "0af305ed4e5f787d", "zdeflate": "0af305ed4e5f787d", "__zlib.test_pyzlib": "53fa0c913947021f", "test_pyzlib": "53fa0c913947021f", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "__zlib.pyzlib": "7e9fab9c7b47c4db", "pyzlib": "7e9fab9c7b47c4db", "__zlib.zchecksum": "95e27d852b773ae8", "zchecksum": "95e27d852b773ae8", "__zlib.zhuff": "c9349bf1e8390dd5", "zhuff": "c9349bf1e8390dd5", "main": "dca7ef1d57347738", "__zlib.zinflate": "e00d9854a0d03f4f", "zinflate": "e00d9854a0d03f4f"} \ No newline at end of file diff --git a/Test/ZlibTest/output/fa3691e66b426950.deps.json b/Test/ZlibTest/output/fa3691e66b426950.deps.json deleted file mode 100644 index f29b4ab..0000000 --- a/Test/ZlibTest/output/fa3691e66b426950.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"__zlib.zdeflate": "0af305ed4e5f787d", "zdeflate": "0af305ed4e5f787d", "__zlib.test_pyzlib": "53fa0c913947021f", "test_pyzlib": "53fa0c913947021f", "stdint": "56cdd754a8a09347", "w32.win32base": "5a6a2137958c28c5", "win32base": "5a6a2137958c28c5", "string": "6aee24fdefa3cbc0", "stdlib": "6c2029b306556c00", "w32.win32memory": "72e2d5ccb7cedcf1", "win32memory": "72e2d5ccb7cedcf1", "stdio": "73edbcf76e32d00b", "__zlib.pyzlib": "7e9fab9c7b47c4db", "pyzlib": "7e9fab9c7b47c4db", "__zlib.zchecksum": "95e27d852b773ae8", "zchecksum": "95e27d852b773ae8", "__zlib.zhuff": "c9349bf1e8390dd5", "zhuff": "c9349bf1e8390dd5", "main": "dca7ef1d57347738", "__zlib.zinflate": "e00d9854a0d03f4f", "zinflate": "e00d9854a0d03f4f", "__zlib.zdef": "f9cd063200178785", "zdef": "f9cd063200178785", "w32.fileio": "fa3691e66b426950", "fileio": "fa3691e66b426950"} \ No newline at end of file diff --git a/Test/ZlibTest/temp/dca7ef1d57347738.pyi b/Test/ZlibTest/temp/03b24bc1d9327958.pyi similarity index 95% rename from Test/ZlibTest/temp/dca7ef1d57347738.pyi rename to Test/ZlibTest/temp/03b24bc1d9327958.pyi index 64bfc75..8757634 100644 --- a/Test/ZlibTest/temp/dca7ef1d57347738.pyi +++ b/Test/ZlibTest/temp/03b24bc1d9327958.pyi @@ -16,5 +16,6 @@ import __zlib.zhuff as zhuff import __zlib.test_pyzlib as tpz import w32.win32memory import c +import testcheck def main() -> t.CInt: pass diff --git a/Test/ZlibTest/temp/7e9fab9c7b47c4db.pyi b/Test/ZlibTest/temp/0f8134f67bdaba8f.pyi similarity index 98% rename from Test/ZlibTest/temp/7e9fab9c7b47c4db.pyi rename to Test/ZlibTest/temp/0f8134f67bdaba8f.pyi index ec4964b..3f2901b 100644 --- a/Test/ZlibTest/temp/7e9fab9c7b47c4db.pyi +++ b/Test/ZlibTest/temp/0f8134f67bdaba8f.pyi @@ -44,7 +44,7 @@ MAX_WBITS: t.CDefine = 15 DEF_BUF_SIZE: t.CDefine = 16384 DEF_MEM_LEVEL: t.CDefine = 8 ZLIB_VERSION: t.CDefine = "1.3.2" -pyzlib_error_msg: t.CExtern | list[t.CChar, 512] +pyzlib_error_msg: t.CExtern | t.CArray[t.CChar, 512] pyzlib_error_code_val: t.CExtern | t.CInt @t.Object diff --git a/Test/ZlibTest/temp/53fa0c913947021f.pyi b/Test/ZlibTest/temp/26e23066e8c7208d.pyi similarity index 100% rename from Test/ZlibTest/temp/53fa0c913947021f.pyi rename to Test/ZlibTest/temp/26e23066e8c7208d.pyi diff --git a/Test/ZlibTest/temp/49bd8cba55979f76.pyi b/Test/ZlibTest/temp/49bd8cba55979f76.pyi new file mode 100644 index 0000000..f1d844a --- /dev/null +++ b/Test/ZlibTest/temp/49bd8cba55979f76.pyi @@ -0,0 +1,75 @@ +""" +Auto-generated Python stub file from stdint.py +Module: stdint +""" + +import c + + +import t + +INT: t.CTypedef = t.CInt +INTPTR: t.CTypedef = t.CInt | t.CPtr +BOOL: t.CTypedef = t.CInt +UINT: t.CTypedef = t.CUnsignedInt +UINTPTR: t.CTypedef = UINT | t.CPtr +BYTE: t.CTypedef = t.CUnsignedChar +BYTEPTR: t.CTypedef = BYTE | t.CPtr +WORD: t.CTypedef = t.CUInt16T +DWORD: t.CTypedef = t.CUInt32T +QWORD: t.CTypedef = t.CUInt64T +TCHAR: t.CTypedef = t.CChar +CHARLIST: t.CTypedef = str | t.CPtr +VOID: t.CTypedef = t.CVoid +SHORT: t.CTypedef = t.CShort +SHORTPTR: t.CTypedef = t.CShort | t.CPtr +USHORT: t.CTypedef = t.CUnsignedShort +USHORTPTR: t.CTypedef = t.CUnsignedShort | t.CPtr +LONGLONG: t.CTypedef = t.CLong | t.CLong +ULONGLONG: t.CTypedef = t.CUnsignedLong | t.CLong +LONG: t.CTypedef = t.CLong +ULONG: t.CTypedef = t.CUnsignedLong +WCHAR: t.CTypedef = WORD +WCHARPTR: t.CTypedef = WORD | t.CPtr +CHARPTR: t.CTypedef = t.CChar | t.CPtr +FSIZE_t: t.CTypedef = DWORD +LBA_t: t.CTypedef = DWORD +UINTPTR: t.CTypedef = t.CUnsignedInt | t.CPtr +VOIDPTR: t.CTypedef = t.CVoid | t.CPtr +FLOAT: t.CTypedef = t.CFloat +DOUBLE: t.CTypedef = t.CDouble +FLOAT8: t.CTypedef = t.CFloat8T +FLOAT16: t.CTypedef = t.CFloat16T +FLOAT32: t.CTypedef = t.CFloat32T +FLOAT64: t.CTypedef = t.CFloat64T +FLOAT128: t.CTypedef = t.CFloat128T +INT8: t.CTypedef = t.CInt8T +INT16: t.CTypedef = t.CInt16T +INT32: t.CTypedef = t.CInt32T +INT64: t.CTypedef = t.CInt64T +UINT8: t.CTypedef = t.CUInt8T +UINT16: t.CTypedef = t.CUInt16T +UINT32: t.CTypedef = t.CUInt32T +UINT64: t.CTypedef = t.CUInt64T +INT8PTR: t.CTypedef = t.CInt8T | t.CPtr +INT16PTR: t.CTypedef = t.CInt16T | t.CPtr +INT32PTR: t.CTypedef = t.CInt32T | t.CPtr +INT64PTR: t.CTypedef = t.CInt64T | t.CPtr +UINT8PTR: t.CTypedef = t.CUInt8T | t.CPtr +UINT16PTR: t.CTypedef = t.CUInt16T | t.CPtr +UINT32PTR: t.CTypedef = t.CUInt32T | t.CPtr +UINT64PTR: t.CTypedef = t.CUInt64T | t.CPtr +CHAR8: t.CTypedef = t.CChar8T +CHAR16: t.CTypedef = t.CChar16T +CHAR32: t.CTypedef = t.CChar32T +CHAR8PTR: t.CTypedef = t.CChar8T | t.CPtr +CHAR16PTR: t.CTypedef = t.CChar16T | t.CPtr +CHAR32PTR: t.CTypedef = t.CChar32T | t.CPtr +i8: t.CTypedef = t.CInt8T +i16: t.CTypedef = t.CInt16T +i32: t.CTypedef = t.CInt32T +i64: t.CTypedef = t.CInt64T +u8: t.CTypedef = t.CUInt8T +u16: t.CTypedef = t.CUInt16T +u32: t.CTypedef = t.CUInt32T +u64: t.CTypedef = t.CUInt64T \ No newline at end of file diff --git a/Test/ZlibTest/temp/56cdd754a8a09347.pyi b/Test/ZlibTest/temp/56cdd754a8a09347.pyi deleted file mode 100644 index 007ccb8..0000000 --- a/Test/ZlibTest/temp/56cdd754a8a09347.pyi +++ /dev/null @@ -1,67 +0,0 @@ -""" -Auto-generated Python stub file from stdint.py -Module: stdint -""" - -import c - - -import t - -INT: t.CTypedef = t.CInt -INTPTR: t.CTypedef = t.CInt | t.CPtr -BOOL: t.CTypedef = t.CInt -UINT: t.CTypedef = t.CUnsignedInt -UINTPTR: t.CTypedef = UINT | t.CPtr -BYTE: t.CTypedef = t.CUnsignedChar -BYTEPTR: t.CTypedef = BYTE | t.CPtr -WORD: t.CTypedef = t.CUInt16T -DWORD: t.CTypedef = t.CUInt32T -QWORD: t.CTypedef = t.CUInt64T -TCHAR: t.CTypedef = t.CChar -CHARLIST: t.CTypedef = str | t.CPtr -VOID: t.CTypedef = t.CVoid -SHORT: t.CTypedef = t.CShort -SHORTPTR: t.CTypedef = t.CShort | t.CPtr -USHORT: t.CTypedef = t.CUnsignedShort -USHORTPTR: t.CTypedef = t.CUnsignedShort | t.CPtr -LONGLONG: t.CTypedef = t.CLong | t.CLong -ULONGLONG: t.CTypedef = t.CUnsignedLong | t.CLong -LONG: t.CTypedef = t.CLong -ULONG: t.CTypedef = t.CUnsignedLong -WCHAR: t.CTypedef = WORD -WCHARPTR: t.CTypedef = WORD | t.CPtr -CHARPTR: t.CTypedef = t.CChar | t.CPtr -FSIZE_t: t.CTypedef = DWORD -LBA_t: t.CTypedef = DWORD -UINTPTR: t.CTypedef = t.CUnsignedInt | t.CPtr -VOIDPTR: t.CTypedef = t.CVoid | t.CPtr -FLOAT: t.CTypedef = t.CFloat -DOUBLE: t.CTypedef = t.CDouble -FLOAT8: t.CTypedef = t.CFloat8T -FLOAT16: t.CTypedef = t.CFloat16T -FLOAT32: t.CTypedef = t.CFloat32T -FLOAT64: t.CTypedef = t.CFloat64T -FLOAT128: t.CTypedef = t.CFloat128T -INT8: t.CTypedef = t.CInt8T -INT16: t.CTypedef = t.CInt16T -INT32: t.CTypedef = t.CInt32T -INT64: t.CTypedef = t.CInt64T -UINT8: t.CTypedef = t.CUInt8T -UINT16: t.CTypedef = t.CUInt16T -UINT32: t.CTypedef = t.CUInt32T -UINT64: t.CTypedef = t.CUInt64T -INT8PTR: t.CTypedef = t.CInt8T | t.CPtr -INT16PTR: t.CTypedef = t.CInt16T | t.CPtr -INT32PTR: t.CTypedef = t.CInt32T | t.CPtr -INT64PTR: t.CTypedef = t.CInt64T | t.CPtr -UINT8PTR: t.CTypedef = t.CUInt8T | t.CPtr -UINT16PTR: t.CTypedef = t.CUInt16T | t.CPtr -UINT32PTR: t.CTypedef = t.CUInt32T | t.CPtr -UINT64PTR: t.CTypedef = t.CUInt64T | t.CPtr -CHAR8: t.CTypedef = t.CChar8T -CHAR16: t.CTypedef = t.CChar16T -CHAR32: t.CTypedef = t.CChar32T -CHAR8PTR: t.CTypedef = t.CChar8T | t.CPtr -CHAR16PTR: t.CTypedef = t.CChar16T | t.CPtr -CHAR32PTR: t.CTypedef = t.CChar32T | t.CPtr \ No newline at end of file diff --git a/Test/ZlibTest/temp/f9cd063200178785.pyi b/Test/ZlibTest/temp/5d8612e70097f0ba.pyi similarity index 89% rename from Test/ZlibTest/temp/f9cd063200178785.pyi rename to Test/ZlibTest/temp/5d8612e70097f0ba.pyi index a5f2ed8..3552322 100644 --- a/Test/ZlibTest/temp/f9cd063200178785.pyi +++ b/Test/ZlibTest/temp/5d8612e70097f0ba.pyi @@ -26,11 +26,11 @@ ZDEFLATE_LIT_COUNT: t.CDefine = 286 ZDEFLATE_DIST_COUNT: t.CDefine = 30 ZDEFLATE_LEN_SYMBOLS_BASE: t.CDefine = 257 ZDEFLATE_END_OF_BLOCK: t.CDefine = 256 -zdeflate_len_extra_bits: t.CExtern | list[t.CInt, 29] -zdeflate_len_base: t.CExtern | list[t.CInt, 29] -zdeflate_dist_extra_bits: t.CExtern | list[t.CInt, 30] -zdeflate_dist_base: t.CExtern | list[t.CInt, 30] -zdeflate_codelen_order: t.CExtern | list[int, 19] +zdeflate_len_extra_bits: t.CExtern | t.CArray[t.CInt, 29] +zdeflate_len_base: t.CExtern | t.CArray[t.CInt, 29] +zdeflate_dist_extra_bits: t.CExtern | t.CArray[t.CInt, 30] +zdeflate_dist_base: t.CExtern | t.CArray[t.CInt, 30] +zdeflate_codelen_order: t.CExtern | t.CArray[int, 19] @t.Object class zbit_writer: diff --git a/Test/ZlibTest/temp/6aee24fdefa3cbc0.pyi b/Test/ZlibTest/temp/6aee24fdefa3cbc0.pyi deleted file mode 100644 index c17475f..0000000 --- a/Test/ZlibTest/temp/6aee24fdefa3cbc0.pyi +++ /dev/null @@ -1,44 +0,0 @@ -""" -Auto-generated Python stub file from string.py -Module: string -""" - - -from stdint import * -import t, c - -def strcpy(dest: str, src: str) -> str: pass - -def strncpy(dest: str, src: str, n: t.CSizeT) -> str: pass - -def strlen(src: str) -> t.CSizeT | t.CExport: pass - -def strcmp(str1: str, str2: str) -> t.CInt: pass - -def samestr(str1: str, str2: str) -> bool: pass - -def strncmp(str1: str, str2: str, n: t.CSizeT) -> t.CInt: pass - -def memcmp(ptr1: t.CVoid | t.CPtr, ptr2: t.CVoid | t.CPtr, n: t.CSizeT) -> t.CInt: pass - -def strchr(s: str, cr: t.CInt) -> str: pass - -def strrchr(s: str, cr: t.CInt) -> str: pass - -def strspn(s: str, skip: str) -> int: pass - -def memset(ptr: t.CVoid | t.CPtr, value: t.CInt, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass - -def memset32(ptr: t.CVoid | t.CPtr, value: t.CUInt32T, count: t.CSizeT) -> t.CVoid | t.CPtr: pass - -def memcpy(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass - -def memmove(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr: pass - -def atoi(src: str) -> t.CInt: pass - -def atoll(src: str) -> t.CInt64T: pass - -def atof(src: str) -> t.CDouble: pass - -def split(s: str, delim: str, result: list[str]) -> int: pass diff --git a/Test/ZlibTest/temp/0af305ed4e5f787d.pyi b/Test/ZlibTest/temp/77deeee736684e3e.pyi similarity index 100% rename from Test/ZlibTest/temp/0af305ed4e5f787d.pyi rename to Test/ZlibTest/temp/77deeee736684e3e.pyi diff --git a/Test/ZlibTest/temp/c9349bf1e8390dd5.pyi b/Test/ZlibTest/temp/8407b4239b208bdb.pyi similarity index 91% rename from Test/ZlibTest/temp/c9349bf1e8390dd5.pyi rename to Test/ZlibTest/temp/8407b4239b208bdb.pyi index cad3f7f..898995b 100644 --- a/Test/ZlibTest/temp/c9349bf1e8390dd5.pyi +++ b/Test/ZlibTest/temp/8407b4239b208bdb.pyi @@ -16,7 +16,7 @@ class zhuff_code: bits: t.CInt @t.Object class zhuff_tree: - codes: list[zhuff_code, ZHUFF_MAX_CODES] + codes: t.CArray[zhuff_code, ZHUFF_MAX_CODES] count: t.CInt max_bits: t.CInt def __init__(self: zhuff_tree) -> t.CInt: pass @@ -29,11 +29,11 @@ class zhuff_tree: def get_fixed_dist_lengths(self: zhuff_tree, lengths: INTPTR) -> t.CInt: pass def build_tree_from_lengths(self: zhuff_tree, lengths: INTPTR, count: t.CInt, max_bits: t.CInt) -> t.CInt: pass class zhuff_decode_node: - children: list[t.CInt, 2] + children: t.CArray[t.CInt, 2] symbol: t.CInt @t.Object class zhuff_decode_tree: - nodes: list[zhuff_decode_node, 2 * ZHUFF_MAX_CODES] + nodes: t.CArray[zhuff_decode_node, 2 * ZHUFF_MAX_CODES] node_count: t.CInt root: t.CInt def __init__(self: zhuff_decode_tree) -> t.CInt: pass diff --git a/Test/ZlibTest/temp/9dbecd0942a39782.pyi b/Test/ZlibTest/temp/9dbecd0942a39782.pyi new file mode 100644 index 0000000..41648c1 --- /dev/null +++ b/Test/ZlibTest/temp/9dbecd0942a39782.pyi @@ -0,0 +1,25 @@ +""" +Auto-generated Python stub file from testcheck.py +Module: testcheck +""" + + +import t, c +import stdio + +_pass_count: t.CExtern | t.CInt +_fail_count: t.CExtern | t.CInt + +def begin(name: str) -> t.CInt: pass + +def section(name: str) -> t.CInt: pass + +def ok(msg: str) -> t.CInt: pass + +def fail(msg: str) -> t.CInt: pass + +def check(cond: t.CInt, ok_msg: str, fail_msg: str) -> t.CInt: pass + +def info(msg: str) -> t.CInt: pass + +def end() -> t.CInt: pass diff --git a/Test/ZlibTest/temp/_sha1_map.txt b/Test/ZlibTest/temp/_sha1_map.txt index ec470f2..e530d07 100644 --- a/Test/ZlibTest/temp/_sha1_map.txt +++ b/Test/ZlibTest/temp/_sha1_map.txt @@ -1,14 +1,15 @@ -0af305ed4e5f787d:__zlib\zdeflate.py -53fa0c913947021f:__zlib\test_pyzlib.py -56cdd754a8a09347:includes/stdint.py +03b24bc1d9327958:main.py +0f8134f67bdaba8f:__zlib\pyzlib.py +26e23066e8c7208d:__zlib\test_pyzlib.py +49bd8cba55979f76:includes/stdint.py 5a6a2137958c28c5:includes/w32\win32base.py -6aee24fdefa3cbc0:includes/string.py +5d8612e70097f0ba:__zlib\zdef.py 6c2029b306556c00:includes/stdlib.py 72e2d5ccb7cedcf1:includes/w32\win32memory.py 73edbcf76e32d00b:includes/stdio.py -7e9fab9c7b47c4db:__zlib\pyzlib.py -95e27d852b773ae8:__zlib\zchecksum.py -c9349bf1e8390dd5:__zlib\zhuff.py -dca7ef1d57347738:main.py -e00d9854a0d03f4f:__zlib\zinflate.py -f9cd063200178785:__zlib\zdef.py +77deeee736684e3e:__zlib\zdeflate.py +8407b4239b208bdb:__zlib\zhuff.py +9dbecd0942a39782:includes/testcheck.py +b5f1dc665c52a1bd:includes/string.py +cb151b297f4ea56d:__zlib\zchecksum.py +e445a2bb299d1b7d:__zlib\zinflate.py diff --git a/Test/ZlibTest/temp/_shared_sym.json b/Test/ZlibTest/temp/_shared_sym.json new file mode 100644 index 0000000..e69de29 diff --git a/Test/ZlibTest/temp/_shared_sym.pkl b/Test/ZlibTest/temp/_shared_sym.pkl deleted file mode 100644 index b7812d04f7a43a206f56b16cd7382de6bf2c4186..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 407147 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 str: pass + +def strncpy(dest: str, src: str, n: t.CSizeT) -> str: pass + +def strlen(src: str) -> t.CSizeT | t.CExport: pass + +def strcmp(str1: str, str2: str) -> t.CInt: pass + +def samestr(str1: str, str2: str) -> bool: pass + +def strncmp(str1: str, str2: str, n: t.CSizeT) -> t.CInt: pass + +def memcmp(ptr1: t.CVoid | t.CPtr, ptr2: t.CVoid | t.CPtr, n: t.CSizeT) -> t.CInt: pass + +def strchr(s: str, cr: t.CInt) -> str: pass + +def strrchr(s: str, cr: t.CInt) -> str: pass + +def strspn(s: str, skip: str) -> int: pass + +def memset(ptr: t.CVoid | t.CPtr, value: t.CInt, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass + +def memset32(ptr: t.CVoid | t.CPtr, value: t.CUInt32T, count: t.CSizeT) -> t.CVoid | t.CPtr: pass + +def memcpy(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport: pass + +def memmove(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr: pass + +def atoi(src: str) -> t.CInt: pass + +def atoll(src: str) -> t.CInt64T: pass + +def atof(src: str) -> t.CDouble: pass + +def split(s: str, delim: str, result: t.CArray[str]) -> int: pass diff --git a/Test/ZlibTest/temp/95e27d852b773ae8.pyi b/Test/ZlibTest/temp/cb151b297f4ea56d.pyi similarity index 85% rename from Test/ZlibTest/temp/95e27d852b773ae8.pyi rename to Test/ZlibTest/temp/cb151b297f4ea56d.pyi index db9e1d8..125a3b3 100644 --- a/Test/ZlibTest/temp/95e27d852b773ae8.pyi +++ b/Test/ZlibTest/temp/cb151b297f4ea56d.pyi @@ -10,6 +10,6 @@ import t, c def zchecksum_adler32(data: UINT8PTR, length: t.CSizeT, init: UINT32) -> t.CUInt32T: pass -crc32_table: t.CExtern | list[t.CUInt32T, 256] +crc32_table: t.CExtern | t.CArray[t.CUInt32T, 256] def zchecksum_crc32(data: UINT8PTR, length: t.CSizeT, init: t.CUInt32T) -> t.CUInt32T: pass diff --git a/Test/ZlibTest/temp/e00d9854a0d03f4f.pyi b/Test/ZlibTest/temp/e445a2bb299d1b7d.pyi similarity index 100% rename from Test/ZlibTest/temp/e00d9854a0d03f4f.pyi rename to Test/ZlibTest/temp/e445a2bb299d1b7d.pyi diff --git a/Test/fbnq copy 2.py b/Test/fbnq copy 2.py deleted file mode 100644 index a6939d9..0000000 --- a/Test/fbnq copy 2.py +++ /dev/null @@ -1,147 +0,0 @@ -from string import atoi -from stdlib import malloc, free -from stdint import * -import string -import w32.win32console -from stdarg import va_start, va_end, va_arg, va_list -import t -import c - - -class Struct1: - a: UINT - b: UINT = 123 -S1: list[Struct1, 5] = [ - Struct1(1, 2), - Struct1(b=3, a=4), - Struct1(a=5, b=6), - Struct1(7, b=8), - Struct1(9) -] -S1_: Struct1 = Struct1(10) -S1_2 = Struct1(112) - - -def reptr(p: UINT | t.CPtr, v: UINT): - c.Set(c.Deref(p), v) - -GLOBAL_VAR: t.CInt = 0 - -@t.Object -class OOPTest: - a: UINT - b: UINT = 12345 - c: UINT - def __init__(self): - self.a = 451 - def set_c(self, v: UINT): - self.c = v - global GLOBAL_VAR - GLOBAL_VAR = v - def __call__(self, a: UINT, b: UINT) -> UINT: - # print(a, b) - return a + b - def __enter__(self) -> 'OOPTest' | t.CPtr: - return self - def __exit__(self): - self.a = 99 - self.b = 99 - self.c = 99 - def __add__(self, other: 'OOPTest' | t.CPtr) -> 'OOPTest' | t.CPtr: - s = OOPTest() - s.a = (self.a + other.a) - return s - def print1(self): - print(114514) - def __str__(self) -> str: - return f"OOPTest ({self.a}) ({self.b}) ({self.c})" - def __delete__(self, instance): - print(f"delete {instance}") - def __bool__(self) -> bool: - return bool(self.a != 0) - def __len__(self) -> UINT: - return self.a - def __delitem__(self, key: UINT): - print(f"delitem {key}") - def __getitem__(self, key: UINT) -> UINT: - print(f"getitem {key}") - return self.a - def __setitem__(self, key: UINT, value: UINT): - print(f"setitem {key} {value}") - self.a = value - def __abs__(self) -> UINT: - if self.a < 0: - return -self.a - return self.a - - -@t.Object -class RangeOOPSimulation: - start: UINT - end: UINT - def __init__(self, start: UINT, end: UINT): - self.start = start - self.end = end - - def __iter__(self) -> 'RangeOOPSimulation' | t.CPtr: - return self - - def __next__(self) -> UINT: - if self.start >= self.end: - raise StopIteration - self.start += 1 - return self.start - 1 - -def main() -> t.CInt: - w32.win32console.SetConsoleOutputCP(65001) - w32.win32console.SetConsoleCP(65001) - - d = OOPTest() - d.set_c(1000000) - d.a = 1 - print("d.a: ", d.a) - print("d.b: ", d.b) - print("d.c: ", d.c) - #print(GLOBAL_VAR) - - with OOPTest() as d: - print("with __call__:", d(1, 2)) - print("_d.a: ", d.a) - print("_d.b: ", d.b) - print("_d.c: ", d.c) - - l = OOPTest() - l.a = 100 - (d + l).print1() - print("d + l.a: ", d.a + l.a) - print("(d + l).a: ", (d + l).a) - - print(f"d.a, l.a: {d.a} {l.a}") - print("d:", d) - - if d: - print("d.a 不是 zero, 说得对", d.a) - else: - print("d.a 是 zero, 说得对") - print("abs(d):", abs(d)) - print("len(d):", len(d)) - del d[114514] - d[114514] = 1145142 - - llll = "你好" - print(f"{llll},世界") - - for i in RangeOOPSimulation(0, 5 + 1): - print("RangeOOPSimulation:", i) - - free(d) - callit_args(0, 1, 2, "你知道", 666) - - -# args -def callit_args(a: t.CInt, *args): - print(arg(int), arg(int), arg(str), arg(int)) - #l: t.CInt = va_arg(args_va_list, int) - #print(l) - - diff --git a/Test/fbnq.py b/Test/fbnq.py deleted file mode 100644 index aed2780..0000000 --- a/Test/fbnq.py +++ /dev/null @@ -1,405 +0,0 @@ -from stdlib import malloc, free -import ctypes -from stdint import * -import string -import w32.win32console -from stdarg import va_start, va_end, va_arg, va_list -import t -import c - - -class Struct1: - a: UINT - b: UINT = 123 - -S1: list[Struct1, 5] = [ - Struct1(1, 2), - Struct1(b=3, a=4), - Struct1(a=5, b=6), - Struct1(7, b=8), - Struct1(9) -] -S1_: Struct1 = Struct1(10) -S1_2 = Struct1(112) - - -def reptr(p: UINT | t.CPtr, v: UINT): - c.DerefAs(p, v) - -GLOBAL_VAR: t.CInt = 0 - -@t.Object -class OOPTest2: - fb: t.CVoid | t.CPtr - def __init__(self): - self.fb = malloc(1024) - for i in range(0, 1024): - self.fb[i] = '1' - c.Set(t.CChar(self.fb[1023], t.CPtr), '\0') - def GetFB(self) -> t.CChar | t.CPtr: - return t.CChar(self.fb, t.CPtr) - def __del__(self): - print("OOPTest2 __del__") - free(self.fb) - -@t.Object -class OOPTest: - a: UINT - b: UINT = 12345 - c: UINT - oop2: OOPTest2 | t.CPtr - def __init__(self): - self.a = 451 - self.oop2 = c.Addr(OOPTest2()) - # c.Set(c.Deref(self.oop2.GetFB()[0]), 1) - self.oop2.GetFB()[0] = '1' - cp = self.oop2.fb # t.CChar(self.oop2.fb, t.CPtr) - cp[1] = '4' - cp[2] = '5' - cp[3] = '6' - cp[4] = '7' - cp[5] = '8' - cp[6] = '9' - cp[7] = '0' - cp[8] = '9' - - print(t.CChar(cp[0], t.CPtr)) - print("长度:", t.CChar(cp, t.CPtr).__sizeof__()) - print("cp[0]:", cp[0]) - cp += 1 - print("cp[0]:", cp[0]) - cp += 1 - - print("self.oop2.GetFB()[0]:", int(cp[0])) - #k = t.CChar(self.oop2.fb[1], t.CPtr) - #k[0] = "4" - - cp -= 2 - # print(t.CChar(cp, t.CPtr)) - - lambda_a = lambda: 1 - print(cp[0], lambda_a()) - - print(type(cp)) - print(dir(OOPTest2)) - - vkt: t.CVoid | t.CPtr = malloc(1024) - c.Set(c.Deref(vkt[0]), 8080) - vkt[0] = '2' - # vkt[0] = 20 - print(t.CChar(vkt[0], t.CPtr)[0]) - print(type(vkt[0])) - print(t.CChar(t.CInt("Hello"), t.CPtr)) - print(str((c.Addr("你好")))) - # print(vkt) - free(vkt) - # print("vkt:", vkt) - - vkt: t.CVoid | t.CPtr = malloc(1024) - vkt2: t.CChar | t.CPtr = t.CChar(vkt, t.CPtr) - vkt2[0] = '1' - vkt2[100] = '1' - print("首个参数:", vkt2[0]) - print("第100参数:", vkt2[100]) - #print("HEX", str_to_hex(vkt)) - free(vkt) - print("HEX", str_to_hex("ABCDEFHIJKLMN")) - print("HEX", str_to_hex("1")) - - del self.oop2 - - -def str_to_hex(s: str) -> str: - buf: str = malloc(1024) - out: str = buf - hex: list[str, None] = "0123456789ABCDEF" - while c.Deref(s) != 0: - cr: t.CUnsignedChar = c.Deref(s) - c.Set(c.Deref(out), hex[(cr >> 4) & 0xF]) # 高 4 位 - out += 1 - c.Set(c.Deref(out), hex[cr & 0xF]) # 低 4 位 - out += 1 - s += 1 # 移动指针! - c.Set(c.Deref(out), 0) # 结尾 - return buf - -# 十进制 int → 16进制字符串(小写 0x 开头) -# 内部 malloc(128),外部必须 free() -def int_to_hex(num: int) -> str: - buf = t.CChar(malloc(128), t.CPtr) - if not buf: return None - - hex_chars: list[t.CChar, None] = "0123456789ABCDEF" - i = 0 - - # 先加 0x 前缀 - buf[i] = '0' - buf[i + 1] = 'x' - i += 2 - - # 处理 0 - if num == 0: - buf[i] = '0' - i += 1 - buf[i] = '0' - i += 1 - buf[i] = '\0' - return buf - - # 存储逆序的十六进制字符 - temp: list[t.CChar, 32] - temp_idx = 0 - - # 转为无符号,避免负数问题 - n: t.CUnsignedInt = t.CUnsignedInt(num) - - while n > 0: - rem: t.CInt = n & 0xF; # 取低4位(等价%16) - temp[temp_idx] = hex_chars[rem] - temp_idx += 1 - n = n >> 4; # 右移4位(等价/16) - - # 反转写入最终缓冲区 - while temp_idx > 0: - temp_idx -= 1 - buf[i] = temp[temp_idx] - i += 1 - - buf[i] = '\0' - return buf - - - -def int_to_str(num: int) -> str: - # 直接分配 128 字节(足够存任何 64 位整数) - buf: t.CChar | t.CPtr = t.CChar(malloc(128), t.CPtr) - if not buf: return None - is_negative = 0 - i = 0 - # 处理 0 - if num == 0: - buf[i] = '0' - i += 1 - buf[i] = '\0' - return buf - # 处理负数 - if num < 0: - is_negative = 1 - num = -num - # 生成逆序数字 - while num > 0: - rem = num % 10 - buf[i] = '0' + rem - i += 1 - num = num / 10 - # 负号 - if is_negative: - buf[i] = '-' - i += 1 - # 结束符 - buf[i] = '\0' - # 反转字符串 - start = 0 - end = i - 1 - while start < end: - tr: t.CChar = buf[start] - buf[start] = buf[end] - buf[end] = tr - start += 1 - end -= 1 - return buf - - - - - - - - - - -# 一个元素:存 数据指针 + 数据大小 -class Item: - data: t.CVoid | t.CPtr # i8* 数据指针 - size: t.CSizeT # 存字节大小(用于拷贝、释放) - -# 可变长列表 -class List: - items: Item | t.CPtr - count: t.CSizeT = 0 - capacity: t.CSizeT = 4 - # 初始化列表 - def __init__(self): - # l: List | t.CPtr = malloc(List.__sizeof__()) - self.count = 0 - self.capacity = 4 - self.items = malloc(self.capacity * Item.__sizeof__()) - - # 自动扩容 - def __grow(self): - if self.count >= self.capacity: - self.capacity *= 2 - self.items = realloc(self.items, self.capacity * Item.__sizeof__()) - - # 添加任意类型数据(深拷贝) - def append(self, data: t.CVoid | t.CPtr, size: t.CSizeT): - self.__grow() - item: Item | t.CPtr = self.items[self.count] - item.size = size - item.data = malloc(size + 1) - memcpy(item.data, data, size) - c.Set(t.CUnsignedChar(item.data + size, t.CPtr), '\0') - self.count += 1 - - # 获取元素:返回 i8*(int8_t*),强转 - def get(self, index: t.CSizeT) -> t.CInt8T | t.CPtr: - if index >= self.count: return None - return self.items[index].data - - def __getitem__(self, index: t.CSizeT) -> t.CInt8T | t.CPtr: - return self.get(index) - - # 销毁列表(所有内存全部释放) - def free(self): - i: t.CSizeT = 0 - for i in range(self.count): - if self.items[i].data != 0: - free(self.items[i].data) - free(self.items) - # free(self) - - - - - - -DEFINE_T: t.CDefine = 2423432423 - - -class EnumTest(t.CEnum): - A: t.State - B: t.State - C: t.State - Len: t.State - - -def main() -> t.CInt: - w32.win32console.SetConsoleOutputCP(65001) - w32.win32console.SetConsoleCP(65001) - - d = OOPTest() - - l = List() - nihao = "你好!世界,这是一个可变列表" - l.append(c.Addr(114514), t.CInt.__sizeof__()) - l.append(nihao, len(nihao)) - print("列表取值0:", c.Deref(t.CInt(l[0], t.CPtr))) - print("列表取值1:", l.get(1)) - l.free() - # free(l) - print("结束") - - # 未实现 - #a = t.CInt32T - #print(a(-1)) - #print(type(a(-1))) - - E: EnumTest = EnumTest.B - print(E) - print(EnumTest.Len) - - print(EnumTest(1)) - print(type(EnumTest.B)) - - # c.Asm("mov eax, 1", op=[t.ASM_DESCR.CLOBBER_EAX]) - - u = Union() - u.A.a = 114514 - u.A.b = 222222 - print("u.A.a", u.A.a) - print("u.A.b", u.A.b) - print("u.A.c", u.B.c) # -16558 - - wb = WBIT() - wb.a = 1 - wb.b = 1 - wb.c = 1 - wb.d = 12 - print(wb.a) - print(wb.b) - print(wb.c) - print(wb.d) - wb.a = 2 - print(wb.a) # 10 -> 0 -> 0 - print(wb.__sizeof__()) - print(type(wb)) - - ble = BLE() - ble.a = 0x114514 - ble.b = 0x114514 - print(ble.a) - print(ble.b) - print("a:", int_to_str(ble.a)) - print("a_hex:", str_to_hex(int_to_str(ble.a))) - print(int_to_hex(ble.a[0])) # 0x00114514 00 - print(int_to_hex(ble.a[1])) # 0x00114514 11 - print(int_to_hex(ble.a[2])) # 0x00114514 45 - print(int_to_hex(ble.a[3])) # 0x00114514 14 - - print(int_to_hex(ble.b[0])) # 0x00114514 14 - print(int_to_hex(ble.b[1])) # 0x00114514 45 - print(int_to_hex(ble.b[2])) # 0x00114514 11 - print(int_to_hex(ble.b[3])) # 0x00114514 00 - - li = 0x0000000100000001 - - #bool_ = 0 - #if bool_: - # tcls = t.CUInt32T - #else: - # tcls = LIWORK - #lx = tcls(li) - #print(type(lx)) - #print(lx.b) - #print("END") - #未能完全实现 - # x[-1]取值 - - print(DEFINE_T) - if c.CIf(DEFINE_T == 2423432423): - print("DEFINE_T == 2423432423") - elif c.CIf(DEFINE_T == 123): - print("DEFINE_T == 123") - else: - print("DEFINE_T != 2423432423 and DEFINE_T != 123") - #c.CIf - #c.CIfdef - #c.CIfndef - #c.CElif - #c.CElse - -class LIWORK: - a: t.CUInt32T - b: t.CUInt32T - -# class Union -class Union(t.CUnion): - class A: - a: t.CInt32T - b: t.CInt32T - class B: - c: t.CInt16T - d: t.CInt64T - -class WBIT: - a: t.CInt | t.Bit(1) - b: t.CInt | t.Bit(1) - c: t.CInt | t.Bit(1) - d: t.CInt | t.Bit(5) - -class BLE: - a: t.CInt | t.BigEndian - b: t.CInt | t.LittleEndian - - - diff --git a/Test/test.py b/Test/test.py deleted file mode 100644 index 01d8764..0000000 --- a/Test/test.py +++ /dev/null @@ -1,133 +0,0 @@ -import t, c -# import stdint - - -MAX_ORDER = 123 - -print - -@t.Object -class ClassObject: - k: t.CInt - def __init__(self, k: t.CInt): - self.k = k - def __enter__(self) -> 'ClassObject': - return c.Deref(self) - def __exit__(self): - self.work() - def work(self): - print(1) - -@t.Object -class ClassObject1(ClassObject): - def __init__(self): - super().__init__(123) - ClassObject.__init__(self, 123) - -class ClassObject2: - a: t.CInt - b: t.CInt - c: t.CInt - -LONGLONG1: t.CTypedef = t.CLong -LONGLONG2: t.CTypedef | t.CLong | t.CLong -LONGLONG3: t.CTypedef = t.CLong | t.CLong -ULONGLONG: t.CTypedef = t.CUnsignedLong | t.CLong - -class A: - a: int -class B: - b: int -ccc: list[B, 1212] | t.CPtr = [] -ccc[0].b - -class memory_block: - f: t.CInt - -class __buddy_system(t.CStruct): - free_lists1: list[memory_block, 1] | t.CPtr # 空闲块链表 - free_lists1: list[memory_block, 1] | t.CPtr # 空闲块链表 - free_lists2: list[memory_block, MAX_ORDER] | t.CPtr # 空闲块链表 - free_lists3: list[memory_block, 1 + 1] | t.CPtr # 空闲块链表 - free_lists4: list[memory_block, MAX_ORDER + 1] | t.CPtr[t.CArrayPtr[t.CArrayPtr]] # 空闲块链表 - total_memory: t.CUInt64T # 总内存大小 - used_memory: t.CUInt64T # 已使用内存大小 - free_memory: t.CUInt64T # 空闲内存大小 - start_addr: t.CVoid | t.CPtr # 内存起始地址 - end_addr: t.CVoid | t.CPtr # 内存结束地址 - -UINT1: t.CTypedef = t.CUnsignedInt -UINT: t.CTypedef | t.CUnsignedInt # int must be 16-bit or 32-bit -BYTE: t.CTypedef | t.CUnsignedChar # char must be 8-bit -WORD: t.CTypedef | t.CUInt16T # 16-bit unsigned -DWORD: t.CTypedef | t.CUInt32T # 32-bit unsigned -QWORD: t.CTypedef | t.CUInt64T # 64-bit unsigned -TCHAR: t.CTypedef | t.CChar -WCHAR: t.CTypedef | WORD # UTF-16 code unit -FSIZE_t: t.CTypedef | DWORD -LBA_t: t.CTypedef | DWORD - -def DEF_NAMEBUFF() -> t.CDefine: - lfn: WCHAR | t.CPtr # Pointer to LFN working buffer and directory entry block scratchpad buffer - -def add(a: t.CInt, b: t.CInt) -> t.CConst | t.CInt | t.CPtr[t.CPtr]: - return c.Deref(c.Deref((a + b))) - -def main(l: t.CInt = 1): - kkkkkkkkkkkk1: UINT1 - kkkkkkkkkkkk2: UINT - print(kkkkkkkkkkkk1 + kkkkkkkkkkkkk2) - ssr: ClassObject | t.CPtr = ClassObject(6) - with ClassObject(1) as a: - a.work() - aaa: t.CInt | t.CPtr[t.CPtr] - cursor: t.CConst | t.CChar[112] | t.CArrayPtr[t.CArrayPtr] - k = add(1, 2) - - co2: ClassObject2 - co22: ClassObject2 = ClassObject2() - co23 = ClassObject2(a=1, b=1) - - b: ClassObject | t.CPtr = malloc(ClassObject.__sizeof__()) - b = ClassObject(1) - with b as llll: - llll.work() - - match (l): - case 1: - print(1) - case 2: - print(2) - case _: - print(3) - if l == 3 and k == 1: - c.Break() - print(4) - c.NoBreak() - match 3: - case 1: - print(1) - case 2: - print(2) - case _: - print(3) - if l == 3 and k == 1: - c.Break() - print(4) - c.NoBreak() - # a := b 格式 - - UINT(123, t.CPtr).__sizeof__() # enum,union的实例化也和typedef一样 - x: t.CInt - if (x := k) and 666: - print(x) - - t.CType(123, UINT).__sizeof__() - - DEF_NAMEBUFF - - len(x) - - math_test: t.CInt = 1+1-2+(3*4/2+1-6)/12+9*9 - -import base64 \ No newline at end of file diff --git a/Test/test_out.txt b/Test/test_out.txt deleted file mode 100644 index f302d06..0000000 --- a/Test/test_out.txt +++ /dev/null @@ -1 +0,0 @@ -UnicodeEncodeError: 'gbk' codec can't encode character '\ufffd' in position 3: illegal multibyte sequence diff --git a/Test/test_output.txt b/Test/test_output.txt deleted file mode 100644 index 5838da2..0000000 --- a/Test/test_output.txt +++ /dev/null @@ -1 +0,0 @@ -====================================================================== diff --git a/_debug_find.txt b/_debug_find.txt new file mode 100644 index 0000000..e69de29 diff --git a/build_log.txt b/build_log.txt new file mode 100644 index 0000000..899fda8 --- /dev/null +++ b/build_log.txt @@ -0,0 +1,321 @@ +├ INFO: 读取配置文件: ./Test/DictTest/project.json +├ INFO: 项目目录: D:\Users\TermiNexus\Desktop\TransPyC\Test\DictTest +├ INFO: 源目录: D:\Users\TermiNexus\Desktop\TransPyC\Test\DictTest\App +├ INFO: 临时目录: D:\Users\TermiNexus\Desktop\TransPyC\Test\DictTest\temp +├ INFO: 输出目录: D:\Users\TermiNexus\Desktop\TransPyC\Test\DictTest\output +├ INFO: 阶段: all +├ INFO: 编译器: llc -filetype=obj -relocation-model=pic +├ INFO: 目标三元组: x86_64-pc-windows-gnu +├ INFO: 数据布局: e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128 +├ INFO: output: 已清空 D:\Users\TermiNexus\Desktop\TransPyC\Test\DictTest\output +├ INFO: temp: 已清空 D:\Users\TermiNexus\Desktop\TransPyC\Test\DictTest\temp +├ INFO: 清理完成 +├ INFO: 找到 1 个可达源文件(从入口遍历) +├ INFO: [1/1] 生成签名: main.py +├ INFO: -> 308818c3f022824c.pyi (签名) +├ INFO: 处理 14 个被引用的 Python 库文件 +├ INFO: 生成签名: atom.py -> 271ea3decb810db2.pyi +├ INFO: 生成签名: json\__init__.py -> 8ee3170049c70333.pyi +├ INFO: 生成签名: json\__parser.py -> bd2e7db1744476fe.pyi +├ INFO: 生成签名: json\__writer.py -> eaf7a981f0ef5b22.pyi +├ INFO: 生成签名: mbuddy.py -> 0eaa586c42dcd931.pyi +├ INFO: 缓存命中: mpool.py -> 0991af0d22263577.pyi +├ INFO: 缓存命中: stdint.py -> 49bd8cba55979f76.pyi +├ INFO: 缓存命中: stdio.py -> 73edbcf76e32d00b.pyi +├ INFO: 缓存命中: stdlib.py -> 6c2029b306556c00.pyi +├ INFO: 缓存命中: string.py -> b5f1dc665c52a1bd.pyi +├ INFO: 缓存命中: testcheck.py -> 9dbecd0942a39782.pyi +├ INFO: 缓存命中: viperio.py -> c9f4be41ca1cc2b4.pyi +├ INFO: 缓存命中: w32\win32base.py -> 5a6a2137958c28c5.pyi +├ INFO: 缓存命中: w32\win32console.py -> bbdf3bbd4c3bc28c.pyi +├ INFO: 结构体注册表: 21 个类型, 0 个枚举 +├ INFO: -> 308818c3f022824c.stub.ll (缓存) +├ INFO: 缓存命中: atom.py -> 271ea3decb810db2.stub.ll +├ INFO: 缓存命中: json\__init__.py -> 8ee3170049c70333.stub.ll +├ INFO: 缓存命中: json\__parser.py -> bd2e7db1744476fe.stub.ll +├ INFO: 缓存命中: json\__writer.py -> eaf7a981f0ef5b22.stub.ll +├ INFO: 缓存命中: mbuddy.py -> 0eaa586c42dcd931.stub.ll +├ INFO: 缓存命中: mpool.py -> 0991af0d22263577.stub.ll +├ INFO: 缓存命中: stdint.py -> 49bd8cba55979f76.stub.ll +├ INFO: 缓存命中: stdio.py -> 73edbcf76e32d00b.stub.ll +├ INFO: 缓存命中: stdlib.py -> 6c2029b306556c00.stub.ll +├ INFO: 缓存命中: string.py -> b5f1dc665c52a1bd.stub.ll +├ INFO: 缓存命中: testcheck.py -> 9dbecd0942a39782.stub.ll +├ INFO: 缓存命中: viperio.py -> c9f4be41ca1cc2b4.stub.ll +├ INFO: 缓存命中: w32\win32base.py -> 5a6a2137958c28c5.stub.ll +├ INFO: 缓存命中: w32\win32console.py -> bbdf3bbd4c3bc28c.stub.ll +├ SUCCESS: 声明接口生成到: D:\Users\TermiNexus\Desktop\TransPyC\Test\DictTest\temp +├ INFO: SHA1 映射表 (15 个文件): +├ INFO: 找到 1 个可达源文件(已按依赖排序) +├ INFO: 处理顺序: +├ INFO: 1. main.py +├ INFO: [缓存] 构建共享符号表数据... +├ INFO: [缓存] 共享符号表构建完成 (0.53s, 571 符号, 3 泛型模板) +├ INFO: +需要翻译 1 个文件 +├ INFO: -> 308818c3f022824c.ll +├ INFO: [1/1] main.py (1.9s) +├ INFO: 翻译总耗时: 1.9s +├ INFO: +[阶段二完成] .ll 文件生成到: D:\Users\TermiNexus\Desktop\TransPyC\Test\DictTest\output +├ INFO: [includes] 发现 Python 源文件: stdio.py +├ INFO: [includes] 发现 Python 源文件: stdint.py +├ INFO: [includes] 发现 Python 包文件: w32\fileio.py +├ INFO: [includes] 发现 Python 包文件: w32\win32base.py +├ INFO: [includes] 发现 Python 包文件: w32\win32console.py +├ INFO: [includes] 发现 Python 包文件: w32\win32file.py +├ INFO: [includes] 发现 Python 包文件: w32\win32memory.py +├ INFO: [includes] 发现 Python 包文件: w32\win32process.py +├ INFO: [includes] 发现 Python 包文件: w32\win32sync.py +├ INFO: [includes] 发现 Python 源文件: stdlib.py +├ INFO: [includes] 发现 Python 源文件: mbuddy.py +├ INFO: [includes] 发现 Python 源文件: string.py +├ INFO: [includes] 发现 Python 源文件: testcheck.py +├ INFO: [includes] 发现 Python 源文件: mpool.py +├ INFO: [includes] 发现间接依赖: atom.py +├ INFO: [includes] 发现间接依赖: viperio.py +├ INFO: +[includes 编译] 找到 16 个 Python 源文件 +├ INFO: 翻译: atom.py -> 271ea3decb810db2.ll +├ INFO: -> 271ea3decb810db2.ll +├ INFO: 编译: 271ea3decb810db2.ll -> 271ea3decb810db2.obj +├ SUCCESS: 编译成功 +├ INFO: 跳过(声明文件): stdint.py +├ INFO: 跳过(声明文件): stdio.py +├ INFO: 跳过(声明文件): stdlib.py +├ INFO: 翻译: string.py -> b5f1dc665c52a1bd.ll +├ INFO: -> b5f1dc665c52a1bd.ll +├ INFO: 编译: b5f1dc665c52a1bd.ll -> b5f1dc665c52a1bd.obj +├ SUCCESS: 编译成功 +├ INFO: 翻译: mbuddy.py -> 0eaa586c42dcd931.ll +├ INFO: -> 0eaa586c42dcd931.ll +├ INFO: 编译: 0eaa586c42dcd931.ll -> 0eaa586c42dcd931.obj +├ SUCCESS: 编译成功 +├ INFO: 翻译: testcheck.py -> 9dbecd0942a39782.ll +├ INFO: -> 9dbecd0942a39782.ll +├ INFO: 编译: 9dbecd0942a39782.ll -> 9dbecd0942a39782.obj +├ SUCCESS: 编译成功 +├ INFO: 翻译: viperio.py -> c9f4be41ca1cc2b4.ll +├ INFO: -> c9f4be41ca1cc2b4.ll +├ INFO: 编译: c9f4be41ca1cc2b4.ll -> c9f4be41ca1cc2b4.obj +├ SUCCESS: 编译成功 +├ INFO: 翻译: mpool.py -> 0991af0d22263577.ll +├ INFO: -> 0991af0d22263577.ll +├ INFO: 编译: 0991af0d22263577.ll -> 0991af0d22263577.obj +├ SUCCESS: 编译成功 +├ INFO: 翻译: win32base.py -> 5a6a2137958c28c5.ll +├ INFO: -> 5a6a2137958c28c5.ll +├ INFO: 编译: 5a6a2137958c28c5.ll -> 5a6a2137958c28c5.obj +├ SUCCESS: 编译成功 +├ INFO: 翻译: win32console.py -> bbdf3bbd4c3bc28c.ll +├ INFO: -> bbdf3bbd4c3bc28c.ll +├ INFO: 编译: bbdf3bbd4c3bc28c.ll -> bbdf3bbd4c3bc28c.obj +├ SUCCESS: 编译成功 +├ INFO: 翻译: win32file.py -> abf9ce3160c9279e.ll +├ INFO: -> abf9ce3160c9279e.ll +├ INFO: 编译: abf9ce3160c9279e.ll -> abf9ce3160c9279e.obj +├ SUCCESS: 编译成功 +├ INFO: 翻译: fileio.py -> fa3691e66b426950.ll +├ INFO: -> fa3691e66b426950.ll +├ INFO: 编译: fa3691e66b426950.ll -> fa3691e66b426950.obj +├ SUCCESS: 编译成功 +├ INFO: 翻译: win32memory.py -> 72e2d5ccb7cedcf1.ll +├ INFO: -> 72e2d5ccb7cedcf1.ll +├ INFO: 编译: 72e2d5ccb7cedcf1.ll -> 72e2d5ccb7cedcf1.obj +├ SUCCESS: 编译成功 +├ INFO: 翻译: win32process.py -> 067c78e9f121dce3.ll +├ INFO: -> 067c78e9f121dce3.ll +├ INFO: 编译: 067c78e9f121dce3.ll -> 067c78e9f121dce3.obj +├ SUCCESS: 编译成功 +├ INFO: 翻译: win32sync.py -> 06f53cc594b4ac6c.ll +├ INFO: -> 06f53cc594b4ac6c.ll +├ INFO: 编译: 06f53cc594b4ac6c.ll -> 06f53cc594b4ac6c.obj +├ SUCCESS: 编译成功 +├ INFO: +[编译] 找到 1 个 .ll 文件需要编译 +├ INFO: 并行编译 1 个文件 (workers=1) +├ INFO: [DEBUG] replaced_declare_names: {'ReadConsoleInputW', 'ReadConsoleW', 'bd2e7db1744476fe._parse_object', 'GetConsoleMode', 'SetConsoleCursorPosition', '0991af0d22263577.MPool.__enter__', '8ee3170049c70333.JsonValue.is_string', 'sprintf', '0eaa586c42dcd931.MBuddy.realloc', '8ee3170049c70333.null', 'b5f1dc665c52a1bd.memset32', '0eaa586c42dcd931.MBuddy.calloc', 'WriteConsoleA', '8ee3170049c70333.JsonValue.as_float', '0eaa586c42dcd931.MBuddy._is_valid_ptr', '0991af0d22263577.bump_create', '0991af0d22263577.MPool.alloc', '0eaa586c42dcd931.MBuddy._lock', '9dbecd0942a39782.begin', '0eaa586c42dcd931._largest_pow2_le', '0eaa586c42dcd931.MBuddy._fl_pop', '8ee3170049c70333.array', 'fflush', '9dbecd0942a39782.check', 'memset', 'bd2e7db1744476fe.parse', '0eaa586c42dcd931.MBuddy._fl_push', 'SetConsoleTitleW', '0991af0d22263577.alloc', '0eaa586c42dcd931.MBuddy._coalesce', '0eaa586c42dcd931.MBuddy.__exit__', 'GetConsoleTitleW', 'bd2e7db1744476fe._skip_whitespace', '8ee3170049c70333.JsonValue._append_child', '0eaa586c42dcd931.MBuddy.free', '8ee3170049c70333.float_val', 'FillConsoleOutputAttribute', '0991af0d22263577.MPool.__exit__', '0991af0d22263577.MPool._slab_reset', '0991af0d22263577.MPool.reset', 'b5f1dc665c52a1bd.strcpy', 'b5f1dc665c52a1bd.atoi', '0eaa586c42dcd931.MBuddy.free_count', '8ee3170049c70333.JsonValue.__len__', '0991af0d22263577.MPool.alloc_buf', '8ee3170049c70333.JsonValue.get_item', 'eaf7a981f0ef5b22.write', 'memcpy', '0eaa586c42dcd931.MBuddy._fl_count', '9dbecd0942a39782.ok', 'puts', '8ee3170049c70333.JsonValue.is_array', '8ee3170049c70333.JsonValue.is_null', 'GetConsoleCursorInfo', 'bd2e7db1744476fe._parse_string', '8ee3170049c70333.JsonValue.type', 'strlen', '0eaa586c42dcd931.MBuddy.self_check', '0eaa586c42dcd931.MBuddy.__enter__', 'GetConsoleTitleA', '0991af0d22263577.MPool._init_slab', '8ee3170049c70333.JsonValue.as_bool', '0eaa586c42dcd931.MBuddy.alloc', '8ee3170049c70333.JsonValue.is_bool', '0991af0d22263577.MPool.free', 'b5f1dc665c52a1bd.strchr', 'bd2e7db1744476fe._parse_number', 'bd2e7db1744476fe._expect', '0eaa586c42dcd931.MBuddy.stats', '8ee3170049c70333.JsonValue.as_int', 'SetConsoleWindowInfo', 'printf', '8ee3170049c70333.string_val', '8ee3170049c70333.int_val', '0eaa586c42dcd931.MBuddy._buddy_of', 'FlushConsoleInputBuffer', 'bd2e7db1744476fe._peek', 'eaf7a981f0ef5b22._write_value', 'SetConsoleOutputCP', 'b5f1dc665c52a1bd.strncpy', 'snprintf', '9dbecd0942a39782.fail', 'SetConsoleTitleA', '9dbecd0942a39782.section', '8ee3170049c70333.JsonValue.__new__', '0991af0d22263577.reset', 'SetConsoleTextAttribute', 'GetConsoleScreenBufferInfo', '8ee3170049c70333.object_set', '8ee3170049c70333.bool_val', '8ee3170049c70333.JsonValue.__setitem__', '0991af0d22263577.MPool._bump_alloc', 'b5f1dc665c52a1bd.memmove', '8ee3170049c70333.JsonValue.is_float', '8ee3170049c70333.object', '0eaa586c42dcd931.MBuddy._unlock', '0eaa586c42dcd931.MBuddy.__init__', 'SetConsoleMode', 'bd2e7db1744476fe._parse_array', '8ee3170049c70333.JsonValue._pool_alloc', 'bd2e7db1744476fe._parse_value', '0991af0d22263577._align_up', 'bd2e7db1744476fe.ParseState.__init__', 'fgets', '0991af0d22263577.MPool._init_bump', 'fputs', '8ee3170049c70333.JsonValue.is_int', '0eaa586c42dcd931.MBuddy._fl_find_and_remove', 'ReadConsoleA', '9dbecd0942a39782.info', '8ee3170049c70333.JsonValue.__getitem__', 'SetConsoleCursorInfo', '0991af0d22263577.MPool._slab_free', '0eaa586c42dcd931.MBuddy.__before_init__', '8ee3170049c70333.JsonValue.__before_init__', 'fprintf', '0991af0d22263577.MPool.__init__', 'SetConsoleCP', 'b5f1dc665c52a1bd.samestr', 'ScrollConsoleScreenBufferA', 'b5f1dc665c52a1bd.strrchr', 'FillConsoleOutputCharacterA', 'b5f1dc665c52a1bd.strncmp', 'b5f1dc665c52a1bd.atoll', 'b5f1dc665c52a1bd.strcmp', 'FillConsoleOutputCharacterW', 'b5f1dc665c52a1bd.split', 'bd2e7db1744476fe._advance', '8ee3170049c70333.array_append', '0eaa586c42dcd931.MBuddy._order_for_size', '0991af0d22263577.MPool.realloc', '0991af0d22263577.MPool._slab_alloc', 'b5f1dc665c52a1bd.strspn', 'SetConsoleScreenBufferSize', '0eaa586c42dcd931.MBuddy._split_to_order', '8ee3170049c70333.JsonValue.is_object', 'b5f1dc665c52a1bd.memcmp', '8ee3170049c70333.JsonValue.as_string', 'ReadConsoleInputA', 'WriteConsoleW', '0991af0d22263577.MPool.__before_init__', '0eaa586c42dcd931.MBuddy.reset', '0eaa586c42dcd931._block_size_at_order', 'GetNumberOfConsoleInputEvents', 'b5f1dc665c52a1bd.atof'} +├ INFO: [DEBUG] removing lines {134} for ReadConsoleInputW +├ INFO: [DEBUG] removing lines {126} for ReadConsoleW +├ INFO: [DEBUG] removing lines {80} for bd2e7db1744476fe._parse_object +├ INFO: [DEBUG] removing lines {128} for GetConsoleMode +├ INFO: [DEBUG] removing lines {106} for SetConsoleCursorPosition +├ INFO: [DEBUG] removing lines {279} for 0991af0d22263577.MPool.__enter__ +├ INFO: [DEBUG] removing lines {18} for 8ee3170049c70333.JsonValue.is_string +├ INFO: [DEBUG] removing lines {160} for sprintf +├ INFO: [DEBUG] removing lines {261} for 0eaa586c42dcd931.MBuddy.realloc +├ INFO: [DEBUG] removing lines {44} for 8ee3170049c70333.null +├ INFO: [DEBUG] removing lines {205} for b5f1dc665c52a1bd.memset32 +├ INFO: [DEBUG] removing lines {259} for 0eaa586c42dcd931.MBuddy.calloc +├ INFO: [DEBUG] removing lines {120} for WriteConsoleA +├ INFO: [DEBUG] removing lines {28} for 8ee3170049c70333.JsonValue.as_float +├ INFO: [DEBUG] removing lines {247} for 0eaa586c42dcd931.MBuddy._is_valid_ptr +├ INFO: [DEBUG] removing lines {301} for 0991af0d22263577.bump_create +├ INFO: [DEBUG] removing lines {285} for 0991af0d22263577.MPool.alloc +├ INFO: [DEBUG] removing lines {251} for 0eaa586c42dcd931.MBuddy._lock +├ INFO: [DEBUG] removing lines {307} for 9dbecd0942a39782.begin +├ INFO: [DEBUG] removing lines {219} for 0eaa586c42dcd931._largest_pow2_le +├ INFO: [DEBUG] removing lines {235} for 0eaa586c42dcd931.MBuddy._fl_pop +├ INFO: [DEBUG] removing lines {54} for 8ee3170049c70333.array +├ INFO: [DEBUG] removing lines {170} for fflush +├ INFO: [DEBUG] removing lines {315} for 9dbecd0942a39782.check +├ INFO: [DEBUG] removing lines {203} for memset +├ INFO: [DEBUG] removing lines {82} for bd2e7db1744476fe.parse +├ INFO: [DEBUG] removing lines {233} for 0eaa586c42dcd931.MBuddy._fl_push +├ INFO: [DEBUG] removing lines {142} for SetConsoleTitleW +├ INFO: [DEBUG] removing lines {303} for 0991af0d22263577.alloc +├ INFO: [DEBUG] removing lines {245} for 0eaa586c42dcd931.MBuddy._coalesce +├ INFO: [DEBUG] removing lines {229} for 0eaa586c42dcd931.MBuddy.__exit__ +├ INFO: [DEBUG] removing lines {146} for GetConsoleTitleW +├ INFO: [DEBUG] removing lines {68} for bd2e7db1744476fe._skip_whitespace +├ INFO: [DEBUG] removing lines {42} for 8ee3170049c70333.JsonValue._append_child +├ INFO: [DEBUG] removing lines {257} for 0eaa586c42dcd931.MBuddy.free +├ INFO: [DEBUG] removing lines {50} for 8ee3170049c70333.float_val +├ INFO: [DEBUG] removing lines {118} for FillConsoleOutputAttribute +├ INFO: [DEBUG] removing lines {281} for 0991af0d22263577.MPool.__exit__ +├ INFO: [DEBUG] removing lines {283} for 0991af0d22263577.MPool._slab_reset +├ INFO: [DEBUG] removing lines {293} for 0991af0d22263577.MPool.reset +├ INFO: [DEBUG] removing lines {183} for b5f1dc665c52a1bd.strcpy +├ INFO: [DEBUG] removing lines {211} for b5f1dc665c52a1bd.atoi +├ INFO: [DEBUG] removing lines {265} for 0eaa586c42dcd931.MBuddy.free_count +├ INFO: [DEBUG] removing lines {32} for 8ee3170049c70333.JsonValue.__len__ +├ INFO: [DEBUG] removing lines {287} for 0991af0d22263577.MPool.alloc_buf +├ INFO: [DEBUG] removing lines {38} for 8ee3170049c70333.JsonValue.get_item +├ INFO: [DEBUG] removing lines {92} for eaf7a981f0ef5b22.write +├ INFO: [DEBUG] removing lines {207} for memcpy +├ INFO: [DEBUG] removing lines {249} for 0eaa586c42dcd931.MBuddy._fl_count +├ INFO: [DEBUG] removing lines {311} for 9dbecd0942a39782.ok +├ INFO: [DEBUG] removing lines {164} for puts +├ INFO: [DEBUG] removing lines {20} for 8ee3170049c70333.JsonValue.is_array +├ INFO: [DEBUG] removing lines {10} for 8ee3170049c70333.JsonValue.is_null +├ INFO: [DEBUG] removing lines {108} for GetConsoleCursorInfo +├ INFO: [DEBUG] removing lines {72} for bd2e7db1744476fe._parse_string +├ INFO: [DEBUG] removing lines {8} for 8ee3170049c70333.JsonValue.type +├ INFO: [DEBUG] removing lines {187} for strlen +├ INFO: [DEBUG] removing lines {267} for 0eaa586c42dcd931.MBuddy.self_check +├ INFO: [DEBUG] removing lines {227} for 0eaa586c42dcd931.MBuddy.__enter__ +├ INFO: [DEBUG] removing lines {144} for GetConsoleTitleA +├ INFO: [DEBUG] removing lines {277} for 0991af0d22263577.MPool._init_slab +├ INFO: [DEBUG] removing lines {24} for 8ee3170049c70333.JsonValue.as_bool +├ INFO: [DEBUG] removing lines {255} for 0eaa586c42dcd931.MBuddy.alloc +├ INFO: [DEBUG] removing lines {12} for 8ee3170049c70333.JsonValue.is_bool +├ INFO: [DEBUG] removing lines {289} for 0991af0d22263577.MPool.free +├ INFO: [DEBUG] removing lines {197} for b5f1dc665c52a1bd.strchr +├ INFO: [DEBUG] removing lines {74} for bd2e7db1744476fe._parse_number +├ INFO: [DEBUG] removing lines {70} for bd2e7db1744476fe._expect +├ INFO: [DEBUG] removing lines {263} for 0eaa586c42dcd931.MBuddy.stats +├ INFO: [DEBUG] removing lines {26} for 8ee3170049c70333.JsonValue.as_int +├ INFO: [DEBUG] removing lines {152} for SetConsoleWindowInfo +├ INFO: [DEBUG] removing lines {156} for printf +├ INFO: [DEBUG] removing lines {52} for 8ee3170049c70333.string_val +├ INFO: [DEBUG] removing lines {48} for 8ee3170049c70333.int_val +├ INFO: [DEBUG] removing lines {239} for 0eaa586c42dcd931.MBuddy._buddy_of +├ INFO: [DEBUG] removing lines {138} for FlushConsoleInputBuffer +├ INFO: [DEBUG] removing lines {64} for bd2e7db1744476fe._peek +├ INFO: [DEBUG] removing lines {90} for eaf7a981f0ef5b22._write_value +├ INFO: [DEBUG] removing lines {94} for SetConsoleOutputCP +├ INFO: [DEBUG] removing lines {185} for b5f1dc665c52a1bd.strncpy +├ INFO: [DEBUG] removing lines {162} for snprintf +├ INFO: [DEBUG] removing lines {313} for 9dbecd0942a39782.fail +├ INFO: [DEBUG] removing lines {140} for SetConsoleTitleA +├ INFO: [DEBUG] removing lines {309} for 9dbecd0942a39782.section +├ INFO: [DEBUG] removing lines {6} for 8ee3170049c70333.JsonValue.__new__ +├ INFO: [DEBUG] removing lines {305} for 0991af0d22263577.reset +├ INFO: [DEBUG] removing lines {112} for SetConsoleTextAttribute +├ INFO: [DEBUG] removing lines {102} for GetConsoleScreenBufferInfo +├ INFO: [DEBUG] removing lines {60} for 8ee3170049c70333.object_set +├ INFO: [DEBUG] removing lines {46} for 8ee3170049c70333.bool_val +├ INFO: [DEBUG] removing lines {36} for 8ee3170049c70333.JsonValue.__setitem__ +├ INFO: [DEBUG] removing lines {295} for 0991af0d22263577.MPool._bump_alloc +├ INFO: [DEBUG] removing lines {209} for b5f1dc665c52a1bd.memmove +├ INFO: [DEBUG] removing lines {16} for 8ee3170049c70333.JsonValue.is_float +├ INFO: [DEBUG] removing lines {56} for 8ee3170049c70333.object +├ INFO: [DEBUG] removing lines {253} for 0eaa586c42dcd931.MBuddy._unlock +├ INFO: [DEBUG] removing lines {225} for 0eaa586c42dcd931.MBuddy.__init__ +├ INFO: [DEBUG] removing lines {130} for SetConsoleMode +├ INFO: [DEBUG] removing lines {78} for bd2e7db1744476fe._parse_array +├ INFO: [DEBUG] removing lines {40} for 8ee3170049c70333.JsonValue._pool_alloc +├ INFO: [DEBUG] removing lines {76} for bd2e7db1744476fe._parse_value +├ INFO: [DEBUG] removing lines {269} for 0991af0d22263577._align_up +├ INFO: [DEBUG] removing lines {62} for bd2e7db1744476fe.ParseState.__init__ +├ INFO: [DEBUG] removing lines {168} for fgets +├ INFO: [DEBUG] removing lines {275} for 0991af0d22263577.MPool._init_bump +├ INFO: [DEBUG] removing lines {166} for fputs +├ INFO: [DEBUG] removing lines {14} for 8ee3170049c70333.JsonValue.is_int +├ INFO: [DEBUG] removing lines {237} for 0eaa586c42dcd931.MBuddy._fl_find_and_remove +├ INFO: [DEBUG] removing lines {124} for ReadConsoleA +├ INFO: [DEBUG] removing lines {317} for 9dbecd0942a39782.info +├ INFO: [DEBUG] removing lines {34} for 8ee3170049c70333.JsonValue.__getitem__ +├ INFO: [DEBUG] removing lines {110} for SetConsoleCursorInfo +├ INFO: [DEBUG] removing lines {299} for 0991af0d22263577.MPool._slab_free +├ INFO: [DEBUG] removing lines {223} for 0eaa586c42dcd931.MBuddy.__before_init__ +├ INFO: [DEBUG] removing lines {4} for 8ee3170049c70333.JsonValue.__before_init__ +├ INFO: [DEBUG] removing lines {158} for fprintf +├ INFO: [DEBUG] removing lines {273} for 0991af0d22263577.MPool.__init__ +├ INFO: [DEBUG] removing lines {96} for SetConsoleCP +├ INFO: [DEBUG] removing lines {191} for b5f1dc665c52a1bd.samestr +├ INFO: [DEBUG] removing lines {154} for ScrollConsoleScreenBufferA +├ INFO: [DEBUG] removing lines {199} for b5f1dc665c52a1bd.strrchr +├ INFO: [DEBUG] removing lines {114} for FillConsoleOutputCharacterA +├ INFO: [DEBUG] removing lines {193} for b5f1dc665c52a1bd.strncmp +├ INFO: [DEBUG] removing lines {213} for b5f1dc665c52a1bd.atoll +├ INFO: [DEBUG] removing lines {189} for b5f1dc665c52a1bd.strcmp +├ INFO: [DEBUG] removing lines {116} for FillConsoleOutputCharacterW +├ INFO: [DEBUG] removing lines {217} for b5f1dc665c52a1bd.split +├ INFO: [DEBUG] removing lines {66} for bd2e7db1744476fe._advance +├ INFO: [DEBUG] removing lines {58} for 8ee3170049c70333.array_append +├ INFO: [DEBUG] removing lines {241} for 0eaa586c42dcd931.MBuddy._order_for_size +├ INFO: [DEBUG] removing lines {291} for 0991af0d22263577.MPool.realloc +├ INFO: [DEBUG] removing lines {297} for 0991af0d22263577.MPool._slab_alloc +├ INFO: [DEBUG] removing lines {201} for b5f1dc665c52a1bd.strspn +├ INFO: [DEBUG] removing lines {104} for SetConsoleScreenBufferSize +├ INFO: [DEBUG] removing lines {243} for 0eaa586c42dcd931.MBuddy._split_to_order +├ INFO: [DEBUG] removing lines {22} for 8ee3170049c70333.JsonValue.is_object +├ INFO: [DEBUG] removing lines {195} for b5f1dc665c52a1bd.memcmp +├ INFO: [DEBUG] removing lines {30} for 8ee3170049c70333.JsonValue.as_string +├ INFO: [DEBUG] removing lines {132} for ReadConsoleInputA +├ INFO: [DEBUG] removing lines {122} for WriteConsoleW +├ INFO: [DEBUG] removing lines {271} for 0991af0d22263577.MPool.__before_init__ +├ INFO: [DEBUG] removing lines {231} for 0eaa586c42dcd931.MBuddy.reset +├ INFO: [DEBUG] removing lines {221} for 0eaa586c42dcd931._block_size_at_order +├ INFO: [DEBUG] removing lines {136} for GetNumberOfConsoleInputEvents +├ INFO: [DEBUG] removing lines {215} for b5f1dc665c52a1bd.atof +├ SUCCESS: 308818c3f022824c.ll +├ INFO: +[链接] 找到 1 个 .obj 文件 +├ INFO: [链接] 额外库文件: 13 个 +├ INFO: - 271ea3decb810db2.obj +├ INFO: - b5f1dc665c52a1bd.obj +├ INFO: - 0eaa586c42dcd931.obj +├ INFO: - 9dbecd0942a39782.obj +├ INFO: - c9f4be41ca1cc2b4.obj +├ INFO: - 0991af0d22263577.obj +├ INFO: - 5a6a2137958c28c5.obj +├ INFO: - bbdf3bbd4c3bc28c.obj +├ INFO: - abf9ce3160c9279e.obj +├ INFO: - fa3691e66b426950.obj +├ INFO: - 72e2d5ccb7cedcf1.obj +├ INFO: - 067c78e9f121dce3.obj +├ INFO: - 06f53cc594b4ac6c.obj +├ INFO: 执行: clang++ -Wl,--allow-multiple-definition -o D:\Users\TermiNexus\Desktop\TransPyC\Test\DictTest\output\DictTest.exe D:\Users\TermiNexus\Desktop\TransPyC\Test\DictTest\output\308818c3f022824c.obj D:\Users\TermiNexus\Desktop\TransPyC\Test\DictTest\output\271ea3decb810db2.obj D:\Users\TermiNexus\Desktop\TransPyC\Test\DictTest\output\b5f1dc665c52a1bd.obj D:\Users\TermiNexus\Desktop\TransPyC\Test\DictTest\output\0eaa586c42dcd931.obj D:\Users\TermiNexus\Desktop\TransPyC\Test\DictTest\output\9dbecd0942a39782.obj D:\Users\TermiNexus\Desktop\TransPyC\Test\DictTest\output\c9f4be41ca1cc2b4.obj D:\Users\TermiNexus\Desktop\TransPyC\Test\DictTest\output\0991af0d22263577.obj D:\Users\TermiNexus\Desktop\TransPyC\Test\DictTest\output\5a6a2137958c28c5.obj D:\Users\TermiNexus\Desktop\TransPyC\Test\DictTest\output\bbdf3bbd4c3bc28c.obj D:\Users\TermiNexus\Desktop\TransPyC\Test\DictTest\output\abf9ce3160c9279e.obj D:\Users\TermiNexus\Desktop\TransPyC\Test\DictTest\output\fa3691e66b426950.obj D:\Users\TermiNexus\Desktop\TransPyC\Test\DictTest\output\72e2d5ccb7cedcf1.obj D:\Users\TermiNexus\Desktop\TransPyC\Test\DictTest\output\067c78e9f121dce3.obj D:\Users\TermiNexus\Desktop\TransPyC\Test\DictTest\output\06f53cc594b4ac6c.obj -lmsvcrt -lucrt -lpthread -lmingwex -lkernel32 +├ ERROR: 链接失败: D:/msys64/mingw64/bin/ld: D:\Users\TermiNexus\Desktop\TransPyC\Test\DictTest\output\308818c3f022824c.obj:308818c3f022824c_dso.ll:(.text+0x1182): undefined reference to `8ee3170049c70333.object' +D:/msys64/mingw64/bin/ld: D:\Users\TermiNexus\Desktop\TransPyC\Test\DictTest\output\308818c3f022824c.obj:308818c3f022824c_dso.ll:(.text+0x11b8): undefined reference to `8ee3170049c70333.object_set' +D:/msys64/mingw64/bin/ld: D:\Users\TermiNexus\Desktop\TransPyC\Test\DictTest\output\308818c3f022824c.obj:308818c3f022824c_dso.ll:(.text+0x1205): undefined reference to `8ee3170049c70333.null' +D:/msys64/mingw64/bin/ld: D:\Users\TermiNexus\Desktop\TransPyC\Test\DictTest\output\308818c3f022824c.obj:308818c3f022824c_dso.ll:(.text+0x1252): undefined reference to `8ee3170049c70333.object' +D:/msys64/mingw64/bin/ld: D:\Users\TermiNexus\Desktop\TransPyC\Test\DictTest\output\308818c3f022824c.obj:308818c3f022824c_dso.ll:(.text+0x1288): undefined reference to `8ee3170049c70333.object_set' +D:/msys64/mingw64/bin/ld: D:\Users\TermiNexus\Desktop\TransPyC\Test\DictTest\output\308818c3f022824c.obj:308818c3f022824c_dso.ll:(.text+0x12d5): undefined reference to `8ee3170049c70333.null' +D:/msys64/mingw64/bin/ld: D:\Users\TermiNexus\Desktop\TransPyC\Test\DictTest\output\308818c3f022824c.obj:308818c3f022824c_dso.ll:(.text+0x13e4): undefined reference to `eaf7a981f0ef5b22.write' +D:/msys64/mingw64/bin/ld: D:\Users\TermiNexus\Desktop\TransPyC\Test\DictTest\output\308818c3f022824c.obj:308818c3f022824c_dso.ll:(.text+0x1414): undefined reference to `eaf7a981f0ef5b22.write' +D:/msys64/mingw64/bin/ld: D:\Users\TermiNexus\Desktop\TransPyC\Test\DictTest\output\308818c3f022824c.obj:308818c3f022824c_dso.ll:(.text+0x143a): undefined reference to `bd2e7db1744476fe.parse' +D:/msys64/mingw64/bin/ld: D:\Users\TermiNexus\Desktop\TransPyC\Test\DictTest\output\308818c3f022824c.obj:308818c3f022824c_dso.ll:(.text+0x1892): undefined reference to `8ee3170049c70333.object' +D:/msys64/mingw64/bin/ld: D:\Users\TermiNexus\Desktop\TransPyC\Test\DictTest\output\308818c3f022824c.obj:308818c3f022824c_dso.ll:(.text+0x18c8): undefined reference to `8ee3170049c70333.object_set' +D:/msys64/mingw64/bin/ld: D:\Users\TermiNexus\Desktop\TransPyC\Test\DictTest\output\308818c3f022824c.obj:308818c3f022824c_dso.ll:(.text+0x1917): undefined reference to `8ee3170049c70333.null' +D:/msys64/mingw64/bin/ld: D:\Users\TermiNexus\Desktop\TransPyC\Test\DictTest\output\308818c3f022824c.obj:308818c3f022824c_dso.ll:(.text+0x1962): undefined reference to `8ee3170049c70333.object' +D:/msys64/mingw64/bin/ld: D:\Users\TermiNexus\Desktop\TransPyC\Test\DictTest\output\308818c3f022824c.obj:308818c3f022824c_dso.ll:(.text+0x1998): undefined reference to `8ee3170049c70333.object_set' +D:/msys64/mingw64/bin/ld: D:\Users\TermiNexus\Desktop\TransPyC\Test\DictTest\output\308818c3f022824c.obj:308818c3f022824c_dso.ll:(.text+0x19e7): undefined reference to `8ee3170049c70333.null' +D:/msys64/mingw64/bin/ld: D:\Users\TermiNexus\Desktop\TransPyC\Test\DictTest\output\308818c3f022824c.obj:308818c3f022824c_dso.ll:(.text+0x1af4): undefined reference to `eaf7a981f0ef5b22.write' +D:/msys64/mingw64/bin/ld: D:\Users\TermiNexus\Desktop\TransPyC\Test\DictTest\output\308818c3f022824c.obj:308818c3f022824c_dso.ll:(.text+0x1b24): undefined reference to `eaf7a981f0ef5b22.write' +D:/msys64/mingw64/bin/ld: D:\Users\TermiNexus\Desktop\TransPyC\Test\DictTest\output\308818c3f022824c.obj:308818c3f022824c_dso.ll:(.text+0x1b4a): undefined reference to `bd2e7db1744476fe.parse' +clang++: error: linker command failed with exit code 1 (use -v to see invocation) +├ ERROR: +链接失败,立即终止编译。 diff --git a/build_log2.txt b/build_log2.txt new file mode 100644 index 0000000..b5b7fc3 --- /dev/null +++ b/build_log2.txt @@ -0,0 +1 @@ +├ INFO: [剥离] 调试段已移除 (llvm-strip) diff --git a/compile_log.txt b/compile_log.txt new file mode 100644 index 0000000..b5b7fc3 --- /dev/null +++ b/compile_log.txt @@ -0,0 +1 @@ +├ INFO: [剥离] 调试段已移除 (llvm-strip) diff --git a/compile_output.txt b/compile_output.txt new file mode 100644 index 0000000..05ba769 --- /dev/null +++ b/compile_output.txt @@ -0,0 +1 @@ +链接失败,立即终止编译。 diff --git a/compile_trace.txt b/compile_trace.txt new file mode 100644 index 0000000..b5b7fc3 --- /dev/null +++ b/compile_trace.txt @@ -0,0 +1 @@ +├ INFO: [剥离] 调试段已移除 (llvm-strip) diff --git a/includes/__builtin.py b/includes/__builtin.py new file mode 100644 index 0000000..a8a3e93 --- /dev/null +++ b/includes/__builtin.py @@ -0,0 +1,425 @@ +# GCC/Clang 内建函数声明 +# 所有函数均为仅声明(t.State 等价于 CExtern | CExport),由编译器/运行时提供实现 +import t + + +# ============================================================ +# 随机数生成 (RDRAND / RDSEED) +# ============================================================ + +def __builtin_ia32_rdrand16_step(p: t.CUInt16T | t.CPtr) -> t.CInt | t.State: pass +def __builtin_ia32_rdrand32_step(p: t.CUInt32T | t.CPtr) -> t.CInt | t.State: pass +def __builtin_ia32_rdrand64_step(p: t.CUInt64T | t.CPtr) -> t.CInt | t.State: pass +def __builtin_ia32_rdseed16_step(p: t.CUInt16T | t.CPtr) -> t.CInt | t.State: pass +def __builtin_ia32_rdseed32_step(p: t.CUInt32T | t.CPtr) -> t.CInt | t.State: pass +def __builtin_ia32_rdseed64_step(p: t.CUInt64T | t.CPtr) -> t.CInt | t.State: pass + + +# ============================================================ +# 时间戳计数器 (RDTSC / RDTSCP) +# ============================================================ + +def __builtin_ia32_rdtsc() -> t.CUInt64T | t.State: pass +def __builtin_ia32_rdtscp(p: t.CUInt32T | t.CPtr) -> t.CUInt64T | t.State: pass +def __builtin_ia32_rdpmc(counter: t.CUInt32T) -> t.CUInt64T | t.State: pass + + +# ============================================================ +# CPUID +# ============================================================ + +def __builtin_ia32_cpuid(level: t.CUInt32T, a: t.CUInt32T | t.CPtr, b: t.CUInt32T | t.CPtr, c: t.CUInt32T | t.CPtr, d: t.CUInt32T | t.CPtr) -> t.CUInt32T | t.State: pass +def __builtin_ia32_cpuid_count(level: t.CUInt32T, count: t.CUInt32T, a: t.CUInt32T | t.CPtr, b: t.CUInt32T | t.CPtr, c: t.CUInt32T | t.CPtr, d: t.CUInt32T | t.CPtr) -> t.CUInt32T | t.State: pass + + +# ============================================================ +# 内存屏障 (Fence) +# ============================================================ + +def __builtin_ia32_lfence() -> t.State: pass +def __builtin_ia32_mfence() -> t.State: pass +def __builtin_ia32_sfence() -> t.State: pass +def __builtin_ia32_pause() -> t.State: pass + + +# ============================================================ +# 位操作 (POPCNT / BSF / BSR / TZCNT / LZCNT / BEXTR / PDEP / PEXT / ANDN) +# ============================================================ + +def __builtin_ia32_popcntsi(x: t.CUInt32T) -> t.CInt | t.State: pass +def __builtin_ia32_popcntdi(x: t.CUInt64T) -> t.CInt | t.State: pass +def __builtin_ia32_popcntqi(x: t.CUInt64T) -> t.CInt | t.State: pass + +def __builtin_ia32_bsfsi(src: t.CUInt32T, dst: t.CUInt32T | t.CPtr) -> t.CInt | t.State: pass +def __builtin_ia32_bsrsi(src: t.CUInt32T, dst: t.CUInt32T | t.CPtr) -> t.CInt | t.State: pass +def __builtin_ia32_bsfqi(src: t.CUInt64T, dst: t.CUInt64T | t.CPtr) -> t.CInt | t.State: pass +def __builtin_ia32_bsrqi(src: t.CUInt64T, dst: t.CUInt64T | t.CPtr) -> t.CInt | t.State: pass + +def __builtin_ia32_tzcntsi(x: t.CUInt32T) -> t.CUInt32T | t.State: pass +def __builtin_ia32_tzcntdi(x: t.CUInt64T) -> t.CUInt64T | t.State: pass +def __builtin_ia32_lzcntsi(x: t.CUInt32T) -> t.CUInt32T | t.State: pass +def __builtin_ia32_lzcntdi(x: t.CUInt64T) -> t.CUInt64T | t.State: pass + +def __builtin_ia32_bextrsi(src: t.CUInt32T, start: t.CUInt32T, len: t.CUInt32T) -> t.CUInt32T | t.State: pass +def __builtin_ia32_bextrdi(src: t.CUInt64T, start: t.CUInt32T, len: t.CUInt32T) -> t.CUInt64T | t.State: pass + +def __builtin_ia32_pdep_si(src: t.CUInt32T, mask: t.CUInt32T) -> t.CUInt32T | t.State: pass +def __builtin_ia32_pext_si(src: t.CUInt32T, mask: t.CUInt32T) -> t.CUInt32T | t.State: pass +def __builtin_ia32_pdep_di(src: t.CUInt64T, mask: t.CUInt64T) -> t.CUInt64T | t.State: pass +def __builtin_ia32_pext_di(src: t.CUInt64T, mask: t.CUInt64T) -> t.CUInt64T | t.State: pass + +def __builtin_ia32_andn_si(a: t.CUInt32T, b: t.CUInt32T) -> t.CUInt32T | t.State: pass +def __builtin_ia32_andn_di(a: t.CUInt64T, b: t.CUInt64T) -> t.CUInt64T | t.State: pass + + +# ============================================================ +# 字节序交换 (BSWAP) +# ============================================================ + +def __builtin_bswap16(x: t.CUInt16T) -> t.CUInt16T | t.State: pass +def __builtin_bswap32(x: t.CUInt32T) -> t.CUInt32T | t.State: pass +def __builtin_bswap64(x: t.CUInt64T) -> t.CUInt64T | t.State: pass + + +# ============================================================ +# 缓存操作 (Cache) +# ============================================================ + +def __builtin_ia32_clflush(p: t.CVoid | t.CConst | t.CPtr) -> t.State: pass +def __builtin_ia32_clflushopt(p: t.CVoid | t.CConst | t.CPtr) -> t.State: pass +def __builtin_ia32_clwb(p: t.CVoid | t.CConst | t.CPtr) -> t.State: pass +def __builtin_ia32_clzero() -> t.State: pass + + +# ============================================================ +# 预取 (Prefetch) +# ============================================================ + +def __builtin_prefetch(addr: t.CVoid | t.CConst | t.CPtr, rw: t.CInt = 0, locality: t.CInt = 3) -> t.State: pass +def __builtin_ia32_prefetch0(p: t.CChar | t.CConst | t.CPtr) -> t.State: pass +def __builtin_ia32_prefetch1(p: t.CChar | t.CConst | t.CPtr) -> t.State: pass +def __builtin_ia32_prefetch2(p: t.CChar | t.CConst | t.CPtr) -> t.State: pass +def __builtin_ia32_prefetchnta(p: t.CChar | t.CConst | t.CPtr) -> t.State: pass + + +# ============================================================ +# 非临时存储 (Non-Temporal Store) +# ============================================================ + +def __builtin_ia32_movnti(p: t.CUInt32T | t.CPtr, val: t.CUInt32T) -> t.State: pass +def __builtin_ia32_movnti64(p: t.CUInt64T | t.CPtr, val: t.CUInt64T) -> t.State: pass +def __builtin_ia32_movntdq(p: t.CVoid | t.CPtr, val: t.CVoid | t.CPtr) -> t.State: pass +def __builtin_ia32_movntps(p: t.CFloat | t.CPtr, val: t.CFloat) -> t.State: pass +def __builtin_ia32_movntpd(p: t.CDouble | t.CPtr, val: t.CDouble) -> t.State: pass + + +# ============================================================ +# I/O 端口操作 (Port I/O) +# ============================================================ + +def __builtin_ia32_inb(port: t.CUInt16T) -> t.CUInt8T | t.State: pass +def __builtin_ia32_inw(port: t.CUInt16T) -> t.CUInt16T | t.State: pass +def __builtin_ia32_inl(port: t.CUInt16T) -> t.CUInt32T | t.State: pass +def __builtin_ia32_outb(val: t.CUInt8T, port: t.CUInt16T) -> t.State: pass +def __builtin_ia32_outw(val: t.CUInt16T, port: t.CUInt16T) -> t.State: pass +def __builtin_ia32_outl(val: t.CUInt32T, port: t.CUInt16T) -> t.State: pass + + +# ============================================================ +# 模型特定寄存器 (MSR) +# ============================================================ + +def __builtin_ia32_rdmsr(msr: t.CUInt32T, val: t.CUInt64T | t.CPtr) -> t.State: pass +def __builtin_ia32_wrmsr(msr: t.CUInt32T, val: t.CUInt64T) -> t.State: pass + + +# ============================================================ +# 系统指令 (System) +# ============================================================ + +def __builtin_ia32_hlt() -> t.State: pass +def __builtin_ia32_invd() -> t.State: pass +def __builtin_ia32_wbinvd() -> t.State: pass +def __builtin_ia32_invlpg(p: t.CVoid | t.CPtr) -> t.State: pass +def __builtin_ia32_clts() -> t.State: pass +def __builtin_ia32_cli() -> t.State: pass +def __builtin_ia32_sti() -> t.State: pass +def __builtin_ia32_int3() -> t.State: pass +def __builtin_ia32_int(n: t.CUInt8T) -> t.State: pass +def __builtin_ia32_ud2() -> t.State: pass + + +# ============================================================ +# 描述符表 (GDT / IDT / LDT / TR) +# ============================================================ + +def __builtin_ia32_lgdt(p: t.CVoid | t.CPtr) -> t.State: pass +def __builtin_ia32_sgdt(p: t.CVoid | t.CPtr) -> t.State: pass +def __builtin_ia32_lidt(p: t.CVoid | t.CPtr) -> t.State: pass +def __builtin_ia32_sidt(p: t.CVoid | t.CPtr) -> t.State: pass +def __builtin_ia32_lldt(sel: t.CUInt32T) -> t.State: pass +def __builtin_ia32_sldt(p: t.CVoid | t.CPtr) -> t.State: pass +def __builtin_ia32_ltr(sel: t.CUInt32T) -> t.State: pass +def __builtin_ia32_str(p: t.CVoid | t.CPtr) -> t.State: pass + + +# ============================================================ +# 控制寄存器 (CR / MSW) +# ============================================================ + +def __builtin_ia32_lmsw(val: t.CUInt32T) -> t.State: pass +def __builtin_ia32_smsw(p: t.CVoid | t.CPtr) -> t.State: pass + + +# ============================================================ +# 监控等待 (MONITOR / MWAIT) +# ============================================================ + +def __builtin_ia32_monitor(p: t.CVoid | t.CPtr, extensions: t.CUInt32T, hints: t.CUInt32T) -> t.State: pass +def __builtin_ia32_mwait(extensions: t.CUInt32T, hints: t.CUInt32T) -> t.State: pass + + +# ============================================================ +# XSAVE 状态操作 +# ============================================================ + +def __builtin_ia32_xsave(p: t.CVoid | t.CPtr, mask: t.CUInt64T) -> t.State: pass +def __builtin_ia32_xrstor(p: t.CVoid | t.CConst | t.CPtr, mask: t.CUInt64T) -> t.State: pass +def __builtin_ia32_xsaveopt(p: t.CVoid | t.CPtr, mask: t.CUInt64T) -> t.State: pass +def __builtin_ia32_xsavec(p: t.CVoid | t.CPtr, mask: t.CUInt64T) -> t.State: pass +def __builtin_ia32_xrstors(p: t.CVoid | t.CConst | t.CPtr, mask: t.CUInt64T) -> t.State: pass +def __builtin_ia32_xsaves(p: t.CVoid | t.CPtr, mask: t.CUInt64T) -> t.State: pass + + +# ============================================================ +# 通用内建函数 (Generic Builtins) +# ============================================================ + +def __builtin_expect(exp: t.CLong, c: t.CLong) -> t.CLong | t.State: pass +def __builtin_unreachable() -> t.State: pass +def __builtin_trap() -> t.State: pass +def __builtin_abort() -> t.State: pass +def __builtin_assume_aligned(addr: t.CVoid | t.CConst | t.CPtr, align: t.CSizeT, *args) -> t.CVoid | t.CPtr | t.State: pass +def __builtin_constant_p(expr: t.CVoid) -> t.CInt | t.State: pass +def __builtin_types_compatible_p(t1: t.CVoid, t2: t.CVoid) -> t.CInt | t.State: pass +def __builtin_choose_expr(const_exp: t.CUInt32T, exp1: t.CVoid, exp2: t.CVoid) -> t.CVoid | t.CPtr | t.State: pass +def __builtin_offsetof(typ: t.CVoid, member: t.CVoid) -> t.CSizeT | t.State: pass +def __builtin_function_start(func: t.CVoid | t.CPtr) -> t.CVoid | t.CPtr | t.State: pass + + +# ============================================================ +# 可变参数 (VaList) +# ============================================================ + +def __builtin_va_start(va: t.CVoid | t.CPtr, *args) -> t.State: pass +def __builtin_va_end(va: t.CVoid | t.CPtr) -> t.State: pass +def __builtin_va_arg(va: t.CVoid | t.CPtr, typ: t.CVoid) -> t.State: pass +def __builtin_va_copy(dst: t.CVoid | t.CPtr, src: t.CVoid | t.CConst | t.CPtr) -> t.State: pass + + +# ============================================================ +# 栈与调用信息 (Stack / Frame) +# ============================================================ + +def __builtin_return_address(level: t.CUInt32T) -> t.CVoid | t.CPtr | t.State: pass +def __builtin_frame_address(level: t.CUInt32T) -> t.CVoid | t.CPtr | t.State: pass +def __builtin_alloca(size: t.CSizeT) -> t.CVoid | t.CPtr | t.State: pass +def __builtin_alloca_with_align(size: t.CSizeT, alignment: t.CSizeT) -> t.CVoid | t.CPtr | t.State: pass + + +# ============================================================ +# 内存操作 (Memory) +# ============================================================ + +def __builtin_memcpy(dst: t.CVoid | t.CPtr, src: t.CVoid | t.CConst | t.CPtr, n: t.CSizeT) -> t.CVoid | t.CPtr | t.State: pass +def __builtin_memset(s: t.CVoid | t.CPtr, c: t.CInt, n: t.CSizeT) -> t.CVoid | t.CPtr | t.State: pass +def __builtin_memmove(dst: t.CVoid | t.CPtr, src: t.CVoid | t.CConst | t.CPtr, n: t.CSizeT) -> t.CVoid | t.CPtr | t.State: pass +def __builtin_memcmp(s1: t.CVoid | t.CConst | t.CPtr, s2: t.CVoid | t.CConst | t.CPtr, n: t.CSizeT) -> t.CInt | t.State: pass +def __builtin_mempcpy(dst: t.CVoid | t.CPtr, src: t.CVoid | t.CConst | t.CPtr, n: t.CSizeT) -> t.CVoid | t.CPtr | t.State: pass +def __builtin_memchr(s: t.CVoid | t.CConst | t.CPtr, c: t.CInt, n: t.CSizeT) -> t.CVoid | t.CPtr | t.State: pass + + +# ============================================================ +# 字符串操作 (String) +# ============================================================ + +def __builtin_strcpy(dst: t.CChar | t.CPtr, src: t.CChar | t.CConst | t.CPtr) -> t.CChar | t.CPtr | t.State: pass +def __builtin_strncpy(dst: t.CChar | t.CPtr, src: t.CChar | t.CConst | t.CPtr, n: t.CSizeT) -> t.CChar | t.CPtr | t.State: pass +def __builtin_strcat(dst: t.CChar | t.CPtr, src: t.CChar | t.CConst | t.CPtr) -> t.CChar | t.CPtr | t.State: pass +def __builtin_strncat(dst: t.CChar | t.CPtr, src: t.CChar | t.CConst | t.CPtr, n: t.CSizeT) -> t.CChar | t.CPtr | t.State: pass +def __builtin_strlen(s: t.CChar | t.CConst | t.CPtr) -> t.CSizeT | t.State: pass +def __builtin_strcmp(s1: t.CChar | t.CConst | t.CPtr, s2: t.CChar | t.CConst | t.CPtr) -> t.CInt | t.State: pass +def __builtin_strncmp(s1: t.CChar | t.CConst | t.CPtr, s2: t.CChar | t.CConst | t.CPtr, n: t.CSizeT) -> t.CInt | t.State: pass +def __builtin_strchr(s: t.CChar | t.CConst | t.CPtr, c: t.CInt) -> t.CChar | t.CPtr | t.State: pass +def __builtin_strrchr(s: t.CChar | t.CConst | t.CPtr, c: t.CInt) -> t.CChar | t.CPtr | t.State: pass +def __builtin_strstr(haystack: t.CChar | t.CConst | t.CPtr, needle: t.CChar | t.CConst | t.CPtr) -> t.CChar | t.CPtr | t.State: pass + + +# ============================================================ +# 数学内建函数 (Math) +# ============================================================ + +def __builtin_sqrt(x: t.CDouble) -> t.CDouble | t.State: pass +def __builtin_sqrtf(x: t.CFloat) -> t.CFloat | t.State: pass +def __builtin_sqrtl(x: t.CDouble) -> t.CDouble | t.State: pass +def __builtin_pow(x: t.CDouble, y: t.CDouble) -> t.CDouble | t.State: pass +def __builtin_powf(x: t.CFloat, y: t.CFloat) -> t.CFloat | t.State: pass +def __builtin_sin(x: t.CDouble) -> t.CDouble | t.State: pass +def __builtin_sinf(x: t.CFloat) -> t.CFloat | t.State: pass +def __builtin_cos(x: t.CDouble) -> t.CDouble | t.State: pass +def __builtin_cosf(x: t.CFloat) -> t.CFloat | t.State: pass +def __builtin_tan(x: t.CDouble) -> t.CDouble | t.State: pass +def __builtin_tanf(x: t.CFloat) -> t.CFloat | t.State: pass +def __builtin_atan(x: t.CDouble) -> t.CDouble | t.State: pass +def __builtin_atan2(y: t.CDouble, x: t.CDouble) -> t.CDouble | t.State: pass +def __builtin_exp(x: t.CDouble) -> t.CDouble | t.State: pass +def __builtin_log(x: t.CDouble) -> t.CDouble | t.State: pass +def __builtin_log2(x: t.CDouble) -> t.CDouble | t.State: pass +def __builtin_log10(x: t.CDouble) -> t.CDouble | t.State: pass +def __builtin_fabs(x: t.CDouble) -> t.CDouble | t.State: pass +def __builtin_fabsf(x: t.CFloat) -> t.CFloat | t.State: pass +def __builtin_abs(x: t.CInt) -> t.CInt | t.State: pass +def __builtin_labs(x: t.CLong) -> t.CLong | t.State: pass +def __builtin_llabs(x: t.CInt64T) -> t.CInt64T | t.State: pass +def __builtin_fma(x: t.CDouble, y: t.CDouble, z: t.CDouble) -> t.CDouble | t.State: pass +def __builtin_fmod(x: t.CDouble, y: t.CDouble) -> t.CDouble | t.State: pass +def __builtin_floor(x: t.CDouble) -> t.CDouble | t.State: pass +def __builtin_ceil(x: t.CDouble) -> t.CDouble | t.State: pass +def __builtin_trunc(x: t.CDouble) -> t.CDouble | t.State: pass +def __builtin_round(x: t.CDouble) -> t.CDouble | t.State: pass +def __builtin_nearbyint(x: t.CDouble) -> t.CDouble | t.State: pass +def __builtin_rint(x: t.CDouble) -> t.CDouble | t.State: pass + + +# ============================================================ +# 位计数内建函数 (Bit Counting) +# ============================================================ + +def __builtin_ffs(x: t.CUInt32T) -> t.CInt | t.State: pass +def __builtin_clz(x: t.CUInt32T) -> t.CInt | t.State: pass +def __builtin_ctz(x: t.CUInt32T) -> t.CInt | t.State: pass +def __builtin_popcount(x: t.CUInt32T) -> t.CInt | t.State: pass +def __builtin_parity(x: t.CUInt32T) -> t.CInt | t.State: pass + +def __builtin_ffsl(x: t.CULong) -> t.CInt | t.State: pass +def __builtin_clzl(x: t.CULong) -> t.CInt | t.State: pass +def __builtin_ctzl(x: t.CULong) -> t.CInt | t.State: pass +def __builtin_popcountl(x: t.CULong) -> t.CInt | t.State: pass +def __builtin_parityl(x: t.CULong) -> t.CInt | t.State: pass + +def __builtin_ffsll(x: t.CUInt64T) -> t.CInt | t.State: pass +def __builtin_clzll(x: t.CUInt64T) -> t.CInt | t.State: pass +def __builtin_ctzll(x: t.CUInt64T) -> t.CInt | t.State: pass +def __builtin_popcountll(x: t.CUInt64T) -> t.CInt | t.State: pass +def __builtin_parityll(x: t.CUInt64T) -> t.CInt | t.State: pass + + +# ============================================================ +# 对象大小检查 (Object size check) +# ============================================================ + +def __builtin_object_size(ptr: t.CVoid | t.CConst | t.CPtr, typ: t.CInt) -> t.CSizeT | t.State: pass +def __builtin_dynamic_object_size(ptr: t.CVoid | t.CConst | t.CPtr, typ: t.CInt) -> t.CSizeT | t.State: pass + +def __builtin___memcpy_chk(dst: t.CVoid | t.CPtr, src: t.CVoid | t.CConst | t.CPtr, n: t.CSizeT, objsize: t.CSizeT) -> t.CVoid | t.CPtr | t.State: pass +def __builtin___memmove_chk(dst: t.CVoid | t.CPtr, src: t.CVoid | t.CConst | t.CPtr, n: t.CSizeT, objsize: t.CSizeT) -> t.CVoid | t.CPtr | t.State: pass +def __builtin___memset_chk(s: t.CVoid | t.CPtr, c: t.CInt, n: t.CSizeT, objsize: t.CSizeT) -> t.CVoid | t.CPtr | t.State: pass +def __builtin___mempcpy_chk(dst: t.CVoid | t.CPtr, src: t.CVoid | t.CConst | t.CPtr, n: t.CSizeT, objsize: t.CSizeT) -> t.CVoid | t.CPtr | t.State: pass +def __builtin___strcpy_chk(dst: t.CChar | t.CPtr, src: t.CChar | t.CConst | t.CPtr, objsize: t.CSizeT) -> t.CChar | t.CPtr | t.State: pass +def __builtin___strncpy_chk(dst: t.CChar | t.CPtr, src: t.CChar | t.CConst | t.CPtr, n: t.CSizeT, objsize: t.CSizeT) -> t.CChar | t.CPtr | t.State: pass +def __builtin___strcat_chk(dst: t.CChar | t.CPtr, src: t.CChar | t.CConst | t.CPtr, objsize: t.CSizeT) -> t.CChar | t.CPtr | t.State: pass +def __builtin___strncat_chk(dst: t.CChar | t.CPtr, src: t.CChar | t.CConst | t.CPtr, n: t.CSizeT, objsize: t.CSizeT) -> t.CChar | t.CPtr | t.State: pass +def __builtin___snprintf_chk(s: t.CChar | t.CPtr, maxlen: t.CSizeT, flag: t.CInt, slen: t.CSizeT, fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.State: pass +def __builtin___sprintf_chk(s: t.CChar | t.CPtr, flag: t.CInt, slen: t.CSizeT, fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.State: pass + + +# ============================================================ +# 浮点分类 (FP Classification) +# ============================================================ + +def __builtin_isnan(x: t.CDouble) -> t.CInt | t.State: pass +def __builtin_isinf(x: t.CDouble) -> t.CInt | t.State: pass +def __builtin_isinf_sign(x: t.CDouble) -> t.CInt | t.State: pass +def __builtin_isfinite(x: t.CDouble) -> t.CInt | t.State: pass +def __builtin_isnormal(x: t.CDouble) -> t.CInt | t.State: pass +def __builtin_signbit(x: t.CDouble) -> t.CInt | t.State: pass +def __builtin_isgreater(x: t.CDouble, y: t.CDouble) -> t.CInt | t.State: pass +def __builtin_isgreaterequal(x: t.CDouble, y: t.CDouble) -> t.CInt | t.State: pass +def __builtin_isless(x: t.CDouble, y: t.CDouble) -> t.CInt | t.State: pass +def __builtin_islessequal(x: t.CDouble, y: t.CDouble) -> t.CInt | t.State: pass +def __builtin_islessgreater(x: t.CDouble, y: t.CDouble) -> t.CInt | t.State: pass +def __builtin_isunordered(x: t.CDouble, y: t.CDouble) -> t.CInt | t.State: pass + + +# ============================================================ +# 特殊值 (Special Values) +# ============================================================ + +def __builtin_nan(s: t.CChar | t.CConst | t.CPtr) -> t.CDouble | t.State: pass +def __builtin_nanf(s: t.CChar | t.CConst | t.CPtr) -> t.CFloat | t.State: pass +def __builtin_nanl(s: t.CChar | t.CConst | t.CPtr) -> t.CDouble | t.State: pass +def __builtin_nans(s: t.CChar | t.CConst | t.CPtr) -> t.CDouble | t.State: pass +def __builtin_nansf(s: t.CChar | t.CConst | t.CPtr) -> t.CFloat | t.State: pass +def __builtin_inf() -> t.CDouble | t.State: pass +def __builtin_inff() -> t.CFloat | t.State: pass +def __builtin_infl() -> t.CDouble | t.State: pass +def __builtin_huge_val() -> t.CDouble | t.State: pass +def __builtin_huge_valf() -> t.CFloat | t.State: pass +def __builtin_huge_vall() -> t.CDouble | t.State: pass +def __builtin_inf_sign() -> t.CInt | t.State: pass + + +# ============================================================ +# 类型转换与溢出检查 (Overflow) +# ============================================================ + +def __builtin_add_overflow(a: t.CUInt64T, b: t.CUInt64T, res: t.CUInt64T | t.CPtr) -> t.CBool | t.State: pass +def __builtin_sub_overflow(a: t.CUInt64T, b: t.CUInt64T, res: t.CUInt64T | t.CPtr) -> t.CBool | t.State: pass +def __builtin_mul_overflow(a: t.CUInt64T, b: t.CUInt64T, res: t.CUInt64T | t.CPtr) -> t.CBool | t.State: pass +def __builtin_sadd_overflow(a: t.CInt64T, b: t.CInt64T, res: t.CInt64T | t.CPtr) -> t.CBool | t.State: pass +def __builtin_ssub_overflow(a: t.CInt64T, b: t.CInt64T, res: t.CInt64T | t.CPtr) -> t.CBool | t.State: pass +def __builtin_smul_overflow(a: t.CInt64T, b: t.CInt64T, res: t.CInt64T | t.CPtr) -> t.CBool | t.State: pass +def __builtin_uadd_overflow(a: t.CUInt64T, b: t.CUInt64T, res: t.CUInt64T | t.CPtr) -> t.CBool | t.State: pass +def __builtin_usub_overflow(a: t.CUInt64T, b: t.CUInt64T, res: t.CUInt64T | t.CPtr) -> t.CBool | t.State: pass +def __builtin_umul_overflow(a: t.CUInt64T, b: t.CUInt64T, res: t.CUInt64T | t.CPtr) -> t.CBool | t.State: pass + + +# ============================================================ +# MMX / SSE 状态 +# ============================================================ + +def __builtin_ia32_emms() -> t.State: pass +def __builtin_ia32_femms() -> t.State: pass + + +# ============================================================ +# 排队指令 (ENQCMD) +# ============================================================ + +def __builtin_ia32_enqcmd(dst: t.CVoid | t.CPtr, src: t.CVoid | t.CConst | t.CPtr) -> t.CBool | t.State: pass +def __builtin_ia32_enqcmds(dst: t.CVoid | t.CPtr, src: t.CVoid | t.CConst | t.CPtr) -> t.CBool | t.State: pass + + +# ============================================================ +# 用户级等待 (UMWAIT / UMONITOR / TPAUSE) +# ============================================================ + +def __builtin_ia32_umonitor(p: t.CVoid | t.CPtr) -> t.State: pass +def __builtin_ia32_umwait(extensions: t.CUInt32T, counter: t.CUInt64T) -> t.CUInt8T | t.State: pass +def __builtin_ia32_tpause(extensions: t.CUInt32T, counter: t.CUInt64T) -> t.CUInt8T | t.State: pass + + +# ============================================================ +# 访问控制 (CLAC / STAC) +# ============================================================ + +def __builtin_ia32_clac() -> t.State: pass +def __builtin_ia32_stac() -> t.State: pass + + +# ============================================================ +# TLB 无效化 (INVLPG 变体) +# ============================================================ + +def __builtin_ia32_invlpgb(aux: t.CUInt64T, pcid: t.CUInt64T) -> t.State: pass +def __builtin_ia32_tlbsync() -> t.State: pass diff --git a/includes/_dict.py b/includes/_dict.py new file mode 100644 index 0000000..ef2145d --- /dev/null +++ b/includes/_dict.py @@ -0,0 +1,283 @@ +import t, c +import mbuddy +import string +import json +import mpool +from stdint import * + +# Variant 类型标签 (与 _variant.py 保持一致) +VARIANT_NONE: t.CDefine = 0 # 无类型/空值 +VARIANT_INT: t.CDefine = 1 # int (i64) +VARIANT_FLOAT: t.CDefine = 2 # float (f32) +VARIANT_DOUBLE: t.CDefine = 3 # double (f64) +VARIANT_STR: t.CDefine = 4 # str (i8*) +VARIANT_DICT: t.CDefine = 5 # dict* +VARIANT_LIST: t.CDefine = 6 # list* +VARIANT_BOOL: t.CDefine = 7 # bool (i1/i32) +VARIANT_PTR: t.CDefine = 8 # 自定义指针类型 + +# Variant 结构体大小: vtype(i32, 4 bytes) + padding(4 bytes) + ptr(i8*, 8 bytes) = 16 bytes +_VARIANT_SIZE: t.CDefine = 16 + + +class dict: + """堆上动态字典容器,基于 mbuddy 分配器。 + 键类型固定为 str (i8*),值使用 Variant 存储 (类型标签 + 无类型指针)。 + 支持嵌套 dict/list 和 JSON 序列化。 + + 用法: + mb: mbuddy.MBuddy = mbuddy.MBuddy(arena, arena_size) + d: dict = dict(mb) + d.set_int("x", 42) + p: t.CPtr = d["x"] + v: int = c.Deref(p) + + # 嵌套 dict + inner: dict = dict(mb) + inner.set_int("a", 1) + d.set_dict("sub", inner) + sub: dict = c.Deref(d["sub"]) + av: int = c.Deref(sub["a"]) + """ + __keys__: t.CVoid | t.CPtr + __values__: t.CVoid | t.CPtr + __count__: t.CSizeT + __capacity__: t.CSizeT + __mbuddy__: mbuddy.MBuddy | t.CPtr + __iter_index__: t.CSizeT + + def __new__(self, mb: mbuddy.MBuddy | t.CPtr) -> t.CPtr: + # 堆分配 dict 对象 (6 字段 × 8 字节 = 48 字节) + buf: t.CVoid | t.CPtr = mb.alloc(48) + return buf + + def __init__(self, mb: mbuddy.MBuddy | t.CPtr): + self.__mbuddy__ = mb + self.__count__ = 0 + self.__capacity__ = 8 + self.__keys__ = mb.alloc(self.__capacity__ * 8) + self.__values__ = mb.alloc(self.__capacity__ * _VARIANT_SIZE) + self.__iter_index__ = 0 + + def __len__(self) -> t.CSizeT: + return self.__count__ + + def _find(self, key: str) -> t.CSizeT: + """查找 key 的索引,找不到返回 __count__""" + i: t.CSizeT = 0 + while i < self.__count__: + key_ptr: str | t.CPtr = t.CVoid(t.CUInt64T(self.__keys__) + i * 8, t.CPtr) + if string.strcmp(key_ptr[0], key) == 0: + return i + i += 1 + return self.__count__ + + def __getitem__(self, key: str) -> t.CPtr: + """返回值的无类型指针。用户用 c.Deref 解引用获取实际值。 + 例: p: t.CPtr = d["x"]; v: int = c.Deref(p)""" + idx: t.CSizeT = self._find(key) + if idx >= self.__count__: + return None + # Variant.ptr 在 Variant 结构体偏移 8 处 + val_ptr: str | t.CPtr = t.CVoid(t.CUInt64T(self.__values__) + idx * _VARIANT_SIZE + 8, t.CPtr) + return val_ptr[0] + + def __setitem__(self, key: str, val: t.CNeedPtr): + """存储值为 VARIANT_PTR。val 自动取地址 (t.CNeedPtr)。 + 注意: val 指向的值生命周期由调用者管理。 + 如需持久存储,请使用 set_int / set_str 等类型化方法。""" + self._set_variant_raw(key, VARIANT_PTR, val) + + def _set_variant_raw(self, key: str, vtype: t.CInt, ptr: t.CPtr): + """内部方法: 存储 Variant (vtype + ptr)。不自动取地址。""" + idx: t.CSizeT = self._find(key) + if idx < self.__count__: + # 更新已有键 + vtype_ptr: t.CInt | t.CPtr = t.CVoid(t.CUInt64T(self.__values__) + idx * _VARIANT_SIZE, t.CPtr) + vtype_ptr[0] = vtype + val_ptr: str | t.CPtr = t.CVoid(t.CUInt64T(self.__values__) + idx * _VARIANT_SIZE + 8, t.CPtr) + val_ptr[0] = ptr + return + if self.__count__ >= self.__capacity__: + new_cap: t.CSizeT = self.__capacity__ * 2 + new_keys: t.CVoid | t.CPtr = self.__mbuddy__.alloc(new_cap * 8) + new_values: t.CVoid | t.CPtr = self.__mbuddy__.alloc(new_cap * _VARIANT_SIZE) + if new_keys == None: + return + if new_values == None: + return + string.memcpy(new_keys, self.__keys__, self.__count__ * 8) + string.memcpy(new_values, self.__values__, self.__count__ * _VARIANT_SIZE) + self.__keys__ = new_keys + self.__values__ = new_values + self.__capacity__ = new_cap + key_ptr: str | t.CPtr = t.CVoid(t.CUInt64T(self.__keys__) + self.__count__ * 8, t.CPtr) + key_ptr[0] = key + vtype_ptr: t.CInt | t.CPtr = t.CVoid(t.CUInt64T(self.__values__) + self.__count__ * _VARIANT_SIZE, t.CPtr) + vtype_ptr[0] = vtype + val_ptr: str | t.CPtr = t.CVoid(t.CUInt64T(self.__values__) + self.__count__ * _VARIANT_SIZE + 8, t.CPtr) + val_ptr[0] = ptr + self.__count__ += 1 + + # ============================================================ + # 类型化 setter — 在 __mbuddy__ 中分配持久存储 + # ============================================================ + + def set_int(self, key: str, val: int): + """存储 int 值 (VARIANT_INT)。值复制到 __mbuddy__ 持久存储。""" + storage: t.CVoid | t.CPtr = self.__mbuddy__.alloc(8) + int_ptr: int | t.CPtr = t.CVoid(t.CUInt64T(storage), t.CPtr) + int_ptr[0] = val + self._set_variant_raw(key, VARIANT_INT, storage) + + def set_str(self, key: str, val: str): + """存储 str 值 (VARIANT_STR)。直接存储字符串指针。""" + self._set_variant_raw(key, VARIANT_STR, val) + + def set_float(self, key: str, val: float): + """存储 float 值 (VARIANT_FLOAT)。值复制到 __mbuddy__ 持久存储。""" + storage: t.CVoid | t.CPtr = self.__mbuddy__.alloc(8) + float_ptr: float | t.CPtr = t.CVoid(t.CUInt64T(storage), t.CPtr) + float_ptr[0] = val + self._set_variant_raw(key, VARIANT_FLOAT, storage) + + def set_double(self, key: str, val: t.CDouble): + """存储 double 值 (VARIANT_DOUBLE)。值复制到 __mbuddy__ 持久存储。""" + storage: t.CVoid | t.CPtr = self.__mbuddy__.alloc(8) + dbl_ptr: t.CDouble | t.CPtr = t.CVoid(t.CUInt64T(storage), t.CPtr) + dbl_ptr[0] = val + self._set_variant_raw(key, VARIANT_DOUBLE, storage) + + def set_dict(self, key: str, val: dict | t.CPtr): + """存储嵌套 dict 指针 (VARIANT_DICT)。""" + self._set_variant_raw(key, VARIANT_DICT, val) + + def set_list(self, key: str, val: t.CPtr): + """存储嵌套 list 指针 (VARIANT_LIST)。""" + self._set_variant_raw(key, VARIANT_LIST, val) + + def set_bool(self, key: str, val: t.CInt): + """存储 bool 值 (VARIANT_BOOL)。值复制到 __mbuddy__ 持久存储。""" + storage: t.CVoid | t.CPtr = self.__mbuddy__.alloc(8) + bool_ptr: t.CInt | t.CPtr = t.CVoid(t.CUInt64T(storage), t.CPtr) + bool_ptr[0] = val + self._set_variant_raw(key, VARIANT_BOOL, storage) + + # ============================================================ + # 查询方法 + # ============================================================ + + def get_vtype(self, key: str) -> t.CInt: + """返回 key 对应值的 Variant 类型标签。""" + idx: t.CSizeT = self._find(key) + if idx >= self.__count__: + return VARIANT_NONE + vtype_ptr: t.CInt | t.CPtr = t.CVoid(t.CUInt64T(self.__values__) + idx * _VARIANT_SIZE, t.CPtr) + return vtype_ptr[0] + + def get(self, key: str, default: t.CPtr) -> t.CPtr: + """返回值指针,不存在则返回 default。""" + idx: t.CSizeT = self._find(key) + if idx >= self.__count__: + return default + val_ptr: str | t.CPtr = t.CVoid(t.CUInt64T(self.__values__) + idx * _VARIANT_SIZE + 8, t.CPtr) + return val_ptr[0] + + def contains(self, key: str) -> t.CInt: + """检查 key 是否存在。""" + idx: t.CSizeT = self._find(key) + if idx < self.__count__: + return 1 + return 0 + + def __iter__(self) -> dict | t.CPtr: + self.__iter_index__ = 0 + return self + + def __next__(self) -> str: + if self.__iter_index__ >= self.__count__: + raise StopIteration + idx: t.CSizeT = self.__iter_index__ + self.__iter_index__ = idx + 1 + key_ptr: str | t.CPtr = t.CVoid(t.CUInt64T(self.__keys__) + idx * 8, t.CPtr) + return key_ptr[0] + + # ============================================================ + # JSON 处理:利用 includes/json 库实现序列化/反序列化 + # ============================================================ + + def to_json(self, pool: mpool.MPool | t.CPtr) -> json.JsonValue | t.CPtr: + """将 dict 转换为 JsonValue 对象 (JSON_OBJECT)。 + 根据 Variant 类型标签自动选择合适的 JSON 值类型。""" + obj: json.JsonValue | t.CPtr = json.object(pool) + i: t.CSizeT = 0 + while i < self.__count__: + key_ptr: str | t.CPtr = t.CVoid(t.CUInt64T(self.__keys__) + i * 8, t.CPtr) + vtype_ptr: t.CInt | t.CPtr = t.CVoid(t.CUInt64T(self.__values__) + i * _VARIANT_SIZE, t.CPtr) + val_ptr: str | t.CPtr = t.CVoid(t.CUInt64T(self.__values__) + i * _VARIANT_SIZE + 8, t.CPtr) + vt: t.CInt = vtype_ptr[0] + vp: t.CPtr = val_ptr[0] + jv: json.JsonValue | t.CPtr = json.null(pool) + if jv != None: + if vt == VARIANT_INT: + jv.vtype = 2 # JSON_INT + ip: int | t.CPtr = t.CVoid(t.CUInt64T(vp), t.CPtr) + jv.int_val = ip[0] + elif vt == VARIANT_STR: + jv.vtype = 4 # JSON_STRING + jv.str_val = vp + elif vt == VARIANT_BOOL: + jv.vtype = 1 # JSON_BOOL + bp: t.CInt | t.CPtr = t.CVoid(t.CUInt64T(vp), t.CPtr) + jv.bool_val = bp[0] + elif vt == VARIANT_FLOAT: + jv.vtype = 3 # JSON_FLOAT + fp: float | t.CPtr = t.CVoid(t.CUInt64T(vp), t.CPtr) + jv.float_val = fp[0] + elif vt == VARIANT_PTR: + # 默认: 将 PTR 作为整数处理 + jv.vtype = 2 # JSON_INT + ip: int | t.CPtr = t.CVoid(t.CUInt64T(vp), t.CPtr) + jv.int_val = ip[0] + json.object_set(pool, obj, key_ptr[0], jv) + i += 1 + return obj + + def from_json(self, pool: mpool.MPool | t.CPtr, root: json.JsonValue | t.CPtr): + """从 JsonValue 对象填充 dict。 + 根据 JSON 值类型自动提取并存储为对应 Variant 类型。""" + if root == None: + return + if root.vtype != 6: # JSON_OBJECT + return + cur: json.JsonValue | t.CPtr = root.child + while cur != None: + if cur.key != None: + if cur.vtype == 2: # JSON_INT + storage: t.CVoid | t.CPtr = self.__mbuddy__.alloc(8) + ip: int | t.CPtr = t.CVoid(t.CUInt64T(storage), t.CPtr) + ip[0] = cur.int_val + self._set_variant_raw(cur.key, VARIANT_INT, storage) + elif cur.vtype == 4: # JSON_STRING + self._set_variant_raw(cur.key, VARIANT_STR, cur.str_val) + elif cur.vtype == 1: # JSON_BOOL + storage: t.CVoid | t.CPtr = self.__mbuddy__.alloc(8) + bp: t.CInt | t.CPtr = t.CVoid(t.CUInt64T(storage), t.CPtr) + bp[0] = cur.bool_val + self._set_variant_raw(cur.key, VARIANT_BOOL, storage) + elif cur.vtype == 3: # JSON_FLOAT + storage: t.CVoid | t.CPtr = self.__mbuddy__.alloc(8) + fp: float | t.CPtr = t.CVoid(t.CUInt64T(storage), t.CPtr) + fp[0] = cur.float_val + self._set_variant_raw(cur.key, VARIANT_FLOAT, storage) + cur = cur.next + + def dumps(self, pool: mpool.MPool | t.CPtr) -> str: + """将 dict 序列化为 JSON 字符串。""" + obj: json.JsonValue | t.CPtr = self.to_json(pool) + return json.write(pool, obj, False) + + def loads(self, pool: mpool.MPool | t.CPtr, json_str: str): + """从 JSON 字符串解析并填充 dict。""" + root: json.JsonValue | t.CPtr = json.parse(pool, json_str) + self.from_json(pool, root) diff --git a/includes/_fakeduck.py b/includes/_fakeduck.py new file mode 100644 index 0000000..c87d67c --- /dev/null +++ b/includes/_fakeduck.py @@ -0,0 +1,325 @@ +import t +import mbuddy +import string + + +class _Type: + def type_id(self) -> int: + return 99 + + +class _str: + # 编译期元数据:声明此类希望从 with 上下文获取 __mbuddy__ 字段(非必要,找不到不报错) + __requires__: list[str] = ['__mbuddy__'] + __data__: str + __mbuddy__: mbuddy.MBuddy | t.CPtr + + def b(self) -> int: + return 42 + + def SELF(self) -> str: + return self.__data__ + + def upper(self) -> str: + src: str = self.__data__ + length: t.CSizeT = len(src) + buf: bytes = self.__mbuddy__.alloc(length + 1) + if buf == None: return self.__data__ + for i, ch in enumerate(src): + if ch >= 97: + if ch <= 122: + buf[i] = ch - 32 + else: + buf[i] = ch + else: + buf[i] = ch + buf[length] = 0 + return str(buf) + + def lower(self) -> str: + src: str = self.__data__ + length: t.CSizeT = len(src) + buf: bytes = self.__mbuddy__.alloc(length + 1) + if buf == None: return self.__data__ + for i, ch in enumerate(src): + if ch >= 65: + if ch <= 90: + buf[i] = ch + 32 + else: + buf[i] = ch + else: + buf[i] = ch + buf[length] = 0 + return str(buf) + + def capitalize(self) -> str: + src: str = self.__data__ + length: t.CSizeT = len(src) + buf: bytes = self.__mbuddy__.alloc(length + 1) + if buf == None: return self.__data__ + first: bool = True + for i, ch in enumerate(src): + if first: + first = False + if ch >= 97: + if ch <= 122: + buf[i] = ch - 32 + else: + buf[i] = ch + else: + buf[i] = ch + else: + if ch >= 65: + if ch <= 90: + buf[i] = ch + 32 + else: + buf[i] = ch + else: + buf[i] = ch + buf[length] = 0 + return str(buf) + + def swapcase(self) -> str: + src: str = self.__data__ + length: t.CSizeT = len(src) + buf: bytes = self.__mbuddy__.alloc(length + 1) + if buf == None: return self.__data__ + for i, ch in enumerate(src): + if ch >= 97: + if ch <= 122: + buf[i] = ch - 32 + else: + buf[i] = ch + else: + if ch >= 65: + if ch <= 90: + buf[i] = ch + 32 + else: + buf[i] = ch + else: + buf[i] = ch + buf[length] = 0 + return str(buf) + + def title(self) -> str: + src: str = self.__data__ + length: t.CSizeT = len(src) + buf: bytes = self.__mbuddy__.alloc(length + 1) + if buf == None: return self.__data__ + prev_alpha: bool = False + for i, ch in enumerate(src): + cur_alpha: bool = False + if ch >= 65: + if ch <= 90: + cur_alpha = True + else: + if ch >= 97: + if ch <= 122: + cur_alpha = True + if cur_alpha: + if prev_alpha: + if ch >= 65: + if ch <= 90: + buf[i] = ch + 32 + else: + buf[i] = ch + else: + buf[i] = ch + else: + if ch >= 97: + if ch <= 122: + buf[i] = ch - 32 + else: + buf[i] = ch + else: + buf[i] = ch + else: + buf[i] = ch + prev_alpha = cur_alpha + buf[length] = 0 + return str(buf) + + def casefold(self) -> str: + src: str = self.__data__ + length: t.CSizeT = len(src) + buf: bytes = self.__mbuddy__.alloc(length + 1) + if buf == None: return self.__data__ + for i, ch in enumerate(src): + if ch >= 65: + if ch <= 90: + buf[i] = ch + 32 + else: + buf[i] = ch + else: + buf[i] = ch + buf[length] = 0 + return str(buf) + + def isupper(self) -> bool: + src: str = self.__data__ + has_alpha: bool = False + for ch in src: + if ch >= 65: + if ch <= 90: + has_alpha = True + else: + if ch >= 97: + if ch <= 122: + return False + return has_alpha + + def islower(self) -> bool: + src: str = self.__data__ + has_alpha: bool = False + for ch in src: + if ch >= 97: + if ch <= 122: + has_alpha = True + if ch >= 65: + if ch <= 90: + return False + return has_alpha + + def isalpha(self) -> bool: + src: str = self.__data__ + has_char: bool = False + for ch in src: + has_char = True + cur_alpha: bool = False + if ch >= 65: + if ch <= 90: + cur_alpha = True + else: + if ch >= 97: + if ch <= 122: + cur_alpha = True + if not cur_alpha: + return False + return has_char + + def isdigit(self) -> bool: + src: str = self.__data__ + has_char: bool = False + for ch in src: + has_char = True + if ch >= 48: + if ch > 57: + return False + else: + return False + return has_char + + def isalnum(self) -> bool: + src: str = self.__data__ + has_char: bool = False + for ch in src: + has_char = True + ok: bool = False + if ch >= 48: + if ch <= 57: + ok = True + if not ok: + if ch >= 65: + if ch <= 90: + ok = True + else: + if ch >= 97: + if ch <= 122: + ok = True + if not ok: + return False + return has_char + + def isspace(self) -> bool: + src: str = self.__data__ + has_char: bool = False + for ch in src: + has_char = True + is_space: bool = False + if ch == 32 or ch == 9 or ch == 10 or ch == 13 or ch == 11 or ch == 12: + is_space = True + if not is_space: + return False + return has_char + + def isascii(self) -> bool: + src: str = self.__data__ + has_char: bool = False + for ch in src: + has_char = True + if ch > 127: return False + return has_char + + def istitle(self) -> bool: + src: str = self.__data__ + has_char: bool = False + prev_alpha: bool = False + for ch in src: + has_char = True + cur_alpha: bool = False + if ch >= 65: + if ch <= 90: + cur_alpha = True + else: + if ch >= 97: + if ch <= 122: + cur_alpha = True + if cur_alpha: + if not prev_alpha: + if ch >= 97: + if ch <= 122: + return False + else: + if ch >= 65: + if ch <= 90: + return False + prev_alpha = cur_alpha + return has_char + + def split(self, delimiter: str) -> list[str]: + result = list[str](self.__mbuddy__) + src: str = self.__data__ + length: t.CSizeT = len(src) + delim_len: t.CSizeT = string.strlen(delimiter) + start: t.CSizeT = 0 + i: t.CSizeT = 0 + cur: str = src + sub_len: t.CSizeT = 0 + sub: bytes = None + src_off: bytes = None + term: bytes = None + if delim_len == 0: + sub_len = length + sub = self.__mbuddy__.alloc(sub_len + 1) + if sub != None: + src_off = bytes(t.CUInt64T(src) + start) + string.memcpy(sub, src_off, sub_len) + term = sub + term[sub_len] = 0 + result.append(str(sub)) + return result + while i + delim_len <= length: + if string.strncmp(cur, delimiter, delim_len) == 0: + sub_len = i - start + sub = self.__mbuddy__.alloc(sub_len + 1) + if sub != None: + src_off = bytes(t.CUInt64T(src) + start) + string.memcpy(sub, src_off, sub_len) + term = sub + term[sub_len] = 0 + result.append(str(sub)) + start = i + delim_len + cur += delim_len + i += delim_len + else: + cur += 1 + i += 1 + sub_len = length - start + sub = self.__mbuddy__.alloc(sub_len + 1) + if sub != None: + src_off = bytes(t.CUInt64T(src) + start) + string.memcpy(sub, src_off, sub_len) + term = sub + term[sub_len] = 0 + result.append(str(sub)) + return result diff --git a/includes/_list.py b/includes/_list.py new file mode 100644 index 0000000..94bb26c --- /dev/null +++ b/includes/_list.py @@ -0,0 +1,85 @@ +import t, c +import mbuddy +import string +from stdint import * + + +class list[T]: + """堆上动态列表容器,基于 mbuddy 分配器。 + + 用法: + mb: mbuddy.MBuddy = mbuddy.MBuddy(arena, arena_size) + nums: list[int] = list[int](mb) + nums.append(42) + x: int = nums.get(0) + """ + __data__: t.CVoid | t.CPtr + __count__: t.CSizeT + __capacity__: t.CSizeT + __mbuddy__: mbuddy.MBuddy | t.CPtr + __iter_index__: t.CSizeT + + def __new__(self, mb: mbuddy.MBuddy | t.CPtr): + # 堆分配 list[T] 对象 (5 字段 × 8 字节 = 40 字节) + # 避免栈上分配导致返回后 use-after-free + buf: t.CVoid | t.CPtr = mb.alloc(40) + return buf + + def __init__(self, mb: mbuddy.MBuddy | t.CPtr): + self.__mbuddy__ = mb + self.__count__ = 0 + self.__capacity__ = 8 + self.__data__ = mb.alloc(self.__capacity__ * T.__sizeof__()) + self.__iter_index__ = 0 + + def __len__(self) -> t.CSizeT: + return self.__count__ + + def append(self, item: T): + if self.__count__ >= self.__capacity__: + new_cap: t.CSizeT = self.__capacity__ * 2 + new_data: t.CVoid | t.CPtr = self.__mbuddy__.alloc(new_cap * T.__sizeof__()) + if new_data == None: + return + string.memcpy(new_data, self.__data__, self.__count__ * T.__sizeof__()) + self.__data__ = new_data + self.__capacity__ = new_cap + elem_ptr: T | t.CPtr = t.CVoid(t.CUInt64T(self.__data__) + self.__count__ * T.__sizeof__(), t.CPtr) + elem_ptr[0] = item + self.__count__ += 1 + + def get(self, index: t.CSizeT) -> T: + elem_ptr: T | t.CPtr = t.CVoid(t.CUInt64T(self.__data__) + index * T.__sizeof__(), t.CPtr) + return elem_ptr[0] + + def __getitem__(self, index: t.CSizeT) -> T: + elem_ptr: T | t.CPtr = t.CVoid(t.CUInt64T(self.__data__) + index * T.__sizeof__(), t.CPtr) + return elem_ptr[0] + + def set(self, index: t.CSizeT, value: T): + elem_ptr: T | t.CPtr = t.CVoid(t.CUInt64T(self.__data__) + index * T.__sizeof__(), t.CPtr) + elem_ptr[0] = value + + def __setitem__(self, index: t.CSizeT, value: T): + elem_ptr: T | t.CPtr = t.CVoid(t.CUInt64T(self.__data__) + index * T.__sizeof__(), t.CPtr) + elem_ptr[0] = value + + def pop(self) -> T: + self.__count__ -= 1 + elem_ptr: T | t.CPtr = t.CVoid(t.CUInt64T(self.__data__) + self.__count__ * T.__sizeof__(), t.CPtr) + return elem_ptr[0] + + def clear(self): + self.__count__ = 0 + + def __iter__(self): + self.__iter_index__ = 0 + return self + + def __next__(self) -> T: + if self.__iter_index__ >= self.__count__: + raise StopIteration + idx: t.CSizeT = self.__iter_index__ + self.__iter_index__ = idx + 1 + elem_ptr: T | t.CPtr = t.CVoid(t.CUInt64T(self.__data__) + idx * T.__sizeof__(), t.CPtr) + return elem_ptr[0] diff --git a/includes/_variant.py b/includes/_variant.py new file mode 100644 index 0000000..6cc06b3 --- /dev/null +++ b/includes/_variant.py @@ -0,0 +1,64 @@ +import t, c +from stdint import * + +# Variant 类型标签 (固定枚举 + 自定义 PTR) +VARIANT_NONE: t.CDefine = 0 # 无类型/空值 +VARIANT_INT: t.CDefine = 1 # int (i64) +VARIANT_FLOAT: t.CDefine = 2 # float (f32) +VARIANT_DOUBLE: t.CDefine = 3 # double (f64) +VARIANT_STR: t.CDefine = 4 # str (i8*) +VARIANT_DICT: t.CDefine = 5 # dict* +VARIANT_LIST: t.CDefine = 6 # list* +VARIANT_BOOL: t.CDefine = 7 # bool (i1/i32) +VARIANT_PTR: t.CDefine = 8 # 自定义指针类型 + + +class Variant: + """通用变体类型,存储类型标签 + 无类型指针。 + 用于 dict/list 的万能对象存储,支持嵌套和 JSON 序列化。 + + 用法: + v: Variant = Variant(VARIANT_INT, t.CNeedPtr(42)) + v2: Variant = Variant(VARIANT_STR, t.CNeedPtr("hello")) + + # 获取值 + ptr: t.CPtr = v.ptr + i: int = c.Deref(ptr) + """ + vtype: t.CInt + ptr: t.CPtr + + def __init__(self, vtype: t.CInt, val: t.CNeedPtr): + """构造 Variant。 + val 使用 t.CNeedPtr 自动取地址(非指针值自动 alloca+store)。 + 注意: val 的生命周期由调用者管理,Variant 仅存储指针。 + """ + self.vtype = vtype + self.ptr = val + + def is_none(self) -> t.CInt: + return self.vtype == VARIANT_NONE + + def is_int(self) -> t.CInt: + return self.vtype == VARIANT_INT + + def is_float(self) -> t.CInt: + return self.vtype == VARIANT_FLOAT + + def is_double(self) -> t.CInt: + return self.vtype == VARIANT_DOUBLE + + def is_str(self) -> t.CInt: + return self.vtype == VARIANT_STR + + def is_dict(self) -> t.CInt: + return self.vtype == VARIANT_DICT + + def is_list(self) -> t.CInt: + return self.vtype == VARIANT_LIST + + def is_bool(self) -> t.CInt: + return self.vtype == VARIANT_BOOL + + def is_ptr(self) -> t.CInt: + return self.vtype == VARIANT_PTR diff --git a/includes/_withcontent.py b/includes/_withcontent.py new file mode 100644 index 0000000..630780d --- /dev/null +++ b/includes/_withcontent.py @@ -0,0 +1,69 @@ +import t, c +from stdint import * +from w32.win32process import TlsAlloc, TlsGetValue, TlsSetValue +import stdlib +import stdio +import string + + +# 最大提供者栈深度(编译器会检查是否够用,不够再往上提) +_MAX_PROVIDER_DEPTH: t.CDefine = 32 + + +@t.Object +class _ProviderStack: + """提供者栈,存储字段名和指针对。""" + names: t.CArray[VOIDPTR, 32] + ptrs: t.CArray[VOIDPTR, 32] + top: UINT64 + + +# TLS 索引(全局,所有线程共享同一个索引) +_tls_index: ULONG = 0 + + +@t.TLS +def _init_tls(): + """初始化 TLS 索引(一次性执行,后续调用跳过)。""" + global _tls_index + _tls_index = TlsAlloc() + + +def _get_stack() -> _ProviderStack | t.CPtr: + """获取当前线程的提供者栈,不存在则分配。""" + _init_tls() + stack: _ProviderStack | t.CPtr = TlsGetValue(_tls_index) + if stack == None: + stack = stdlib.malloc(_ProviderStack.__sizeof__()) + string.memset(stack, 0, _ProviderStack.__sizeof__()) + TlsSetValue(_tls_index, stack) + return stack + + +def _push_provider(field_name: str, ptr: t.CPtr): + """压入提供者 (field_name, ptr) 到栈中。""" + stack: _ProviderStack | t.CPtr = _get_stack() + if stack.top >= _MAX_PROVIDER_DEPTH: + stdio.printf("[with] ERROR: provider stack overflow (depth=%lu, max=%d), field '%s' not injected\n", stack.top, _MAX_PROVIDER_DEPTH, field_name) + return + stack.names[stack.top] = field_name + stack.ptrs[stack.top] = ptr + stack.top = stack.top + 1 + + +def _pop_provider(): + """弹出栈顶提供者。""" + stack: _ProviderStack | t.CPtr = _get_stack() + if stack.top > 0: + stack.top = stack.top - 1 + + +def _find_provider(field_name: str) -> t.CPtr: + """从栈顶向下查找匹配 field_name 的提供者,返回对应的指针。找不到返回 NULL。""" + stack: _ProviderStack | t.CPtr = _get_stack() + i: UINT64 = stack.top + while i > 0: + i = i - 1 + if string.strcmp(stack.names[i], field_name) == 0: + return stack.ptrs[i] + return None diff --git a/includes/atom.py b/includes/atom.py index f3927da..c01664f 100644 --- a/includes/atom.py +++ b/includes/atom.py @@ -9,7 +9,7 @@ ATOMIC_ACQ_REL: t.CDefine = 4 ATOMIC_SEQ_CST: t.CDefine = 5 -def __atomic_test_and_set(ptr: t.CUInt64T | t.CPtr, order: t.CInt) -> t.CBool | t.State: +def __atomic_test_and_set(ptr: t.CUInt64T | t.CPtr, order: t.CInt) -> t.CBool: result: t.CUInt8T = 1 c.Asm(f"""mov al, 1 xchg byte ptr [{c.AsmInp(ptr, t.ASM_DESCR.REG_ANY)}], al @@ -20,23 +20,23 @@ def __atomic_test_and_set(ptr: t.CUInt64T | t.CPtr, order: t.CInt) -> t.CBool | return t.CBool(result) -def __atomic_clear(ptr: t.CUInt64T | t.CPtr, order: t.CInt) -> t.CVoid | t.State: +def __atomic_clear(ptr: t.CUInt64T | t.CPtr, order: t.CInt) -> t.CVoid: c.Asm(f"""mov byte ptr [{c.AsmInp(ptr, t.ASM_DESCR.REG_ANY)}], 0""", inp = [c.AsmInp(ptr, t.ASM_DESCR.REG_ANY)], op = [t.ASM_DESCR.CLOBBER_MEMORY]) -def __atomic_thread_fence(order: t.CInt) -> t.CVoid | t.State: +def __atomic_thread_fence(order: t.CInt) -> t.CVoid: c.Asm("mfence", op=[t.ASM_DESCR.CLOBBER_MEMORY]) -def __atomic_signal_fence(order: t.CInt) -> t.CVoid | t.State: +def __atomic_signal_fence(order: t.CInt) -> t.CVoid: pass -def __atomic_always_lock_free(size: t.CSizeT, ptr: t.CVoid | t.CPtr) -> t.CBool | t.State: +def __atomic_always_lock_free(size: t.CSizeT, ptr: t.CVoid | t.CPtr) -> t.CBool: return t.CBool(1) -def __atomic_is_lock_free(size: t.CSizeT, ptr: t.CVoid | t.CPtr) -> t.CBool | t.State: +def __atomic_is_lock_free(size: t.CSizeT, ptr: t.CVoid | t.CPtr) -> t.CBool: return t.CBool(1) diff --git a/includes/base64.py b/includes/base64.py index 899e2a8..bf18d0b 100644 --- a/includes/base64.py +++ b/includes/base64.py @@ -5,10 +5,10 @@ import t, c # Base64 编解码 纯裸实现 # ============================================== # Base64 编码对照表 -b64_tab: list[t.CChar, None] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" +b64_tab: t.CArray[t.CChar, None] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" # Base64 反向解码表,映射字符到索引值 -b64_dec_tab: list[t.CInt8T, 80] = [ +b64_dec_tab: t.CArray[t.CInt8T, 80] = [ 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, diff --git a/includes/binascii.py b/includes/binascii.py index 07b8b62..4c9b7b5 100644 --- a/includes/binascii.py +++ b/includes/binascii.py @@ -1,13 +1,13 @@ import t, c -HEX_CHARS: list[t.CChar, None] = "0123456789abcdef" -HEX_VALS: list[t.CInt, 256] +HEX_CHARS: t.CArray[t.CChar, None] = "0123456789abcdef" +HEX_VALS: t.CArray[t.CInt, 256] -B64_CHARS: list[t.CChar, None] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" -B64_VALS: list[t.CInt, 256] +B64_CHARS: t.CArray[t.CChar, None] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" +B64_VALS: t.CArray[t.CInt, 256] -HQX_CHARS: list[t.CChar, 64] = [ +HQX_CHARS: t.CArray[t.CChar, 64] = [ ' ', '!', chr(34), '#', '$', '%', '&', "'", '(', ')', '*', '+', ',', '-', '.', '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '@', @@ -16,11 +16,11 @@ HQX_CHARS: list[t.CChar, 64] = [ '[', chr(92), '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm' ] -HQX_VALS: list[t.CInt, 256] +HQX_VALS: t.CArray[t.CInt, 256] -UU_CHARS: list[t.CChar, None] = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_" +UU_CHARS: t.CArray[t.CChar, None] = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_" -CRC32_TABLE: list[t.CUnsignedInt, 256] = [ +CRC32_TABLE: t.CArray[t.CUnsignedInt, 256] = [ 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, @@ -55,7 +55,7 @@ CRC32_TABLE: list[t.CUnsignedInt, 256] = [ 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D ] -CRC_HQX_TABLE: list[t.CUnsignedShort, 256] = [ +CRC_HQX_TABLE: t.CArray[t.CUnsignedShort, 256] = [ 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, diff --git a/includes/condition.py b/includes/condition.py new file mode 100644 index 0000000..f999e4e --- /dev/null +++ b/includes/condition.py @@ -0,0 +1,53 @@ +import t, c +from stdint import * +from w32.win32base import * +from w32.win32sync import ( + CRITICAL_SECTION, + InitializeCriticalSection, EnterCriticalSection, LeaveCriticalSection, DeleteCriticalSection, + InitializeConditionVariable, SleepConditionVariableCS, + WakeConditionVariable, WakeAllConditionVariable +) + + +@t.Object +class Condition: + """基于 Windows 条件变量的条件变量,内部包含 CRITICAL_SECTION。 + + 用法: + cond: Condition = Condition() + with cond: + while not ready: + cond.wait() + cond.notify() + """ + cond_var: VOIDPTR + cs: CRITICAL_SECTION + + def __init__(self): + InitializeCriticalSection(c.Addr(self.cs)) + InitializeConditionVariable(c.Addr(self.cond_var)) + + def wait(self, timeout_ms: ULONG = INFINITE) -> BOOL: + return SleepConditionVariableCS(c.Addr(self.cond_var), c.Addr(self.cs), timeout_ms) + + def notify(self): + WakeConditionVariable(c.Addr(self.cond_var)) + + def notify_all(self): + WakeAllConditionVariable(c.Addr(self.cond_var)) + + def acquire(self): + EnterCriticalSection(c.Addr(self.cs)) + + def release(self): + LeaveCriticalSection(c.Addr(self.cs)) + + def __enter__(self) -> 'Condition' | t.CPtr: + self.acquire() + return self + + def __exit__(self): + self.release() + + def delete(self): + DeleteCriticalSection(c.Addr(self.cs)) diff --git a/includes/ctraits.pyi b/includes/ctraits.pyi new file mode 100644 index 0000000..9649dc0 --- /dev/null +++ b/includes/ctraits.pyi @@ -0,0 +1,20 @@ +"""ctraits — 编译时类型特征库 + +提供编译时类型判断函数,不纳入运行时编译。 +所有函数仅在编译时求值,可与 c.CIf 等编译时条件配合使用。 +""" +import t + + +def isptr(x: t.CType) -> bool: + """编译时判断 x 的类型是否为指针类型。 + + 返回 True 如果 x 是指针(ptr_count > 0),否则返回 False。 + 可与 c.CIf 配合使用实现条件编译。 + + 示例: + if c.CIf(ctraits.isptr(my_var)): + # 仅当 my_var 是指针类型时编译此分支 + ... + """ + pass diff --git a/includes/event.py b/includes/event.py new file mode 100644 index 0000000..449c06b --- /dev/null +++ b/includes/event.py @@ -0,0 +1,36 @@ +import t, c +from stdint import * +from w32.win32base import * +from w32.win32sync import CreateEventA, SetEvent, ResetEvent, WaitForSingleObject + + +@t.Object +class Event: + """基于 Windows Event 的事件对象,支持手动/自动重置。 + + 用法: + evt: Event = Event(FALSE, FALSE) + evt.set() + evt.wait() + """ + handle: HANDLE + manual_reset: BOOL + + def __init__(self, manual_reset: BOOL = FALSE, initial_state: BOOL = FALSE): + self.manual_reset = manual_reset + self.handle = CreateEventA(NULL, manual_reset, initial_state, NULL) + + def set(self): + SetEvent(self.handle) + + def clear(self): + ResetEvent(self.handle) + + def is_set(self) -> BOOL: + return WaitForSingleObject(self.handle, 0) == WAIT_OBJECT_0 + + def wait(self, timeout_ms: ULONG = INFINITE) -> BOOL: + return WaitForSingleObject(self.handle, timeout_ms) == WAIT_OBJECT_0 + + def close(self): + CloseHandle(self.handle) diff --git a/includes/hashlib/__md5.py b/includes/hashlib/__md5.py index 63ed23c..a3bfebc 100644 --- a/includes/hashlib/__md5.py +++ b/includes/hashlib/__md5.py @@ -16,7 +16,7 @@ def md5_I(x: t.CUInt32T, y: t.CUInt32T, z: t.CUInt32T) -> t.CUInt32T: return y ^ def md5_rotl(x: t.CUInt32T, n: t.CInt) -> t.CUInt32T: return (x << n) | (x >> (32 - n)) # MD5 常量表、移位表 -md5_T: list[t.CUInt32T, 64] = [ +md5_T: t.CArray[t.CUInt32T, 64] = [ 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, @@ -27,7 +27,7 @@ md5_T: list[t.CUInt32T, 64] = [ 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 ] -md5_S: list[t.CInt, 64] = [ +md5_S: t.CArray[t.CInt, 64] = [ 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, @@ -37,9 +37,9 @@ md5_S: list[t.CInt, 64] = [ # MD5 上下文结构体 @t.Object class md5: - state: list[t.CUInt32T, 4] # 4个32位状态寄存器 + state: t.CArray[t.CUInt32T, 4] # 4个32位状态寄存器 count: t.CUInt64T # 已处理比特数 - buf: list[t.CUInt8T, MD5_BLOCK_LEN] # 分组缓冲区 + buf: t.CArray[t.CUInt8T, MD5_BLOCK_LEN] # 分组缓冲区 # 初始化MD5上下文 def __init__(self): memset(self.buf, 0, MD5_BLOCK_LEN) @@ -54,7 +54,7 @@ class md5: b: t.CUInt32T = self.state[1] c: t.CUInt32T = self.state[2] d: t.CUInt32T = self.state[3] - w: list[t.CUInt32T, 16] + w: t.CArray[t.CUInt32T, 16] # 字节序转32位字 for i in range(16): w[i] = ((t.CUInt32T(block[i * 4 + 0]) << 0) | @@ -105,7 +105,7 @@ class md5: if length > 0: memcpy(self.buf + idx, data, length) # 结束计算,输出16字节摘要 - def final(self, out: list[t.CUInt8T, MD5_DIGEST_LEN]): + def final(self, out: t.CArray[t.CUInt8T, MD5_DIGEST_LEN]): idx: t.CSizeT = self.count % MD5_BLOCK_LEN # 填充0x80结尾 self.buf[idx] = 0x80 diff --git a/includes/hashlib/__sha1.py b/includes/hashlib/__sha1.py index 5c2f8ca..5f97b18 100644 --- a/includes/hashlib/__sha1.py +++ b/includes/hashlib/__sha1.py @@ -17,9 +17,9 @@ def sha1_f3(b: t.CUInt32T, c: t.CUInt32T, d: t.CUInt32T) -> t.CUInt32T: return ( # SHA1 上下文 @t.Object class sha1: - state: list[t.CUInt32T, 5] + state: t.CArray[t.CUInt32T, 5] count: t.CUInt64T - buf: list[t.CUInt8T, SHA1_BLOCK_LEN] + buf: t.CArray[t.CUInt8T, SHA1_BLOCK_LEN] def __init__(self): memset(self.buf, 0, SHA1_BLOCK_LEN) self.state[0] = 0x67452301 @@ -30,7 +30,7 @@ class sha1: self.count = 0 # 单分组压缩 def transform(self, block: t.CUInt8T | t.CPtr): - w: list[t.CUInt32T, 80] + w: t.CArray[t.CUInt32T, 80] data: t.CUInt8T | t.CPtr = block # 前16个字 for i in range(16): @@ -97,7 +97,7 @@ class sha1: length -= SHA1_BLOCK_LEN if length > 0: memcpy(self.buf + idx, data, length) - def final(self, out: list[t.CUInt8T, SHA1_DIGEST_LEN]): + def final(self, out: t.CArray[t.CUInt8T, SHA1_DIGEST_LEN]): idx: t.CSizeT = self.count % SHA1_BLOCK_LEN self.buf[idx] = 0x80 idx += 1 diff --git a/includes/hashlib/__sha256.py b/includes/hashlib/__sha256.py index 698d4f3..718a3c2 100644 --- a/includes/hashlib/__sha256.py +++ b/includes/hashlib/__sha256.py @@ -8,7 +8,7 @@ SHA256_BLOCK_LEN: t.CDefine = 64 SHA256_DIGEST_LEN: t.CDefine = 32 # SHA256 常量K -sha256_K: list[t.CUInt32T, 64] = [ +sha256_K: t.CArray[t.CUInt32T, 64] = [ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, @@ -30,9 +30,9 @@ def Maj(x: t.CUInt32T, y: t.CUInt32T, z: t.CUInt32T) -> t.CUInt32T: return (x & # SHA256 上下文 @t.Object class sha256: - state: list[t.CUInt32T, 8] + state: t.CArray[t.CUInt32T, 8] count: t.CUInt64T - buf: list[t.CUInt8T, SHA256_BLOCK_LEN] + buf: t.CArray[t.CUInt8T, SHA256_BLOCK_LEN] def __init__(self): memset(self, 0, sha256.__sizeof__()) self.state[0] = 0x6a09e667 @@ -47,7 +47,7 @@ class sha256: # memset(self.buf, 0, SHA256_BLOCK_LEN) # 单分组压缩 def transform(self, block: t.CUInt8T | t.CPtr): - w: list[t.CUInt32T, 64] + w: t.CArray[t.CUInt32T, 64] for i in range(16): w[i] = ((t.CUInt32T(block[i * 4 + 0]) << 24) | (t.CUInt32T(block[i * 4 + 1]) << 16) | @@ -102,7 +102,7 @@ class sha256: length -= SHA256_BLOCK_LEN if length > 0: memcpy(self.buf + idx, data, length) - def final(self, out: list[t.CUInt8T, SHA256_DIGEST_LEN]): + def final(self, out: t.CArray[t.CUInt8T, SHA256_DIGEST_LEN]): idx: t.CSizeT = self.count % SHA256_BLOCK_LEN self.buf[idx] = 0x80 idx += 1 diff --git a/includes/hashlib/__sha512.py b/includes/hashlib/__sha512.py index 3ca787b..3db4c86 100644 --- a/includes/hashlib/__sha512.py +++ b/includes/hashlib/__sha512.py @@ -16,7 +16,7 @@ def sha512_BigSigma1(x: t.CUInt64T) -> t.CUInt64T: return sha512_ror(x, 14) ^ sh def sha512_Sigma0(x: t.CUInt64T) -> t.CUInt64T: return sha512_ror(x, 1) ^ sha512_ror(x, 8) ^ sha512_shr(x, 7) def sha512_Sigma1(x: t.CUInt64T) -> t.CUInt64T: return sha512_ror(x, 19) ^ sha512_ror(x, 61) ^ sha512_shr(x, 6) -sha512_K: list[t.CUInt64T, 80] = [ +sha512_K: t.CArray[t.CUInt64T, 80] = [ 0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc, 0x3956c25bf348b538, 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118, 0xd807aa98a3030242, 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2, @@ -41,9 +41,9 @@ sha512_K: list[t.CUInt64T, 80] = [ @t.Object class sha512: - state: list[t.CUInt64T, 8] - count: list[t.CUInt64T, 2] - buf: list[t.CUInt8T, SHA512_BLOCK_LEN] + state: t.CArray[t.CUInt64T, 8] + count: t.CArray[t.CUInt64T, 2] + buf: t.CArray[t.CUInt8T, SHA512_BLOCK_LEN] def __init__(self): memset(self, 0, sha512.__sizeof__()) self.state[0] = 0x6a09e667f3bcc908 @@ -54,8 +54,8 @@ class sha512: self.state[5] = 0x9b05688c2b3e6c1f self.state[6] = 0x1f83d9abfb41bd6b self.state[7] = 0x5be0cd19137e2179 - def transform(self, block: list[t.CUInt8T, SHA512_BLOCK_LEN]): - w: list[t.CUInt64T, 80] + def transform(self, block: t.CArray[t.CUInt8T, SHA512_BLOCK_LEN]): + w: t.CArray[t.CUInt64T, 80] a: t.CUInt64T b: t.CUInt64T c: t.CUInt64T @@ -121,7 +121,7 @@ class sha512: length -= SHA512_BLOCK_LEN if length > 0: memcpy(self.buf + idx, data, length) - def final(self, out: list[t.CUInt8T, SHA512_DIGEST_LEN]): + def final(self, out: t.CArray[t.CUInt8T, SHA512_DIGEST_LEN]): bits_lo: t.CUInt64T = self.count[0] << 3 bits_hi: t.CUInt64T = (self.count[1] << 3) | (self.count[0] >> 61) idx: t.CUInt32T = t.CUInt32T(self.count[0] % SHA512_BLOCK_LEN) diff --git a/includes/lock.py b/includes/lock.py new file mode 100644 index 0000000..b3ce100 --- /dev/null +++ b/includes/lock.py @@ -0,0 +1,39 @@ +import t, c +from stdint import * +from w32.win32base import * +from w32.win32sync import CRITICAL_SECTION, InitializeCriticalSection, EnterCriticalSection, LeaveCriticalSection, DeleteCriticalSection, TryEnterCriticalSection + + +@t.Object +class Lock: + """基于 CRITICAL_SECTION 的互斥锁,支持递归加锁。 + + 用法: + lock: Lock = Lock() + with lock: + # 临界区 + pass + """ + cs: CRITICAL_SECTION + + def __init__(self): + InitializeCriticalSection(c.Addr(self.cs)) + + def acquire(self): + EnterCriticalSection(c.Addr(self.cs)) + + def release(self): + LeaveCriticalSection(c.Addr(self.cs)) + + def try_acquire(self) -> BOOL: + return TryEnterCriticalSection(c.Addr(self.cs)) + + def __enter__(self) -> 'Lock' | t.CPtr: + self.acquire() + return self + + def __exit__(self): + self.release() + + def delete(self): + DeleteCriticalSection(c.Addr(self.cs)) diff --git a/includes/mbuddy.py b/includes/mbuddy.py new file mode 100644 index 0000000..e551fc3 --- /dev/null +++ b/includes/mbuddy.py @@ -0,0 +1,374 @@ +import t, c +from stdint import * +import string +import atom + +# 伙伴系统内存分配器 +# 支持可变大小分配 (malloc/free/calloc/realloc) +# 通过二分块 (buddy splitting) 和合并 (coalescing) 管理内存 +# 使用 atom 库的原子操作实现自旋锁 (线程安全) + +MBUDDY_MIN_BLOCK: t.CDefine = 32 # 最小块大小 (字节),需 >= 16 以容纳链表指针 +MBUDDY_MAX_ORDERS: t.CDefine = 32 # 最大阶数数量 +MBUDDY_HEADER_SIZE: t.CDefine = 8 # 块头大小 (存储阶数) + + +def _largest_pow2_le(val: t.CSizeT) -> t.CSizeT: + """返回 <= val 的最大 2 的幂""" + if val == 0: return 0 + p: t.CSizeT = 1 + while p * 2 <= val: + p = p * 2 + return p + + +def _block_size_at_order(order: t.CInt) -> t.CSizeT: + """返回指定阶数的块大小""" + bs: t.CSizeT = MBUDDY_MIN_BLOCK + i: t.CInt + for i in range(order): + bs = bs << 1 + return bs + + +class MBuddy: + # 编译期元数据:声明此类在 with 上下文中提供 __mbuddy__ 字段 + __provides__: list[str] = ['__mbuddy__'] + mem: t.CVoid | t.CPtr # 可用内存基址 + mem_size: t.CSizeT # 可用内存大小 (2 的幂) + max_order: t.CInt # 最大阶数 + free_lists: t.CUInt64T | t.CPtr # 空闲链头数组 (存储在 arena 开头) + lock_val: t.CVolatile | t.CInt # 自旋锁标志 (0=未锁, 1=已锁) + + def __init__(self, arena: t.CVoid | t.CPtr, arena_size: t.CSizeT): + # 初始化自旋锁 + self.lock_val = 0 + # 空闲链数组放在 arena 开头 + fl_bytes: t.CSizeT = (MBUDDY_MAX_ORDERS + 1) * 8 + self.free_lists = arena + + # 初始化所有空闲链头为 0 (NULL) + i: t.CInt + for i in range(MBUDDY_MAX_ORDERS + 1): + self.free_lists[i] = 0 + + # 计算可用区域 + if arena_size <= fl_bytes: + self.mem = None + self.mem_size = 0 + self.max_order = 0 + return + + remaining: t.CSizeT = arena_size - fl_bytes + usable: t.CSizeT = _largest_pow2_le(remaining) + + if usable < MBUDDY_MIN_BLOCK: + self.mem = None + self.mem_size = 0 + self.max_order = 0 + return + + self.mem = t.CVoid(t.CUInt64T(arena) + fl_bytes, t.CPtr) + self.mem_size = usable + + # 计算 max_order: log2(usable / MIN_BLOCK) + self.max_order = 0 + bs: t.CSizeT = MBUDDY_MIN_BLOCK + while bs < usable: + bs = bs << 1 + self.max_order += 1 + + # 将整个可用区域作为一个 max_order 阶的空闲块加入空闲链 + self._fl_push(self.max_order, self.mem) + + def __enter__(self) -> 'MBuddy' | t.CPtr: + return self + + def __exit__(self): + self.reset() + + def reset(self): + """重置分配器: 清空所有空闲链,将整个可用区域作为单个大块归还""" + if self.mem == None: + return + # 清空所有空闲链头 + i: t.CInt + for i in range(MBUDDY_MAX_ORDERS + 1): + self.free_lists[i] = 0 + # 将整个可用区域作为单个 max_order 阶块加入 + self._fl_push(self.max_order, self.mem) + + # === 空闲链操作 === + + def _fl_push(self, order: t.CInt, block: t.CVoid | t.CPtr): + """将块压入指定阶数的空闲链头部""" + old_head: t.CUInt64T = self.free_lists[order] + c.DerefAs(block, t.CVoid(old_head, t.CPtr)) + self.free_lists[order] = t.CUInt64T(block) + + def _fl_pop(self, order: t.CInt) -> t.CVoid | t.CPtr: + """从指定阶数的空闲链头部弹出块""" + head_val: t.CUInt64T = self.free_lists[order] + if head_val == 0: + return None + block: t.CVoid | t.CPtr = t.CVoid(head_val, t.CPtr) + next_ptr: t.CVoid | t.CPtr = t.CVoid(c.Deref(t.CUInt64T(block, t.CPtr)), t.CPtr) + self.free_lists[order] = t.CUInt64T(next_ptr) + return block + + def _fl_find_and_remove(self, order: t.CInt, target: t.CVoid | t.CPtr) -> t.CInt: + """在指定阶数的空闲链中查找并移除 target 块。返回 1=找到, 0=未找到""" + head_val: t.CUInt64T = self.free_lists[order] + if head_val == 0: + return 0 + + head: t.CVoid | t.CPtr = t.CVoid(head_val, t.CPtr) + if t.CUInt64T(head) == t.CUInt64T(target): + next_ptr: t.CVoid | t.CPtr = t.CVoid(c.Deref(t.CUInt64T(head, t.CPtr)), t.CPtr) + self.free_lists[order] = t.CUInt64T(next_ptr) + return 1 + + prev: t.CVoid | t.CPtr = head + cur: t.CVoid | t.CPtr = t.CVoid(c.Deref(t.CUInt64T(head, t.CPtr)), t.CPtr) + while cur != None: + if t.CUInt64T(cur) == t.CUInt64T(target): + next_ptr: t.CVoid | t.CPtr = t.CVoid(c.Deref(t.CUInt64T(cur, t.CPtr)), t.CPtr) + c.DerefAs(prev, next_ptr) + return 1 + prev = cur + cur = t.CVoid(c.Deref(t.CUInt64T(cur, t.CPtr)), t.CPtr) + + return 0 + + # === 伙伴系统核心操作 === + + def _buddy_of(self, block: t.CVoid | t.CPtr, order: t.CInt) -> t.CVoid | t.CPtr: + """计算指定块的伙伴块地址""" + offset: t.CSizeT = t.CUInt64T(block) - t.CUInt64T(self.mem) + bs: t.CSizeT = _block_size_at_order(order) + buddy_offset: t.CSizeT = offset ^ bs + return t.CVoid(t.CUInt64T(self.mem) + buddy_offset, t.CPtr) + + def _order_for_size(self, size: t.CSizeT) -> t.CInt: + """返回使 MIN_BLOCK << order >= size 的最小阶数""" + order: t.CInt = 0 + bs: t.CSizeT = MBUDDY_MIN_BLOCK + while bs < size: + bs = bs << 1 + order += 1 + return order + + def _split_to_order(self, to_order: t.CInt) -> t.CVoid | t.CPtr: + """找到可用块并分裂到目标阶数。返回块指针或 None""" + # 寻找第一个有空闲块的阶数 >= to_order + found_order: t.CInt = to_order + while found_order <= self.max_order: + if self.free_lists[found_order] != 0: + break + found_order += 1 + + if found_order > self.max_order: + return None + + # 弹出块 + block: t.CVoid | t.CPtr = self._fl_pop(found_order) + + # 逐级分裂到 to_order + while found_order > to_order: + found_order -= 1 + bs: t.CSizeT = _block_size_at_order(found_order) + buddy: t.CVoid | t.CPtr = t.CVoid(t.CUInt64T(block) + bs, t.CPtr) + self._fl_push(found_order, buddy) + + return block + + def _coalesce(self, block: t.CVoid | t.CPtr, order: t.CInt): + """尝试与伙伴合并,递归直到无法合并""" + while order < self.max_order: + buddy: t.CVoid | t.CPtr = self._buddy_of(block, order) + found: t.CInt = self._fl_find_and_remove(order, buddy) + if found == 0: + break + # 使用地址较低的一半作为合并后的块 + if t.CUInt64T(buddy) < t.CUInt64T(block): + block = buddy + order += 1 + + self._fl_push(order, block) + + def _is_valid_ptr(self, ptr: t.CVoid | t.CPtr) -> t.CInt: + """验证指针是否为有效的已分配块指针。返回 1=有效, 0=无效""" + if ptr == None: + return 0 + if self.mem == None: + return 0 + block: t.CVoid | t.CPtr = t.CVoid(t.CUInt64T(ptr) - MBUDDY_HEADER_SIZE, t.CPtr) + # 检查范围 + if t.CUInt64T(block) < t.CUInt64T(self.mem): + return 0 + if t.CUInt64T(block) >= t.CUInt64T(self.mem) + self.mem_size: + return 0 + # 检查对齐 (所有块都 MIN_BLOCK 对齐) + offset: t.CSizeT = t.CUInt64T(block) - t.CUInt64T(self.mem) + if offset % MBUDDY_MIN_BLOCK != 0: + return 0 + # 读取头部编码值: (order << 1) | allocated_flag + stored: t.CVoid | t.CPtr = t.CVoid(c.Deref(t.CUInt64T(block, t.CPtr)), t.CPtr) + stored_val: t.CUInt64T = t.CUInt64T(stored) + # 检查 allocated 标志位 (bit 0 = 1 表示已分配) + if (stored_val & 1) == 0: + return 0 # 未分配或已释放 (双重 free 检测) + # 提取阶数 + order: t.CInt = t.CInt(stored_val >> 1) + if order < 0: + return 0 + if order > self.max_order: + return 0 + return 1 + + def _fl_count(self, order: t.CInt) -> t.CSizeT: + """统计指定阶数空闲链中的块数""" + count: t.CSizeT = 0 + cur_val: t.CUInt64T = self.free_lists[order] + while cur_val != 0: + count += 1 + cur: t.CVoid | t.CPtr = t.CVoid(cur_val, t.CPtr) + cur_val = t.CUInt64T(t.CVoid(c.Deref(t.CUInt64T(cur, t.CPtr)), t.CPtr)) + return count + + # === 公共 API === + + def _lock(self): + """自旋锁: 原子测试并设置 lock_val,旧值为 1 时自旋等待""" + while atom.__atomic_test_and_set(c.Addr(self.lock_val), atom.ATOMIC_ACQUIRE): + pass + + def _unlock(self): + """解锁: 原子清除 lock_val""" + atom.__atomic_clear(c.Addr(self.lock_val), atom.ATOMIC_RELEASE) + + def alloc(self, size: t.CSizeT) -> t.CVoid | t.CPtr: + """分配至少 size 字节的内存。返回用户数据指针或 None (线程安全)""" + self._lock() + result: t.CVoid | t.CPtr = None + if self.mem != None: + if size != 0: + needed: t.CSizeT = size + MBUDDY_HEADER_SIZE + order: t.CInt = self._order_for_size(needed) + if order <= self.max_order: + block: t.CVoid | t.CPtr = self._split_to_order(order) + if block != None: + c.DerefAs(block, t.CVoid(t.CUInt64T((order << 1) | 1), t.CPtr)) + result = t.CVoid(t.CUInt64T(block) + MBUDDY_HEADER_SIZE, t.CPtr) + self._unlock() + return result + + def free(self, ptr: t.CVoid | t.CPtr): + """释放之前分配的内存。非法指针将被忽略 (线程安全)""" + self._lock() + if ptr != None: + if self._is_valid_ptr(ptr) != 0: + # 从头部读取阶数 (编码: (order << 1) | 1) + block: t.CVoid | t.CPtr = t.CVoid(t.CUInt64T(ptr) - MBUDDY_HEADER_SIZE, t.CPtr) + stored: t.CVoid | t.CPtr = t.CVoid(c.Deref(t.CUInt64T(block, t.CPtr)), t.CPtr) + stored_val: t.CUInt64T = t.CUInt64T(stored) + order: t.CInt = t.CInt(stored_val >> 1) + # 清除 allocated 标志,防止双重 free + c.DerefAs(block, t.CVoid(0, t.CPtr)) + # 合并并加入空闲链 + self._coalesce(block, order) + self._unlock() + + def calloc(self, count: t.CSizeT, size: t.CSizeT) -> t.CVoid | t.CPtr: + """分配 count*size 字节并清零""" + total: t.CSizeT = count * size + ptr: t.CVoid | t.CPtr = self.alloc(total) + if ptr != None: + string.memset(ptr, 0, total) + return ptr + + def realloc(self, ptr: t.CVoid | t.CPtr, new_size: t.CSizeT) -> t.CVoid | t.CPtr: + """重新分配内存大小""" + if ptr == None: + return self.alloc(new_size) + if new_size == 0: + self.free(ptr) + return None + if self._is_valid_ptr(ptr) == 0: + return None # 非法指针 + + # 读取旧阶数 (编码: (order << 1) | 1) + block: t.CVoid | t.CPtr = t.CVoid(t.CUInt64T(ptr) - MBUDDY_HEADER_SIZE, t.CPtr) + stored: t.CVoid | t.CPtr = t.CVoid(c.Deref(t.CUInt64T(block, t.CPtr)), t.CPtr) + stored_val: t.CUInt64T = t.CUInt64T(stored) + old_order: t.CInt = t.CInt(stored_val >> 1) + + # 计算新阶数 + needed: t.CSizeT = new_size + MBUDDY_HEADER_SIZE + new_order: t.CInt = self._order_for_size(needed) + + # 如果新阶数 <= 旧阶数,无需重新分配 + if new_order <= old_order: + return ptr + + # 分配新块 + new_ptr: t.CVoid | t.CPtr = self.alloc(new_size) + if new_ptr == None: + return ptr # 保留旧块 + + # 复制旧数据 + old_block_size: t.CSizeT = _block_size_at_order(old_order) + old_data_size: t.CSizeT = old_block_size - MBUDDY_HEADER_SIZE + string.memcpy(new_ptr, ptr, old_data_size) + + # 释放旧块 + self.free(ptr) + return new_ptr + + def stats(self) -> t.CSizeT: + """返回总可用内存大小""" + return self.mem_size + + def free_count(self) -> t.CSizeT: + """统计所有空闲链中的总块数""" + total: t.CSizeT = 0 + i: t.CInt + for i in range(self.max_order + 1): + total += self._fl_count(i) + return total + + def self_check(self) -> t.CInt: + """自检: 遍历所有空闲链,验证块的范围、对齐和阶数一致性。返回错误数 (0=正常)""" + if self.mem == None: + return 0 + errors: t.CInt = 0 + order: t.CInt + for order in range(self.max_order + 1): + bs: t.CSizeT = _block_size_at_order(order) + max_in_order: t.CSizeT = self.mem_size / bs + 1 + seen: t.CSizeT = 0 + cur_val: t.CUInt64T = self.free_lists[order] + while cur_val != 0: + seen += 1 + if seen > max_in_order: + errors += 1 + break + cur: t.CVoid | t.CPtr = t.CVoid(cur_val, t.CPtr) + # 检查范围 + if t.CUInt64T(cur) < t.CUInt64T(self.mem): + errors += 1 + break + if t.CUInt64T(cur) >= t.CUInt64T(self.mem) + self.mem_size: + errors += 1 + break + # 检查对齐 + offset: t.CSizeT = t.CUInt64T(cur) - t.CUInt64T(self.mem) + if offset % MBUDDY_MIN_BLOCK != 0: + errors += 1 + break + # 检查阶数一致性: 块偏移应是其块大小的倍数 + if offset % bs != 0: + errors += 1 + break + cur_val = t.CUInt64T(t.CVoid(c.Deref(t.CUInt64T(cur, t.CPtr)), t.CPtr)) + return errors diff --git a/includes/mpool.py b/includes/mpool.py index 5999cb4..89e525e 100644 --- a/includes/mpool.py +++ b/includes/mpool.py @@ -5,7 +5,7 @@ import string MPOOL_ALIGN: t.CDefine = 8 MPOOL_TYPE_SLAB: t.CDefine = 0 -MPOOL_TYPE_BUMP: t.CDefine = 2 +MPOOL_TYPE_BUMP: t.CDefine = 1 def _align_up(val: t.CSizeT, align: t.CSizeT) -> t.CSizeT: @@ -39,7 +39,6 @@ class MPool: self.alloc_map = None self.alloc_map_size = 0 - if mem == None: return if block_size > 0: self._init_slab(mem, mem_size, block_size) else: @@ -113,9 +112,7 @@ class MPool: def alloc(self, size: t.CSizeT) -> t.CVoid | t.CPtr: if self.mtype == MPOOL_TYPE_SLAB: return self._slab_alloc() - if self.mtype == MPOOL_TYPE_BUMP: - return self._bump_alloc(size) - return None + return self._bump_alloc(size) def alloc_buf(self, capacity: t.CSizeT) -> viperio.Buf | t.CPtr: ptr: t.CVoid | t.CPtr = self.alloc(capacity) diff --git a/includes/numpy/__init__.py b/includes/numpy/__init__.py index 328d033..fb39839 100644 --- a/includes/numpy/__init__.py +++ b/includes/numpy/__init__.py @@ -27,8 +27,8 @@ e: t.CDefine = 2.71828182845904523536 @t.Object class ndarray: data: t.CDouble | t.CPtr - shape: list[t.CSizeT, MAX_NDIM] - strides: list[t.CSizeT, MAX_NDIM] + shape: t.CArray[t.CSizeT, MAX_NDIM] + strides: t.CArray[t.CSizeT, MAX_NDIM] ndim: t.CInt size: t.CSizeT owns_data: t.CInt diff --git a/includes/rwlock.py b/includes/rwlock.py new file mode 100644 index 0000000..0166bfb --- /dev/null +++ b/includes/rwlock.py @@ -0,0 +1,46 @@ +import t, c +from stdint import * +from w32.win32base import * +from w32.win32sync import ( + InitializeSRWLock, + AcquireSRWLockExclusive, ReleaseSRWLockExclusive, + AcquireSRWLockShared, ReleaseSRWLockShared +) + + +@t.Object +class RWLock: + """基于 SRWLock 的读写锁,支持多读单写,不支持递归。 + + 用法: + rwlock: RWLock = RWLock() + rwlock.acquire_read() + # ... 读取共享数据 + rwlock.release_read() + rwlock.acquire_write() + # ... 修改共享数据 + rwlock.release_write() + """ + lock: VOIDPTR + + def __init__(self): + InitializeSRWLock(c.Addr(self.lock)) + + def acquire_read(self): + AcquireSRWLockShared(c.Addr(self.lock)) + + def release_read(self): + ReleaseSRWLockShared(c.Addr(self.lock)) + + def acquire_write(self): + AcquireSRWLockExclusive(c.Addr(self.lock)) + + def release_write(self): + ReleaseSRWLockExclusive(c.Addr(self.lock)) + + def __enter__(self) -> 'RWLock' | t.CPtr: + self.acquire_write() + return self + + def __exit__(self): + self.release_write() diff --git a/includes/spinlock.py b/includes/spinlock.py index df7d3c8..4208a1b 100644 --- a/includes/spinlock.py +++ b/includes/spinlock.py @@ -5,7 +5,7 @@ import atom @t.Object class _spinlock: locked: t.CVolatile | t.CInt - name: list[t.CChar, 32] + name: t.CArray[t.CChar, 32] def __init__(self): self.locked = 0 diff --git a/includes/stdint.py b/includes/stdint.py index bc12f01..b9d54ce 100644 --- a/includes/stdint.py +++ b/includes/stdint.py @@ -70,3 +70,13 @@ CHAR32: t.CTypedef = t.CChar32T CHAR8PTR: t.CTypedef = t.CChar8T | t.CPtr CHAR16PTR: t.CTypedef = t.CChar16T | t.CPtr CHAR32PTR: t.CTypedef = t.CChar32T | t.CPtr + +i8: t.CTypedef = t.CInt8T +i16: t.CTypedef = t.CInt16T +i32: t.CTypedef = t.CInt32T +i64: t.CTypedef = t.CInt64T + +u8: t.CTypedef = t.CUInt8T +u16: t.CTypedef = t.CUInt16T +u32: t.CTypedef = t.CUInt32T +u64: t.CTypedef = t.CUInt64T diff --git a/includes/string.py b/includes/string.py index 016596b..d806d89 100644 --- a/includes/string.py +++ b/includes/string.py @@ -289,7 +289,7 @@ def atof(src: str) -> t.CDouble: exp += 1 return result -def split(s: str, delim: str, result: list[str]) -> int: +def split(s: str, delim: str, result: t.CArray[str]) -> int: count: int = 0 start: str = s if not s or not delim or not result: diff --git a/includes/testcheck.py b/includes/testcheck.py new file mode 100644 index 0000000..68c13d9 --- /dev/null +++ b/includes/testcheck.py @@ -0,0 +1,54 @@ +# testcheck - 回归测试格式化输出库 +# 提供 PASS/FAIL 计数、分节标题、汇总报告 +import t, c +import stdio + +_pass_count: t.CInt = 0 +_fail_count: t.CInt = 0 + + +def begin(name: str): + """开始测试套件,打印头部并重置计数器""" + global _pass_count, _fail_count + _pass_count = 0 + _fail_count = 0 + stdio.printf("=== %s ===\n\n", name) + + +def section(name: str): + """打印分节标题""" + stdio.printf("--- %s ---\n", name) + + +def ok(msg: str): + """打印 PASS 并计数""" + global _pass_count + _pass_count += 1 + stdio.printf("PASS: %s\n", msg) + + +def fail(msg: str): + """打印 FAIL 并计数""" + global _fail_count + _fail_count += 1 + stdio.printf("FAIL: %s\n", msg) + + +def check(cond: t.CInt, ok_msg: str, fail_msg: str): + """条件检查,自动选择 PASS/FAIL""" + if cond: + ok(ok_msg) + else: + fail(fail_msg) + + +def info(msg: str): + """打印信息消息(不计入 PASS/FAIL)""" + stdio.printf("%s\n", msg) + + +def end() -> t.CInt: + """打印汇总,返回失败数""" + stdio.printf("\n--- Summary ---\n") + stdio.printf("PASS: %d, FAIL: %d\n", _pass_count, _fail_count) + return _fail_count diff --git a/includes/viperlib.py b/includes/viperlib.py index d4f2b8f..fd791d8 100644 --- a/includes/viperlib.py +++ b/includes/viperlib.py @@ -24,7 +24,7 @@ def snprintf(buf: t.CChar | t.CPtr, size: t.CSizeT, fmt: str, *args) -> t.CInt | if buf == None or fmt == None or size == 0: return 0 ptr: t.CChar | t.CPtr = buf write_count: t.CInt = 0 - temp: list[t.CChar, 24] + temp: t.CArray[t.CChar, 24] temp[0] = '\t' while c.Deref(fmt) != 0 and write_count < size - 1: if c.Deref(fmt) != 37: diff --git a/includes/vrandom.py b/includes/vrandom.py new file mode 100644 index 0000000..55356b9 --- /dev/null +++ b/includes/vrandom.py @@ -0,0 +1,379 @@ +# vrandom - 硬件随机数生成库 +# 基于 x86 RDRAND / RDSEED 指令,使用内嵌汇编实现 +import t, c +import vipermath + + +# 重试次数限制(RDRAND 通常不需要重试,RDSEED 可能需要) +RDRAND_RETRY_LIMIT: t.CDefine = 10 +RDSEED_RETRY_LIMIT: t.CDefine = 100 + + +# ============================================================ +# RDRAND - 硬件随机数(伪随机数发生器输出) +# ============================================================ + +def rdrand16() -> t.CUInt16T: + val: t.CUInt32T = 0 + c.Asm(f"rdrand {c.AsmOut(val, t.ASM_DESCR.OUTPUT_REG)}", + out=[c.AsmOut(val, t.ASM_DESCR.OUTPUT_REG)], + op=[t.ASM_DESCR.CLOBBER_CC]) + return t.CUInt16T(val) + + +def rdrand32() -> t.CUInt32T: + val: t.CUInt32T = 0 + c.Asm(f"rdrand {c.AsmOut(val, t.ASM_DESCR.OUTPUT_REG)}", + out=[c.AsmOut(val, t.ASM_DESCR.OUTPUT_REG)], + op=[t.ASM_DESCR.CLOBBER_CC]) + return val + + +def rdrand64() -> t.CUInt64T: + val: t.CUInt64T = 0 + c.Asm(f"rdrand {c.AsmOut(val, t.ASM_DESCR.OUTPUT_REG)}", + out=[c.AsmOut(val, t.ASM_DESCR.OUTPUT_REG)], + op=[t.ASM_DESCR.CLOBBER_CC]) + return val + + +# ============================================================ +# RDSEED - 硬件随机种子(熵源直接输出) +# ============================================================ + +def rdseed16() -> t.CUInt16T: + val: t.CUInt32T = 0 + c.Asm(f"rdseed {c.AsmOut(val, t.ASM_DESCR.OUTPUT_REG)}", + out=[c.AsmOut(val, t.ASM_DESCR.OUTPUT_REG)], + op=[t.ASM_DESCR.CLOBBER_CC]) + return t.CUInt16T(val) + + +def rdseed32() -> t.CUInt32T: + val: t.CUInt32T = 0 + c.Asm(f"rdseed {c.AsmOut(val, t.ASM_DESCR.OUTPUT_REG)}", + out=[c.AsmOut(val, t.ASM_DESCR.OUTPUT_REG)], + op=[t.ASM_DESCR.CLOBBER_CC]) + return val + + +def rdseed64() -> t.CUInt64T: + val: t.CUInt64T = 0 + c.Asm(f"rdseed {c.AsmOut(val, t.ASM_DESCR.OUTPUT_REG)}", + out=[c.AsmOut(val, t.ASM_DESCR.OUTPUT_REG)], + op=[t.ASM_DESCR.CLOBBER_CC]) + return val + + +# ============================================================ +# Step 版本(带成功标志,匹配 GCC builtin 接口) +# 返回 1 表示成功,0 表示失败;随机值写入 *p +# ============================================================ + +def rdrand16_step(p: t.CUInt16T | t.CPtr) -> t.CInt: + val: t.CUInt32T = 0 + ok: t.CUInt32T = 0 + c.Asm(f"""rdrand {c.AsmOut(val, t.ASM_DESCR.OUTPUT_REG)} + setc al + movzx {c.AsmOut(ok, t.ASM_DESCR.OUTPUT_REG)}, al""", + out=[c.AsmOut(val, t.ASM_DESCR.OUTPUT_REG), c.AsmOut(ok, t.ASM_DESCR.OUTPUT_REG)], + op=[t.ASM_DESCR.CLOBBER_CC, t.ASM_DESCR.CLOBBER_AL]) + p[0] = t.CUInt16T(val) + return t.CInt(ok) + + +def rdrand32_step(p: t.CUInt32T | t.CPtr) -> t.CInt: + val: t.CUInt32T = 0 + ok: t.CUInt32T = 0 + c.Asm(f"""rdrand {c.AsmOut(val, t.ASM_DESCR.OUTPUT_REG)} + setc al + movzx {c.AsmOut(ok, t.ASM_DESCR.OUTPUT_REG)}, al""", + out=[c.AsmOut(val, t.ASM_DESCR.OUTPUT_REG), c.AsmOut(ok, t.ASM_DESCR.OUTPUT_REG)], + op=[t.ASM_DESCR.CLOBBER_CC, t.ASM_DESCR.CLOBBER_AL]) + p[0] = val + return t.CInt(ok) + + +def rdrand64_step(p: t.CUInt64T | t.CPtr) -> t.CInt: + val: t.CUInt64T = 0 + ok: t.CUInt32T = 0 + c.Asm(f"""rdrand {c.AsmOut(val, t.ASM_DESCR.OUTPUT_REG)} + setc al + movzx {c.AsmOut(ok, t.ASM_DESCR.OUTPUT_REG)}, al""", + out=[c.AsmOut(val, t.ASM_DESCR.OUTPUT_REG), c.AsmOut(ok, t.ASM_DESCR.OUTPUT_REG)], + op=[t.ASM_DESCR.CLOBBER_CC, t.ASM_DESCR.CLOBBER_AL]) + p[0] = val + return t.CInt(ok) + + +def rdseed16_step(p: t.CUInt16T | t.CPtr) -> t.CInt: + val: t.CUInt32T = 0 + ok: t.CUInt32T = 0 + c.Asm(f"""rdseed {c.AsmOut(val, t.ASM_DESCR.OUTPUT_REG)} + setc al + movzx {c.AsmOut(ok, t.ASM_DESCR.OUTPUT_REG)}, al""", + out=[c.AsmOut(val, t.ASM_DESCR.OUTPUT_REG), c.AsmOut(ok, t.ASM_DESCR.OUTPUT_REG)], + op=[t.ASM_DESCR.CLOBBER_CC, t.ASM_DESCR.CLOBBER_AL]) + p[0] = t.CUInt16T(val) + return t.CInt(ok) + + +def rdseed32_step(p: t.CUInt32T | t.CPtr) -> t.CInt: + val: t.CUInt32T = 0 + ok: t.CUInt32T = 0 + c.Asm(f"""rdseed {c.AsmOut(val, t.ASM_DESCR.OUTPUT_REG)} + setc al + movzx {c.AsmOut(ok, t.ASM_DESCR.OUTPUT_REG)}, al""", + out=[c.AsmOut(val, t.ASM_DESCR.OUTPUT_REG), c.AsmOut(ok, t.ASM_DESCR.OUTPUT_REG)], + op=[t.ASM_DESCR.CLOBBER_CC, t.ASM_DESCR.CLOBBER_AL]) + p[0] = val + return t.CInt(ok) + + +def rdseed64_step(p: t.CUInt64T | t.CPtr) -> t.CInt: + val: t.CUInt64T = 0 + ok: t.CUInt32T = 0 + c.Asm(f"""rdseed {c.AsmOut(val, t.ASM_DESCR.OUTPUT_REG)} + setc al + movzx {c.AsmOut(ok, t.ASM_DESCR.OUTPUT_REG)}, al""", + out=[c.AsmOut(val, t.ASM_DESCR.OUTPUT_REG), c.AsmOut(ok, t.ASM_DESCR.OUTPUT_REG)], + op=[t.ASM_DESCR.CLOBBER_CC, t.ASM_DESCR.CLOBBER_AL]) + p[0] = val + return t.CInt(ok) + + +# ============================================================ +# 带重试的便捷接口(自动重试直到成功或达到上限) +# ============================================================ + +def random_u16() -> t.CUInt16T: + r: t.CUInt16T = 0 + i: t.CInt = 0 + while i < RDRAND_RETRY_LIMIT: + if rdrand16_step(c.Addr(r)) == 1: + return r + i += 1 + return 0 + + +def random_u32() -> t.CUInt32T: + r: t.CUInt32T = 0 + i: t.CInt = 0 + while i < RDRAND_RETRY_LIMIT: + if rdrand32_step(c.Addr(r)) == 1: + return r + i += 1 + return 0 + + +def random_u64() -> t.CUInt64T: + r: t.CUInt64T = 0 + i: t.CInt = 0 + while i < RDRAND_RETRY_LIMIT: + if rdrand64_step(c.Addr(r)) == 1: + return r + i += 1 + return 0 + + +def seed_u16() -> t.CUInt16T: + r: t.CUInt16T = 0 + i: t.CInt = 0 + while i < RDSEED_RETRY_LIMIT: + if rdseed16_step(c.Addr(r)) == 1: + return r + i += 1 + return 0 + + +def seed_u32() -> t.CUInt32T: + r: t.CUInt32T = 0 + i: t.CInt = 0 + while i < RDSEED_RETRY_LIMIT: + if rdseed32_step(c.Addr(r)) == 1: + return r + i += 1 + return 0 + + +def seed_u64() -> t.CUInt64T: + r: t.CUInt64T = 0 + i: t.CInt = 0 + while i < RDSEED_RETRY_LIMIT: + if rdseed64_step(c.Addr(r)) == 1: + return r + i += 1 + return 0 + + +# ============================================================ +# Python random 标准库函数实现 +# 默认类型:t.CUInt64T (u64), t.CDouble (f64), t.CInt (i32) +# ============================================================ + +# ---------- 一、随机整数 ---------- + +def randint(a: t.CInt, b: t.CInt) -> t.CInt: + return t.CInt(a + t.CInt(random_u64() % t.CUInt64T(b - a + 1))) + + +def randrange(start: t.CInt, stop: t.CInt, step: t.CInt = 1) -> t.CInt: + width: t.CInt = 0 + if step > 0: + width = (stop - start + step - 1) // step + else: + width = (start - stop - step - 1) // (-step) + return t.CInt(start + t.CInt(random_u64() % t.CUInt64T(width)) * step) + + +def getrandbits(k: t.CInt) -> t.CUInt64T: + r: t.CUInt64T = rdrand64() + if k >= 64: + return r + mask: t.CUInt64T = (t.CUInt64T(1) << k) - t.CUInt64T(1) + return r & mask + + +# ---------- 二、随机浮点数 ---------- + +def random() -> t.CDouble: + return t.CDouble(rdrand64() >> 11) * (t.CDouble(1.0) / t.CDouble(9007199254740992.0)) + + +def uniform(a: t.CDouble, b: t.CDouble) -> t.CDouble: + return a + (b - a) * random() + + +def triangular(low: t.CDouble, high: t.CDouble, mode: t.CDouble) -> t.CDouble: + u: t.CDouble = random() + c: t.CDouble = (mode - low) / (high - low) + if u > c: + u = t.CDouble(1.0) - u + c = t.CDouble(1.0) - c + tmp: t.CDouble = low + low = high + high = tmp + return low + (high - low) * vipermath.sqrt(u * c) + + +def betavariate(alpha: t.CDouble, beta: t.CDouble) -> t.CDouble: + y: t.CDouble = gammavariate(alpha, t.CDouble(1.0)) + if y != t.CDouble(0.0): + return y / (y + gammavariate(beta, t.CDouble(1.0))) + return t.CDouble(0.0) + + +def expovariate(lambd: t.CDouble) -> t.CDouble: + u: t.CDouble = random() + if u < t.CDouble(1e-300): + u = t.CDouble(1e-300) + return -vipermath.log(t.CDouble(1.0) - u) / lambd + + +def gammavariate(alpha: t.CDouble, beta: t.CDouble) -> t.CDouble: + u: t.CDouble = t.CDouble(0.0) + d: t.CDouble = t.CDouble(0.0) + c: t.CDouble = t.CDouble(0.0) + x: t.CDouble = t.CDouble(0.0) + v: t.CDouble = t.CDouble(0.0) + if alpha <= t.CDouble(0.0) or beta <= t.CDouble(0.0): + return t.CDouble(0.0) + if alpha < t.CDouble(1.0): + u = random() + if u < t.CDouble(1e-300): + u = t.CDouble(1e-300) + return gammavariate(alpha + t.CDouble(1.0), beta) * vipermath.pow(u, t.CDouble(1.0) / alpha) + d = alpha - t.CDouble(1.0) / t.CDouble(3.0) + c = t.CDouble(1.0) / vipermath.sqrt(t.CDouble(9.0) * d) + while 1: + x = gauss(t.CDouble(0.0), t.CDouble(1.0)) + v = t.CDouble(1.0) + c * x + if v > t.CDouble(0.0): + v = v * v * v + u = random() + if u < t.CDouble(1.0) - t.CDouble(0.0331) * x * x * x * x: + return d * v * beta + if vipermath.log(u) < t.CDouble(0.5) * x * x + d * (t.CDouble(1.0) - v + vipermath.log(v)): + return d * v * beta + + +def gauss(mu: t.CDouble, sigma: t.CDouble) -> t.CDouble: + u1: t.CDouble = random() + u2: t.CDouble = random() + if u1 < t.CDouble(1e-300): + u1 = t.CDouble(1e-300) + z0: t.CDouble = vipermath.sqrt(t.CDouble(-2.0) * vipermath.log(u1)) * vipermath.cos(t.CDouble(2.0) * vipermath.U_M_PI * u2) + return mu + sigma * z0 + + +def normalvariate(mu: t.CDouble, sigma: t.CDouble) -> t.CDouble: + NV_MAGICCONST: t.CDouble = t.CDouble(1.7155277699214135) + u1: t.CDouble = t.CDouble(0.0) + u2: t.CDouble = t.CDouble(0.0) + z: t.CDouble = t.CDouble(0.0) + zz: t.CDouble = t.CDouble(0.0) + while 1: + u1 = random() + u2 = random() + if u2 < t.CDouble(1e-300): + continue + z = NV_MAGICCONST * (u1 - t.CDouble(0.5)) / u2 + zz = z * z / t.CDouble(4.0) + if zz <= t.CDouble(0.0) - vipermath.log(u2): + break + return mu + z * sigma + + +def lognormvariate(mu: t.CDouble, sigma: t.CDouble) -> t.CDouble: + return vipermath.exp(gauss(mu, sigma)) + + +def vonmisesvariate(mu: t.CDouble, kappa: t.CDouble) -> t.CDouble: + if kappa <= t.CDouble(1e-6): + return vipermath.U_M_PI * t.CDouble(2.0) * random() + s: t.CDouble = t.CDouble(0.5) / kappa + r: t.CDouble = s + vipermath.sqrt(t.CDouble(1.0) + s * s) + u1: t.CDouble = t.CDouble(0.0) + u2: t.CDouble = t.CDouble(0.0) + u3: t.CDouble = t.CDouble(0.0) + z: t.CDouble = t.CDouble(0.0) + d: t.CDouble = t.CDouble(0.0) + q: t.CDouble = t.CDouble(0.0) + f: t.CDouble = t.CDouble(0.0) + theta: t.CDouble = t.CDouble(0.0) + two_pi: t.CDouble = vipermath.U_M_PI * t.CDouble(2.0) + while 1: + u1 = random() + z = vipermath.cos(vipermath.U_M_PI * u1) + d = t.CDouble(1.0) / (r + z) + u2 = random() + if u2 < t.CDouble(1.0) - d * d: + break + if u2 < (t.CDouble(1.0) - z) * vipermath.exp(kappa * (z - t.CDouble(1.0)) - d * kappa * r): + break + q = t.CDouble(1.0) / r + f = (q + z) / (t.CDouble(1.0) + q * z) + u3 = random() + if u3 > t.CDouble(0.5): + theta = mu + vipermath.acos(f) + else: + theta = mu - vipermath.acos(f) + while theta < t.CDouble(0.0): + theta += two_pi + while theta >= two_pi: + theta -= two_pi + return theta + + +def paretovariate(alpha: t.CDouble) -> t.CDouble: + u: t.CDouble = random() + if u < t.CDouble(1e-300): + u = t.CDouble(1e-300) + return t.CDouble(1.0) / vipermath.pow(t.CDouble(1.0) - u, t.CDouble(1.0) / alpha) + + +def weibullvariate(alpha: t.CDouble, beta: t.CDouble) -> t.CDouble: + u: t.CDouble = random() + if u < t.CDouble(1e-300): + u = t.CDouble(1e-300) + return alpha * vipermath.pow(t.CDouble(-1.0) * vipermath.log(t.CDouble(1.0) - u), t.CDouble(1.0) / beta) diff --git a/includes/vthreading.py b/includes/vthreading.py new file mode 100644 index 0000000..a8162fb --- /dev/null +++ b/includes/vthreading.py @@ -0,0 +1,104 @@ +import t, c +from stdint import * +from w32.win32base import * +from w32.win32process import CreateThread, GetExitCodeThread, GetCurrentThreadId, TlsAlloc, TlsFree, TlsGetValue, TlsSetValue +from w32.win32sync import WaitForSingleObject + +# 全部导入锁类,用户也可按需导入 +from lock import Lock +from event import Event +from condition import Condition +from rwlock import RWLock + + +@t.Object +class Thread: + """线程类,封装 Windows CreateThread。 + + 线程回调签名: def thread_func(arg: t.CPtr) -> t.CPtr + 注意: Windows API 限制返回值为 DWORD(32位),64位指针会被截断。 + 如需返回 64 位结果,请通过 arg 参数结构体传递。 + + 用法: + def worker(arg: t.CPtr) -> t.CPtr: + # 线程逻辑 + return NULL + + t: Thread = Thread(worker, arg_ptr) + t.start() + t.join() + """ + handle: HANDLE + thread_id: ULONG + target: VOIDPTR + arg: VOIDPTR + started: BOOL + + def __init__(self, target: VOIDPTR, arg: VOIDPTR = NULL): + self.handle = NULL + self.thread_id = 0 + self.target = target + self.arg = arg + self.started = FALSE + + def start(self): + if self.started: + return + self.handle = CreateThread(NULL, 0, self.target, self.arg, 0, c.Addr(self.thread_id)) + self.started = TRUE + + def join(self, timeout_ms: ULONG = INFINITE) -> BOOL: + if not self.started: + return FALSE + result: ULONG = WaitForSingleObject(self.handle, timeout_ms) + return result == WAIT_OBJECT_0 + + def is_alive(self) -> BOOL: + if not self.started: + return FALSE + result: ULONG = WaitForSingleObject(self.handle, 0) + return result == WAIT_TIMEOUT + + def get_exit_code(self) -> ULONG: + code: ULONG = 0 + GetExitCodeThread(self.handle, c.Addr(code)) + return code + + def close(self): + if self.handle != NULL: + CloseHandle(self.handle) + self.handle = NULL + + +@t.Object +class local: + """TLS (Thread Local Storage) 封装。 + + 用法: + tls: local = local() + tls.set(value_ptr) + val: t.CPtr = tls.get() + """ + index: ULONG + + def __init__(self): + self.index = TlsAlloc() + + def get(self) -> VOIDPTR: + return TlsGetValue(self.index) + + def set(self, value: VOIDPTR) -> BOOL: + return TlsSetValue(self.index, value) + + def free(self) -> BOOL: + return TlsFree(self.index) + + +def get_current_thread_id() -> ULONG: + """获取当前线程 ID""" + return GetCurrentThreadId() + + +def sleep_ms(ms: ULONG): + """让当前线程休眠指定毫秒数""" + Sleep(ms) diff --git a/includes/w32/win32sync.py b/includes/w32/win32sync.py index 9e2a4b1..9f13e6c 100644 --- a/includes/w32/win32sync.py +++ b/includes/w32/win32sync.py @@ -43,3 +43,23 @@ def AcquireSRWLockExclusive(SRWLock: VOIDPTR) -> VOID | t.State: pass def AcquireSRWLockShared(SRWLock: VOIDPTR) -> VOID | t.State: pass def ReleaseSRWLockExclusive(SRWLock: VOIDPTR) -> VOID | t.State: pass def ReleaseSRWLockShared(SRWLock: VOIDPTR) -> VOID | t.State: pass + +# 条件变量 (Condition Variables) - Vista+ +CONDITION_VARIABLE_LOCKMODE_SHARED: t.CDefine = 0x1 + +def InitializeConditionVariable(ConditionVariable: VOIDPTR) -> VOID | t.State: pass +def SleepConditionVariableCS(ConditionVariable: VOIDPTR, CriticalSection: CRITICAL_SECTION | t.CPtr, dwMilliseconds: ULONG) -> BOOL | t.State: pass +def SleepConditionVariableSRW(ConditionVariable: VOIDPTR, SRWLock: VOIDPTR, dwMilliseconds: ULONG, Flags: ULONG) -> BOOL | t.State: pass +def WakeConditionVariable(ConditionVariable: VOIDPTR) -> VOID | t.State: pass +def WakeAllConditionVariable(ConditionVariable: VOIDPTR) -> VOID | t.State: pass + +# 一次性初始化 (One-Time Initialization) - Vista+ +INIT_ONCE_STATIC_INIT: t.CDefine = 0x00000001 +INIT_ONCE_CHECK_ONLY: t.CDefine = 0x00000002 +INIT_ONCE_ASYNC: t.CDefine = 0x00000004 +INIT_ONCE_INIT_FAILED: t.CDefine = 0x00000008 + +class INIT_ONCE: + Ptr: t.CPtr + +def InitOnceExecuteOnce(InitOnce: INIT_ONCE | t.CPtr, InitFn: VOIDPTR, Parameter: VOIDPTR, Context: VOIDPTR | t.CPtr) -> BOOL | t.State: pass diff --git a/includes/zlib/pyzlib.py b/includes/zlib/pyzlib.py index 4c63447..3a6f4d2 100644 --- a/includes/zlib/pyzlib.py +++ b/includes/zlib/pyzlib.py @@ -59,7 +59,7 @@ DEF_MEM_LEVEL: t.CDefine = 8 # Version ZLIB_VERSION: t.CDefine = "1.3.2" -pyzlib_error_msg: list[t.CChar, 512] = "" +pyzlib_error_msg: t.CArray[t.CChar, 512] = "" pyzlib_error_code_val: t.CInt = 0 # ============================================================ @@ -552,7 +552,9 @@ def compress(pool: mpool.MPool | t.CPtr, data: BYTEPTR, data_len: t.CSizeT, actual_wbits: t.CInt = wbits if wbits > MAX_WBITS: actual_wbits = -MAX_WBITS + stdio.printf("[DEBUG] compress: calling zdeflate_one_shot, pool=%p, data=%p, len=%zu, level=%d, wbits=%d\n", pool, data, data_len, level, actual_wbits) raw_result: UINT8PTR = zdeflate.zdeflate_one_shot(pool, data, data_len, level, actual_wbits, out_len) + stdio.printf("[DEBUG] compress: zdeflate_one_shot returned %p\n", raw_result) if not raw_result: set_error(Z_DATA_ERROR, "compression failed") return None diff --git a/includes/zlib/zchecksum.py b/includes/zlib/zchecksum.py index a79d695..d46246f 100644 --- a/includes/zlib/zchecksum.py +++ b/includes/zlib/zchecksum.py @@ -13,7 +13,7 @@ def zchecksum_adler32(data: UINT8PTR, length: t.CSizeT, init: UINT32) -> t.CUInt b = (b + a) % 65521 return (b << 16) | a -crc32_table: list[t.CUInt32T, 256] = [ +crc32_table: t.CArray[t.CUInt32T, 256] = [ 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, diff --git a/includes/zlib/zdef.py b/includes/zlib/zdef.py index fad0797..e55b56a 100644 --- a/includes/zlib/zdef.py +++ b/includes/zlib/zdef.py @@ -34,7 +34,7 @@ ZDEFLATE_END_OF_BLOCK: t.CDefine = 256 # ============================================================ # Length / Distance extra bits tables (RFC 1951) # ============================================================ -zdeflate_len_extra_bits: list[t.CInt, 29] = [ +zdeflate_len_extra_bits: t.CArray[t.CInt, 29] = [ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, @@ -44,7 +44,7 @@ zdeflate_len_extra_bits: list[t.CInt, 29] = [ 0 ] -zdeflate_len_base: list[t.CInt, 29] = [ +zdeflate_len_base: t.CArray[t.CInt, 29] = [ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, @@ -54,7 +54,7 @@ zdeflate_len_base: list[t.CInt, 29] = [ 258 ] -zdeflate_dist_extra_bits: list[t.CInt, 30] = [ +zdeflate_dist_extra_bits: t.CArray[t.CInt, 30] = [ 0, 0, 0, 0, 1, 1, 2, 2, @@ -71,7 +71,7 @@ zdeflate_dist_extra_bits: list[t.CInt, 30] = [ 13, 13 ] -zdeflate_dist_base: list[t.CInt, 30] = [ +zdeflate_dist_base: t.CArray[t.CInt, 30] = [ 1, 2, 3, 4, 5, 7, 9, 13, @@ -88,7 +88,7 @@ zdeflate_dist_base: list[t.CInt, 30] = [ 16385, 24577 ] -zdeflate_codelen_order: list[int, 19] = [ +zdeflate_codelen_order: t.CArray[int, 19] = [ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 ] diff --git a/includes/zlib/zdeflate.py b/includes/zlib/zdeflate.py index db3a7b2..0ebc593 100644 --- a/includes/zlib/zdeflate.py +++ b/includes/zlib/zdeflate.py @@ -122,8 +122,8 @@ class zdeflate_stream: def write_dynamic_block(self, data: UINT8PTR, length: t.CSizeT, final: t.CInt): - lit_freqs: list[t.CInt, 288] - dist_freqs: list[t.CInt, 32] + lit_freqs: t.CArray[t.CInt, 288] + dist_freqs: t.CArray[t.CInt, 32] zdeflate_count_freqs(lit_freqs, dist_freqs, self, data, length) hlit: t.CInt = 286 while hlit > 257 and lit_freqs[hlit - 1] == 0: hlit -= 1 @@ -133,11 +133,11 @@ class zdeflate_stream: dist_tree = zhuff.zhuff_tree() lit_tree.build_codes(lit_freqs, hlit, zdef.ZDEFLATE_MAX_BITS) dist_tree.build_codes(dist_freqs, hdist, zdef.ZDEFLATE_MAX_BITS) - all_lengths: list[t.CInt, 288 + 32] + all_lengths: t.CArray[t.CInt, 288 + 32] for i in range(hlit): all_lengths[i] = lit_tree.codes[i].bits for i in range(hdist): all_lengths[hlit + i] = dist_tree.codes[i].bits total_lengths: t.CInt = hlit + hdist - cl_freqs: list[t.CInt, 19] + cl_freqs: t.CArray[t.CInt, 19] zdeflate_count_cl_freqs(all_lengths, total_lengths, cl_freqs) cl_tree = zhuff.zhuff_tree() cl_tree.build_codes(cl_freqs, 19, 7) @@ -373,14 +373,28 @@ def zdeflate_write_cl_encoded(all_lengths: INTPTR, total: t.CInt, def zdeflate_create(pool: mpool.MPool | t.CPtr, level: t.CInt, wbits: t.CInt, mem_level: t.CInt, strategy: t.CInt) -> zdeflate_stream | t.CPtr: - s: zdeflate_stream | t.CPtr = zdef.zdef_alloc(pool, zdeflate_stream.__sizeof__()) + stdio.printf("[DEBUG] zdeflate_create: pool=%p, level=%d, wbits=%d\n", pool, level, wbits) + n: t.CSizeT = zdeflate_stream.__sizeof__() + stdio.printf("[DEBUG] zdeflate_create: sizeof(zdeflate_stream)=%zu\n", n) + s: zdeflate_stream | t.CPtr = zdef.zdef_alloc(pool, n) + stdio.printf("[DEBUG] zdeflate_create: allocated stream=%p\n", s) if not s: return None + stdio.printf("[DEBUG] zdeflate_create: memset(s, 0)\n") memset(s, 0, zdeflate_stream.__sizeof__()) + stdio.printf("[DEBUG] zdeflate_create: s.pool = pool\n") s.pool = pool + stdio.printf("[DEBUG] zdeflate_create: creating zbit_writer\n") s.writer = zdef.zbit_writer(pool) + stdio.printf("[DEBUG] zdeflate_create: zbit_writer created, writer.buf=%p\n", s.writer.buf) + stdio.printf("[DEBUG] zdeflate_create: allocating window\n") s.window = BYTEPTR(zdef.zdef_alloc(pool, zdef.ZDEFLATE_WINDOW_SIZE)) + stdio.printf("[DEBUG] zdeflate_create: window=%p\n", s.window) + stdio.printf("[DEBUG] zdeflate_create: allocating hash_head\n") s.hash_head = INTPTR(zdef.zdef_alloc(pool, zdef.ZDEFLATE_HASH_SIZE * int.__sizeof__())) + stdio.printf("[DEBUG] zdeflate_create: hash_head=%p\n", s.hash_head) + stdio.printf("[DEBUG] zdeflate_create: allocating hash_prev\n") s.hash_prev = INTPTR(zdef.zdef_alloc(pool, zdef.ZDEFLATE_WINDOW_SIZE * int.__sizeof__())) + stdio.printf("[DEBUG] zdeflate_create: hash_prev=%p\n", s.hash_prev) if not s.window or not s.hash_head or not s.hash_prev: s.destroy() return None @@ -400,7 +414,9 @@ def zdeflate_create(pool: mpool.MPool | t.CPtr, level: t.CInt, wbits: t.CInt, me def zdeflate_one_shot(pool: mpool.MPool | t.CPtr, data: UINT8PTR, length: t.CSizeT, level: t.CInt, wbits: t.CInt, out_len: t.CSizeT | t.CPtr) -> t.CUInt8T | t.CPtr: + stdio.printf("[DEBUG] zdeflate_one_shot: pool=%p, data=%p, length=%zu, level=%d, wbits=%d\n", pool, data, length, level, wbits) s: zdeflate_stream | t.CPtr = zdeflate_create(pool, level, wbits, 8, 0) + stdio.printf("[DEBUG] zdeflate_one_shot: stream created=%p\n", s) if not s: return None memset(s.hash_head, -1, zdef.ZDEFLATE_HASH_SIZE * int.__sizeof__()) diff --git a/includes/zlib/zhuff.py b/includes/zlib/zhuff.py index 7388665..5855d61 100644 --- a/includes/zlib/zhuff.py +++ b/includes/zlib/zhuff.py @@ -15,17 +15,17 @@ class zhuff_code: @t.Object class zhuff_tree: pool: mpool.MPool | t.CPtr - codes: list[zhuff_code, ZHUFF_MAX_CODES] + codes: t.CArray[zhuff_code, ZHUFF_MAX_CODES] count: t.CInt max_bits: t.CInt def __init__(self): - pass + self.pool = None def build_codes(self, freqs: INTPTR, count: t.CInt, max_bits: t.CInt): - lengths: list[t.CInt, ZHUFF_MAX_CODES] - bl_count: list[t.CInt, ZHUFF_MAX_BITS + 1] - next_code: list[UINT, ZHUFF_MAX_BITS + 1] + lengths: t.CArray[t.CInt, ZHUFF_MAX_CODES] + bl_count: t.CArray[t.CInt, ZHUFF_MAX_BITS + 1] + next_code: t.CArray[UINT, ZHUFF_MAX_BITS + 1] self.count = count self.max_bits = max_bits self.build_code_lengths(lengths, freqs, count, max_bits) @@ -47,9 +47,9 @@ class zhuff_tree: self.codes[i].code = 0 def build_fixed_lit_tree(self): - lengths: list[t.CInt, 288] - bl_count: list[t.CInt, 16] - next_code: list[t.CUnsignedInt, 16] + lengths: t.CArray[t.CInt, 288] + bl_count: t.CArray[t.CInt, 16] + next_code: t.CArray[t.CUnsignedInt, 16] self.get_fixed_lit_lengths(lengths) memset(bl_count, 0, bl_count.__sizeof__()) for i in range(288): @@ -71,9 +71,9 @@ class zhuff_tree: self.codes[i].code = 0 def build_fixed_dist_tree(self): - lengths: list[t.CInt, 32] - bl_count: list[t.CInt, 16] - next_code: list[t.CUnsignedInt, 16] + lengths: t.CArray[t.CInt, 32] + bl_count: t.CArray[t.CInt, 16] + next_code: t.CArray[t.CUnsignedInt, 16] self.get_fixed_dist_lengths(lengths) memset(bl_count, 0, bl_count.__sizeof__()) for i in range(32): @@ -103,7 +103,7 @@ class zhuff_tree: def build_code_lengths(self, lengths: t.CInt | t.CPtr, freqs: t.CInt | t.CPtr, count: t.CInt, max_bits: t.CInt): - bl_count: list[t.CInt, ZHUFF_MAX_BITS + 2] + bl_count: t.CArray[t.CInt, ZHUFF_MAX_BITS + 2] sort_count: t.CInt = 0 memset(bl_count, 0, bl_count.__sizeof__()) memset(lengths, 0, int.__sizeof__() * count) @@ -272,8 +272,8 @@ class zhuff_tree: lengths[i] = 5 def build_tree_from_lengths(self, lengths: INTPTR, count: t.CInt, max_bits: t.CInt): - bl_count: list[t.CInt, 16] - next_code: list[t.CUnsignedInt, 16] + bl_count: t.CArray[t.CInt, 16] + next_code: t.CArray[t.CUnsignedInt, 16] memset(bl_count, 0, bl_count.__sizeof__()) for i in range(count): @@ -298,19 +298,19 @@ class zhuff_tree: class zhuff_decode_node: - children: list[t.CInt, 2] + children: t.CArray[t.CInt, 2] symbol: t.CInt @t.Object class zhuff_decode_tree: pool: mpool.MPool | t.CPtr - nodes: list[zhuff_decode_node, 2 * ZHUFF_MAX_CODES] + nodes: t.CArray[zhuff_decode_node, 2 * ZHUFF_MAX_CODES] node_count: t.CInt root: t.CInt def __init__(self): - pass + self.pool = None def build_decode_tree(self, ht: zhuff_tree | t.CPtr): self.node_count = 1 diff --git a/includes/zlib/zinflate.py b/includes/zlib/zinflate.py index b404189..b683de8 100644 --- a/includes/zlib/zinflate.py +++ b/includes/zlib/zinflate.py @@ -213,7 +213,7 @@ class zinflate_stream: hdist: t.CInt = t.CInt(hdist_val) + 1 hclen: t.CInt = t.CInt(hclen_val) + 4 - cl_lengths: list[t.CInt, 19] + cl_lengths: t.CArray[t.CInt, 19] memset(cl_lengths, 0, cl_lengths.__sizeof__()) for i in range(hclen): len_val: UINT @@ -283,13 +283,13 @@ class zinflate_stream: lit_tree = zhuff.zhuff_tree() dist_tree = zhuff.zhuff_tree() - lit_lengths: list[t.CInt, 288] + lit_lengths: t.CArray[t.CInt, 288] memset(lit_lengths, 0, lit_lengths.__sizeof__()) for i in range(hlit): lit_lengths[i] = all_lengths[i] lit_tree.build_tree_from_lengths(lit_lengths, hlit, zdef.ZDEFLATE_MAX_BITS) - dist_lengths: list[t.CInt, 32] + dist_lengths: t.CArray[t.CInt, 32] memset(dist_lengths, 0, dist_lengths.__sizeof__()) for i in range(hdist): dist_lengths[i] = all_lengths[hlit + i] diff --git a/lib/Projectrans/Config.py b/lib/Projectrans/Config.py index 2441065..a7b38e1 100644 --- a/lib/Projectrans/Config.py +++ b/lib/Projectrans/Config.py @@ -1,214 +1,240 @@ -import os -import sys -import shutil -from lib.Projectrans.Phase1Generator import Phase1Generator -from lib.Projectrans.Phase2Translator import Phase2Translator - - -def save_sha1_map(temp_dir: str, sha1_map: dict[str, str]): - """将 SHA1 映射表保存到文件""" - map_path = os.path.join(temp_dir, '_sha1_map.txt') - with open(map_path, 'w', encoding='utf-8') as f: - for sha1, rel in sorted(sha1_map.items()): - f.write(f"{sha1}:{rel}\n") - - -def Load_sha1_map(temp_dir: str) -> dict[str, str]: - """从文件加载 SHA1 映射表""" - map_path = os.path.join(temp_dir, '_sha1_map.txt') - result = {} - if os.path.exists(map_path): - with open(map_path, 'r', encoding='utf-8') as f: - for line in f: - line = line.strip() - if ':' in line: - sha1, rel = line.split(':', 1) - result[sha1] = rel - return result - - -def Load_project_config(project_file: str) -> dict: - """从 project.json 加载配置""" - import json - with open(project_file, 'r', encoding='utf-8') as f: - return json.load(f) - - -def resolve_paths(config: dict, project_file: str) -> dict: - """将配置中的相对路径转换为绝对路径""" - project_dir = os.path.dirname(os.path.abspath(project_file)) - result = dict(config) - - def resolve(p): - if p is None: - return None - if os.path.isabs(p): - return p - return os.path.normpath(os.path.join(project_dir, p)) - - if 'source_dir' in result: - result['source_dir'] = resolve(result.get('source_dir')) - elif 'sources' in result: - resolved_sources = [] - for src in result['sources']: - if '*' in src or '?' in src: - import glob as glob_module - for matched in glob_module.glob(os.path.join(project_dir, src), recursive=True): - if os.path.isfile(matched): - resolved_sources.append(matched) - else: - resolved_sources.append(resolve(src)) - result['sources'] = [s for s in resolved_sources if os.path.isfile(s)] - - result['temp_dir'] = resolve(config.get('temp_dir')) - result['output_dir'] = resolve(config.get('output_dir')) - - if 'includes' in result: - result['includes'] = [resolve(inc) for inc in result['includes']] - - result['_project_dir'] = project_dir - return result - - -def main(): - import argparse - parser = argparse.ArgumentParser( - description='TransPyC 工程翻译器 - 基于 project.json 的两阶段翻译', - formatter_class=argparse.RawDescriptionHelpFormatter, - epilog=''' -示例: - # 从 project.json 读取配置并执行(默认查找当前目录) - python ProjectTrans.py - - # 指定 project.json 文件 - python ProjectTrans.py --project ./TestProject/project.json - - # 使用命令行参数覆盖 project.json 配置 - python ProjectTrans.py --src ./src --temp ./decl --output ./out --phase all - - # 仅运行阶段一 - python ProjectTrans.py --phase 1 - - # 仅运行阶段二 - python ProjectTrans.py --phase 2 - - # 清理临时目录 - python ProjectTrans.py --clean -''' - ) - parser.add_argument('--project', help='project.json 路径(默认查找当前目录)') - parser.add_argument('--src', help='源文件目录(覆盖 project.json)') - parser.add_argument('--temp', help='声明接口临时目录(覆盖 project.json)') - parser.add_argument('--output', help='输出目录(覆盖 project.json)') - parser.add_argument('--phase', choices=['1', '2', 'all'], help='阶段: 1=生成声明, 2=翻译+编译, all=全部') - parser.add_argument('--cc', help='LLVM 编译器命令(覆盖 project.json)') - parser.add_argument('--clean', action='store_true', help='清理 output 和 temp 目录') - - args = parser.parse_args() - - project_file = args.project - if not project_file: - candidates = ['project.json', './project.json'] - for c in candidates: - if os.path.exists(c): - project_file = c - break - - if project_file and os.path.exists(project_file): - print(f"[配置] 读取: {project_file}") - config = Load_project_config(project_file) - project_dir = os.path.dirname(os.path.abspath(project_file)) - print(f"[配置] 项目目录: {project_dir}") - else: - print("[错误] 未找到 project.json,请使用 --project 指定") - sys.exit(1) - - resolved = resolve_paths(config, project_file) - src = args.src or resolved.get('source_dir') or resolved.get('sources') - temp_dir = args.temp or resolved.get('temp_dir') - output_dir = args.output or resolved.get('output_dir') - phase = args.phase or 'all' - cc_cmd = args.cc or resolved.get('compiler', {}).get('cmd', 'llc') - cc_flags = resolved.get('compiler', {}).get('flags', ['-filetype=obj']) - slice_level = resolved.get('options', {}).get('slice_level', 3) - project_include_dirs = resolved.get('includes', []) - target_triple = resolved.get('target', {}).get('triple') - target_datalayout = resolved.get('target', {}).get('datalayout') - - if isinstance(src, list): - if len(src) == 1 and os.path.isdir(src[0]): - src = src[0] - else: - src = src[0] if len(src) == 1 else os.path.dirname(os.path.commonpath(src)) if all(os.path.exists(p) for p in src) else src[0] - - print(f"[配置] 源目录: {src}") - print(f"[配置] 临时目录: {temp_dir}") - print(f"[配置] 输出目录: {output_dir}") - print(f"[配置] 阶段: {phase}") - print(f"[配置] 编译器: {cc_cmd} {' '.join(cc_flags)}") - if target_triple: - print(f"[配置] 目标三元组: {target_triple}") - if target_datalayout: - print(f"[配置] 数据布局: {target_datalayout}") - - if args.clean: - if output_dir and os.path.exists(output_dir): - for f in os.listdir(output_dir): - fpath = os.path.join(output_dir, f) - try: - if os.path.isfile(fpath) or os.path.islink(fpath): - os.remove(fpath) - elif os.path.isdir(fpath): - shutil.rmtree(fpath, ignore_errors=True) - except: - pass - print(f"[清理] output: 已清空 {output_dir}") - if temp_dir and os.path.exists(temp_dir): - for f in os.listdir(temp_dir): - fpath = os.path.join(temp_dir, f) - try: - if os.path.isfile(fpath) or os.path.islink(fpath): - os.remove(fpath) - elif os.path.isdir(fpath): - shutil.rmtree(fpath, ignore_errors=True) - except: - pass - print(f"[清理] temp: 已清空 {temp_dir}") - print("[清理] 完成") - if (not phase or phase == 'all') and not args.project: - return - - if phase in ('1', 'all'): - if isinstance(src, list): - print("[错误] 阶段一需要指定源目录,不支持文件列表") - sys.exit(1) - all_include_dirs = list(project_include_dirs) if project_include_dirs else [] - for d in Phase2Translator.INCLUDE_DIRS: - if os.path.isdir(d): - d = os.path.abspath(d) - if d not in [os.path.abspath(x) for x in all_include_dirs]: - all_include_dirs.append(d) - gen = Phase1Generator(src, temp_dir, include_dirs=all_include_dirs, target_triple=target_triple, target_datalayout=target_datalayout) - gen.run() - save_sha1_map(temp_dir, gen.sha1_map) - - if phase in ('2', 'all'): - if not output_dir: - print("[错误] 阶段二需要指定 --output 目录") - sys.exit(1) - if not os.path.exists(temp_dir): - print(f"[错误] 声明目录不存在,请先运行阶段一: {temp_dir}") - sys.exit(1) - if isinstance(src, list): - print("[错误] 阶段二需要指定源目录,不支持文件列表") - sys.exit(1) - linker_cmd = resolved.get('linker', {}).get('cmd') - linker_flags = resolved.get('linker', {}).get('flags', []) - linker_output = resolved.get('linker', {}).get('output') - target_triple = resolved.get('target', {}).get('triple') - target_datalayout = resolved.get('target', {}).get('datalayout') - startup = resolved.get('options', {}).get('startup') - trans = Phase2Translator(src, temp_dir, output_dir, compile_cmd=cc_cmd, compile_flags=cc_flags, linker_cmd=linker_cmd, linker_flags=linker_flags, linker_output=linker_output, include_dirs=project_include_dirs, target_triple=target_triple, target_datalayout=target_datalayout, startup=startup) - trans.sha1_map = Load_sha1_map(temp_dir) - trans.slice_level = slice_level - trans.run() +from __future__ import annotations + +import os +import sys +import json +import glob as glob_module +import argparse +import shutil +import subprocess +from typing import Any + +from lib.core.VLogger import get_logger as _vlog +from lib.Projectrans.Phase1Generator import Phase1Generator +from lib.Projectrans.Phase2Translator import Phase2Translator + + +def save_sha1_map(temp_dir: str, sha1_map: dict[str, str]) -> None: + """将 SHA1 映射表保存到文件""" + map_path: str = os.path.join(temp_dir, '_sha1_map.txt') + with open(map_path, 'w', encoding='utf-8') as f: + for sha1, rel in sorted(sha1_map.items()): + f.write(f"{sha1}:{rel}\n") + + +def Load_sha1_map(temp_dir: str) -> dict[str, str]: + """从文件加载 SHA1 映射表""" + map_path: str = os.path.join(temp_dir, '_sha1_map.txt') + result: dict[str, str] = {} + if os.path.exists(map_path): + with open(map_path, 'r', encoding='utf-8') as f: + for line in f: + line: str = line.strip() + if ':' in line: + sha1: str + rel: str + sha1, rel = line.split(':', 1) + result[sha1] = rel + return result + + +def Load_project_config(project_file: str) -> dict[str, Any]: + """从 project.json 加载配置""" + with open(project_file, 'r', encoding='utf-8') as f: + return json.load(f) + + +def resolve_paths(config: dict[str, Any], project_file: str) -> dict[str, Any]: + """将配置中的相对路径转换为绝对路径""" + project_dir: str = os.path.dirname(os.path.abspath(project_file)) + result: dict[str, Any] = dict(config) + + def resolve(p: str | None) -> str | None: + if p is None: + return None + if os.path.isabs(p): + return p + return os.path.normpath(os.path.join(project_dir, p)) + + if 'source_dir' in result: + result['source_dir'] = resolve(result.get('source_dir')) + elif 'sources' in result: + resolved_sources: list[str] = [] + for src in result['sources']: + if '*' in src or '?' in src: + for matched in glob_module.glob(os.path.join(project_dir, src), recursive=True): + if os.path.isfile(matched): + resolved_sources.append(matched) + else: + resolved_sources.append(resolve(src)) + result['sources'] = [s for s in resolved_sources if os.path.isfile(s)] + + result['temp_dir'] = resolve(config.get('temp_dir')) + result['output_dir'] = resolve(config.get('output_dir')) + + if 'includes' in result: + result['includes'] = [resolve(inc) for inc in result['includes']] + + result['_project_dir'] = project_dir + return result + + +def main() -> None: + parser: argparse.ArgumentParser = argparse.ArgumentParser( + description='TransPyC 工程翻译器 - 基于 project.json 的两阶段翻译', + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog=''' +示例: + # 从 project.json 读取配置并执行(默认查找当前目录) + python ProjectTrans.py + + # 指定 project.json 文件 + python ProjectTrans.py --project ./TestProject/project.json + + # 使用命令行参数覆盖 project.json 配置 + python ProjectTrans.py --src ./src --temp ./decl --output ./out --phase all + + # 仅运行阶段一 + python ProjectTrans.py --phase 1 + + # 仅运行阶段二 + python ProjectTrans.py --phase 2 + + # 清理临时目录 + python ProjectTrans.py --clean + + # 编译并立即执行 + python Projectrans.py --project ./TestProject/project.json --clean --run +''' + ) + parser.add_argument('--project', help='project.json 路径(默认查找当前目录)') + parser.add_argument('--src', help='源文件目录(覆盖 project.json)') + parser.add_argument('--temp', help='声明接口临时目录(覆盖 project.json)') + parser.add_argument('--output', help='输出目录(覆盖 project.json)') + parser.add_argument('--phase', choices=['1', '2', 'all'], help='阶段: 1=生成声明, 2=翻译+编译, all=全部') + parser.add_argument('--cc', help='LLVM 编译器命令(覆盖 project.json)') + parser.add_argument('--clean', action='store_true', help='清理 output 和 temp 目录') + parser.add_argument('--run', action='store_true', help='编译成功后立即执行生成的可执行文件') + + args: argparse.Namespace = parser.parse_args() + + project_file: str | None = args.project + if not project_file: + candidates: list[str] = ['project.json', './project.json'] + for c in candidates: + if os.path.exists(c): + project_file = c + break + + if project_file and os.path.exists(project_file): + _vlog().info(f"读取配置文件: {project_file}") + config: dict[str, Any] = Load_project_config(project_file) + project_dir: str = os.path.dirname(os.path.abspath(project_file)) + _vlog().info(f"项目目录: {project_dir}") + else: + _vlog().error("未找到 project.json,请使用 --project 指定") + sys.exit(1) + + resolved: dict[str, Any] = resolve_paths(config, project_file) + src: str | list[str] | None = args.src or resolved.get('source_dir') or resolved.get('sources') + temp_dir: str | None = args.temp or resolved.get('temp_dir') + output_dir: str | None = args.output or resolved.get('output_dir') + phase: str = args.phase or 'all' + cc_cmd: str = args.cc or resolved.get('compiler', {}).get('cmd', 'llc') + cc_flags: list[str] = resolved.get('compiler', {}).get('flags', ['-filetype=obj']) + slice_level: int = resolved.get('options', {}).get('slice_level', 3) + project_include_dirs: list[str] = resolved.get('includes', []) + target_triple: str | None = resolved.get('target', {}).get('triple') + target_datalayout: str | None = resolved.get('target', {}).get('datalayout') + + if isinstance(src, list): + if len(src) == 1 and os.path.isdir(src[0]): + src = src[0] + else: + src = src[0] if len(src) == 1 else os.path.dirname(os.path.commonpath(src)) if all(os.path.exists(p) for p in src) else src[0] + + _vlog().info(f"源目录: {src}") + _vlog().info(f"临时目录: {temp_dir}") + _vlog().info(f"输出目录: {output_dir}") + _vlog().info(f"阶段: {phase}") + _vlog().info(f"编译器: {cc_cmd} {' '.join(cc_flags)}") + if target_triple: + _vlog().info(f"目标三元组: {target_triple}") + if target_datalayout: + _vlog().info(f"数据布局: {target_datalayout}") + + if args.clean: + if output_dir and os.path.exists(output_dir): + for f in os.listdir(output_dir): + fpath: str = os.path.join(output_dir, f) + try: + if os.path.isfile(fpath) or os.path.islink(fpath): + os.remove(fpath) + elif os.path.isdir(fpath): + shutil.rmtree(fpath, ignore_errors=True) + except: + pass + _vlog().info(f"output: 已清空 {output_dir}") + if temp_dir and os.path.exists(temp_dir): + for f in os.listdir(temp_dir): + fpath: str = os.path.join(temp_dir, f) + try: + if os.path.isfile(fpath) or os.path.islink(fpath): + os.remove(fpath) + elif os.path.isdir(fpath): + shutil.rmtree(fpath, ignore_errors=True) + except: + pass + _vlog().info(f"temp: 已清空 {temp_dir}") + _vlog().info("清理完成") + if (not phase or phase == 'all') and not args.project: + return + + if phase in ('1', 'all'): + if isinstance(src, list): + _vlog().error("阶段一需要指定源目录,不支持文件列表") + sys.exit(1) + all_include_dirs: list[str] = list(project_include_dirs) if project_include_dirs else [] + for d in Phase2Translator.INCLUDE_DIRS: + if os.path.isdir(d): + d = os.path.abspath(d) + if d not in [os.path.abspath(x) for x in all_include_dirs]: + all_include_dirs.append(d) + gen: Phase1Generator = Phase1Generator(src, temp_dir, include_dirs=all_include_dirs, target_triple=target_triple, target_datalayout=target_datalayout) + gen.run() + save_sha1_map(temp_dir, gen.sha1_map) + + if phase in ('2', 'all'): + if not output_dir: + _vlog().error("阶段二需要指定 --output 目录") + sys.exit(1) + if not os.path.exists(temp_dir): + _vlog().error(f"声明目录不存在,请先运行阶段一: {temp_dir}") + sys.exit(1) + if isinstance(src, list): + _vlog().error("阶段二需要指定源目录,不支持文件列表") + sys.exit(1) + linker_cmd: str | None = resolved.get('linker', {}).get('cmd') + linker_flags: list[str] = resolved.get('linker', {}).get('flags', []) + linker_output: str | None = resolved.get('linker', {}).get('output') + target_triple = resolved.get('target', {}).get('triple') + target_datalayout = resolved.get('target', {}).get('datalayout') + startup: str | None = resolved.get('options', {}).get('startup') + trans: Phase2Translator = Phase2Translator(src, temp_dir, output_dir, compile_cmd=cc_cmd, compile_flags=cc_flags, linker_cmd=linker_cmd, linker_flags=linker_flags, linker_output=linker_output, include_dirs=project_include_dirs, target_triple=target_triple, target_datalayout=target_datalayout, startup=startup) + trans.sha1_map = Load_sha1_map(temp_dir) + trans.slice_level = slice_level + trans.run() + + if args.run and linker_output and not linker_output.endswith('.bin'): + exe_path: str = os.path.join(output_dir, linker_output) + if os.path.isfile(exe_path): + _vlog().info(f"\n[运行] 执行: {exe_path}") + try: + result: subprocess.CompletedProcess = subprocess.run([exe_path], cwd=output_dir) + _vlog().info(f"[运行] 退出码: {result.returncode}") + except Exception as e: + _vlog().error(f"[运行] 执行失败: {e}") + sys.exit(1) + else: + _vlog().error(f"[运行] 找不到可执行文件: {exe_path}") + sys.exit(1) diff --git a/lib/Projectrans/DeclarationGenerator.py b/lib/Projectrans/DeclarationGenerator.py index 49ad2f9..9d9a276 100644 --- a/lib/Projectrans/DeclarationGenerator.py +++ b/lib/Projectrans/DeclarationGenerator.py @@ -1,45 +1,78 @@ +from __future__ import annotations + import ast +import re from typing import List + +import llvmlite.ir as ir + from lib.includes import t +from lib.includes.t import CTypeRegistry +from lib.core.SymbolUtils import IsListAnnotation, AnnotationContainsName class DeclarationGenerator: """从 .pyi AST 生成纯 LLVM IR 声明(不使用字符串操作)""" - def __init__(self, struct_names=None, enum_names=None, module_sha1=None, target_triple=None, target_datalayout=None, struct_sha1_map=None, exception_names=None, typedef_map=None): - import llvmlite.ir as ir - self.ir = ir - self.module = None - self.builder = None - self._DefineConstants = {} - self.struct_names = struct_names or set() - self.enum_names = enum_names or set() - self.module_sha1 = module_sha1 - self.struct_sha1_map = struct_sha1_map or {} - self.exception_names = exception_names or set() - self.target_triple = target_triple or "x86_64-none-elf" - self.target_datalayout = target_datalayout or "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - self.typedef_map = typedef_map or {} + # 匹配 LLVM 数组类型:[N x elem_type] + _ARRAY_TYPE_RE: re.Pattern = re.compile(r'^\[(\d+)\s+x\s+(.+)\]$') + + @staticmethod + def _decay_array_to_ptr(type_str: str) -> str: + """C 语言中数组参数退化为指针:[N x elem_type] → elem_type*""" + m = DeclarationGenerator._ARRAY_TYPE_RE.match(type_str) + if m: + return f'{m.group(2)}*' + return type_str + + def __init__(self, struct_names: set[str] | None = None, enum_names: set[str] | None = None, module_sha1: str | None = None, target_triple: str | None = None, target_datalayout: str | None = None, struct_sha1_map: dict[str, str] | None = None, exception_names: set[str] | None = None, typedef_map: dict[str, ast.AST] | None = None) -> None: + self.ir: ir.Module = ir + self.module: ir.Module | None = None + self.builder: ir.IRBuilder | None = None + self._DefineConstants: dict[str, int | str] = {} + self.struct_names: set[str] = struct_names or set() + self.enum_names: set[str] = enum_names or set() + self.module_sha1: str | None = module_sha1 + self.struct_sha1_map: dict[str, str] = struct_sha1_map or {} + self.exception_names: set[str] = exception_names or set() + self.target_triple: str = target_triple or "x86_64-none-elf" + self.target_datalayout: str = target_datalayout or "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" + self.typedef_map: dict[str, ast.AST] = typedef_map or {} + self._pyi_tree: ast.Module | None = None + self._t_alias_map: dict[str, type] = {} t.configure_platform(self.target_triple) def generate(self, pyi_content: str, src_path: str) -> str: - import ast - tree = ast.parse(pyi_content) + tree: ast.Module = ast.parse(pyi_content) - self._DefineConstants = {} + self._DefineConstants: dict[str, int | str] = {} self._pyi_tree = tree - global_typedef_map = self.typedef_map - self.typedef_map = {} + global_typedef_map: dict[str, ast.AST] = self.typedef_map + self.typedef_map: dict[str, ast.AST] = {} if global_typedef_map: self.typedef_map.update(global_typedef_map) + + # 构建 t/c 类型别名映射(from t import CInt as myint) + self._t_alias_map: dict[str, type] = {} + for node in ast.iter_child_nodes(tree): + if isinstance(node, ast.ImportFrom): + if node.module in ('t', 'c'): + for alias in node.names: + name: str = alias.name + asname: str = alias.asname or name + if node.module == 't': + t_cls: type | None = getattr(t, name, None) + if isinstance(t_cls, type) and issubclass(t_cls, t.CType): + self._t_alias_map[asname] = t_cls + for node in ast.iter_child_nodes(tree): if isinstance(node, ast.AnnAssign) and isinstance(node.target, ast.Name): - var_name = node.target.id + var_name: str = node.target.id if node.value and isinstance(node.value, ast.Constant): self._DefineConstants[var_name] = node.value.value elif node.value and isinstance(node.value, ast.Name): self._DefineConstants[var_name] = node.value.id - is_typedef = False + is_typedef: bool = False if isinstance(node.annotation, ast.Attribute) and hasattr(node.annotation, 'attr') and node.annotation.attr == 'CTypedef': is_typedef = True elif isinstance(node.annotation, ast.Name) and node.annotation.id == 'CTypedef': @@ -52,7 +85,7 @@ class DeclarationGenerator: elif isinstance(node.annotation, ast.BinOp) and node.annotation.right: self.typedef_map[var_name] = node.annotation.right - lines = [] + lines: list[str] = [] lines.append('; ModuleID = "transpyc_decl"') lines.append(f'target triple = "{self.target_triple}"') lines.append(f'target datalayout = "{self.target_datalayout}"') @@ -62,32 +95,32 @@ class DeclarationGenerator: if isinstance(node, ast.FunctionDef): if hasattr(node, 'type_params') and node.type_params: continue - decl = self._generate_func_decl(node) + decl: str | None = self._generate_func_decl(node) if decl: lines.append(decl) elif isinstance(node, ast.AnnAssign): - decl = self._generate_global_decl(node) + decl: str | None = self._generate_global_decl(node) if decl: lines.append(decl) elif isinstance(node, ast.Assign): - decl = self._generate_global_assign_decl(node) + decl: str | None = self._generate_global_assign_decl(node) if decl: lines.append(decl) elif isinstance(node, ast.ClassDef): if hasattr(node, 'type_params') and node.type_params: continue - decls = self._generate_class_decl(node) + decls: list[str] = self._generate_class_decl(node) lines.extend(decls) return '\n'.join(lines) - def _generate_func_decl(self, node: ast.FunctionDef) -> str: + def _generate_func_decl(self, node: ast.FunctionDef) -> str | None: """生成函数声明""" - func_name = node.name - is_export = self._is_export_func(node) + func_name: str = node.name + is_export: bool = self._is_export_func(node) if self.module_sha1 and not is_export: func_name = f"{self.module_sha1}.{func_name}" - CReturnTypes = [] + CReturnTypes: list[ast.AST] = [] if node.decorator_list: for decorator in node.decorator_list: if isinstance(decorator, ast.Call) and isinstance(decorator.func, ast.Attribute): @@ -96,14 +129,15 @@ class DeclarationGenerator: CReturnTypes.append(arg) if node.returns: if isinstance(node.returns, ast.Subscript) and isinstance(node.returns.value, ast.Name) and node.returns.value.id == 'tuple': - slice_node = node.returns.slice + slice_node: ast.AST = node.returns.slice if isinstance(slice_node, ast.Tuple): for elt in slice_node.elts: CReturnTypes.append(elt) else: CReturnTypes.append(slice_node) + ret_type: str if CReturnTypes: - elem_types = [self._get_type_str(rt, embedded=True) for rt in CReturnTypes] + elem_types: list[str] = [self._get_type_str(rt, embedded=True) for rt in CReturnTypes] ret_type = '{ ' + ', '.join(elem_types) + ' }' else: ret_type = self._get_type_str(node.returns) @@ -113,16 +147,19 @@ class DeclarationGenerator: if node.returns is None: ret_type = 'void' - params = [] + params: list[str] = [] for arg in node.args.args: + arg_type: str if arg.annotation: arg_type = self._get_type_str(arg.annotation) else: arg_type = 'i8*' + # C 语言中数组参数退化为指针:[N x elem_type] → elem_type* + arg_type = self._decay_array_to_ptr(arg_type) if arg_type and arg_type != 'void': params.append(arg_type) - param_str = ', '.join(params) if params else '' + param_str: str = ', '.join(params) if params else '' if node.args.vararg: param_str = param_str + ', ...' if param_str else '...' if func_name[0].isdigit(): @@ -135,91 +172,125 @@ class DeclarationGenerator: return False return self._check_annotation_for_export(node.returns) - def _check_annotation_for_export(self, annotation) -> bool: + def _check_annotation_for_export(self, annotation: ast.AST | None) -> bool: """递归检查类型注解中是否包含 CExport 或 t.State""" - if isinstance(annotation, ast.Attribute): - if hasattr(annotation, 'attr') and annotation.attr in ('CExport', 'State'): - return True - elif isinstance(annotation, ast.BinOp) and isinstance(annotation.op, ast.BitOr): - return self._check_annotation_for_export(annotation.left) or self._check_annotation_for_export(annotation.right) - elif isinstance(annotation, ast.Name): - return annotation.id in ('CExport', 'State') - return False - - def _generate_global_decl(self, node: ast.AnnAssign) -> str: - """生成全局变量声明""" - if not isinstance(node.target, ast.Name): - return None - var_name = node.target.id - if isinstance(node.annotation, ast.Attribute) and hasattr(node.annotation, 'attr') and node.annotation.attr == 'CDefine': - return None - if isinstance(node.annotation, ast.Attribute) and hasattr(node.annotation, 'attr') and node.annotation.attr == 'CTypedef': - return None - if isinstance(node.annotation, ast.Name) and node.annotation.id == 'CTypedef': - return None - if isinstance(node.annotation, ast.BinOp) and isinstance(node.annotation.left, ast.Attribute) and hasattr(node.annotation.left, 'attr') and node.annotation.left.attr == 'CTypedef': - return None - if isinstance(node.annotation, ast.List): - for elt in node.annotation.elts: - if isinstance(elt, ast.Attribute) and hasattr(elt, 'attr') and elt.attr in ('CTypedef', 'Callable'): - return None - if isinstance(elt, ast.Subscript) and isinstance(elt.value, ast.Attribute) and isinstance(elt.value.value, ast.Name) and elt.value.value.id == 't' and elt.value.attr == 'Callable': - return None - VarType = self._get_type_str(node.annotation) - if VarType.startswith('[0 x ') and node.value and isinstance(node.value, ast.List): - elem_type = VarType[5:-1] - actual_count = len(node.value.elts) - if actual_count > 0: - VarType = f'[{actual_count} x {elem_type}]' - return f'@{var_name} = external global {VarType}' - - def _generate_global_assign_decl(self, node: ast.Assign) -> str: - """从无类型标注赋值推断并生成全局变量声明""" - if not node.targets or not isinstance(node.targets[0], ast.Name): - return None - var_name = node.targets[0].id - VarType = self._infer_type(node.value) - if VarType: - return f'@{var_name} = external global {VarType}' - return None + return bool(annotation) and (AnnotationContainsName(annotation, 'CExport') or AnnotationContainsName(annotation, 'State')) + def _generate_global_decl(self, node: ast.AnnAssign) -> str | None: + """生成全局变量声明""" + if not isinstance(node.target, ast.Name): + return None + var_name: str = node.target.id + if isinstance(node.annotation, ast.Attribute) and hasattr(node.annotation, 'attr') and node.annotation.attr == 'CDefine': + return None + if isinstance(node.annotation, ast.Attribute) and hasattr(node.annotation, 'attr') and node.annotation.attr == 'CTypedef': + return None + if isinstance(node.annotation, ast.Name) and node.annotation.id == 'CTypedef': + return None + if isinstance(node.annotation, ast.BinOp) and isinstance(node.annotation.left, ast.Attribute) and hasattr(node.annotation.left, 'attr') and node.annotation.left.attr == 'CTypedef': + return None + if isinstance(node.annotation, ast.List): + for elt in node.annotation.elts: + if isinstance(elt, ast.Attribute) and hasattr(elt, 'attr') and elt.attr in ('CTypedef', 'Callable'): + return None + if isinstance(elt, ast.Subscript) and isinstance(elt.value, ast.Attribute) and isinstance(elt.value.value, ast.Name) and elt.value.value.id == 't' and elt.value.attr == 'Callable': + return None + VarType: str = self._get_type_str(node.annotation) + if VarType.startswith('[0 x ') and node.value and isinstance(node.value, ast.List): + elem_type: str = VarType[5:-1] + actual_count: int = len(node.value.elts) + if actual_count > 0: + VarType = f'[{actual_count} x {elem_type}]' + return f'@{var_name} = external global {VarType}' + + def _generate_global_assign_decl(self, node: ast.Assign) -> str | None: + """从无类型标注赋值推断并生成全局变量声明""" + if not node.targets or not isinstance(node.targets[0], ast.Name): + return None + var_name: str = node.targets[0].id + VarType: str | None = self._infer_type(node.value) + if VarType: + return f'@{var_name} = external global {VarType}' + return None + + def _resolve_base_kind(self, base_name: str) -> str | None: + """解析基类名称的类型种类(支持别名) + + Returns: + 'enum' | 'union' | 'renum' | 'struct' | None + """ + # 1) 查 t 别名映射(from t import CEnum as en) + if base_name in self._t_alias_map: + t_cls: type = self._t_alias_map[base_name] + if issubclass(t_cls, (t.CEnum, t.REnum)): + return 'renum' if issubclass(t_cls, t.REnum) else 'enum' + if issubclass(t_cls, t.CUnion): + return 'union' + if issubclass(t_cls, t.CStruct): + return 'struct' + + # 2) 直接查 t 模块属性 + t_cls: type | None = getattr(t, base_name, None) + if isinstance(t_cls, type) and issubclass(t_cls, t.CType): + if issubclass(t_cls, (t.CEnum, t.REnum)): + return 'renum' if issubclass(t_cls, t.REnum) else 'enum' + if issubclass(t_cls, t.CUnion): + return 'union' + if issubclass(t_cls, t.CStruct): + return 'struct' + + return None + + def _is_marker_base(self, base_name: str) -> bool: + """检查是否为标记基类(Object/CVTable/Exception/CEnum/CUnion/CStruct/REnum 及其别名)""" + if base_name in ('Object', 'CVTable', 'Exception', 'CEnum', 'Enum', 'CStruct', 'CUnion', 'REnum'): + return True + if self._resolve_base_kind(base_name) is not None: + return True + return False + def _generate_class_decl(self, node: ast.ClassDef) -> List[str]: """生成结构体/类声明""" - decls = [] - class_name = node.name - is_enum = False - is_exception = False + decls: list[str] = [] + class_name: str = node.name + is_enum: bool = False + is_renum: bool = False + is_union: bool = False + is_exception: bool = False if node.bases: for base in node.bases: + base_name: str | None = None if isinstance(base, ast.Attribute) and hasattr(base, 'attr'): - if base.attr == 'CEnum' or base.attr == 'Enum': - is_enum = True - break - elif base.attr == 'Exception' or base.attr in self.exception_names: - is_exception = True - break + base_name = base.attr elif isinstance(base, ast.Name) and hasattr(base, 'id'): - if base.id == 'CEnum' or base.id == 'Enum': - is_enum = True - break - elif base.id == 'Exception' or base.id in self.exception_names: + base_name = base.id + if base_name: + if base_name in self.exception_names or base_name == 'Exception': is_exception = True break + kind: str | None = self._resolve_base_kind(base_name) + if kind == 'enum': + is_enum = True + break + elif kind == 'union': + is_union = True + elif kind == 'renum': + is_renum = True if is_exception: return decls if is_enum: - enum_values = {} - next_value = 0 + enum_values: dict[str, int] = {} + next_value: int = 0 for item in node.body: if isinstance(item, ast.AnnAssign) and isinstance(item.target, ast.Name): - var_name = item.target.id + var_name: str = item.target.id if item.value and isinstance(item.value, ast.Constant) and isinstance(item.value.value, int): enum_values[var_name] = item.value.value else: enum_values[var_name] = next_value next_value += 1 elif isinstance(item, ast.Assign) and len(item.targets) == 1 and isinstance(item.targets[0], ast.Name): - var_name = item.targets[0].id + var_name: str = item.targets[0].id if item.value and isinstance(item.value, ast.Constant) and isinstance(item.value.value, int): enum_values[var_name] = item.value.value next_value = item.value.value + 1 @@ -229,12 +300,12 @@ class DeclarationGenerator: for var_name, value in enum_values.items(): decls.append(f'@__config_{class_name}_{var_name} = external global i32') return decls - member_types = [] - has_bitfield = False - total_bits = 0 - has_methods = any(isinstance(item, ast.FunctionDef) for item in node.body) - is_cvtable = False - is_cpython_object = False + member_types: list[str] = [] + has_bitfield: bool = False + total_bits: int = 0 + has_methods: bool = any(isinstance(item, ast.FunctionDef) for item in node.body) + is_cvtable: bool = False + is_cpython_object: bool = False if hasattr(node, 'decorator_list') and node.decorator_list: for decorator in node.decorator_list: if isinstance(decorator, ast.Attribute): @@ -250,9 +321,9 @@ class DeclarationGenerator: is_cpython_object = True if has_methods and not is_cpython_object: is_cpython_object = True - has_parent_class = False + has_parent_class: bool = False for base in node.bases: - base_name = None + base_name: str | None = None if isinstance(base, ast.Attribute): base_name = base.attr elif isinstance(base, ast.Name): @@ -262,14 +333,14 @@ class DeclarationGenerator: base_name = base.value.attr elif isinstance(base.value, ast.Name): base_name = base.value.id - if base_name and base_name not in ('Object', 'CVTable', 'CEnum', 'Enum', 'CStruct', 'CUnion'): + if base_name and not self._is_marker_base(base_name): has_parent_class = True break if has_parent_class and not is_cvtable: is_cvtable = True - base_has_vtable = False + base_has_vtable: bool = False for base in node.bases: - base_name = None + base_name: str | None = None if isinstance(base, ast.Attribute): base_name = base.attr elif isinstance(base, ast.Name): @@ -279,7 +350,7 @@ class DeclarationGenerator: base_name = base.value.attr elif isinstance(base.value, ast.Name): base_name = base.value.id - if base_name and base_name not in ('Object', 'CVTable', 'CEnum', 'Enum', 'CStruct', 'CUnion'): + if base_name and not self._is_marker_base(base_name): for n in ast.iter_child_nodes(self._pyi_tree): if isinstance(n, ast.ClassDef) and n.name == base_name: if hasattr(n, 'decorator_list') and n.decorator_list: @@ -293,9 +364,9 @@ class DeclarationGenerator: break if has_methods and is_cvtable and not base_has_vtable: member_types.append('i8*') - seen_member_names = set() + seen_member_names: set[str] = set() for base in node.bases: - base_name = None + base_name: str | None = None if isinstance(base, ast.Attribute): base_name = base.attr elif isinstance(base, ast.Name): @@ -305,7 +376,9 @@ class DeclarationGenerator: base_name = base.value.attr elif isinstance(base.value, ast.Name): base_name = base.value.id - if base_name and base_name not in ('Object', 'CVTable', 'CEnum', 'Enum', 'CStruct', 'CUnion'): + if base_name and not self._is_marker_base(base_name): + base_member_types: list[str] + base_seen: set[str] base_member_types, base_seen = self._get_inherited_members(base_name) for mt in base_member_types: member_types.append(mt) @@ -313,7 +386,7 @@ class DeclarationGenerator: for item in node.body: if isinstance(item, ast.AnnAssign) and isinstance(item.target, ast.Name): seen_member_names.add(item.target.id) - init_members = [] + init_members: list[ast.AnnAssign] = [] for item in node.body: if isinstance(item, ast.FunctionDef) and item.name == '__init__': for stmt in item.body: @@ -322,7 +395,7 @@ class DeclarationGenerator: and isinstance(stmt.target.value, ast.Name) and stmt.target.value.id == 'self'): init_members.append(stmt) - untyped_self_members = [] + untyped_self_members: list[ast.Assign] = [] for m_name in [m.attr for m in init_members if isinstance(m.target, ast.Attribute)]: seen_member_names.add(m_name) for item in node.body: @@ -335,25 +408,26 @@ class DeclarationGenerator: and isinstance(stmt.targets[0], ast.Attribute) and isinstance(stmt.targets[0].value, ast.Name) and stmt.targets[0].value.id == 'self'): - attr_name = stmt.targets[0].attr + attr_name: str = stmt.targets[0].attr if attr_name not in seen_member_names: seen_member_names.add(attr_name) untyped_self_members.append(stmt) for item in list(node.body) + init_members + untyped_self_members: if isinstance(item, ast.AnnAssign): - bit_width = self._get_bitfield_width(item.annotation) + # 跳过编译期元数据字段(__provides__/__requires__/__require_must__) + if isinstance(item.target, ast.Name) and item.target.id in ('__provides__', '__requires__', '__require_must__'): + continue + bit_width: int | None = self._get_bitfield_width(item.annotation) if bit_width is not None: has_bitfield = True total_bits += bit_width else: - VarType = self._get_type_str(item.annotation, embedded=True) - if (isinstance(item.annotation, ast.Subscript) - and isinstance(item.annotation.value, ast.Name) - and item.annotation.value.id == 'list'): - slice_node = item.annotation.slice - is_dynamic = False + VarType: str = self._get_type_str(item.annotation, embedded=True) + if IsListAnnotation(item.annotation): + slice_node: ast.AST = item.annotation.slice + is_dynamic: bool = False if isinstance(slice_node, ast.Tuple) and len(slice_node.elts) == 2: - count_node = slice_node.elts[1] + count_node: ast.AST = slice_node.elts[1] if isinstance(count_node, ast.Constant) and count_node.value is None: is_dynamic = True elif not (isinstance(count_node, ast.Constant) and isinstance(count_node.value, int) and count_node.value > 0): @@ -362,23 +436,34 @@ class DeclarationGenerator: elif not isinstance(slice_node, ast.Tuple): is_dynamic = True if is_dynamic: - elem_type = self._get_type_str(slice_node if not isinstance(slice_node, ast.Tuple) else slice_node.elts[0], embedded=True) - init_len = 0 + elem_type: str = self._get_type_str(slice_node if not isinstance(slice_node, ast.Tuple) else slice_node.elts[0], embedded=True) + init_len: int = 0 if isinstance(item.value, ast.List): init_len = len(item.value.elts) elif isinstance(item.value, ast.Constant) and isinstance(item.value.value, str): init_len = len(item.value.value) + 1 VarType = f'[{init_len} x {elem_type}]' + else: + # 固定大小数组: t.CArray[elem_type, count] → [count x elem_type] + if isinstance(slice_node, ast.Tuple) and len(slice_node.elts) == 2: + elem_type: str = self._get_type_str(slice_node.elts[0], embedded=True) + count_val: int = self._get_const_int(slice_node.elts[1]) + if count_val > 0: + VarType = f'[{count_val} x {elem_type}]' + elif isinstance(slice_node, (ast.Attribute, ast.Name, ast.Subscript)): + # 单参数 t.CArray[elem_type] → 指针模式 + elem_type: str = self._get_type_str(slice_node, embedded=True) + VarType = f'{elem_type}*' member_types.append(VarType) elif isinstance(item, ast.Assign): if (len(item.targets) == 1 and isinstance(item.targets[0], ast.Attribute) and isinstance(item.targets[0].value, ast.Name) and item.targets[0].value.id == 'self'): - attr_name = item.targets[0].attr + attr_name: str = item.targets[0].attr if attr_name in seen_member_names: continue - InferredType = 'i32' + InferredType: str = 'i32' if item.value and isinstance(item.value, ast.Constant): if isinstance(item.value.value, float): InferredType = 'float' @@ -398,13 +483,14 @@ class DeclarationGenerator: member_types.insert(0, 'i32') else: member_types.insert(0, 'i64') - struct_type_name = f'%"{self.module_sha1}.{class_name}"' if self.module_sha1 else f'%struct.{class_name}' - struct_decl = f'{struct_type_name} = type {{ {", ".join(member_types)} }}' + struct_type_name: str = f'%"{self.module_sha1}.{class_name}"' if self.module_sha1 else f'%struct.{class_name}' + struct_decl: str = f'{struct_type_name} = type {{ {", ".join(member_types)} }}' decls.append(struct_decl) if is_cpython_object or is_cvtable: - new_func_name = f'{class_name}.__before_init__' + new_func_name: str = f'{class_name}.__before_init__' if self.module_sha1: new_func_name = f"{self.module_sha1}.{new_func_name}" + new_func_decl: str if new_func_name[0].isdigit(): new_func_decl = f'declare void @"{new_func_name}"({struct_type_name}*)' else: @@ -414,45 +500,47 @@ class DeclarationGenerator: if isinstance(item, ast.FunctionDef): if hasattr(item, 'type_params') and item.type_params: continue - method_name = f'{class_name}.{item.name}' + method_name: str = f'{class_name}.{item.name}' if self.module_sha1: method_name = f"{self.module_sha1}.{method_name}" - ret_type = self._get_type_str(item.returns) if item.returns else 'void' + ret_type: str = self._get_type_str(item.returns) if item.returns else 'void' if not ret_type: ret_type = 'void' - params = [] + params: list[str] = [] for arg_idx, arg in enumerate(item.args.args): + arg_type: str if arg.annotation: arg_type = self._get_type_str(arg.annotation) elif arg_idx == 0 and arg.arg == 'self': arg_type = f'{struct_type_name}*' else: arg_type = 'i8*' + # C 语言中数组参数退化为指针:[N x elem_type] → elem_type* + arg_type = self._decay_array_to_ptr(arg_type) params.append(arg_type) - param_str = ', '.join(params) if params else '' + param_str: str = ', '.join(params) if params else '' if method_name[0].isdigit(): decls.append(f'declare {ret_type} @"{method_name}"({param_str})') else: decls.append(f'declare {ret_type} @{method_name}({param_str})') return decls - def _get_inherited_members(self, base_name: str): - import ast - member_types = [] - seen_names = set() + def _get_inherited_members(self, base_name: str) -> tuple[list[str], set[str]]: + member_types: list[str] = [] + seen_names: set[str] = set() if not hasattr(self, '_pyi_tree') or self._pyi_tree is None: return member_types, seen_names - base_node = None + base_node: ast.ClassDef | None = None for node in ast.iter_child_nodes(self._pyi_tree): if isinstance(node, ast.ClassDef) and node.name == base_name: base_node = node break if base_node is None: return member_types, seen_names - base_decls = self._generate_class_decl(base_node) + base_decls: list[str] = self._generate_class_decl(base_node) for decl in base_decls: if '= type {' in decl: - type_body = decl.split('= type {')[1].rstrip('}').strip() + type_body: str = decl.split('= type {')[1].rstrip('}').strip() if type_body: for t in type_body.split(','): t = t.strip() @@ -481,30 +569,29 @@ class DeclarationGenerator: 通过 CTypeRegistry.NameToLLVM 查询,利用 CType 的 position/IsSigned/Size 元属性自动推导,无需手动映射表。 """ - from lib.includes.t import CTypeRegistry - result = CTypeRegistry.NameToLLVM(name) + result: str = CTypeRegistry.NameToLLVM(name) return result - def _get_type_str(self, annotation: ast.AST, embedded: bool = False) -> str: - import ast - from lib.includes.t import CTypeRegistry + def _get_type_str(self, annotation: ast.AST | None, embedded: bool = False) -> str: if annotation is None: return 'i8*' - non_struct_types = {'list', 'dict', 'tuple', 'set', 'array'} + non_struct_types: set[str] = {'list', 'dict', 'tuple', 'set', 'array', 'CArray'} if isinstance(annotation, ast.Name): if annotation.id == 'None': return 'void' if annotation.id in ('str', 'bytes'): return 'i8*' - llvm_type = CTypeRegistry.NameToLLVM(annotation.id) + llvm_type: str | None = CTypeRegistry.NameToLLVM(annotation.id) if llvm_type is not None: return llvm_type - resolved = CTypeRegistry.ResolveName(annotation.id) + resolved: tuple[type, int] | None = CTypeRegistry.ResolveName(annotation.id) if resolved is not None: + ctype_cls: type + ptr_level: int ctype_cls, ptr_level = resolved - base = CTypeRegistry.CTypeToLLVM(ctype_cls) + base: str = CTypeRegistry.CTypeToLLVM(ctype_cls) if ptr_level > 0: if base == 'void': return 'i8*' @@ -512,26 +599,32 @@ class DeclarationGenerator: return base return f'{base}*' return base - if annotation.id in non_struct_types: - return 'i32' - if annotation.id in self.enum_names: - return 'i32' if annotation.id in self.struct_names: - sha1 = self.struct_sha1_map.get(annotation.id, self.module_sha1) - sname = f'%"{sha1}.{annotation.id}"' if sha1 else f'%struct.{annotation.id}' + sha1: str | None = self.struct_sha1_map.get(annotation.id, self.module_sha1) + sname: str = f'%"{sha1}.{annotation.id}"' if sha1 else f'%struct.{annotation.id}' if embedded: return sname else: return f'{sname}*' + if annotation.id in non_struct_types: + return 'i32' + if annotation.id in self.enum_names: + return 'i32' if annotation.id in self.typedef_map: - resolved = self._get_type_str(self.typedef_map[annotation.id], embedded=embedded) - return resolved - sha1 = self.struct_sha1_map.get(annotation.id, self.module_sha1) - sname = f'%"{sha1}.{annotation.id}"' if sha1 else f'%struct.{annotation.id}' + resolved_str: str = self._get_type_str(self.typedef_map[annotation.id], embedded=embedded) + return resolved_str + # 检查 t 类型别名(from t import CInt as myint) + if annotation.id in self._t_alias_map: + t_cls: type = self._t_alias_map[annotation.id] + llvm: str | None = CTypeRegistry.CTypeToLLVM(t_cls) + if llvm: + return llvm + sha1: str | None = self.struct_sha1_map.get(annotation.id, self.module_sha1) + sname: str = f'%"{sha1}.{annotation.id}"' if sha1 else f'%struct.{annotation.id}' return f'{sname}*' elif isinstance(annotation, ast.Attribute): - attr_name = annotation.attr if hasattr(annotation, 'attr') else '' - module_name = '' + attr_name: str = annotation.attr if hasattr(annotation, 'attr') else '' + module_name: str = '' if hasattr(annotation, 'value'): if isinstance(annotation.value, ast.Name): module_name = annotation.value.id @@ -541,13 +634,15 @@ class DeclarationGenerator: return '' if (module_name == 't' and attr_name == 'Callable') or attr_name == 'Callable': return 'i8*' - llvm_type = CTypeRegistry.NameToLLVM(attr_name) + llvm_type: str | None = CTypeRegistry.NameToLLVM(attr_name) if llvm_type is not None: return llvm_type - resolved = CTypeRegistry.ResolveName(attr_name) + resolved: tuple[type, int] | None = CTypeRegistry.ResolveName(attr_name) if resolved is not None: + ctype_cls: type + ptr_level: int ctype_cls, ptr_level = resolved - base = CTypeRegistry.CTypeToLLVM(ctype_cls) + base: str = CTypeRegistry.CTypeToLLVM(ctype_cls) if ptr_level > 0: if base == 'void': return 'i8*' @@ -560,24 +655,24 @@ class DeclarationGenerator: if attr_name in self.enum_names: return 'i32' if attr_name in self.struct_names: - sha1 = self.struct_sha1_map.get(attr_name, self.module_sha1) - sname = f'%"{sha1}.{attr_name}"' if sha1 else f'%struct.{attr_name}' + sha1: str | None = self.struct_sha1_map.get(attr_name, self.module_sha1) + sname: str = f'%"{sha1}.{attr_name}"' if sha1 else f'%struct.{attr_name}' if embedded: return sname else: return f'{sname}*' if attr_name and attr_name[0].isupper() and attr_name not in non_struct_types: - sha1 = self.struct_sha1_map.get(attr_name, self.module_sha1) - sname = f'%"{sha1}.{attr_name}"' if sha1 else f'%struct.{attr_name}' + sha1: str | None = self.struct_sha1_map.get(attr_name, self.module_sha1) + sname: str = f'%"{sha1}.{attr_name}"' if sha1 else f'%struct.{attr_name}' return f'{sname}*' if attr_name and attr_name not in non_struct_types: - sha1 = self.struct_sha1_map.get(attr_name, self.module_sha1) - sname = f'%"{sha1}.{attr_name}"' if sha1 else f'%struct.{attr_name}' + sha1: str | None = self.struct_sha1_map.get(attr_name, self.module_sha1) + sname: str = f'%"{sha1}.{attr_name}"' if sha1 else f'%struct.{attr_name}' return f'{sname}*' return 'i32' elif isinstance(annotation, ast.BinOp): - left_type = self._get_type_str(annotation.left, embedded=embedded) - right_type = self._get_type_str(annotation.right, embedded=embedded) + left_type: str = self._get_type_str(annotation.left, embedded=embedded) + right_type: str = self._get_type_str(annotation.right, embedded=embedded) if left_type in ('', 'void'): return right_type if right_type not in ('', 'void') else (left_type or right_type) if right_type in ('', 'void'): @@ -590,30 +685,56 @@ class DeclarationGenerator: return right_type return left_type elif isinstance(annotation, ast.Subscript): - base = self._get_type_str(annotation.value) + base: str = self._get_type_str(annotation.value) if base == 'i8*' and isinstance(annotation.slice, ast.Constant): return f'[{self._get_const_int(annotation.slice)} x i8]' if isinstance(annotation.slice, ast.Constant) and isinstance(annotation.slice.value, int): return f'[{annotation.slice.value} x {base}]' - if isinstance(annotation.value, ast.Name) and annotation.value.id == 'list': - slice_node = annotation.slice - if isinstance(slice_node, ast.Tuple) and len(slice_node.elts) == 2: - elem_type = self._get_type_str(slice_node.elts[0], embedded=True) - count_node = slice_node.elts[1] - array_count = self._get_const_int(count_node) - if array_count > 0: - return f'[{array_count} x {elem_type}]' - else: - return f'[0 x {elem_type}]' - elem_type = self._get_type_str(slice_node, embedded=True) - return f'[0 x {elem_type}]' if isinstance(annotation.value, ast.Name) and annotation.value.id == 'tuple': - slice_node = annotation.slice + slice_node: ast.AST = annotation.slice + elem_types: list[str] if isinstance(slice_node, ast.Tuple): elem_types = [self._get_type_str(e, embedded=True) for e in slice_node.elts] else: elem_types = [self._get_type_str(slice_node, embedded=True)] return '{ ' + ', '.join(elem_types) + ' }' + # 处理泛型类类型注解(如 list[str]) + if isinstance(annotation.value, ast.Name): + gc_name: str = annotation.value.id + if gc_name in non_struct_types and gc_name != 'tuple': + gc_slice: ast.AST = annotation.slice + gc_args: list[str] = [] + if isinstance(gc_slice, ast.Name): + gc_args.append(gc_slice.id) + elif isinstance(gc_slice, ast.Tuple): + gc_valid: bool = True + for gc_elt in gc_slice.elts: + if isinstance(gc_elt, ast.Name): + gc_args.append(gc_elt.id) + else: + gc_valid = False + break + if not gc_valid: + gc_args = [] + if gc_args: + gc_mangled: list[str] = [] + for gc_ta in gc_args: + gc_llvm: str | None = CTypeRegistry.NameToLLVM(gc_ta) + if gc_llvm: + if gc_llvm in ('float', 'double', 'half', 'fp128'): + gc_cls: type | None = CTypeRegistry.GetClassByName(gc_ta) + gc_sz: int = gc_cls().Size if gc_cls else 0 + gc_mangled.append('f' + str(gc_sz)) + else: + gc_mangled.append(gc_llvm) + else: + gc_mangled.append(gc_ta) + gc_spec: str = gc_name + '[' + ']['.join(gc_mangled) + ']' + gc_sha1: str | None = self.module_sha1 + gc_sname: str = f'%"{gc_sha1}.{gc_spec}"' if gc_sha1 else f'%struct.{gc_spec}' + if embedded: + return gc_sname + return f'{gc_sname}*' return f'{base}' elif isinstance(annotation, ast.Constant): if annotation.value is None: @@ -621,23 +742,25 @@ class DeclarationGenerator: if isinstance(annotation.value, int): return 'i32' if isinstance(annotation.value, str): - type_name = annotation.value + type_name: str = annotation.value if type_name in self.enum_names: return 'i32' if type_name in self.struct_names: - sha1 = self.struct_sha1_map.get(type_name, self.module_sha1) - sname = f'%"{sha1}.{type_name}"' if sha1 else f'%struct.{type_name}' + sha1: str | None = self.struct_sha1_map.get(type_name, self.module_sha1) + sname: str = f'%"{sha1}.{type_name}"' if sha1 else f'%struct.{type_name}' if embedded: return sname else: return f'{sname}*' - llvm_type = CTypeRegistry.NameToLLVM(type_name) + llvm_type: str | None = CTypeRegistry.NameToLLVM(type_name) if llvm_type is not None: return llvm_type - resolved = CTypeRegistry.ResolveName(type_name) + resolved: tuple[type, int] | None = CTypeRegistry.ResolveName(type_name) if resolved is not None: + ctype_cls: type + ptr_level: int ctype_cls, ptr_level = resolved - base = CTypeRegistry.CTypeToLLVM(ctype_cls) + base: str = CTypeRegistry.CTypeToLLVM(ctype_cls) if ptr_level > 0: if base == 'void': return 'i8*' @@ -645,8 +768,8 @@ class DeclarationGenerator: return base return f'{base}*' return base - sha1 = self.struct_sha1_map.get(type_name, self.module_sha1) - sname = f'%"{sha1}.{type_name}"' if sha1 else f'%struct.{type_name}' + sha1: str | None = self.struct_sha1_map.get(type_name, self.module_sha1) + sname: str = f'%"{sha1}.{type_name}"' if sha1 else f'%struct.{type_name}' return f'{sname}*' return 'i8*' elif isinstance(annotation, ast.Call): @@ -663,23 +786,18 @@ class DeclarationGenerator: return type_str + '*' if type_str.endswith('*'): return type_str - from lib.includes.t import CTypeRegistry - resolved = CTypeRegistry.ResolveName(type_str) + resolved: tuple[type, int] | None = CTypeRegistry.ResolveName(type_str) if resolved is not None: + ctype_cls: type + ptr_level: int ctype_cls, ptr_level = resolved - llvm_str = CTypeRegistry.CTypeToLLVM(ctype_cls) + llvm_str: str = CTypeRegistry.CTypeToLLVM(ctype_cls) if llvm_str: return f'{llvm_str}{"*" * (ptr_level + 1)}' - cnameres = CTypeRegistry.CNameToClass(type_str) - if cnameres is not None: - llvm_str = CTypeRegistry.CTypeToLLVM(cnameres) - if llvm_str: - return f'{llvm_str}*' return f'{type_str}*' def _infer_type(self, value: ast.AST) -> str: """从值推断类型""" - import ast if isinstance(value, ast.Constant): if isinstance(value.value, int): return 'i32' @@ -701,17 +819,16 @@ class DeclarationGenerator: return 'i8*' return 'i32' - def _get_bitfield_width(self, annotation: ast.AST): - import ast + def _get_bitfield_width(self, annotation: ast.AST) -> int | None: if isinstance(annotation, ast.BinOp) and isinstance(annotation.op, ast.BitOr): - right_width = self._get_bitfield_width(annotation.right) + right_width: int | None = self._get_bitfield_width(annotation.right) if right_width is not None: return right_width return self._get_bitfield_width(annotation.left) if isinstance(annotation, ast.Call): if isinstance(annotation.func, ast.Attribute) and annotation.func.attr == 'Bit': if annotation.args: - arg = annotation.args[0] + arg: ast.AST = annotation.args[0] if isinstance(arg, ast.Constant) and isinstance(arg.value, int): return arg.value if isinstance(annotation, ast.Subscript): @@ -722,17 +839,16 @@ class DeclarationGenerator: def _get_const_int(self, node: ast.AST) -> int: """获取常量整数值,支持符号常量和简单表达式""" - import ast if isinstance(node, ast.Constant) and isinstance(node.value, int): return node.value if isinstance(node, ast.Name): if node.id in self._DefineConstants: - val = self._DefineConstants[node.id] + val: int | str = self._DefineConstants[node.id] if isinstance(val, int): return val if isinstance(node, ast.BinOp): - left_val = self._get_const_int(node.left) - right_val = self._get_const_int(node.right) + left_val: int = self._get_const_int(node.left) + right_val: int = self._get_const_int(node.right) if left_val and right_val: if isinstance(node.op, ast.Add): return left_val + right_val diff --git a/lib/Projectrans/Phase1Generator.py b/lib/Projectrans/Phase1Generator.py index bc3319e..fa114e6 100644 --- a/lib/Projectrans/Phase1Generator.py +++ b/lib/Projectrans/Phase1Generator.py @@ -1,28 +1,34 @@ +from __future__ import annotations + import os import ast import traceback +from typing import Any + from lib.Projectrans.Utils import compute_sha1, get_file_dependencies, find_reachable_files_from_entries from lib.Projectrans.DeclarationGenerator import DeclarationGenerator +from lib.core.VLogger import get_logger as _vlog +from lib.constants.config import mode as _ConfigMode from StubGen import PythonToStubConverter class Phase1Generator: """阶段一:从源文件生成声明接口""" - def __init__(self, src_root: str, temp_dir: str, include_dirs: list = None, entry_files: list = None, target_triple: str = None, target_datalayout: str = None): - self.src_root = os.path.abspath(src_root) - self.temp_dir = os.path.abspath(temp_dir) - self.include_dirs = include_dirs or [] + def __init__(self, src_root: str, temp_dir: str, include_dirs: list[str] | None = None, entry_files: list[str] | None = None, target_triple: str | None = None, target_datalayout: str | None = None) -> None: + self.src_root: str = os.path.abspath(src_root) + self.temp_dir: str = os.path.abspath(temp_dir) + self.include_dirs: list[str] = include_dirs or [] self.sha1_map: dict[str, str] = {} self.include_py_map: dict[str, str] = {} - self.entry_files = entry_files - self.target_triple = target_triple - self.target_datalayout = target_datalayout + self.entry_files: list[str] | None = entry_files + self.target_triple: str | None = target_triple + self.target_datalayout: str | None = target_datalayout os.makedirs(self.temp_dir, exist_ok=True) - def _get_needed_include_files(self, reachable_source_files: set) -> list: + def _get_needed_include_files(self, reachable_source_files: set[str]) -> list[tuple[str, str, str]]: """从可达源文件收集所有被引用(含传递依赖)的 include 文件""" - include_file_map = {} + include_file_map: dict[str, tuple[str, str, str]] = {} for includes_dir in self.include_dirs: if not os.path.isdir(includes_dir): continue @@ -30,51 +36,87 @@ class Phase1Generator: dirs[:] = [d for d in dirs if not d.startswith('.') and d != '__pycache__'] for fname in files: if fname.endswith('.py') or fname.endswith('.pyi'): - src_path = os.path.join(root, fname) - rel_from_inc = os.path.relpath(src_path, includes_dir) - ModulePath = rel_from_inc.replace(os.sep, '.').replace('/', '.') - module_name = os.path.splitext(ModulePath)[0] - info = (src_path, rel_from_inc, includes_dir) + src_path: str = os.path.join(root, fname) + rel_from_inc: str = os.path.relpath(src_path, includes_dir) + ModulePath: str = rel_from_inc.replace(os.sep, '.').replace('/', '.') + module_name: str = os.path.splitext(ModulePath)[0] + info: tuple[str, str, str] = (src_path, rel_from_inc, includes_dir) include_file_map[module_name] = info - top_pkg = module_name.split('.')[0] + top_pkg: str = module_name.split('.')[0] if top_pkg not in include_file_map: include_file_map[top_pkg] = info - imported_from_src = set() + imported_from_src: set[str] = set() for src_path in reachable_source_files: - deps = get_file_dependencies(src_path, self.src_root) + deps: set[str] = get_file_dependencies(src_path, self.src_root) imported_from_src.update(deps) - needed = set() - queue = list(imported_from_src) + # 检测 dict/list 容器使用,自动添加 _dict/_list/json 依赖 + for src_path in reachable_source_files: + try: + with open(src_path, 'r', encoding='utf-8') as f: + content: str = f.read() + tree = ast.parse(content) + for node in ast.walk(tree): + if isinstance(node, ast.Subscript) and isinstance(node.value, ast.Name): + if node.value.id == 'dict': + imported_from_src.add('_dict') + imported_from_src.add('json') + break + elif node.value.id == 'list': + imported_from_src.add('_list') + break + if isinstance(node, ast.Call) and isinstance(node.func, ast.Name): + if node.func.id == 'dict': + imported_from_src.add('_dict') + imported_from_src.add('json') + break + elif node.func.id == 'list': + imported_from_src.add('_list') + break + # 检测类型注解 d: dict / l: list (非泛型形式) + if isinstance(node, ast.AnnAssign) and isinstance(node.annotation, ast.Name): + if node.annotation.id == 'dict': + imported_from_src.add('_dict') + imported_from_src.add('json') + break + elif node.annotation.id == 'list': + imported_from_src.add('_list') + break + except Exception: + pass + + needed: set[str] = set() + queue: list[str] = list(imported_from_src) while queue: - mod_name = queue.pop(0) + mod_name: str = queue.pop(0) if mod_name in needed: continue if mod_name in include_file_map: needed.add(mod_name) - src_path = include_file_map[mod_name][0] - includes_dir = include_file_map[mod_name][2] - deps = get_file_dependencies(src_path, includes_dir) + src_path: str = include_file_map[mod_name][0] + includes_dir: str = include_file_map[mod_name][2] + deps: set[str] = get_file_dependencies(src_path, includes_dir) for dep in deps: if dep in include_file_map and dep not in needed: queue.append(dep) - needed_infos = [] + needed_infos: list[tuple[str, str, str]] = [] for mod_name in sorted(needed): if mod_name in include_file_map: - info = include_file_map[mod_name] + info: tuple[str, str, str] = include_file_map[mod_name] if info not in needed_infos: needed_infos.append(info) return needed_infos - def run(self): + def run(self) -> None: """扫描源目录,只处理入口文件可达的 .py 文件(导入遍历)""" + py_files: list[str] if self.entry_files: py_files = list(self.entry_files) else: - main_py = os.path.join(self.src_root, 'main.py') + main_py: str = os.path.join(self.src_root, 'main.py') if os.path.exists(main_py): py_files = [main_py] else: @@ -86,50 +128,55 @@ class Phase1Generator: py_files.append(os.path.join(root, file)) if not py_files: - print("[阶段一] 未找到入口文件或源文件") + _vlog().warning("未找到入口文件或源文件") return + reachable: set[str] if self.entry_files: reachable = find_reachable_files_from_entries(self.src_root, py_files) else: reachable = find_reachable_files_from_entries(self.src_root, py_files) - print(f"[阶段一] 找到 {len(reachable)} 个可达源文件(从入口遍历)") + _vlog().info(f"找到 {len(reachable)} 个可达源文件(从入口遍历)") for i, src_path in enumerate(sorted(reachable), 1): - rel = os.path.relpath(src_path, self.src_root) - print(f"[{i}/{len(reachable)}] 生成签名: {rel}") + rel: str = os.path.relpath(src_path, self.src_root) + _vlog().info(f"[{i}/{len(reachable)}] 生成签名: {rel}") try: self._process_file_pyi(src_path, rel) except Exception as e: - print(f" [错误] {e}") + _vlog().error(f"生成签名失败: {e}") traceback.print_exc() - needed_includes = self._get_needed_include_files(reachable) + needed_includes: list[tuple[str, str, str]] = self._get_needed_include_files(reachable) self._process_include_py_files_pyi(needed_includes) + struct_names: set[str] + enum_names: set[str] + struct_sha1_map: dict[str, str] + exception_names: set[str] struct_names, enum_names, struct_sha1_map, exception_names = self._build_struct_registry() - print(f"\n[阶段一] 结构体注册表: {len(struct_names)} 个类型, {len(enum_names)} 个枚举") + _vlog().info(f"结构体注册表: {len(struct_names)} 个类型, {len(enum_names)} 个枚举") for name in sorted(struct_names): - print(f" {name}") + _vlog().debug(f" {name}") for i, src_path in enumerate(sorted(reachable), 1): - rel = os.path.relpath(src_path, self.src_root) + rel: str = os.path.relpath(src_path, self.src_root) try: self._process_file_stub(src_path, rel, struct_names, enum_names=enum_names, struct_sha1_map=struct_sha1_map, exception_names=exception_names) except Exception as e: - print(f" [错误] {e}") + _vlog().error(f"生成声明失败: {e}") traceback.print_exc() self._process_include_py_files_stub(struct_names, needed_includes, enum_names=enum_names, struct_sha1_map=struct_sha1_map, exception_names=exception_names) - print(f"\n[阶段一完成] 声明接口生成到: {self.temp_dir}") - print(f"SHA1 映射表 ({len(self.sha1_map)} 个文件):") + _vlog().success(f"声明接口生成到: {self.temp_dir}") + _vlog().info(f"SHA1 映射表 ({len(self.sha1_map)} 个文件):") for sha1, rel in sorted(self.sha1_map.items()): - print(f" {sha1} -> {rel}") + _vlog().debug(f" {sha1} -> {rel}") - def _collect_include_py_files(self): - include_py_files = [] + def _collect_include_py_files(self) -> list[tuple[str, str, str]]: + include_py_files: list[tuple[str, str, str]] = [] for includes_dir in self.include_dirs: if not os.path.isdir(includes_dir): continue @@ -137,180 +184,190 @@ class Phase1Generator: dirs[:] = [d for d in dirs if not d.startswith('.') and d != '__pycache__'] for fname in files: if fname.endswith('.py') or fname.endswith('.pyi'): - src_path = os.path.join(root, fname) - rel_from_inc = os.path.relpath(src_path, includes_dir) + src_path: str = os.path.join(root, fname) + rel_from_inc: str = os.path.relpath(src_path, includes_dir) include_py_files.append((src_path, rel_from_inc, includes_dir)) return include_py_files - def _process_include_py_files_pyi(self, needed_includes: list = None): + def _process_include_py_files_pyi(self, needed_includes: list[tuple[str, str, str]] | None = None) -> None: + include_py_files: list[tuple[str, str, str]] if needed_includes is not None: include_py_files = needed_includes else: include_py_files = self._collect_include_py_files() if not include_py_files: return - print(f"\n[阶段一-includes] 处理 {len(include_py_files)} 个被引用的 Python 库文件") + _vlog().info(f"处理 {len(include_py_files)} 个被引用的 Python 库文件") for src_path, rel_from_inc, includes_dir in include_py_files: - ModulePath = rel_from_inc.replace(os.sep, '.').replace('/', '.') - module_name = os.path.splitext(ModulePath)[0] + ModulePath: str = rel_from_inc.replace(os.sep, '.').replace('/', '.') + module_name: str = os.path.splitext(ModulePath)[0] try: with open(src_path, 'r', encoding='utf-8') as f: - content = f.read() - sha1 = compute_sha1(content) + content: str = f.read() + sha1: str = compute_sha1(content) self.sha1_map[sha1] = f"includes/{rel_from_inc}" - top_module = rel_from_inc.split(os.sep)[0].split('/')[0] + top_module: str = rel_from_inc.split(os.sep)[0].split('/')[0] if top_module not in self.include_py_map: self.include_py_map[top_module] = sha1 self.include_py_map[module_name] = sha1 - sig_path = os.path.join(self.temp_dir, f"{sha1}.pyi") + sig_path: str = os.path.join(self.temp_dir, f"{sha1}.pyi") if os.path.isfile(sig_path): - print(f" 缓存命中: {rel_from_inc} -> {sha1}.pyi") + _vlog().info(f" 缓存命中: {rel_from_inc} -> {sha1}.pyi") continue - sig_content = PythonToStubConverter.convert(content, module_name) + sig_content: str = PythonToStubConverter.convert(content, module_name) with open(sig_path, 'w', encoding='utf-8', newline='\n') as f: f.write(sig_content) - print(f" 生成签名: {rel_from_inc} -> {sha1}.pyi") + _vlog().info(f" 生成签名: {rel_from_inc} -> {sha1}.pyi") except Exception as e: - print(f" [错误] {rel_from_inc}: {e}") + _vlog().error(f"处理 include 文件失败 {rel_from_inc}: {e}") - def _collect_typedef_map(self): - import ast as _ast - typedef_map = {} + def _collect_typedef_map(self) -> dict[str, ast.AST]: + typedef_map: dict[str, ast.AST] = {} if not os.path.isdir(self.temp_dir): return typedef_map for fname in os.listdir(self.temp_dir): if not fname.endswith('.pyi'): continue - pyi_path = os.path.join(self.temp_dir, fname) + pyi_path: str = os.path.join(self.temp_dir, fname) try: with open(pyi_path, 'r', encoding='utf-8') as f: - content = f.read() - tree = _ast.parse(content) - for node in _ast.iter_child_nodes(tree): - if isinstance(node, _ast.AnnAssign) and isinstance(node.target, _ast.Name): - var_name = node.target.id - is_typedef = False - if isinstance(node.annotation, _ast.Attribute) and hasattr(node.annotation, 'attr') and node.annotation.attr == 'CTypedef': + content: str = f.read() + tree: ast.Module = ast.parse(content) + for node in ast.iter_child_nodes(tree): + if isinstance(node, ast.AnnAssign) and isinstance(node.target, ast.Name): + var_name: str = node.target.id + is_typedef: bool = False + if isinstance(node.annotation, ast.Attribute) and hasattr(node.annotation, 'attr') and node.annotation.attr == 'CTypedef': is_typedef = True - elif isinstance(node.annotation, _ast.Name) and node.annotation.id == 'CTypedef': + elif isinstance(node.annotation, ast.Name) and node.annotation.id == 'CTypedef': is_typedef = True - elif isinstance(node.annotation, _ast.BinOp) and isinstance(node.annotation.left, _ast.Attribute) and hasattr(node.annotation.left, 'attr') and node.annotation.left.attr == 'CTypedef': + elif isinstance(node.annotation, ast.BinOp) and isinstance(node.annotation.left, ast.Attribute) and hasattr(node.annotation.left, 'attr') and node.annotation.left.attr == 'CTypedef': is_typedef = True if is_typedef and node.value and var_name not in typedef_map: typedef_map[var_name] = node.value except Exception as _e: - from lib.core.VLogger import get_logger as _vlog - from lib.constants.config import mode as _ConfigMode if _ConfigMode == "strict": raise _vlog().warning(f"收集 typedef 映射失败: {_e}", "Exception") return typedef_map - def _process_include_py_files_stub(self, struct_names: set, needed_includes: list = None, enum_names: set = None, struct_sha1_map: dict = None, exception_names: set = None): + def _process_include_py_files_stub(self, struct_names: set[str], needed_includes: list[tuple[str, str, str]] | None = None, enum_names: set[str] | None = None, struct_sha1_map: dict[str, str] | None = None, exception_names: set[str] | None = None) -> None: + include_py_files: list[tuple[str, str, str]] if needed_includes is not None: include_py_files = needed_includes else: include_py_files = self._collect_include_py_files() if not include_py_files: return - typedef_map = self._collect_typedef_map() + typedef_map: dict[str, ast.AST] = self._collect_typedef_map() for src_path, rel_from_inc, includes_dir in include_py_files: - ModulePath = rel_from_inc.replace(os.sep, '.').replace('/', '.') - module_name = os.path.splitext(ModulePath)[0] + ModulePath: str = rel_from_inc.replace(os.sep, '.').replace('/', '.') + module_name: str = os.path.splitext(ModulePath)[0] try: with open(src_path, 'r', encoding='utf-8') as f: - content = f.read() - sha1 = compute_sha1(content) + content: str = f.read() + sha1: str = compute_sha1(content) - stub_path = os.path.join(self.temp_dir, f"{sha1}.stub.ll") + stub_path: str = os.path.join(self.temp_dir, f"{sha1}.stub.ll") if os.path.isfile(stub_path): - print(f" 缓存命中: {rel_from_inc} -> {sha1}.stub.ll") + _vlog().info(f" 缓存命中: {rel_from_inc} -> {sha1}.stub.ll") continue - sig_path = os.path.join(self.temp_dir, f"{sha1}.pyi") + sig_path: str = os.path.join(self.temp_dir, f"{sha1}.pyi") with open(sig_path, 'r', encoding='utf-8') as f: - sig_content = f.read() + sig_content: str = f.read() self._generate_decl_ll(sig_content, stub_path, src_path, struct_names, enum_names=enum_names, module_sha1=sha1, struct_sha1_map=struct_sha1_map, exception_names=exception_names, typedef_map=typedef_map) - print(f" 生成声明: {rel_from_inc} -> {sha1}.stub.ll") + _vlog().info(f" 生成声明: {rel_from_inc} -> {sha1}.stub.ll") except Exception as e: - print(f" [错误] {rel_from_inc}: {e}") + _vlog().error(f"处理 include 文件失败 {rel_from_inc}: {e}") - def _process_file_pyi(self, src_path: str, rel_path: str): + def _process_file_pyi(self, src_path: str, rel_path: str) -> None: with open(src_path, 'r', encoding='utf-8') as f: - content = f.read() + content: str = f.read() - sha1 = compute_sha1(content) + sha1: str = compute_sha1(content) self.sha1_map[sha1] = rel_path - sig_path = os.path.join(self.temp_dir, f"{sha1}.pyi") + sig_path: str = os.path.join(self.temp_dir, f"{sha1}.pyi") if os.path.isfile(sig_path): - print(f" -> {sha1}.pyi (缓存)") + _vlog().info(f" -> {sha1}.pyi (缓存)") return - module_name = os.path.splitext(rel_path)[0].replace(os.sep, '.').replace('/', '.') - sig_content = PythonToStubConverter.convert(content, module_name) + module_name: str = os.path.splitext(rel_path)[0].replace(os.sep, '.').replace('/', '.') + sig_content: str = PythonToStubConverter.convert(content, module_name) with open(sig_path, 'w', encoding='utf-8', newline='\n') as f: f.write(sig_content) - print(f" -> {sha1}.pyi (签名)") + _vlog().info(f" -> {sha1}.pyi (签名)") - def _process_file_stub(self, src_path: str, rel_path: str, struct_names: set, enum_names: set = None, struct_sha1_map: dict = None, exception_names: set = None): + def _process_file_stub(self, src_path: str, rel_path: str, struct_names: set[str], enum_names: set[str] | None = None, struct_sha1_map: dict[str, str] | None = None, exception_names: set[str] | None = None) -> None: with open(src_path, 'r', encoding='utf-8') as f: - content = f.read() + content: str = f.read() - sha1 = compute_sha1(content) - stub_path = os.path.join(self.temp_dir, f"{sha1}.stub.ll") + sha1: str = compute_sha1(content) + stub_path: str = os.path.join(self.temp_dir, f"{sha1}.stub.ll") if os.path.isfile(stub_path): - print(f" -> {sha1}.stub.ll (缓存)") + _vlog().info(f" -> {sha1}.stub.ll (缓存)") return - sig_path = os.path.join(self.temp_dir, f"{sha1}.pyi") + sig_path: str = os.path.join(self.temp_dir, f"{sha1}.pyi") with open(sig_path, 'r', encoding='utf-8') as f: - sig_content = f.read() + sig_content: str = f.read() - typedef_map = self._collect_typedef_map() + typedef_map: dict[str, ast.AST] = self._collect_typedef_map() self._generate_decl_ll(sig_content, stub_path, src_path, struct_names, enum_names=enum_names, module_sha1=sha1, struct_sha1_map=struct_sha1_map, exception_names=exception_names, typedef_map=typedef_map) - print(f" -> {sha1}.stub.ll (声明)") + _vlog().info(f" -> {sha1}.stub.ll (声明)") - def _build_struct_registry(self): - struct_names = set() - enum_names = set() - exception_names = set() - struct_sha1_map = {} - valid_sha1_keys = set(self.sha1_map.keys()) + def _build_struct_registry(self) -> tuple[set[str], set[str], dict[str, str], set[str]]: + struct_names: set[str] = set() + enum_names: set[str] = set() + exception_names: set[str] = set() + struct_sha1_map: dict[str, str] = {} + valid_sha1_keys: set[str] = set(self.sha1_map.keys()) for fname in os.listdir(self.temp_dir): if not fname.endswith('.pyi'): continue - sha1_key = fname.replace('.pyi', '') + sha1_key: str = fname.replace('.pyi', '') if sha1_key not in valid_sha1_keys: continue - pyi_path = os.path.join(self.temp_dir, fname) + pyi_path: str = os.path.join(self.temp_dir, fname) try: with open(pyi_path, 'r', encoding='utf-8') as f: - content = f.read() - tree = ast.parse(content) + content: str = f.read() + tree: ast.Module = ast.parse(content) for node in ast.iter_child_nodes(tree): if isinstance(node, ast.ClassDef): - is_enum = False - is_exception = False + is_enum: bool = False + is_exception: bool = False if node.bases: for base in node.bases: if isinstance(base, ast.Attribute) and hasattr(base, 'attr'): - if base.attr in ('CEnum', 'Enum'): + if base.attr in ('CEnum', 'Enum', 'REnum'): is_enum = True break elif base.attr == 'Exception' or base.attr in exception_names: is_exception = True break elif isinstance(base, ast.Name) and hasattr(base, 'id'): - if base.id in ('CEnum', 'Enum'): + if base.id in ('CEnum', 'Enum', 'REnum'): is_enum = True break elif base.id == 'Exception' or base.id in exception_names: is_exception = True break + # 也检查装饰器形式 @t.CEnum / @t.REnum + if not is_enum and not is_exception and hasattr(node, 'decorator_list') and node.decorator_list: + for deco in node.decorator_list: + deco_attr: str | None = None + if isinstance(deco, ast.Attribute) and hasattr(deco, 'attr'): + deco_attr = deco.attr + elif isinstance(deco, ast.Name) and hasattr(deco, 'id'): + deco_attr = deco.id + if deco_attr in ('CEnum', 'Enum', 'REnum'): + is_enum = True + break if is_enum: enum_names.add(node.name) elif is_exception: @@ -319,20 +376,18 @@ class Phase1Generator: struct_names.add(node.name) struct_sha1_map[node.name] = sha1_key except Exception as _e: - from lib.core.VLogger import get_logger as _vlog - from lib.constants.config import mode as _ConfigMode if _ConfigMode == "strict": raise _vlog().warning(f"构建结构体/枚举注册表失败: {_e}", "Exception") return struct_names, enum_names, struct_sha1_map, exception_names - def _generate_decl_ll(self, pyi_content: str, ll_path: str, src_path: str, struct_names: set = None, enum_names: set = None, module_sha1: str = None, struct_sha1_map: dict = None, exception_names: set = None, typedef_map: dict = None): + def _generate_decl_ll(self, pyi_content: str, ll_path: str, src_path: str, struct_names: set[str] | None = None, enum_names: set[str] | None = None, module_sha1: str | None = None, struct_sha1_map: dict[str, str] | None = None, exception_names: set[str] | None = None, typedef_map: dict[str, ast.AST] | None = None) -> None: try: - decl_gen = DeclarationGenerator(struct_names=struct_names, enum_names=enum_names, module_sha1=module_sha1, target_triple=self.target_triple, target_datalayout=self.target_datalayout, struct_sha1_map=struct_sha1_map, exception_names=exception_names, typedef_map=typedef_map) - decl_ll = decl_gen.generate(pyi_content, src_path) + decl_gen: DeclarationGenerator = DeclarationGenerator(struct_names=struct_names, enum_names=enum_names, module_sha1=module_sha1, target_triple=self.target_triple, target_datalayout=self.target_datalayout, struct_sha1_map=struct_sha1_map, exception_names=exception_names, typedef_map=typedef_map) + decl_ll: str = decl_gen.generate(pyi_content, src_path) with open(ll_path, 'w', encoding='utf-8', newline='\n') as f: f.write(decl_ll) except Exception as e: - print(f" [警告] .ll 声明生成失败: {e}") + _vlog().warning(f".ll 声明生成失败: {e}") with open(ll_path, 'w', encoding='utf-8') as f: f.write(f"; declaration for {os.path.basename(src_path)}\n; error: {e}\n") diff --git a/lib/Projectrans/Phase2Translator.py b/lib/Projectrans/Phase2Translator.py index 61d7eab..323b008 100644 --- a/lib/Projectrans/Phase2Translator.py +++ b/lib/Projectrans/Phase2Translator.py @@ -1,11 +1,20 @@ -import sys -import os -import re -import shutil -import subprocess -import ast -import traceback -import json +from __future__ import annotations + +import sys +import os +import re +import shutil +import subprocess +import ast +import traceback +import json +import io +from lib.Shell.Serializer import deSerializeSymbolTable, SerializeSymbolTable +import time +import copy +from concurrent.futures import ProcessPoolExecutor, ThreadPoolExecutor, as_completed +from lib.core.VLogger import get_logger as _vlog +from lib.constants.config import mode as _config_mode from lib.core.Handles.HandlesBase import CTypeInfo from lib.includes import t from lib.Projectrans.Utils import compute_sha1, _check_annotation_for_export, find_reachable_files_from_entries, topological_sort_files @@ -13,14 +22,35 @@ import TransPyC from StubGen import PythonToStubConverter -def _parallel_translate_worker(src_path, out_path, src_root, temp_dir, output_dir, - include_dirs, triple, datalayout, sha1_map, sig_files, - stub_files, include_py_map, slice_level, - shared_sym_pickle_path, struct_sha1_map): +def _ExtractCDefineConstantsFromPyi(pyi_path: str, all_dc: dict[str, object]) -> None: + """从 .pyi 文件中提取 CDefine 常量到 all_dc。文件不存在时静默跳过。""" + if not os.path.exists(pyi_path): + return + try: + with open(pyi_path, 'r', encoding='utf-8') as f: + pyi_content = f.read() + tree = ast.parse(pyi_content) + for node in ast.iter_child_nodes(tree): + if isinstance(node, ast.AnnAssign) and isinstance(node.target, ast.Name): + ann_str = ast.dump(node.annotation) + if 'CDefine' in ann_str and node.value: + val = None + if isinstance(node.value, ast.Constant): + val = node.value.value + elif isinstance(node.value, ast.Call) and isinstance(node.value.func, ast.Name) and node.value.func.id == 'float' and node.value.args and isinstance(node.value.args[0], ast.Constant): + val = node.value.args[0].value + if val is not None: + all_dc[f"{node.target.id}"] = val + except Exception as e: + _vlog().warning(f"Phase2Translator: 忽略异常 {e}", exc_info=e) + + +def _parallel_translate_worker(src_path: str, out_path: str, src_root: str, temp_dir: str, output_dir: str, + include_dirs: list[str], triple: str | None, datalayout: str | None, + sha1_map: dict[str, str], sig_files: dict[str, str], + stub_files: dict[str, str], include_py_map: dict[str, str], slice_level: int, + shared_sym_pickle_path: str, struct_sha1_map: dict[str, str]) -> tuple[str, str, str]: try: - import pickle - from lib.Projectrans import Phase2Translator - from lib.Projectrans.Utils import compute_sha1 trans = Phase2Translator(src_root, temp_dir, output_dir, compile_cmd='llc', include_dirs=include_dirs, target_triple=triple, target_datalayout=datalayout) @@ -33,7 +63,7 @@ def _parallel_translate_worker(src_path, out_path, src_root, temp_dir, output_di if shared_sym_pickle_path and os.path.exists(shared_sym_pickle_path): with open(shared_sym_pickle_path, 'rb') as f: - shared_data = pickle.load(f) + shared_data = deSerializeSymbolTable(f.read()) trans._shared_symbol_table = shared_data['symbol_table'] trans._shared_source_module_sig_files = shared_data['source_module_sig_files'] trans._shared_all_dc = shared_data['all_dc'] @@ -48,21 +78,41 @@ def _parallel_translate_worker(src_path, out_path, src_root, temp_dir, output_di trans._translate_file(src_path, out_path) return ('ok', src_path, '') except Exception as e: - import traceback return ('error', src_path, f'{e}\n{traceback.format_exc()}') # limit +def _count_braces_outside_strings(text: str) -> int: + """统计花括号差值,跳过 c"..." 字符串字面量内部的括号""" + count = 0 + i = 0 + while i < len(text): + if text[i:i+2] == 'c"' and (i == 0 or text[i-1] != '\\'): + # 跳过 c"..." 字面量 + i += 2 + while i < len(text): + if text[i] == '"' and (i == 0 or text[i-1] != '\\'): + i += 1 + break + i += 1 + continue + if text[i] == '{': + count += 1 + elif text[i] == '}': + count -= 1 + i += 1 + return count + + class Phase2Translator: """阶段二:使用声明接口翻译源文件""" - INCLUDE_LIB_EXTENSIONS = ('.dll', '.ll', '.so', '.o', '.a', '.lib') - INCLUDE_SRC_EXTENSIONS = ('.c', '.cpp', '.cc', '.cxx', '.m', '.mm') - INCLUDE_DIRS = [ + INCLUDE_LIB_EXTENSIONS: tuple[str, ...] = ('.dll', '.ll', '.so', '.o', '.a', '.lib') + INCLUDE_SRC_EXTENSIONS: tuple[str, ...] = ('.c', '.cpp', '.cc', '.cxx', '.m', '.mm') + INCLUDE_DIRS: list[str] = [ os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))), 'includes'), - r"d:\Users\TermiNexus\Desktop\TransPyC\includes", ] - def __init__(self, src_root: str, temp_dir: str, output_dir: str, compile_cmd: str = 'llc', compile_flags: list = None, linker_cmd: str = None, linker_flags: list = None, linker_output: str = None, include_dirs: list = None, entry_files: list = None, target_triple: str = None, target_datalayout: str = None, startup=None): + def __init__(self, src_root: str, temp_dir: str, output_dir: str, compile_cmd: str = 'llc', compile_flags: list[str] | None = None, linker_cmd: str | None = None, linker_flags: list[str] | None = None, linker_output: str | None = None, include_dirs: list[str] | None = None, entry_files: list[str] | None = None, target_triple: str | None = None, target_datalayout: str | None = None, startup: bool | dict[str, str] | None = None) -> None: self.src_root = os.path.abspath(src_root) self.temp_dir = os.path.abspath(temp_dir) self.output_dir = os.path.abspath(output_dir) @@ -84,21 +134,24 @@ class Phase2Translator: self.sig_files: dict[str, str] = {} self.stub_files: dict[str, str] = {} self.include_py_map: dict[str, str] = {} - self.used_includes: set = set() - self._last_ErrorStack = None - self.function_default_args: dict = {} - self.inline_func_symbols: dict = {} - self.extra_link_files: list = [] - self.extra_compile_files: list = [] - self.extra_py_files: list = [] - self._include_sha1s: set = set() - self.entry_files = entry_files - self.startup = startup # None | True | dict (如 {"__main": "main"}) - self._shared_symbol_table = None - self._shared_source_module_sig_files = {} - self._shared_all_dc = {} - self._shared_export_extern_funcs = set() - self._stub_decls_cache = {} + self.used_includes: set[str] = set() + self._last_ErrorStack: list | None = None + self.function_default_args: dict[str, list] = {} + self.inline_func_symbols: dict[str, CTypeInfo] = {} + self.extra_link_files: list[str] = [] + self.extra_compile_files: list[str] = [] + self.extra_py_files: list[str] = [] + self._include_sha1s: set[str] = set() + self.entry_files: list[str] | None = entry_files + self.startup: bool | dict[str, str] | None = startup # None | True | dict (如 {"__main": "main"}) + self._shared_symbol_table: object | None = None + self._shared_source_module_sig_files: dict[str, str] = {} + self._shared_all_dc: dict[str, dict] = {} + self._shared_export_extern_funcs: set[str] = set() + self._stub_decls_cache: dict[str, str] = {} + self.include_dirs: list[str] = [] + self.struct_sha1_map: dict[str, str] = {} + self._shared_generic_class_templates: dict[str, dict] = {} default_dirs = [d for d in self.INCLUDE_DIRS if os.path.isdir(d)] if include_dirs: seen = set() @@ -112,10 +165,10 @@ class Phase2Translator: self.include_dirs = default_dirs self._LoadSha1Map() - def _LoadSha1Map(self): + def _LoadSha1Map(self) -> None: """从 temp_dir 加载 SHA1 映射、签名文件和 stub 声明文件列表""" if not os.path.exists(self.temp_dir): - print(f"[错误] 声明目录不存在: {self.temp_dir}") + _vlog().error(f"声明目录不存在: {self.temp_dir}") return for fname in os.listdir(self.temp_dir): @@ -144,7 +197,7 @@ class Phase2Translator: for sha1, stub_path in self.stub_files.items(): self.sha1_map[sha1] = sha1 - def _build_struct_sha1_map(self): + def _build_struct_sha1_map(self) -> dict[str, str]: struct_sha1_map = {} valid_sha1_keys = set(self.sha1_map.keys()) for fname in os.listdir(self.temp_dir): @@ -158,8 +211,6 @@ class Phase2Translator: with open(pyi_path, 'r', encoding='utf-8') as f: tree = ast.parse(f.read()) except Exception as _e: - from lib.core.VLogger import get_logger as _vlog - from lib.constants.config import mode as _config_mode if _config_mode == "strict": raise _vlog().warning(f"解析 .pyi 签名文件失败: {_e}", "Exception") @@ -169,7 +220,7 @@ class Phase2Translator: struct_sha1_map[node.name] = sha1_key return struct_sha1_map - def run(self): + def run(self) -> None: """扫描源目录,翻译并生成 .ll 含代码文件(导入遍历)""" if self.entry_files: py_files = list(self.entry_files) @@ -186,7 +237,7 @@ class Phase2Translator: py_files.append(os.path.join(root, file)) if not py_files: - print("[阶段二] 未找到入口文件或源文件") + _vlog().info("未找到入口文件或源文件") return reachable = find_reachable_files_from_entries(self.src_root, py_files) @@ -194,11 +245,11 @@ class Phase2Translator: py_files = topological_sort_files(py_files, self.src_root) - print(f"[阶段二] 找到 {len(py_files)} 个可达源文件(已按依赖排序)") - print("[阶段二] 处理顺序:") + _vlog().info(f"找到 {len(py_files)} 个可达源文件(已按依赖排序)") + _vlog().info("处理顺序:") for i, f in enumerate(py_files[:10], 1): rel = os.path.relpath(f, self.src_root) - print(f" {i}. {rel}") + _vlog().info(f" {i}. {rel}") os.makedirs(self.output_dir, exist_ok=True) valid_sha1s = set(self.sha1_map.keys()) @@ -207,7 +258,7 @@ class Phase2Translator: self.stub_files = {k: v for k, v in self.stub_files.items() if k in valid_sha1s} self.sig_files = {k: v for k, v in self.sig_files.items() if k in valid_sha1s} if old_stub_count != len(self.stub_files) or old_sig_count != len(self.sig_files): - print(f"[阶段二] 过滤旧文件: stub {old_stub_count}->{len(self.stub_files)}, sig {old_sig_count}->{len(self.sig_files)}") + _vlog().info(f"过滤旧文件: stub {old_stub_count}->{len(self.stub_files)}, sig {old_sig_count}->{len(self.sig_files)}") active_sha1s = set() self._precollect_inline_symbols() @@ -234,9 +285,28 @@ class Phase2Translator: elif isinstance(node, ast.ImportFrom): if node.module: self.used_includes.add(node.module.split('.')[0]) + # 检测 list/dict 容器使用,自动添加 _list/_dict/json 到 used_includes + # 以便 _scan_include_libraries 能发现并编译这些库文件 + if isinstance(node, ast.Subscript) and isinstance(node.value, ast.Name): + if node.value.id == 'dict': + self.used_includes.add('_dict') + self.used_includes.add('json') + elif node.value.id == 'list': + self.used_includes.add('_list') + if isinstance(node, ast.Call) and isinstance(node.func, ast.Name): + if node.func.id == 'dict': + self.used_includes.add('_dict') + self.used_includes.add('json') + elif node.func.id == 'list': + self.used_includes.add('_list') + # 检测类型注解 d: dict / l: list (非泛型形式) + if isinstance(node, ast.AnnAssign) and isinstance(node.annotation, ast.Name): + if node.annotation.id == 'dict': + self.used_includes.add('_dict') + self.used_includes.add('json') + elif node.annotation.id == 'list': + self.used_includes.add('_list') except Exception as _e: - from lib.core.VLogger import get_logger as _vlog - from lib.constants.config import mode as _config_mode if _config_mode == "strict": raise _vlog().warning(f"收集源文件导入的 include 模块失败: {_e}", "Exception") @@ -244,37 +314,34 @@ class Phase2Translator: if os.path.isfile(out_path): deps_changed = self._check_deps_changed(sha1, current_ModuleSha1Map) if not deps_changed: - print(f"[{i}/{len(py_files)}] 跳过(缓存): {rel} -> {sha1}.ll") + _vlog().info(f"[{i}/{len(py_files)}] 跳过(缓存): {rel} -> {sha1}.ll") continue else: if self._recombine_ll(sha1, current_ModuleSha1Map): - print(f"[{i}/{len(py_files)}] 重组(依赖变化): {rel} -> {sha1}.ll") + _vlog().info(f"[{i}/{len(py_files)}] 重组(依赖变化): {rel} -> {sha1}.ll") continue - print(f"[{i}/{len(py_files)}] 重译(依赖变化): {rel} -> {sha1}.ll") + _vlog().info(f"[{i}/{len(py_files)}] 重译(依赖变化): {rel} -> {sha1}.ll") else: stub_cache = os.path.join(self.output_dir, f"{sha1}.stub.ll") text_cache = os.path.join(self.output_dir, f"{sha1}.text.ll") if os.path.isfile(stub_cache) and os.path.isfile(text_cache): if self._recombine_ll(sha1, current_ModuleSha1Map): - print(f"[{i}/{len(py_files)}] 重组(缓存恢复): {rel} -> {sha1}.ll") + _vlog().info(f"[{i}/{len(py_files)}] 重组(缓存恢复): {rel} -> {sha1}.ll") continue need_translate.append((i, src_path, out_path, sha1, current_ModuleSha1Map)) if need_translate: - print(f"\n[阶段二] 需要翻译 {len(need_translate)} 个文件") - import time + _vlog().info(f"\n需要翻译 {len(need_translate)} 个文件") t_start = time.time() n_workers = min(os.cpu_count() or 4, len(need_translate), 8) if n_workers > 1 and len(need_translate) > 1: - from concurrent.futures import ProcessPoolExecutor, as_completed - import pickle - print(f" 并行翻译 (workers={n_workers})") + _vlog().info(f" 并行翻译 (workers={n_workers})") - shared_pickle_path = os.path.join(self.temp_dir, '_shared_sym.pkl') + shared_pickle_path = os.path.join(self.temp_dir, '_shared_sym.json') try: shared_data = { 'symbol_table': self._shared_symbol_table, @@ -286,10 +353,10 @@ class Phase2Translator: 'generic_class_templates': self._shared_generic_class_templates, } with open(shared_pickle_path, 'wb') as f: - pickle.dump(shared_data, f, protocol=pickle.HIGHEST_PROTOCOL) - print(f" 共享符号表已序列化 ({os.path.getsize(shared_pickle_path)//1024}KB)") + f.write(SerializeSymbolTable(shared_data)) + _vlog().info(f" 共享符号表已序列化 ({os.path.getsize(shared_pickle_path)//1024}KB)") except Exception as e: - print(f" [警告] 符号表序列化失败({e}),worker将自行构建") + _vlog().warning(f"符号表序列化失败({e}),worker将自行构建") shared_pickle_path = '' errors = [] @@ -315,16 +382,16 @@ class Phase2Translator: try: status, _, err = future.result() if status == 'ok': - print(f" [{done_count}/{len(need_translate)}] 完成: {rel}") + _vlog().info(f" [{done_count}/{len(need_translate)}] 完成: {rel}") else: - print(f" [错误] {rel}: {err}") + _vlog().error(f" {rel}: {err}") errors.append((rel, err)) except Exception as e: - print(f" [错误] {rel}: {e}") + _vlog().error(f" {rel}: {e}") errors.append((rel, str(e))) if errors: - print(f"\n[编译终止] {len(errors)} 个文件翻译失败") + _vlog().error(f"\n{len(errors)} 个文件翻译失败") sys.exit(1) else: for idx, (i, src_path, out_path, sha1, msm) in enumerate(need_translate): @@ -333,16 +400,16 @@ class Phase2Translator: try: self._translate_file(src_path, out_path, prebuilt_ModuleSha1Map=msm) t1 = time.time() - print(f" [{idx+1}/{len(need_translate)}] {rel} ({t1-t0:.1f}s)") + _vlog().info(f" [{idx+1}/{len(need_translate)}] {rel} ({t1-t0:.1f}s)") except Exception as e: - print(f" [错误] {rel}: {e}") + _vlog().error(f" {rel}: {e}") traceback.print_exc() - print(f"\n[编译终止] 翻译失败") + _vlog().error(f"\n翻译失败") sys.exit(1) t_end = time.time() - print(f" 翻译总耗时: {t_end-t_start:.1f}s") + _vlog().info(f" 翻译总耗时: {t_end-t_start:.1f}s") - print(f"\n[阶段二完成] .ll 文件生成到: {self.output_dir}") + _vlog().info(f"\n[阶段二完成] .ll 文件生成到: {self.output_dir}") self._scan_include_libraries() self._compile_include_py_files(active_sha1s) self._compile_ll_files(active_sha1s) @@ -350,7 +417,7 @@ class Phase2Translator: if self.linker_cmd: self._link_obj_files(active_sha1s) - def _build_current_ModuleSha1Map(self, self_sha1: str) -> dict: + def _build_current_ModuleSha1Map(self, self_sha1: str | None) -> dict[str, str]: """构建当前模块的依赖 SHA1 映射(与 _translate_file 中逻辑一致)""" ModuleSha1Map = {} for sha1_key, sig_path in self.sig_files.items(): @@ -385,13 +452,68 @@ class Phase2Translator: return ModuleSha1Map @staticmethod - def _split_ll(ll_content: str): + def _extract_llvm_type_name(line: str) -> str | None: + """从 LLVM IR 类型定义行提取类型名(字符串操作,不使用正则) + + 支持 list[str]、dict[str, int] 等含特殊字符的类型名。 + 例如: + %"18e6990aa81cc5b6.list[str]" = type { ... } → "18e6990aa81cc5b6.list[str]" + %struct.foo = type { ... } → "struct.foo" + """ + stripped = line.strip() + if not stripped.startswith('%'): + return None + # 处理带引号的情况: %"name" = type ... + if stripped.startswith('%"'): + end_quote = stripped.find('"', 2) + if end_quote > 0: + return stripped[2:end_quote] + return None + # 处理不带引号的情况: %name = type ... + eq_pos = stripped.find('=') + if eq_pos > 1: + return stripped[1:eq_pos].strip() + return None + + @staticmethod + def _find_all_type_refs(text: str) -> set[str]: + """查找文本中所有 %"..."/%name 类型引用(字符串操作,不使用正则) + + 支持 list[str]、dict[str, int] 等含特殊字符的类型名。 + """ + refs: set[str] = set() + i: int = 0 + n: int = len(text) + while i < n: + if text[i] == '%': + if i + 1 < n and text[i + 1] == '"': + # 带引号: %"name" + end: int = text.find('"', i + 2) + if end > 0: + name: str = text[i + 2:end] + if name: + refs.add(name) + i = end + 1 + continue + else: + # 不带引号: %name (仅匹配字母、数字、下划线、点) + j: int = i + 1 + while j < n and (text[j].isalnum() or text[j] in '._'): + j += 1 + if j > i + 1: + refs.add(text[i + 1:j]) + i = j + continue + i += 1 + return refs + + @staticmethod + def _split_ll(ll_content: str) -> tuple[str, str]: """将 .ll 内容拆分为 stub(声明)和 text(代码)两部分 stub: target, 注释, %type = type, declare, @xxx = external global text: define ... { ... }, @xxx = global/constant (带初始化器) """ - import re stub_lines = [] text_lines = [] in_define = False @@ -421,7 +543,7 @@ class Phase2Translator: if in_global_def: text_lines.append(line) global_type_parts.append(stripped) - global_brace_depth += stripped.count('{') - stripped.count('}') + global_brace_depth += _count_braces_outside_strings(stripped) if global_brace_depth <= 0: full_type = ' '.join(global_type_parts).strip() depth = 0 @@ -445,7 +567,7 @@ class Phase2Translator: if in_define: text_lines.append(line) - brace_depth += stripped.count('{') - stripped.count('}') + brace_depth += _count_braces_outside_strings(stripped) if brace_depth <= 0: in_define = False continue @@ -453,7 +575,7 @@ class Phase2Translator: if stripped.startswith('define '): text_lines.append(line) in_define = True - brace_depth = stripped.count('{') - stripped.count('}') + brace_depth = _count_braces_outside_strings(stripped) decl_line = re.sub(r'^define\s+', 'declare ', stripped) decl_line = re.sub(r'\b(linkonce_odr|weak_odr|linkonce|weak|common|appending|internal|private)\s+', '', decl_line) decl_line = re.sub(r'\balwaysinline\s+', '', decl_line) @@ -537,7 +659,7 @@ class Phase2Translator: return ''.join(stub_lines), ''.join(text_lines) - def _save_deps(self, sha1: str, ModuleSha1Map: dict): + def _save_deps(self, sha1: str, ModuleSha1Map: dict[str, str]) -> None: """保存依赖指纹到 .deps.json""" deps_path = os.path.join(self.output_dir, f"{sha1}.deps.json") deps = {} @@ -546,7 +668,7 @@ class Phase2Translator: with open(deps_path, 'w', encoding='utf-8') as f: json.dump(deps, f) - def _LoadDeps(self, sha1: str) -> dict: + def _LoadDeps(self, sha1: str) -> dict[str, str] | None: """加载依赖指纹""" deps_path = os.path.join(self.output_dir, f"{sha1}.deps.json") if os.path.isfile(deps_path): @@ -554,14 +676,12 @@ class Phase2Translator: with open(deps_path, 'r', encoding='utf-8') as f: return json.load(f) except Exception as _e: - from lib.core.VLogger import get_logger as _vlog - from lib.constants.config import mode as _config_mode if _config_mode == "strict": raise _vlog().warning(f"加载依赖指纹 JSON 失败: {_e}", "Exception") return None - def _check_deps_changed(self, sha1: str, current_ModuleSha1Map: dict) -> bool: + def _check_deps_changed(self, sha1: str, current_ModuleSha1Map: dict[str, str]) -> bool: """检查依赖指纹是否变化""" saved_deps = self._LoadDeps(sha1) if saved_deps is None: @@ -574,7 +694,7 @@ class Phase2Translator: return True return False - def _recombine_ll(self, sha1: str, current_ModuleSha1Map: dict) -> bool: + def _recombine_ll(self, sha1: str, current_ModuleSha1Map: dict[str, str]) -> bool: """依赖变化时重新组合 .ll:更新 .stub.ll 中的 SHA1 前缀,拼接 .stub.ll + .text.ll""" saved_deps = self._LoadDeps(sha1) if saved_deps is None: @@ -623,13 +743,88 @@ class Phase2Translator: return True - def _translate_file(self, src_path: str, out_path: str, prebuilt_ModuleSha1Map: dict = None): + def _inject_auto_imports(self, code: str, src_path: str) -> str: + """检测源码中对 list/dict 容器的使用,自动注入 import _list / import _dict。 + 当使用 dict 时,同时注入 import json (用于 dict 的 JSON 处理功能)。 + + 检测模式: + - list[T] / dict[V] 作为类型注解 (ast.Subscript, value=Name(id='list'/'dict')) + - list[T](...) / dict[V](...) 作为构造函数调用 (ast.Call, func=Subscript) + - list(...) / dict(...) 作为构造函数调用 (ast.Call, func=Name) + """ + try: + tree = ast.parse(code) + except SyntaxError: + return code + + # 检查是否已经导入了 _list / _dict / json + has_list_import: bool = False + has_dict_import: bool = False + has_json_import: bool = False + for node in ast.iter_child_nodes(tree): + if isinstance(node, ast.Import): + for alias in node.names: + if alias.name == '_list': + has_list_import = True + elif alias.name == '_dict': + has_dict_import = True + elif alias.name == 'json': + has_json_import = True + elif isinstance(node, ast.ImportFrom): + if node.module == '_list': + has_list_import = True + elif node.module == '_dict': + has_dict_import = True + elif node.module == 'json': + has_json_import = True + if has_list_import and has_dict_import and has_json_import: + break + + # 检查是否使用了 list / dict 容器 + uses_list: bool = False + uses_dict: bool = False + for node in ast.walk(tree): + if isinstance(node, ast.Subscript): + if isinstance(node.value, ast.Name): + if node.value.id == 'list': + uses_list = True + elif node.value.id == 'dict': + uses_dict = True + if isinstance(node, ast.Call) and isinstance(node.func, ast.Name): + if node.func.id == 'list': + uses_list = True + elif node.func.id == 'dict': + uses_dict = True + # 检测类型注解 d: dict / l: list (非泛型形式) + if isinstance(node, ast.AnnAssign) and isinstance(node.annotation, ast.Name): + if node.annotation.id == 'dict': + uses_dict = True + elif node.annotation.id == 'list': + uses_list = True + + # 注入 import 到源码开头 + prefix: str = '' + if uses_list and not has_list_import: + prefix += 'import _list\n' + if uses_dict and not has_dict_import: + prefix += 'import _dict\n' + if uses_dict and not has_json_import: + prefix += 'import json\n' + if prefix: + return prefix + code + return code + + def _translate_file(self, src_path: str, out_path: str, prebuilt_ModuleSha1Map: dict[str, str] | None = None) -> None: """翻译单个源文件,嵌入相关 .stub.ll 声明""" with open(src_path, 'r', encoding='utf-8') as f: code = f.read() + # SHA1 必须在自动导入注入之前计算,以保持与 Phase1 生成的文件名/函数名前缀一致 sha1 = compute_sha1(code) + # 自动导入: 检测 list 容器使用,自动注入 import _list + code = self._inject_auto_imports(code, src_path) + if prebuilt_ModuleSha1Map is not None: ModuleSha1Map = prebuilt_ModuleSha1Map else: @@ -674,8 +869,6 @@ class Phase2Translator: if _check_annotation_for_export(node.returns): export_extern_funcs.add(node.name) except Exception as _e: - from lib.core.VLogger import get_logger as _vlog - from lib.constants.config import mode as _config_mode if _config_mode == "strict": raise _vlog().warning(f"收集导出外部函数声明失败: {_e}", "Exception") @@ -690,7 +883,7 @@ class Phase2Translator: module_name = os.path.splitext(pyi_file)[0] trans.translator.SymbolTable.LoadModuleSymbols(pyi_path, module_name, lineno=0) for py_file in os.listdir(includes_dir): - if py_file.endswith('.py') and not py_file.startswith('_'): + if py_file.endswith('.py') and (not py_file.startswith('_') or py_file == '_list.py' or py_file == '_dict.py'): module_name = os.path.splitext(py_file)[0] sha1_key = self.include_py_map.get(module_name) if sha1_key and sha1_key in self.sig_files: @@ -741,32 +934,14 @@ class Phase2Translator: try: val = int(val_part) all_dc[var_name] = val - except: - pass - except: - pass + except Exception as e: + _vlog().warning(f"Phase2Translator: 忽略异常 {e}", exc_info=e) + except Exception as e: + _vlog().warning(f"Phase2Translator: 忽略异常 {e}", exc_info=e) for sha1_key, pyi_path in self.sig_files.items(): if sha1_key == sha1: continue - if os.path.exists(pyi_path): - try: - import ast as _ast - with open(pyi_path, 'r', encoding='utf-8') as f: - pyi_content = f.read() - tree = _ast.parse(pyi_content) - for node in _ast.iter_child_nodes(tree): - if isinstance(node, _ast.AnnAssign) and isinstance(node.target, _ast.Name): - ann_str = _ast.dump(node.annotation) - if 'CDefine' in ann_str and node.value: - val = None - if isinstance(node.value, _ast.Constant): - val = node.value.value - elif isinstance(node.value, _ast.Call) and isinstance(node.value.func, _ast.Name) and node.value.func.id == 'float' and node.value.args and isinstance(node.value.args[0], _ast.Constant): - val = node.value.args[0].value - if val is not None: - all_dc[f"{node.target.id}"] = val - except: - pass + _ExtractCDefineConstantsFromPyi(pyi_path, all_dc) if all_dc: trans.translator._all_define_constants = all_dc @@ -840,7 +1015,7 @@ class Phase2Translator: f.write(text_content) self._save_deps(sha1, ModuleSha1Map) - print(f" -> {os.path.basename(out_path)}") + _vlog().info(f" -> {os.path.basename(out_path)}") else: stub_path = self.stub_files.get(sha1) if stub_path and os.path.exists(stub_path): @@ -851,9 +1026,9 @@ class Phase2Translator: stub_content = f.read() with open(out_path, 'w', encoding='utf-8', newline='\n') as f: f.write(stub_content) - print(f" -> {os.path.basename(out_path)} (仅声明)") + _vlog().info(f" -> {os.path.basename(out_path)} (仅声明)") - def _register_package_reexports(self, trans, init_pyi_path, package_name): + def _register_package_reexports(self, trans, init_pyi_path: str, package_name: str) -> None: """解析 __init__.pyi 中的 from .xxx import yyy 或 from __xxx import yyy,在包级别注册导出符号""" try: with open(init_pyi_path, 'r', encoding='utf-8') as f: @@ -882,7 +1057,7 @@ class Phase2Translator: trans.translator.SymbolTable[exported_name] = trans.translator.SymbolTable[source_key] break except Exception as e: - print(f" [警告] 解析包重导出失败 {init_pyi_path}: {e}") + _vlog().warning(f" [警告] 解析包重导出失败 {init_pyi_path}: {e}") def _collect_stub_decls(self, self_sha1: str) -> str: """收集 includes 目录中模块的 .stub.ll 声明内容,去重""" @@ -936,7 +1111,6 @@ class Phase2Translator: """收集特定模块需要的 .stub.ll 声明(包括结构体类型定义、函数声明和 typedef)""" if self_sha1 in self._stub_decls_cache: return self._stub_decls_cache[self_sha1] - import re seen_symbols = set() seen_func_symbols = set() decl_lines = [] @@ -949,31 +1123,30 @@ class Phase2Translator: 'atomic_int8', 'atomic_uint8', 'atomic_int16', 'atomic_uint16', 'atomic_int32', 'atomic_uint32', 'atomic_int64', 'atomic_uint64', 'atomic_ptr', 'atomic_flag', 'typedef', - 'list', 'dict', 'tuple', 'set', 'str', 'bytes', 'array'} + 'list', 'dict', 'tuple', 'set', 'str', 'bytes', 'array', 'CArray'} struct_names = set() struct_source_sha1 = {} - def _extract_struct_name(type_def_str): - m = re.match(r'%"?((?:[a-f0-9]+\.)?[\w.]+)"?\s*=\s*type', type_def_str) - if m: - raw = m.group(1) + def _extract_struct_name(type_def_str: str) -> tuple[str | None, str | None]: + raw = Phase2Translator._extract_llvm_type_name(type_def_str) + if raw: if '.' in raw: return raw.split('.', 1)[1], raw.split('.', 1)[0] return raw, None return None, None - def _replace_struct_refs(type_str): - def replace_struct_name(name): + def _replace_struct_refs(type_str: str) -> str: + def replace_struct_name(name: str) -> str | None: if name in struct_names: name_sha1 = struct_source_sha1.get(name, '') return f'%"{name_sha1}.{name}"' if name_sha1 else None return None - def replace_struct_match(match): + def replace_struct_match(match: re.Match[str]) -> str: name = match.group(1) replaced = replace_struct_name(name) return replaced if replaced else match.group(0) - def replace_sha1_struct_match(match): + def replace_sha1_struct_match(match: re.Match[str]) -> str: name = match.group(2) replaced = replace_struct_name(name) return replaced if replaced else match.group(0) @@ -1027,7 +1200,7 @@ class Phase2Translator: def _inject_stub_decls(self, ll_content: str, stub_decls: str) -> str: """将 stub 声明注入到 LLVM IR 模块头之后,替换 opaque 类型为具体定义""" - def normalize_type_name(name): + def normalize_type_name(name: str) -> str: name = name.strip() if name.startswith('%'): return '%' + name[1:].strip().strip('"') @@ -1052,7 +1225,7 @@ class Phase2Translator: replacements = {} # line_index -> new_line new_decls = [] # 新类型定义(不在现有输出中的) - def normalize_type_name(name): + def normalize_type_name(name: str) -> str: name = name.strip() if name.startswith('%'): return '%' + name[1:].strip().strip('"') @@ -1122,13 +1295,13 @@ class Phase2Translator: return result - def _compile_ll_files(self, active_sha1s: set): + def _compile_ll_files(self, active_sha1s: set[str]) -> None: """将 output_dir 中属于 active_sha1s 的 .ll 文件编译为 .obj(跳过已编译过的 include 文件)""" stale_files = [] for root, dirs, files in os.walk(self.output_dir): for file in files: fpath = os.path.join(root, file) - for ext in ('.ll', '.obj', '.stub.ll', '.text.ll', '.deps.json', '_dso.ll'): + for ext in ('_dso.ll', '.stub.ll', '.text.ll', '.ll', '.obj', '.deps.json'): if file.endswith(ext): sha1 = file[:-(len(ext))] if sha1 not in active_sha1s: @@ -1138,9 +1311,9 @@ class Phase2Translator: for fpath in stale_files: try: os.remove(fpath) - except: - pass - print(f"[清理] 删除 {len(stale_files)} 个过时文件") + except Exception as e: + _vlog().warning(f"Phase2Translator: 忽略异常 {e}", exc_info=e) + _vlog().info(f"[清理] 删除 {len(stale_files)} 个过时文件") ll_files = [] for root, dirs, files in os.walk(self.output_dir): for file in files: @@ -1152,9 +1325,9 @@ class Phase2Translator: ll_files.append(os.path.join(root, file)) if not ll_files: - print("[编译] 无 .ll 文件需要重新编译") + _vlog().info("[编译] 无 .ll 文件需要重新编译") else: - print(f"\n[编译] 找到 {len(ll_files)} 个 .ll 文件需要编译") + _vlog().info(f"\n[编译] 找到 {len(ll_files)} 个 .ll 文件需要编译") has_inline = False all_ll_files = [] @@ -1171,14 +1344,14 @@ class Phase2Translator: if 'alwaysinline' in content: has_inline = True break - except: - pass + except Exception as e: + _vlog().warning(f"Phase2Translator: 忽略异常 {e}", exc_info=e) if has_inline: llvm_link = shutil.which('llvm-link') or shutil.which('llvm-link.exe') opt_cmd = shutil.which('opt') or shutil.which('opt.exe') if llvm_link and opt_cmd: - print(" [内联] 检测到 alwaysinline 函数,执行跨模块内联优化...") + _vlog().info(" [内联] 检测到 alwaysinline 函数,执行跨模块内联优化...") for ll_path in all_ll_files: try: with open(ll_path, 'r', encoding='utf-8') as f: @@ -1204,27 +1377,26 @@ class Phase2Translator: fixed = ''.join(lines2[:header_end]) + '\n'.join(type_defs) + '\n' + ''.join(lines2[header_end:]) with open(ll_path, 'w', encoding='utf-8') as f: f.write(fixed) - except: - pass + except Exception as e: + _vlog().warning(f"Phase2Translator: 忽略异常 {e}", exc_info=e) merged_ll = os.path.join(self.output_dir, '_merged.ll') optimized_ll = os.path.join(self.output_dir, '_merged_opt.ll') try: link_cmd = [llvm_link] + all_ll_files + ['-o', merged_ll] result = subprocess.run(link_cmd, capture_output=True, text=True) if result.returncode != 0: - print(f" [警告] llvm-link 失败: {result.stderr.strip()},回退到单独编译") + _vlog().warning(f" llvm-link 失败: {result.stderr.strip()},回退到单独编译") has_inline = False else: opt_result_cmd = [opt_cmd, '-passes=always-inline', merged_ll, '-S', '-o', optimized_ll] result = subprocess.run(opt_result_cmd, capture_output=True, text=True) if result.returncode != 0: - print(f" [警告] opt 失败: {result.stderr.strip()},回退到单独编译") + _vlog().warning(f" opt 失败: {result.stderr.strip()},回退到单独编译") has_inline = False else: - print(" [内联] 跨模块内联优化完成") + _vlog().info(" [内联] 跨模块内联优化完成") with open(optimized_ll, 'r', encoding='utf-8') as f: opt_content = f.read() - import re opt_content = re.sub(r'\b(define|declare)\s+(private|internal|available_externally|linkonce|weak|common|appending|extern_weak|linkonce_odr|weak_odr|external)\s+', r'\1 \2 dso_local ', opt_content) opt_content = re.sub(r'\b(define|declare)\s+(?!private|internal|available_externally|linkonce|weak|common|appending|extern_weak|linkonce_odr|weak_odr|external|dso_local|@)', r'\1 dso_local ', opt_content) opt_content = re.sub(r'(@[\w.]+)\s*=\s*(private|internal|available_externally|linkonce|weak|common|appending|extern_weak|linkonce_odr|weak_odr|external)\s+(global|constant)', r'\1 = \2 dso_local \3', opt_content) @@ -1237,7 +1409,7 @@ class Phase2Translator: result = subprocess.run(cmd, capture_output=True, text=True, cwd=self.output_dir) if result.returncode == 0: - print(f" [成功] 合并模块编译完成") + _vlog().success(f" 合并模块编译完成") for ll_path in ll_files: obj_path = ll_path[:-3] + '.obj' sha1_obj = os.path.join(self.output_dir, os.path.basename(ll_path)[:-3] + '.obj') @@ -1245,21 +1417,18 @@ class Phase2Translator: os.remove(sha1_obj) return else: - print(f" [警告] 合并模块编译失败: {result.stderr.strip()},回退到单独编译") + _vlog().warning(f" 合并模块编译失败: {result.stderr.strip()},回退到单独编译") has_inline = False except Exception as e: - print(f" [警告] 合并模块编译异常: {e},回退到单独编译") + _vlog().warning(f" 合并模块编译异常: {e},回退到单独编译") has_inline = False except FileNotFoundError: - print(f" [警告] 找不到 llvm-link 或 opt,回退到单独编译") + _vlog().warning(f" 找不到 llvm-link 或 opt,回退到单独编译") has_inline = False else: - print(" [警告] 未找到 llvm-link/opt 工具,回退到单独编译(alwaysinline 可能不生效)") + _vlog().warning(" 未找到 llvm-link/opt 工具,回退到单独编译(alwaysinline 可能不生效)") - from concurrent.futures import ThreadPoolExecutor, as_completed - import re - - def _compile_one(ll_path): + def _compile_one(ll_path: str) -> tuple[str, str, str]: rel = os.path.relpath(ll_path, self.output_dir) obj_path = ll_path[:-3] + '.obj' if os.path.isfile(obj_path): @@ -1271,16 +1440,42 @@ class Phase2Translator: deps = self._LoadDeps(sha1) stub_prefix = '' if deps: - existing_symbols = {} - opaque_line_indices = {} - existing_declares = set() - existing_declare_lines = {} + # 去重:同一个全局变量如果同时有 external 声明和实际定义, + # 移除 external 声明,避免 "redefinition of global" 错误 + # 注意:此去重必须在收集现有符号之前执行,否则行号偏移会导致 + # lines_to_remove 误删其他行(如全局变量定义) + ll_lines_for_dedup = ll_content.splitlines() + external_globals: dict[str, int] = {} + non_external_globals: dict[str, int] = {} + for i, line in enumerate(ll_lines_for_dedup): + stripped = line.strip() + if stripped.startswith('@') and (' global ' in stripped or ' constant ' in stripped): + gm = re.match(r'(@\S+)', stripped) + if gm: + gname = gm.group(1) + is_external = re.match(r'@\S+\s*=\s*external\s+', stripped) is not None + if is_external: + external_globals[gname] = i + else: + non_external_globals[gname] = i + lines_to_remove_global_dedup: set[int] = set() + for gname in external_globals: + if gname in non_external_globals: + lines_to_remove_global_dedup.add(external_globals[gname]) + if lines_to_remove_global_dedup: + ll_content = '\n'.join( + line for i, line in enumerate(ll_lines_for_dedup) + if i not in lines_to_remove_global_dedup + ) + '\n' + existing_symbols: dict[str, str] = {} + opaque_line_indices: dict[str, int] = {} + existing_declares: set[str] = set() + existing_declare_lines: dict[str, set[int]] = {} for i, line in enumerate(ll_content.splitlines()): stripped = line.strip() if stripped.startswith('%') and '= type' in stripped: - m = re.match(r'%"?((?:[a-f0-9]+\.)?[\w.]+)"?\s*=', stripped) - if m: - name = m.group(1) + name = Phase2Translator._extract_llvm_type_name(stripped) + if name: if '= type opaque' in stripped: existing_symbols[name] = 'opaque' opaque_line_indices[name] = i @@ -1291,17 +1486,17 @@ class Phase2Translator: if dm: fname = dm.group(1) existing_declares.add(fname) - existing_declare_lines[fname] = i - seen_stub_sha1 = set() - replaced_opaque_names = set() - replaced_declare_names = set() - all_stub_lines = [] - stub_type_map = {} - stub_declare_names = set() - stub_declare_lines = {} - existing_defines = set() - existing_global_defs = set() - stub_global_defs = set() + existing_declare_lines.setdefault(fname, set()).add(i) + seen_stub_sha1: set[str] = set() + replaced_opaque_names: set[str] = set() + replaced_declare_names: set[str] = set() + all_stub_lines: list[str | None] = [] + stub_type_map: dict[str, tuple[bool, int]] = {} + stub_declare_names: set[str] = set() + stub_declare_lines: dict[str, str] = {} + existing_defines: set[str] = set() + existing_global_defs: set[str] = set() + stub_global_defs: set[str] = set() for line in ll_content.splitlines(): stripped = line.strip() if stripped.startswith('define'): @@ -1330,8 +1525,8 @@ class Phase2Translator: dm = re.match(r'declare\s+[^@]*@"?([^"\s(]+)"?', stripped) if dm: fname = dm.group(1) - if re.search(r'%("[^"]+"|[a-f0-9]+\.[A-Za-z_]\w*)\s+%', stripped): - continue + if 'zdef_alloc' in fname: + _vlog().info(f"[DEBUG] stub declare for {fname}: existing_declares={fname in existing_declares}, stub_declare_names={fname in stub_declare_names}, has_struct={'%' in stripped}, existing={existing_declare_lines.get(fname)}") if fname in existing_defines: continue if fname in existing_declares or fname in stub_declare_names: @@ -1361,9 +1556,8 @@ class Phase2Translator: all_stub_lines.append(line) continue if stripped.startswith('%') and '= type' in stripped: - m = re.match(r'%"?((?:[a-f0-9]+\.)?[\w.]+)"?\s*=', stripped) - if m: - name = m.group(1) + name = Phase2Translator._extract_llvm_type_name(stripped) + if name: is_opaque = '= type opaque' in stripped if name in existing_symbols: if existing_symbols[name] == 'opaque' and not is_opaque: @@ -1404,9 +1598,13 @@ class Phase2Translator: if name in opaque_line_indices: lines_to_remove.add(opaque_line_indices[name]) if replaced_declare_names: + _vlog().info(f"[DEBUG] replaced_declare_names: {replaced_declare_names}") for fname in replaced_declare_names: if fname in existing_declare_lines: - lines_to_remove.add(existing_declare_lines[fname]) + lines_to_remove.update(existing_declare_lines[fname]) + _vlog().info(f"[DEBUG] removing lines {existing_declare_lines[fname]} for {fname}") + else: + _vlog().info(f"[DEBUG] fname {fname} not in existing_declare_lines: {list(existing_declare_lines.keys())}") if lines_to_remove: ll_lines = ll_content.splitlines(True) ll_content = ''.join(line for i, line in enumerate(ll_lines) if i not in lines_to_remove) @@ -1436,6 +1634,32 @@ class Phase2Translator: ll_content = re.sub(r'\b(define|declare)\s+(?!private|internal|available_externally|linkonce|weak|common|appending|extern_weak|linkonce_odr|weak_odr|external|dso_local|@)', r'\1 dso_local ', ll_content) ll_content = re.sub(r'(@[\w.]+)\s*=\s*(private|internal|available_externally|linkonce|weak|common|appending|extern_weak|linkonce_odr|weak_odr|external)\s+(global|constant)', r'\1 = \2 dso_local \3', ll_content) ll_content = re.sub(r'(@[\w.]+)\s*=\s+(?!private|internal|available_externally|linkonce|weak|common|appending|extern_weak|linkonce_odr|weak_odr|external|dso_local)(global|constant)', r'\1 = dso_local \2', ll_content) + # LLVM 22+: 移除同一模块中已有 define 的 declare 语句(LLVM 22 将 declare+define 视为重复定义) + defined_funcs: set[str] = set() + for m in re.finditer(r'^define\s+(?:dso_local\s+)?[^@]*@\"?([\w.]+)\"?\s*\(', ll_content, re.MULTILINE): + defined_funcs.add(m.group(1)) + if defined_funcs: + lines: list[str] = ll_content.splitlines(True) + kept_lines: list[str] = [] + for line in lines: + m = re.match(r'^declare\s+(?:dso_local\s+)?[^@]*@\"?([\w.]+)\"?\s*\(', line) + if m and m.group(1) in defined_funcs: + continue + kept_lines.append(line) + ll_content = ''.join(kept_lines) + # 移除重复的 declare 语句(同一函数多次 declare 但没有 define) + seen_declares: set[str] = set() + dedup_lines: list[str] = ll_content.splitlines(True) + dedup_kept: list[str] = [] + for line in dedup_lines: + dm = re.match(r'^declare\s+(?:dso_local\s+)?[^@]*@\"?([\w.]+)\"?\s*\(', line) + if dm: + fname = dm.group(1) + if fname in seen_declares: + continue + seen_declares.add(fname) + dedup_kept.append(line) + ll_content = ''.join(dedup_kept) final_type_defs = [] final_type_def_indices = set() for i, line in enumerate(ll_content.splitlines()): @@ -1478,24 +1702,24 @@ class Phase2Translator: if need_compile: n_workers = min(os.cpu_count() or 4, len(need_compile), 8) - print(f" 并行编译 {len(need_compile)} 个文件 (workers={n_workers})") + _vlog().info(f" 并行编译 {len(need_compile)} 个文件 (workers={n_workers})") errors = [] with ThreadPoolExecutor(max_workers=n_workers) as executor: futures = {executor.submit(_compile_one, ll_path): ll_path for ll_path in need_compile} for future in as_completed(futures): rel, status, err = future.result() if status == 'ok': - print(f" [成功] {rel}") + _vlog().success(f" {rel}") elif status == 'error': - print(f" [错误] {rel}: {err}") + _vlog().error(f" {rel}: {err}") errors.append((rel, err)) elif status == 'cached': pass if errors: - print(f"\n[编译终止] {len(errors)} 个文件编译失败") + _vlog().error(f"\n{len(errors)} 个文件编译失败") sys.exit(1) - def _scan_include_libraries(self): + def _scan_include_libraries(self) -> None: """扫描 includes 目录,检测被使用的模块对应的库文件和源文件""" if not self.used_includes: return @@ -1515,35 +1739,35 @@ class Phase2Translator: py_path = os.path.join(root, fname) if py_path not in self.extra_py_files: self.extra_py_files.append(py_path) - print(f" [includes] 发现 Python 包文件: {os.path.relpath(py_path, includes_dir)}") + _vlog().info(f" [includes] 发现 Python 包文件: {os.path.relpath(py_path, includes_dir)}") for ext in self.INCLUDE_LIB_EXTENSIONS: lib_path = os.path.join(includes_dir, module_name + ext) if os.path.isfile(lib_path): self.extra_link_files.append(lib_path) - print(f" [includes] 发现库文件: {os.path.relpath(lib_path, includes_dir)}") + _vlog().info(f" [includes] 发现库文件: {os.path.relpath(lib_path, includes_dir)}") for ext in self.INCLUDE_SRC_EXTENSIONS: src_path = os.path.join(includes_dir, module_name + ext) if os.path.isfile(src_path): self.extra_compile_files.append(src_path) - print(f" [includes] 发现源文件: {os.path.relpath(src_path, includes_dir)}") + _vlog().info(f" [includes] 发现源文件: {os.path.relpath(src_path, includes_dir)}") py_path = os.path.join(includes_dir, module_name + '.py') if os.path.isfile(py_path): self.extra_py_files.append(py_path) - print(f" [includes] 发现 Python 源文件: {os.path.relpath(py_path, includes_dir)}") + _vlog().info(f" [includes] 发现 Python 源文件: {os.path.relpath(py_path, includes_dir)}") discovered = set() for ef in list(self.extra_py_files): self._discover_transitive_deps(ef, includes_dir, discovered) if self.extra_link_files: - print(f"\n[includes] 需要链接的库文件: {len(self.extra_link_files)} 个") + _vlog().info(f"\n[includes] 需要链接的库文件: {len(self.extra_link_files)} 个") if self.extra_compile_files: - print(f"[includes] 需要编译的源文件: {len(self.extra_compile_files)} 个") + _vlog().info(f"[includes] 需要编译的源文件: {len(self.extra_compile_files)} 个") - def _scan_dir_for_libs(self, directory: str, module_name: str): + def _scan_dir_for_libs(self, directory: str, module_name: str) -> None: """递归扫描目录中的库文件和源文件""" for root, dirs, files in os.walk(directory): for fname in files: @@ -1552,12 +1776,12 @@ class Phase2Translator: ext = ext.lower() if ext in self.INCLUDE_LIB_EXTENSIONS: self.extra_link_files.append(fpath) - print(f" [includes] 发现库文件: {os.path.relpath(fpath, directory)}") + _vlog().info(f" [includes] 发现库文件: {os.path.relpath(fpath, directory)}") elif ext in self.INCLUDE_SRC_EXTENSIONS: self.extra_compile_files.append(fpath) - print(f" [includes] 发现源文件: {os.path.relpath(fpath, directory)}") + _vlog().info(f" [includes] 发现源文件: {os.path.relpath(fpath, directory)}") - def _discover_transitive_deps(self, py_path: str, includes_dir: str, discovered: set): + def _discover_transitive_deps(self, py_path: str, includes_dir: str, discovered: set[str]) -> None: """递归发现 Python 文件的间接依赖""" if py_path in discovered: return @@ -1565,20 +1789,17 @@ class Phase2Translator: try: with open(py_path, 'r', encoding='utf-8') as f: content = f.read() - import ast as _ast - tree = _ast.parse(content) - for node in _ast.walk(tree): - if isinstance(node, _ast.Import): + tree = ast.parse(content) + for node in ast.walk(tree): + if isinstance(node, ast.Import): for alias in node.names: mod = alias.name.split('.')[0] self._try_add_include_dep(mod, includes_dir, discovered) - elif isinstance(node, _ast.ImportFrom): + elif isinstance(node, ast.ImportFrom): if node.module and node.level == 0: mod = node.module.split('.')[0] self._try_add_include_dep(mod, includes_dir, discovered) except Exception as _e: - from lib.core.VLogger import get_logger as _vlog - from lib.constants.config import mode as _config_mode if _config_mode == "strict": raise _vlog().warning(f"发现 include 传递依赖失败: {_e}", "Exception") @@ -1588,40 +1809,35 @@ class Phase2Translator: py_path = os.path.join(includes_dir, module_name + '.py') if os.path.isfile(py_path) and py_path not in self.extra_py_files: self.extra_py_files.append(py_path) - print(f" [includes] 发现间接依赖: {os.path.relpath(py_path, includes_dir)}") + _vlog().info(f" [includes] 发现间接依赖: {os.path.relpath(py_path, includes_dir)}") self._discover_transitive_deps(py_path, includes_dir, discovered) def _is_decl_only_file(self, src_path: str) -> bool: try: with open(src_path, 'r', encoding='utf-8') as f: content = f.read() - import ast as _ast - tree = _ast.parse(content) - for node in _ast.walk(tree): - if isinstance(node, _ast.ClassDef): + tree = ast.parse(content) + for node in ast.walk(tree): + if isinstance(node, ast.ClassDef): return False - if isinstance(node, _ast.FunctionDef): + if isinstance(node, ast.FunctionDef): body = node.body if len(body) == 1: stmt = body[0] - if isinstance(stmt, _ast.Expr) and isinstance(stmt.value, _ast.Constant) and stmt.value.value is ...: + if isinstance(stmt, ast.Expr) and isinstance(stmt.value, ast.Constant) and stmt.value.value is ...: continue - if isinstance(stmt, _ast.Pass): + if isinstance(stmt, ast.Pass): continue return False return True except Exception as _e: - from lib.core.VLogger import get_logger as _vlog - from lib.constants.config import mode as _config_mode if _config_mode == "strict": raise _vlog().warning(f"判断是否为声明文件失败: {_e}", "Exception") return False - def _sort_include_files_by_deps(self, file_list: list) -> list: + def _sort_include_files_by_deps(self, file_list: list[str]) -> list[str]: """按依赖关系对 include 文件进行拓扑排序,确保被依赖的文件先编译""" - import ast as _ast - # 构建文件名到路径的映射 name_to_path = {} for fpath in file_list: @@ -1646,21 +1862,28 @@ class Phase2Translator: try: with open(fpath, 'r', encoding='utf-8') as f: content = f.read() - tree = _ast.parse(content) - for node in _ast.iter_child_nodes(tree): - if isinstance(node, _ast.Import): + tree = ast.parse(content) + for node in ast.iter_child_nodes(tree): + if isinstance(node, ast.Import): for alias in node.names: - mod = alias.name.split('.')[0] - if mod in name_to_path and name_to_path[mod] != fpath: - deps[fpath].add(name_to_path[mod]) - elif isinstance(node, _ast.ImportFrom): + # 尝试完整路径和各级前缀,确保同包内子模块依赖能被正确解析 + # 例如 import zlib.zhuff -> 应先匹配 zlib.zhuff,再回退到 zlib + parts = alias.name.split('.') + for i in range(len(parts), 0, -1): + mod = '.'.join(parts[:i]) + if mod in name_to_path and name_to_path[mod] != fpath: + deps[fpath].add(name_to_path[mod]) + break + elif isinstance(node, ast.ImportFrom): if node.module and node.level == 0: - mod = node.module.split('.')[0] - if mod in name_to_path and name_to_path[mod] != fpath: - deps[fpath].add(name_to_path[mod]) + # 同样尝试完整路径和各级前缀 + parts = node.module.split('.') + for i in range(len(parts), 0, -1): + mod = '.'.join(parts[:i]) + if mod in name_to_path and name_to_path[mod] != fpath: + deps[fpath].add(name_to_path[mod]) + break except Exception as _e: - from lib.core.VLogger import get_logger as _vlog - from lib.constants.config import mode as _config_mode if _config_mode == "strict": raise _vlog().warning(f"分析 include 文件导入依赖失败: {_e}", "Exception") @@ -1695,7 +1918,7 @@ class Phase2Translator: return result - def _compile_include_py_files(self, active_sha1s: set): + def _compile_include_py_files(self, active_sha1s: set[str]) -> None: """通过 TransPyC 翻译器编译 includes 目录中发现的 .py 文件""" if not self.extra_py_files: return @@ -1703,7 +1926,7 @@ class Phase2Translator: # 按依赖关系排序 include 文件,确保被依赖的文件先编译 sorted_files = self._sort_include_files_by_deps(self.extra_py_files) - print(f"\n[includes 编译] 找到 {len(sorted_files)} 个 Python 源文件") + _vlog().info(f"\n[includes 编译] 找到 {len(sorted_files)} 个 Python 源文件") # 构建 include 文件的模块 SHA1 映射 # 必须在编译前预构建完整的映射,否则后续文件引用前面文件时会用错误的 SHA1 @@ -1732,25 +1955,24 @@ class Phase2Translator: obj_path = os.path.join(self.output_dir, f"{sha1}.obj") if self._is_decl_only_file(src_path): - print(f" 跳过(声明文件): {module_name}.py") + _vlog().info(f" 跳过(声明文件): {module_name}.py") self._collect_inline_symbols(src_path) continue if os.path.isfile(obj_path): - print(f" 跳过(缓存): {module_name}.py -> {sha1}.obj") + _vlog().info(f" 跳过(缓存): {module_name}.py -> {sha1}.obj") self._collect_inline_symbols(src_path) self.extra_link_files.append(obj_path) continue - print(f" 翻译: {os.path.basename(src_path)} -> {sha1}.ll") + _vlog().info(f" 翻译: {os.path.basename(src_path)} -> {sha1}.ll") try: self._translate_file(src_path, ll_path, prebuilt_ModuleSha1Map=include_ModuleSha1Map) if os.path.isfile(ll_path): - print(f" 编译: {sha1}.ll -> {sha1}.obj") + _vlog().info(f" 编译: {sha1}.ll -> {sha1}.obj") with open(ll_path, 'r', encoding='utf-8') as f: ll_content = f.read() - import re ll_content = re.sub(r'\b(define|declare)\s+(private|internal|available_externally|linkonce|weak|common|appending|extern_weak|linkonce_odr|weak_odr|external)\s+', r'\1 \2 dso_local ', ll_content) ll_content = re.sub(r'\b(define|declare)\s+(?!private|internal|available_externally|linkonce|weak|common|appending|extern_weak|linkonce_odr|weak_odr|external|dso_local)', r'\1 dso_local ', ll_content) ll_content = re.sub(r'(@[\w.]+)\s*=\s*(private|internal|available_externally|linkonce|weak|common|appending|extern_weak|linkonce_odr|weak_odr|external)\s+(global|constant)', r'\1 = \2 dso_local \3', ll_content) @@ -1765,16 +1987,16 @@ class Phase2Translator: for sline in sf: sl = sline.strip() if sl.startswith('%') and '= type' in sl and 'opaque' not in sl: - struct_name_match = re.match(r'%"?([\w.]+)"?\s*=', sl) - if struct_name_match: + struct_name = Phase2Translator._extract_llvm_type_name(sl) + if struct_name: stub_decls.append(sl) - except: - pass + except Exception as e: + _vlog().warning(f"Phase2Translator: 忽略异常 {e}", exc_info=e) if stub_decls: + # 第一遍:替换 opaque 类型为具体定义 for sdecl in stub_decls: - sname_match = re.match(r'%"?([\w.]+)"?\s*=\s*type', sdecl) - if sname_match: - sname = sname_match.group(1) + sname = Phase2Translator._extract_llvm_type_name(sdecl) + if sname: short = sname.split('.')[-1] if '.' in sname else sname ll_content = re.sub( r'%"?' + re.escape(sname) + r'"?\s*=\s*type\s*opaque', @@ -1783,6 +2005,53 @@ class Phase2Translator: ll_content = re.sub( r'%"?' + re.escape(short) + r'"?\s*=\s*type\s*opaque', sdecl, ll_content) + + # 第二遍:注入被引用但未定义的类型(递归解析依赖类型) + all_type_defs = {} + for sdecl in stub_decls: + tname = Phase2Translator._extract_llvm_type_name(sdecl) + if tname: + all_type_defs[tname] = sdecl + + max_iterations = 10 + for _ in range(max_iterations): + defined_types = set() + for line in ll_content.splitlines(): + sl = line.strip() + if sl.startswith('%') and '= type' in sl: + tname = Phase2Translator._extract_llvm_type_name(sl) + if tname: + defined_types.add(tname) + + referenced_types = Phase2Translator._find_all_type_refs(ll_content) + + missing = referenced_types - defined_types + new_defs = [] + for tname in sorted(missing): + if tname in all_type_defs: + new_defs.append(all_type_defs[tname]) + else: + short_key = tname.split('.')[-1] if '.' in tname else tname + for full_name, defn in all_type_defs.items(): + if full_name.split('.')[-1] == short_key: + if short_key not in defined_types: + new_defs.append(defn) + break + + if not new_defs: + break + + inject_block = '\n'.join(new_defs) + '\n' + lines = ll_content.splitlines(True) + insert_pos = 0 + for i, line in enumerate(lines): + stripped = line.strip() + if stripped and not stripped.startswith(';') and not stripped.startswith('target ') and not stripped.startswith('source_filename') and not stripped.startswith('declare ') and not stripped.startswith('@') and not stripped.startswith('define ') and not stripped.startswith('attributes ') and not stripped.startswith('!') and not stripped.startswith('module '): + insert_pos = i + break + if insert_pos == 0: + insert_pos = len(lines) + ll_content = ''.join(lines[:insert_pos]) + inject_block + ''.join(lines[insert_pos:]) dso_ll_path = ll_path[:-3] + '_dso.ll' with open(dso_ll_path, 'w', encoding='utf-8') as f: f.write(ll_content) @@ -1794,32 +2063,31 @@ class Phase2Translator: cwd=self.output_dir ) if result.returncode == 0: - print(f" [成功]") + _vlog().success(" 编译成功") self.extra_link_files.append(obj_path) # 编译成功后,生成 .pyi 签名文件和 .stub.ll 文件 # 并注册到符号表和签名映射中,以便后续 include 文件可以引用 self._register_compiled_include(src_path, sha1, ll_content, include_ModuleSha1Map) else: - print(f" [警告] 编译失败: {result.stderr.strip()}") + _vlog().warning(f" 编译失败: {result.stderr.strip()}") for ext in ['.ll', '_dso.ll']: p = ll_path[:-3] + ext if os.path.isfile(p): os.remove(p) else: - print(f" [错误] 翻译未生成 .ll 文件") + _vlog().error(f" 翻译未生成 .ll 文件") except Exception as e: - import traceback for ext in ['.ll', '_dso.ll']: p = ll_path[:-3] + ext if os.path.isfile(p): os.remove(p) - print(f" [错误] 翻译异常: {e}") + _vlog().error(f" 翻译异常: {e}") traceback.print_exc() - print(f"\n[编译终止] includes 文件翻译失败") + _vlog().error(f"\nincludes 文件翻译失败") sys.exit(1) - def _register_compiled_include(self, src_path, sha1, ll_content, include_ModuleSha1Map): + def _register_compiled_include(self, src_path: str, sha1: str, ll_content: str, include_ModuleSha1Map: dict[str, str]) -> None: """编译 include 文件成功后,生成签名和 stub 文件并注册到符号表中""" module_name = os.path.splitext(os.path.basename(src_path))[0] @@ -1844,8 +2112,6 @@ class Phase2Translator: with open(sig_path, 'w', encoding='utf-8', newline='\n') as f: f.write(sig_content) except Exception as e: - from lib.core.VLogger import get_logger as _vlog - from lib.constants.config import mode as _config_mode if _config_mode == "strict": raise _vlog().warning(f"签名生成失败不阻塞编译: {e}", "Exception") @@ -1863,8 +2129,6 @@ class Phase2Translator: try: self._shared_symbol_table.LoadModuleSymbols(sig_path, mod_full, lineno=0) except Exception as _e: - from lib.core.VLogger import get_logger as _vlog - from lib.constants.config import mode as _config_mode if _config_mode == "strict": raise _vlog().warning(f"加载模块签名到共享符号表失败: {_e}", "Exception") @@ -1877,8 +2141,6 @@ class Phase2Translator: with open(stub_path, 'w', encoding='utf-8', newline='\n') as f: f.write(stub_content) except Exception as _e: - from lib.core.VLogger import get_logger as _vlog - from lib.constants.config import mode as _config_mode if _config_mode == "strict": raise _vlog().warning(f"生成 .stub.ll 文件失败: {_e}", "Exception") @@ -1892,7 +2154,7 @@ class Phase2Translator: if os.path.isfile(temp_stub): self.stub_files[sha1] = temp_stub - def _precollect_inline_symbols(self): + def _precollect_inline_symbols(self) -> None: """在主翻译循环之前,扫描includes目录中used_includes相关的模块收集内联函数AST""" if not self.used_includes: return @@ -1949,19 +2211,15 @@ class Phase2Translator: self.inline_func_symbols[func_name] = info self.inline_func_symbols[sym_key] = info except Exception as _e: - from lib.core.VLogger import get_logger as _vlog - from lib.constants.config import mode as _config_mode if _config_mode == "strict": raise _vlog().warning(f"预收集内联函数符号失败: {_e}", "Exception") - def _build_shared_symbol_data(self): + def _build_shared_symbol_data(self) -> None: """一次性构建所有文件共享的符号表数据,避免每个文件重复加载""" - import copy - import time t0 = time.time() - print("[缓存] 构建共享符号表数据...") + _vlog().info("[缓存] 构建共享符号表数据...") base_trans = TransPyC.TransPyC(code="pass", triple=self.triple, datalayout=self.datalayout) base_trans.translator.LlvmGen = None @@ -1976,7 +2234,7 @@ class Phase2Translator: module_name = os.path.splitext(pyi_file)[0] base_trans.translator.SymbolTable.LoadModuleSymbols(pyi_path, module_name, lineno=0) for py_file in os.listdir(includes_dir): - if py_file.endswith('.py') and not py_file.startswith('_'): + if py_file.endswith('.py') and (not py_file.startswith('_') or py_file == '_list.py' or py_file == '_dict.py'): module_name = os.path.splitext(py_file)[0] sha1_key = self.include_py_map.get(module_name) if sha1_key and sha1_key in self.sig_files: @@ -2023,30 +2281,13 @@ class Phase2Translator: try: val = int(val_part) all_dc[var_name] = val - except: - pass - except: - pass + except Exception as e: + _vlog().warning(f"Phase2Translator: 忽略异常 {e}", exc_info=e) + except Exception as e: + _vlog().warning(f"Phase2Translator: 忽略异常 {e}", exc_info=e) for sha1_key, pyi_path in self.sig_files.items(): - if os.path.exists(pyi_path): - try: - with open(pyi_path, 'r', encoding='utf-8') as f: - pyi_content = f.read() - tree = ast.parse(pyi_content) - for node in ast.iter_child_nodes(tree): - if isinstance(node, ast.AnnAssign) and isinstance(node.target, ast.Name): - ann_str = ast.dump(node.annotation) - if 'CDefine' in ann_str and node.value: - val = None - if isinstance(node.value, ast.Constant): - val = node.value.value - elif isinstance(node.value, ast.Call) and isinstance(node.value.func, ast.Name) and node.value.func.id == 'float' and node.value.args and isinstance(node.value.args[0], ast.Constant): - val = node.value.args[0].value - if val is not None: - all_dc[f"{node.target.id}"] = val - except: - pass + _ExtractCDefineConstantsFromPyi(pyi_path, all_dc) export_extern_funcs = set() for sha1_key, sig_path in self.sig_files.items(): @@ -2059,8 +2300,6 @@ class Phase2Translator: if _check_annotation_for_export(node.returns): export_extern_funcs.add(node.name) except Exception as _e: - from lib.core.VLogger import get_logger as _vlog - from lib.constants.config import mode as _config_mode if _config_mode == "strict": raise _vlog().warning(f"收集共享导出外部函数失败: {_e}", "Exception") @@ -2087,7 +2326,7 @@ class Phase2Translator: if not os.path.isdir(abs_includes): abs_includes = includes_dir for py_file in os.listdir(abs_includes): - if py_file.endswith('.py') and not py_file.startswith('_'): + if py_file.endswith('.py') and (not py_file.startswith('_') or py_file == '_list.py' or py_file == '_dict.py'): py_path = os.path.join(abs_includes, py_file) try: with open(py_path, 'r', encoding='utf-8') as f: @@ -2101,15 +2340,13 @@ class Phase2Translator: 'type_params': type_params, } except Exception as _e: - from lib.core.VLogger import get_logger as _vlog - from lib.constants.config import mode as _config_mode if _config_mode == "strict": raise _vlog().warning(f"收集泛型类模板失败: {_e}", "Exception") self._shared_generic_class_templates = generic_class_templates t1 = time.time() - print(f"[缓存] 共享符号表构建完成 ({t1-t0:.2f}s, {len(self._shared_symbol_table)} 符号, {len(generic_class_templates)} 泛型模板)") + _vlog().info(f"[缓存] 共享符号表构建完成 ({t1-t0:.2f}s, {len(self._shared_symbol_table)} 符号, {len(generic_class_templates)} 泛型模板)") def _compile_include_sources(self): """扫描项目目录中的汇编存根,编译 includes 目录中发现的 C/C++ 源文件""" @@ -2140,7 +2377,7 @@ class Phase2Translator: '.s': 'gcc', '.S': 'gcc', } - print(f"\n[includes 编译] 找到 {len(extra_sources)} 个源文件") + _vlog().info(f"\n[includes 编译] 找到 {len(extra_sources)} 个源文件") for src_path in extra_sources: _, ext = os.path.splitext(src_path) @@ -2154,36 +2391,35 @@ class Phase2Translator: cc = cc_map.get(ext, 'gcc') extra_flags = ['-c', '-o', obj_path, src_path] - print(f" 编译: {os.path.basename(src_path)} -> {os.path.basename(obj_path)}") + _vlog().info(f" 编译: {os.path.basename(src_path)} -> {os.path.basename(obj_path)}") try: cmd = [cc] + extra_flags result = subprocess.run(cmd, capture_output=True, text=True) if result.returncode == 0: - print(f" [成功]") + _vlog().success(" 编译成功") self.extra_link_files.append(obj_path) else: - print(f" [错误] 编译失败: {result.stderr.strip()}") - print(f"\n[编译终止] C/C++ 源文件编译失败,立即终止编译。") + _vlog().error(f" 编译失败: {result.stderr.strip()}") + _vlog().error(f"\nC/C++ 源文件编译失败,立即终止编译。") sys.exit(1) except FileNotFoundError: - print(f" [错误] 找不到编译器: {cc}") - print(f"\n[编译终止] 找不到编译器,立即终止编译。") + _vlog().error(f" 找不到编译器: {cc}") + _vlog().error(f"\n找不到编译器,立即终止编译。") sys.exit(1) except Exception as e: - print(f" [错误] {e}") - print(f"\n[编译终止] 编译异常,立即终止编译。") + _vlog().error(f" {e}") + _vlog().error(f"\n编译异常,立即终止编译。") sys.exit(1) - def _strip_debug_sections(self, exe_path: str): + def _strip_debug_sections(self, exe_path: str) -> None: """剥离 .exe 中的调试段(跳过裸机二进制)""" if not os.path.exists(exe_path): return ext = os.path.splitext(exe_path)[1].lower() if ext not in ('.exe', '.dll', '.obj', '.o', '.elf'): - print(f" [剥离] 跳过({ext} 格式无需剥离)") + _vlog().info(f" [剥离] 跳过({ext} 格式无需剥离)") return - import shutil for tool in ['llvm-strip', 'strip']: strip_cmd = shutil.which(tool) if strip_cmd: @@ -2193,12 +2429,10 @@ class Phase2Translator: capture_output=True, text=True ) if result.returncode == 0: - print(f" [剥离] 调试段已移除 ({tool})") + _vlog().info(f" [剥离] 调试段已移除 ({tool})") else: - print(f" [剥离] 警告: {result.stderr.strip()}") + _vlog().warning(f" [剥离] 警告: {result.stderr.strip()}") except Exception as _e: - from lib.core.VLogger import get_logger as _vlog - from lib.constants.config import mode as _config_mode if _config_mode == "strict": raise _vlog().warning(f"剥离可执行文件调试段失败: {_e}", "Exception") @@ -2251,13 +2485,13 @@ class Phase2Translator: cmd = [self.compile_cmd] + self.compile_flags + ['-o', obj_path, ll_path] result = subprocess.run(cmd, capture_output=True, text=True, cwd=self.output_dir or '.') if result.returncode != 0: - print(f" [startup] 编译失败: {result.stderr.strip()}") + _vlog().error(f" [startup] 编译失败: {result.stderr.strip()}") return None - print(f" [startup] 生成符号别名: {aliases}") + _vlog().info(f" [startup] 生成符号别名: {aliases}") return obj_path - def _link_obj_files(self, active_sha1s: set): + def _link_obj_files(self, active_sha1s: set[str]) -> None: """将 active_sha1s 对应的 .obj 文件和 includes 库文件链接为可执行文件""" obj_files = [] merged_obj = os.path.join(self.output_dir, '_merged.obj') @@ -2272,7 +2506,7 @@ class Phase2Translator: obj_files.append(os.path.join(root, file)) if not obj_files and not self.extra_link_files: - print("[链接] 无文件可链接") + _vlog().info("[链接] 无文件可链接") return # 生成 startup 符号别名 shim @@ -2280,18 +2514,18 @@ class Phase2Translator: if startup_obj: obj_files.append(startup_obj) - print(f"\n[链接] 找到 {len(obj_files)} 个 .obj 文件") + _vlog().info(f"\n[链接] 找到 {len(obj_files)} 个 .obj 文件") all_link_files = obj_files + self.extra_link_files seen = set() all_link_files = [f for f in all_link_files if not (f in seen or seen.add(f))] if self.extra_link_files: - print(f"[链接] 额外库文件: {len(self.extra_link_files)} 个") + _vlog().info(f"[链接] 额外库文件: {len(self.extra_link_files)} 个") for lib in self.extra_link_files: - print(f" - {os.path.basename(lib)}") + _vlog().info(f" - {os.path.basename(lib)}") if not self.linker_cmd: - print("[链接] 未配置链接器") + _vlog().info("[链接] 未配置链接器") return exe_path = os.path.join(self.output_dir, self.linker_output) if self.linker_output else os.path.join(self.output_dir, 'a.exe') @@ -2309,9 +2543,8 @@ class Phase2Translator: linker_ld_src = os.path.join(os.path.dirname(self.output_dir), 'linker.ld') linker_ld_dst = os.path.join(self.output_dir, 'linker.ld') if os.path.isfile(linker_ld_src) and not os.path.isfile(linker_ld_dst): - import shutil shutil.copy2(linker_ld_src, linker_ld_dst) - print(f" [链接] 使用链接脚本: linker.ld") + _vlog().info(f" [链接] 使用链接脚本: linker.ld") elif not os.path.isfile(linker_ld_dst) and any('-T' in f or '-T' in f.replace(',', ' ') for f in self.linker_flags): default_ld = """ENTRY(_start) @@ -2352,7 +2585,7 @@ SECTIONS { """ with open(linker_ld_dst, 'w', encoding='utf-8', newline='\n') as f: f.write(default_ld) - print(f" [链接] 自动创建默认链接脚本: linker.ld") + _vlog().info(f" [链接] 自动创建默认链接脚本: linker.ld") try: # 将 linker_flags 拆分为非库标志和库标志(-l/-L),库标志放在目标文件之后 @@ -2376,7 +2609,7 @@ SECTIONS { non_lib_flags.append(flag) i += 1 cmd = [self.linker_cmd] + non_lib_flags + ['-o', link_output] + all_link_files + lib_flags - print(f" 执行: {' '.join(cmd)}") + _vlog().info(f" 执行: {' '.join(cmd)}") result = subprocess.run( cmd, capture_output=True, @@ -2385,7 +2618,6 @@ SECTIONS { ) if result.returncode == 0: if is_binary and not is_direct_binary: - import shutil objcopy = shutil.which('llvm-objcopy') or shutil.which('objcopy') if objcopy: conv = subprocess.run( @@ -2394,30 +2626,30 @@ SECTIONS { ) if conv.returncode == 0: os.remove(link_output) - print(f" [成功] 生成裸机二进制: {exe_path}") + _vlog().success(f" 生成裸机二进制: {exe_path}") file_size = os.path.getsize(exe_path) - print(f" [大小] {file_size} 字节") + _vlog().info(f" [大小] {file_size} 字节") else: - print(f" [错误] 二进制转换失败: {conv.stderr.strip()}") + _vlog().error(f" 二进制转换失败: {conv.stderr.strip()}") sys.exit(1) else: - print(" [错误] 找不到 llvm-objcopy,无法生成裸机二进制") + _vlog().error(" 找不到 llvm-objcopy,无法生成裸机二进制") sys.exit(1) else: - print(f" [成功] 生成: {exe_path}") + _vlog().success(f" 生成: {exe_path}") file_size = os.path.getsize(exe_path) - print(f" [大小] {file_size} 字节") + _vlog().info(f" [大小] {file_size} 字节") if not is_binary: self._strip_debug_sections(exe_path) else: - print(f" [错误] 链接失败: {result.stderr.strip()}") - print(f"\n[编译终止] 链接失败,立即终止编译。") + _vlog().error(f" 链接失败: {result.stderr.strip()}") + _vlog().error(f"\n链接失败,立即终止编译。") sys.exit(1) except FileNotFoundError: - print(f" [错误] 找不到链接器: {self.linker_cmd}") - print(f"\n[编译终止] 找不到链接器,立即终止编译。") + _vlog().error(f" 找不到链接器: {self.linker_cmd}") + _vlog().error(f"\n找不到链接器,立即终止编译。") sys.exit(1) except Exception as e: - print(f" [错误] {e}") - print(f"\n[编译终止] 链接异常,立即终止编译。") + _vlog().error(f" {e}") + _vlog().error(f"\n链接异常,立即终止编译。") sys.exit(1) diff --git a/lib/Projectrans/Utils.py b/lib/Projectrans/Utils.py index 834fec7..e25bc00 100644 --- a/lib/Projectrans/Utils.py +++ b/lib/Projectrans/Utils.py @@ -1,53 +1,51 @@ +from __future__ import annotations + import hashlib import os import ast +from lib.core.VLogger import get_logger as _vlog +from lib.constants.config import mode as _ConfigMode +from lib.core.SymbolUtils import AnnotationContainsName + def compute_sha1(content: str) -> str: return hashlib.sha1(content.encode('utf-8')).hexdigest()[:16] -def _check_annotation_for_export(annotation) -> bool: +def _check_annotation_for_export(annotation: ast.AST | None) -> bool: """递归检查类型注解中是否包含 CExport""" - if annotation is None: - return False - if isinstance(annotation, ast.Attribute): - if hasattr(annotation, 'attr') and annotation.attr == 'CExport': - return True - elif isinstance(annotation, ast.BinOp) and isinstance(annotation.op, ast.BitOr): - return _check_annotation_for_export(annotation.left) or _check_annotation_for_export(annotation.right) - elif isinstance(annotation, ast.Name): - return annotation.id == 'CExport' - return False + return AnnotationContainsName(annotation, 'CExport') if annotation else False def sha1_file(filepath: str) -> str: with open(filepath, 'r', encoding='utf-8') as f: - content = f.read() + content: str = f.read() return compute_sha1(content) -def get_file_dependencies(filepath: str, src_root: str) -> set: +def get_file_dependencies(filepath: str, src_root: str) -> set[str]: """解析 Python 文件的导入依赖""" - dependencies = set() + dependencies: set[str] = set() try: with open(filepath, 'r', encoding='utf-8') as f: - content = f.read() - tree = ast.parse(content) + content: str = f.read() + tree: ast.Module = ast.parse(content) for node in ast.walk(tree): if isinstance(node, ast.Import): for alias in node.names: - module = alias.name + module: str = alias.name dependencies.add(module) elif isinstance(node, ast.ImportFrom): if node.module: - module = node.module + module: str = node.module if node.level > 0: # from .module import name → 依赖 pkg.module(模块本身) - pkg_dir = os.path.dirname(filepath) - pkg_rel = os.path.relpath(pkg_dir, src_root).replace(os.sep, '.').replace('/', '.') + pkg_dir: str = os.path.dirname(filepath) + pkg_rel: str = os.path.relpath(pkg_dir, src_root).replace(os.sep, '.').replace('/', '.') if pkg_rel == '.': pkg_rel = '' + dep_module: str if pkg_rel: dep_module = f'{pkg_rel}.{module}' else: @@ -59,51 +57,49 @@ def get_file_dependencies(filepath: str, src_root: str) -> set: elif node.level > 0 and node.names: # from . import name → 依赖 pkg.name(子模块) for alias in node.names: - pkg_dir = os.path.dirname(filepath) - pkg_rel = os.path.relpath(pkg_dir, src_root).replace(os.sep, '.').replace('/', '.') + pkg_dir: str = os.path.dirname(filepath) + pkg_rel: str = os.path.relpath(pkg_dir, src_root).replace(os.sep, '.').replace('/', '.') if pkg_rel == '.': pkg_rel = '' - dep_module = f'{pkg_rel}.{alias.name}' if pkg_rel else alias.name + dep_module: str = f'{pkg_rel}.{alias.name}' if pkg_rel else alias.name dependencies.add(dep_module) except Exception as _e: - from lib.core.VLogger import get_logger as _vlog - from lib.constants.config import mode as _ConfigMode if _ConfigMode == "strict": raise _vlog().warning(f"解析文件导入依赖失败: {_e}", "Exception") return dependencies -def find_reachable_files_from_entries(src_root: str, entry_files: list) -> set: +def find_reachable_files_from_entries(src_root: str, entry_files: list[str]) -> set[str]: """从入口文件出发,找出所有可达的 .py 文件(通过导入关系)""" - all_files = {} # module_name -> filepath + all_files: dict[str, str] = {} # module_name -> filepath for root, dirs, files in os.walk(src_root): dirs[:] = [d for d in dirs if d not in ('__pycache__',)] for file in files: if file.endswith('.py'): - filepath = os.path.join(root, file) - rel = os.path.relpath(filepath, src_root) - module = os.path.splitext(rel)[0].replace(os.sep, '.').replace('/', '.') + filepath: str = os.path.join(root, file) + rel: str = os.path.relpath(filepath, src_root) + module: str = os.path.splitext(rel)[0].replace(os.sep, '.').replace('/', '.') if filepath.endswith('__init__.py'): all_files[module] = filepath - parent_module = module.rsplit('.', 1)[0] if '.' in module else module + parent_module: str = module.rsplit('.', 1)[0] if '.' in module else module if parent_module not in all_files or not all_files[parent_module].endswith('__init__.py'): all_files[parent_module] = filepath elif module not in all_files: all_files[module] = filepath - top_module = module.split('.')[0] + top_module: str = module.split('.')[0] if top_module not in all_files: all_files[top_module] = filepath - reachable = set() - queue = list(entry_files) + reachable: set[str] = set() + queue: list[str] = list(entry_files) while queue: - current = queue.pop(0) + current: str = queue.pop(0) if current in reachable: continue reachable.add(current) - deps = get_file_dependencies(current, src_root) + deps: set[str] = get_file_dependencies(current, src_root) for dep in deps: if dep in all_files and all_files[dep] not in reachable: queue.append(all_files[dep]) @@ -117,43 +113,43 @@ def find_reachable_files_from_entries(src_root: str, entry_files: list) -> set: return reachable -def topological_sort_files(py_files: list, src_root: str) -> list: +def topological_sort_files(py_files: list[str], src_root: str) -> list[str]: """对 Python 文件进行拓扑排序,确保依赖模块先被处理""" # 构建模块名到文件路径的映射 - module_to_file = {} + module_to_file: dict[str, str] = {} for filepath in py_files: - rel = os.path.relpath(filepath, src_root) - module = os.path.splitext(rel)[0].replace(os.sep, '.').replace('/', '.') + rel: str = os.path.relpath(filepath, src_root) + module: str = os.path.splitext(rel)[0].replace(os.sep, '.').replace('/', '.') module_to_file[module] = filepath # 也添加顶层模块名 - top_module = module.split('.')[0] + top_module: str = module.split('.')[0] if top_module not in module_to_file: module_to_file[top_module] = filepath # 构建依赖图 - graph = {f: set() for f in py_files} + graph: dict[str, set[str]] = {f: set() for f in py_files} for filepath in py_files: - deps = get_file_dependencies(filepath, src_root) + deps: set[str] = get_file_dependencies(filepath, src_root) for dep in deps: if dep in module_to_file: - dep_file = module_to_file[dep] + dep_file: str = module_to_file[dep] if dep_file != filepath: # 避免自依赖 graph[filepath].add(dep_file) # 拓扑排序 (Kahn's algorithm) - in_degree = {f: 0 for f in py_files} + in_degree: dict[str, int] = {f: 0 for f in py_files} for f, deps in graph.items(): for dep in deps: if dep in in_degree: in_degree[f] += 1 - queue = [f for f, degree in in_degree.items() if degree == 0] - sorted_files = [] + queue: list[str] = [f for f, degree in in_degree.items() if degree == 0] + sorted_files: list[str] = [] while queue: # 按字母顺序处理同级别的文件,确保确定性 queue.sort() - current = queue.pop(0) + current: str = queue.pop(0) sorted_files.append(current) for f, deps in graph.items(): @@ -164,7 +160,7 @@ def topological_sort_files(py_files: list, src_root: str) -> list: # 如果有环,添加剩余文件 if len(sorted_files) < len(py_files): - remaining = [f for f in py_files if f not in sorted_files] + remaining: list[str] = [f for f in py_files if f not in sorted_files] sorted_files.extend(remaining) return sorted_files diff --git a/lib/Shell/Config.py b/lib/Shell/Config.py index 77bcaae..5bfcfc7 100644 --- a/lib/Shell/Config.py +++ b/lib/Shell/Config.py @@ -1,5 +1,8 @@ +from __future__ import annotations + + class Config: """配置类""" - def __init__(self): - self.debug = False - self.mode = 'relaxed' # 'relaxed' 或 'strict' + def __init__(self) -> None: + self.debug: bool = False + self.mode: str = 'relaxed' # 'relaxed' 或 'strict' diff --git a/lib/Shell/Serializer.py b/lib/Shell/Serializer.py index 8df3965..f87409e 100644 --- a/lib/Shell/Serializer.py +++ b/lib/Shell/Serializer.py @@ -1,8 +1,11 @@ +from __future__ import annotations + import json import struct +from typing import Any -def SerializeSymbolTable(SymbolTable: dict) -> bytes: +def SerializeSymbolTable(SymbolTable: dict[str, Any]) -> bytes: """将符号表序列化为二进制格式 格式: @@ -15,14 +18,14 @@ def SerializeSymbolTable(SymbolTable: dict) -> bytes: Returns: 二进制字节数据 """ - JsonData = json.dumps(SymbolTable, ensure_ascii=False).encode('utf-8') - length = len(JsonData) + JsonData: bytes = json.dumps(SymbolTable, ensure_ascii=False).encode('utf-8') + length: int = len(JsonData) # 使用4字节小端序整数表示长度 - header = struct.pack(' dict: +def deSerializeSymbolTable(data: bytes) -> dict[str, Any]: """从二进制数据反序列化符号表 Args: @@ -34,15 +37,15 @@ def deSerializeSymbolTable(data: bytes) -> dict: if len(data) < 4: raise ValueError("Invalid symbin file: data too short") # 解析4字节长度头(小端序) - length = struct.unpack(' None: """初始化SymbolFile对象 Args: @@ -51,8 +54,8 @@ class SymbolFile: type: 文件类型,支持"c"或"py" encoding: 文件编码 """ - self.FilePath = file - self.CodeString = string - self.FileType = type - self.encoding = encoding - self.symbols = {} + self.FilePath: str | None = file + self.CodeString: str | None = string + self.FileType: str | None = type + self.encoding: str = encoding + self.symbols: dict[str, Any] = {} diff --git a/lib/Shell/TransPyC.py b/lib/Shell/TransPyC.py index 9491100..6586ed2 100644 --- a/lib/Shell/TransPyC.py +++ b/lib/Shell/TransPyC.py @@ -1,8 +1,15 @@ +from __future__ import annotations + import sys import os import ast import json +import shlex import struct +import datetime +import tempfile +import subprocess +from typing import Any # 添加lib目录到Python路径 sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'lib', 'includes')) from lib.includes import c @@ -17,7 +24,9 @@ from lib.utils.helpers import ( DetectFileType, ExecuteCommand, AppendFileContent ) +from lib.core.VLogger import info, warning, error, success, debug from lib.core.translator import Translator +from lib.core.Handles.HandlesBase import CTypeInfo from lib.Shell.Serializer import SerializeSymbolTable, deSerializeSymbolTable, SymbolFile from lib.Shell.Config import Config @@ -25,7 +34,7 @@ from lib.Shell.Config import Config class TransPyC: """TransPyC 主类""" - def __init__(self, code=None, debug=False, triple=None, datalayout=None): + def __init__(self, code: str | None = None, debug: bool = False, triple: str | None = None, datalayout: str | None = None) -> None: """初始化TransPyC对象 Args: @@ -34,27 +43,27 @@ class TransPyC: triple: LLVM target triple (e.g. "x86_64-pc-linux-gnu") datalayout: LLVM data layout string """ - self.Args = {} - self.HeaderFiles = [] - self.HelperFiles = [] - self.AnnotationFiles = [] - self.translator = Translator() - self.code = code + self.Args: dict[str, Any] = {} + self.HeaderFiles: list[str] = [] + self.HelperFiles: list[str] = [] + self.AnnotationFiles: list[str] = [] + self.translator: Translator = Translator() + self.code: str | None = code self.translator.Content = code - self.config = Config() + self.config: Config = Config() self.translator.config = self.config self.config.debug = debug - self.SymbolFiles = [] - self.SliceLevel = 3 - self.SliceCount = 0 - self.SliceInfos = [] - self.metadata = DEFAULT_METADATA.copy() - self.triple = triple - self.datalayout = datalayout - self._source_module_sig_files = {} + self.SymbolFiles: list[SymbolFile] = [] + self.SliceLevel: int | str = 3 + self.SliceCount: int = 0 + self.SliceInfos: list[Any] = [] + self.metadata: dict[str, Any] = DEFAULT_METADATA.copy() + self.triple: str | None = triple + self.datalayout: str | None = datalayout + self._source_module_sig_files: dict[str, Any] = {} @staticmethod - def PreProcessSymbol(SymbolFile, debug=False): + def PreProcessSymbol(SymbolFile: SymbolFile, debug: bool = False) -> bytes | tuple[bytes, str]: """预处理符号文件,提取符号表并返回二进制数据 Args: @@ -67,21 +76,21 @@ class TransPyC: 如果debug为False: bytes - 序列化后的符号表二进制数据 如果debug为True: (bytes, str) - (二进制数据, 调试日志) """ - translator = Translator() - DebugLogs = [] + translator: Translator = Translator() + DebugLogs: list[str] | str = [] try: # 读取文件内容 if SymbolFile.FilePath: with open(SymbolFile.FilePath, 'r', encoding=SymbolFile.encoding) as f: - content = f.read() + content: str = f.read() elif SymbolFile.CodeString: content = SymbolFile.CodeString else: raise ValueError("SymbolFile must have either FilePath or CodeString") # 根据文件类型处理 - FileType = SymbolFile.FileType + FileType: str | None = SymbolFile.FileType if not FileType and SymbolFile.FilePath: # 从文件路径推断类型 if SymbolFile.FilePath.endswith('.py'): @@ -96,14 +105,14 @@ class TransPyC: # 设置调试文件(如果需要) if debug: - DebugFile = SymbolFile.FilePath.replace('.py', '.p2c') if SymbolFile.FilePath else 'debug.p2c' + DebugFile: str = SymbolFile.FilePath.replace('.py', '.p2c') if SymbolFile.FilePath else 'debug.p2c' translator.SetDebugFile(DebugFile) # 清空调试文件 with open(DebugFile, 'w', encoding=SymbolFile.encoding) as f: f.write('') # 解析AST并提取符号 - tree = ast.parse(content) + tree: ast.Module = ast.parse(content) if debug: with open(DebugFile, 'a', encoding=SymbolFile.encoding) as f: @@ -117,10 +126,10 @@ class TransPyC: translator.SymbolTable[node.name] = {'type': 'struct', 'members': {}} for item in node.body: if isinstance(item, ast.AnnAssign) and isinstance(item.target, ast.Name): - VarName = item.target.id - TypeInfo = translator.TypeMergeHandler.GetCTypeInfo(item.annotation) if item.annotation else None - VarType = TypeInfo.ToString() if TypeInfo else 'unknown' - IsPtr = TypeInfo.IsPtr if TypeInfo else False + VarName: str = item.target.id + TypeInfo: CTypeInfo | None = translator.TypeMergeHandler.GetCTypeInfo(item.annotation) if item.annotation else None + VarType: str = TypeInfo.ToString() if TypeInfo else 'unknown' + IsPtr: bool = TypeInfo.IsPtr if TypeInfo else False translator.SymbolTable[node.name]['members'][VarName] = { 'type': VarType, 'IsPtr': IsPtr @@ -129,12 +138,12 @@ class TransPyC: translator.SymbolTable[node.name] = {'type': 'function'} elif isinstance(node, ast.AnnAssign): if isinstance(node.target, ast.Name): - VarName = node.target.id - VarType = 'unknown' - IsPtr = False + VarName: str = node.target.id + VarType: str = 'unknown' + IsPtr: bool = False if node.annotation: try: - TypeInfo = translator.TypeMergeHandler.GetCTypeInfo(node.annotation) + TypeInfo: CTypeInfo | None = translator.TypeMergeHandler.GetCTypeInfo(node.annotation) VarType = TypeInfo.ToString() if TypeInfo else 'unknown' IsPtr = TypeInfo.IsPtr if TypeInfo else False except: @@ -168,49 +177,49 @@ class TransPyC: raise ValueError(f"Unsupported file type: {FileType}") # 序列化符号表 - BinaryData = SerializeSymbolTable(translator.SymbolTable) + BinaryData: bytes = SerializeSymbolTable(translator.SymbolTable) if debug: return BinaryData, DebugLogs return BinaryData except Exception as e: - error_msg = f"Error processing symbol file: {e}" + error_msg: str = f"Error processing symbol file: {e}" if debug: return b'', error_msg raise RuntimeError(error_msg) - def ParseArgs(self): + def ParseArgs(self) -> None: """解析命令行参数""" - I = 1 + I: int = 1 while I < len(sys.argv): if sys.argv[I] == '-f': if I + 1 < len(sys.argv): self.Args['Input'] = sys.argv[I + 1] I += 2 else: - print(f'Error: -f requires an argument') + error('-f requires an argument') sys.exit(1) elif sys.argv[I] == '-o': if I + 1 < len(sys.argv): self.Args['Output'] = sys.argv[I + 1] I += 2 else: - print(f'Error: -o requires an argument') + error('-o requires an argument') sys.exit(1) elif sys.argv[I] == '-wh': if I + 1 < len(sys.argv): self.HeaderFiles = sys.argv[I + 1:] break else: - print(f'Error: -wh requires arguments') + error('-wh requires arguments') sys.exit(1) elif sys.argv[I] == '-debug': if I + 1 < len(sys.argv): self.Args['Debug'] = sys.argv[I + 1] I += 2 else: - print(f'Error: -debug requires an argument') + error('-debug requires an argument') sys.exit(1) elif sys.argv[I] == '-cc': # 编译命令 @@ -218,7 +227,7 @@ class TransPyC: self.Args['CompileCommand'] = sys.argv[I + 1] I += 2 else: - print(f'Error: -cc requires an argument') + error('-cc requires an argument') sys.exit(1) elif sys.argv[I] == '-cflags': # 编译标志 @@ -226,7 +235,7 @@ class TransPyC: self.Args['CompileFlags'] = sys.argv[I + 1] I += 2 else: - print(f'Error: -cflags requires an argument') + error('-cflags requires an argument') sys.exit(1) elif sys.argv[I] == '-run': # 是否运行生成的程序 @@ -238,11 +247,11 @@ class TransPyC: self.Args['RunArgs'] = sys.argv[I + 1] I += 2 else: - print(f'Error: -args requires an argument') + error('-args requires an argument') sys.exit(1) elif sys.argv[I] == '-level' or sys.argv[I] == '-l': if I + 1 < len(sys.argv): - LevelArg = sys.argv[I + 1] + LevelArg: str = sys.argv[I + 1] if LevelArg.isdigit(): self.Args['SliceLevel'] = int(LevelArg) elif LevelArg == 's': @@ -261,32 +270,32 @@ class TransPyC: I += 1 I += 1 else: - print(f'Error: -h requires arguments') + error('-h requires arguments') sys.exit(1) elif sys.argv[I] == '-presym': # 预处理符号文件,生成.symbin文件 # 格式: -presym -o [-debug ] if I + 1 < len(sys.argv): - InputFile = sys.argv[I + 1] + InputFile: str = sys.argv[I + 1] I += 2 # 解析可选参数 - OutputFile = None - DebugFile = None + OutputFile: str | None = None + DebugFile: str | None = None while I < len(sys.argv) and sys.argv[I].startswith('-'): if sys.argv[I] == '-o': if I + 1 < len(sys.argv): OutputFile = sys.argv[I + 1] I += 2 else: - print(f'Error: -o requires an argument') + error('-o requires an argument') sys.exit(1) elif sys.argv[I] == '-debug': if I + 1 < len(sys.argv): DebugFile = sys.argv[I + 1] I += 2 else: - print(f'Error: -debug requires an argument') + error('-debug requires an argument') sys.exit(1) else: break @@ -302,94 +311,94 @@ class TransPyC: 'debug': DebugFile } else: - print(f'Error: -presym requires an argument') + error('-presym requires an argument') sys.exit(1) elif sys.argv[I] == '-e' or sys.argv[I] == '--encoding': if I + 1 < len(sys.argv): self.Args['Encoding'] = sys.argv[I + 1] I += 2 else: - print(f'Error: -e/--encoding requires an argument') + error('-e/--encoding requires an argument') sys.exit(1) elif sys.argv[I] == '--triple': if I + 1 < len(sys.argv): self.triple = sys.argv[I + 1] I += 2 else: - print(f'Error: --triple requires an argument') + error('--triple requires an argument') sys.exit(1) elif sys.argv[I] == '--datalayout': if I + 1 < len(sys.argv): self.datalayout = sys.argv[I + 1] I += 2 else: - print(f'Error: --datalayout requires an argument') + error('--datalayout requires an argument') sys.exit(1) else: - print(f'Error: Unknown argument {sys.argv[I]}') + error(f'Unknown argument {sys.argv[I]}') sys.exit(1) # 检查是否有预处理符号文件的请求,如果有则跳过输入输出检查 if 'PreSym' not in self.Args and ('Input' not in self.Args or 'Output' not in self.Args): - print(ERROR_MESSAGES['MISSING_ARGS']) - print(HELP_MESSAGE) + error('缺少参数') + info(HELP_MESSAGE) sys.exit(1) - def CompileAndRun(self, OutputFile): + def CompileAndRun(self, OutputFile: str) -> None: """编译并运行生成的C代码""" # 获取编译命令 - CompileCmd = self.Args.get('CompileCommand', DEFAULT_COMPILE_COMMAND) - CompileFlags = self.Args.get('CompileFlags', DEFAULT_COMPILE_FLAGS) + CompileCmd: str = self.Args.get('CompileCommand', DEFAULT_COMPILE_COMMAND) + CompileFlags: str = self.Args.get('CompileFlags', DEFAULT_COMPILE_FLAGS) - # 构建编译命令 - FullCompileCmd = f'{CompileCmd} {CompileFlags} {OutputFile} -o {OutputFile}.exe' - print(f'Compiling: {FullCompileCmd}') + # 构建编译命令(使用列表形式,避免 shell 注入) + FullCompileCmd: list[str] = shlex.split(CompileCmd) + shlex.split(CompileFlags) + [OutputFile, '-o', f'{OutputFile}.exe'] + info(f'编译命令: {" ".join(FullCompileCmd)}') # 执行编译命令 try: - CompileResult = ExecuteCommand(FullCompileCmd) + CompileResult: subprocess.CompletedProcess[str] | None = ExecuteCommand(FullCompileCmd) if CompileResult: - print('Compilation successful!') + success('编译成功!') # 检查是否需要运行 if self.Args.get('Run', False): - RunArgs = self.Args.get('RunArgs', '') - RunCmd = f'{OutputFile}.exe {RunArgs}'.strip() - print(f'Running: {RunCmd}') + RunArgs: str = self.Args.get('RunArgs', '') + RunCmd: list[str] = [f'{OutputFile}.exe'] + (shlex.split(RunArgs) if RunArgs else []) + info(f'运行: {" ".join(RunCmd)}') # 执行运行命令 - RunResult = ExecuteCommand(RunCmd) + RunResult: subprocess.CompletedProcess[str] | None = ExecuteCommand(RunCmd) if RunResult: - print('Execution output:') - print(RunResult.stdout) + info('执行输出:') + info(RunResult.stdout) if RunResult.stderr: - print('Execution errors:') - print(RunResult.stderr) + warning('执行错误:') + warning(RunResult.stderr) except Exception as e: - print(f'{ERROR_MESSAGES["COMPILE_FAILED"]}: {e}') + error(f'编译失败: {e}') - def WriteDebugInfo(self, content): + def WriteDebugInfo(self, content: str) -> None: """写入调试信息到指定文件""" # 获取调试文件路径 if 'Debug' in self.Args: - DebugFile = self.Args['Debug'] + DebugFile: str = self.Args['Debug'] else: - DebugFile = self.Args.get('Output', '').replace('.c', '.p2c') + DebugFile: str = self.Args.get('Output', '').replace('.c', '.p2c') if DebugFile: AppendFileContent(DebugFile, content) - def PythonToC(self, InputFile, OutputFile): + def PythonToC(self, InputFile: str, OutputFile: str) -> None: """Python到C的转换""" # 获取编码参数 - encoding = self.Args.get('Encoding', 'utf-8') + encoding: str = self.Args.get('Encoding', 'utf-8') # 设置调试文件路径(使用 .p2c 扩展名) if 'Debug' in self.Args: - DebugFile = self.Args['Debug'] + DebugFile: str = self.Args['Debug'] else: # 默认使用 .p2c 文件 - DebugFile = OutputFile.replace('.c', '.p2c') + DebugFile: str = OutputFile.replace('.c', '.p2c') # 设置翻译器的调试文件 self.translator.SetDebugFile(DebugFile) @@ -409,14 +418,14 @@ class TransPyC: # 获取编码参数 encoding = self.Args.get('Encoding', 'utf-8') with open(InputFile, 'r', encoding=encoding) as F: - Content = F.read() + Content: str = F.read() # 保存原始代码行 self.translator.OriginalLines = Content.split('\n') self.translator.Content = Content # 解析Python代码为AST - Tree = ast.parse(Content) + Tree: ast.Module = ast.parse(Content) # 解析文件以提取类型信息(用于 EmbeddedAssignments) self.translator.ParsePythonFile(InputFile, encoding) @@ -427,23 +436,22 @@ class TransPyC: f.write(ast.dump(Tree)) f.write('\n\n') - Target = 'llvm' - CCode = self.translator.GenerateCCode(Tree, target=Target) + Target: str = 'llvm' + CCode: str = self.translator.GenerateCCode(Tree, target=Target) - import datetime - timestamp = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') - filename = os.path.basename(OutputFile) + timestamp: str = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') + filename: str = os.path.basename(OutputFile) encoding = self.Args.get('Encoding', 'utf-8') with open(OutputFile, 'w', encoding=encoding) as F: F.write(CCode) F.write('\n') - def CToPython(self, InputFile, OutputFile, HeaderFiles): + def CToPython(self, InputFile: str, OutputFile: str, HeaderFiles: list[str]) -> None: """C到Python的转换(暂时禁用)""" - print("C到Python的转换功能暂时禁用,请使用Python到C的转换功能。") + warning("C到Python的转换功能暂时禁用,请使用Python到C的转换功能。") - def AddSymbol(self, SymbolFiles): + def AddSymbol(self, SymbolFiles: SymbolFile | list[SymbolFile]) -> None: """添加符号文件 Args: @@ -455,11 +463,11 @@ class TransPyC: self.SymbolFiles.append(SymbolFiles) # 收集文件路径和编码 - HelperFiles = [] - encodings = [] + HelperFiles: list[str] = [] + encodings: list[str] = [] for SymbolFile in self.SymbolFiles: - FilePath = SymbolFile.FilePath - encoding = SymbolFile.encoding + FilePath: str | None = SymbolFile.FilePath + encoding: str = SymbolFile.encoding if FilePath: HelperFiles.append(FilePath) encodings.append(encoding) @@ -470,7 +478,7 @@ class TransPyC: encoding = encodings[0] if encodings else 'utf-8' self.translator.ParseHelperFiles(HelperFiles, encoding) - def Convert(self, OutputFilename=None, SourceFilename=None, target='llvm'): + def Convert(self, OutputFilename: str | None = None, SourceFilename: str | None = None, target: str = 'llvm') -> str | tuple[str, dict[str, Any]] | None: """转换代码 Args: @@ -483,7 +491,7 @@ class TransPyC: 如果debug是True,则返回生成的代码和调试信息 """ if not self.code: - print('Error: No code provided') + error('未提供代码') return None from lib.core.Handles.HandlesImports import ImportHandle @@ -502,24 +510,24 @@ class TransPyC: self.translator.OriginalLines = self.code.split('\n') # 解析Python代码为AST - Tree = ast.parse(self.code) + Tree: ast.Module = ast.parse(self.code) # 从源代码直接预扫描 import 语句,注册别名 # 注意:不能依赖 Tree 中的 import 节点,因为 ParsePythonFile 可能修改了 AST if not getattr(self.translator, '_ImportedModules', None): self.translator._ImportedModules = set() - _prescan_tree = ast.parse(self.code) + _prescan_tree: ast.Module = ast.parse(self.code) for _node in ast.iter_child_nodes(_prescan_tree): if isinstance(_node, ast.Import): for _alias in _node.names: - _name = _alias.name + _name: str = _alias.name if _name in ('c', 't'): continue self.translator._ImportedModules.add(_name) if _alias.asname: self.translator.SymbolTable.import_aliases[_alias.asname] = _name elif isinstance(_node, ast.ImportFrom): - _module_name = _node.module + _module_name: str | None = _node.module if _module_name and _module_name not in ('c', 't'): self.translator._ImportedModules.add(_module_name) for _alias in _node.names: @@ -528,11 +536,9 @@ class TransPyC: # 解析代码以提取类型信息(用于 EmbeddedAssignments 和 TypedefAssignments) # 创建临时文件路径用于解析 - import tempfile - import os with tempfile.NamedTemporaryFile(mode='w', suffix='.py', delete=False, encoding='utf-8') as f: f.write(self.code) - TempFile = f.name + TempFile: str = f.name try: # UpdateCurrentFile=False 表示不修改 CurrentFile if SourceFilename: @@ -542,8 +548,7 @@ class TransPyC: finally: os.unlink(TempFile) - import datetime - timestamp = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') + timestamp: str = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') if self.triple: self.translator.triple = self.triple @@ -551,8 +556,8 @@ class TransPyC: self.translator.datalayout = self.datalayout # 生成代码 - code = self.translator.GenerateCCode(Tree, target='llvm') - filename = os.path.basename(OutputFilename) if OutputFilename else 'generated.ll' + code: str = self.translator.GenerateCCode(Tree, target='llvm') + filename: str = os.path.basename(OutputFilename) if OutputFilename else 'generated.ll' # 处理调试信息 if isinstance(self.config.debug, str): @@ -569,7 +574,7 @@ class TransPyC: return code elif self.config.debug: # 如果debug是True,返回生成的代码和调试信息 - DebugInfo = { + DebugInfo: dict[str, Any] = { 'SymbolTable': self.translator.SymbolTable, 'ast_tree': ast.dump(Tree, indent=2), 'Exportable': self.translator.Exportable.to_dict(), @@ -580,7 +585,7 @@ class TransPyC: # 如果debug是False,只返回生成的代码 return code - def Run(self): + def Run(self) -> None: """主运行函数""" # 检查是否有命令行参数 if len(sys.argv) > 1: @@ -589,46 +594,48 @@ class TransPyC: # 检查是否有预处理符号文件的请求 if 'PreSym' in self.Args: - PresymConfig = self.Args['PreSym'] - InputFile = PresymConfig['input'] - OutputFile = PresymConfig['output'] - DebugFile = PresymConfig['debug'] + PresymConfig: dict[str, Any] = self.Args['PreSym'] + InputFile: str = PresymConfig['input'] + OutputFile: str = PresymConfig['output'] + DebugFile: str | None = PresymConfig['debug'] # 获取编码参数 - encoding = self.Args.get('Encoding', 'utf-8') + encoding: str = self.Args.get('Encoding', 'utf-8') # 推断文件类型 - FileType = 'py' if InputFile.endswith('.py') else 'c' if InputFile.endswith('.c') else None + FileType: str | None = 'py' if InputFile.endswith('.py') else 'c' if InputFile.endswith('.c') else None # 创建 SymbolFile 对象,传入编码参数 - SymbolFile = SymbolFile(file=InputFile, type=FileType, encoding=encoding) + SymbolFile: SymbolFile = SymbolFile(file=InputFile, type=FileType, encoding=encoding) # 调用 PreProcessSymbol if DebugFile: + BinaryData: bytes + DebugInfo: str BinaryData, DebugInfo = TransPyC.PreProcessSymbol(SymbolFile, debug=True) # 写入调试文件 with open(DebugFile, 'w', encoding=encoding) as f: f.write(DebugInfo) - print(f"Debug info written to: {DebugFile}") + info(f"调试信息写入: {DebugFile}") else: - BinaryData = TransPyC.PreProcessSymbol(SymbolFile, debug=False) + BinaryData: bytes = TransPyC.PreProcessSymbol(SymbolFile, debug=False) # 写入二进制符号文件 with open(OutputFile, 'wb') as f: f.write(BinaryData) - print(f"Symbol file generated: {OutputFile}") + success(f"符号文件生成: {OutputFile}") return - InputFile = self.Args['Input'] - OutputFile = self.Args['Output'] + InputFile: str = self.Args['Input'] + OutputFile: str = self.Args['Output'] else: # 没有命令行参数,使用默认的测试文件名称 - InputFile = DEFAULT_INPUT_FILE - OutputFile = DEFAULT_OUTPUT_FILE - print('Using default test files: test.py -> test.c') + InputFile: str = DEFAULT_INPUT_FILE + OutputFile: str = DEFAULT_OUTPUT_FILE + info('使用默认测试文件: test.py -> test.c') - FileType = DetectFileType(InputFile) + FileType: str = DetectFileType(InputFile) if FileType == '.py': self.PythonToC(InputFile, OutputFile) @@ -638,5 +645,5 @@ class TransPyC: elif FileType == '.c': self.CToPython(InputFile, OutputFile, self.HeaderFiles) else: - print(f'Error: Unsupported file type {FileType}') + error(f'不支持的文件类型: {FileType}') sys.exit(1) diff --git a/lib/StubGen/Config.py b/lib/StubGen/Config.py index fae30bc..4e3b135 100644 --- a/lib/StubGen/Config.py +++ b/lib/StubGen/Config.py @@ -1,42 +1,43 @@ -"""StubGen 配置模块""" -import json -from dataclasses import dataclass, field -from typing import List, Dict, Optional - - -@dataclass -class StubGenConfig: - """存根生成器配置""" - InputDir: Optional[str] = None - OutputDir: str = "./stubs" - InputFiles: List[str] = field(default_factory=list) - IncludePatterns: List[str] = field(default_factory=lambda: ["*.h", "*.c", "*.py"]) - ExcludePatterns: List[str] = field(default_factory=list) - TypeMappings: Dict[str, str] = field(default_factory=dict) - PreserveStructure: bool = True # 保持目录结构 - GenerateGuards: bool = True # 生成宏守卫 - verbose: bool = False - DryRun: bool = False - - @classmethod - def from_dict(cls, data: Dict) -> 'StubGenConfig': - """从字典创建配置""" - return cls( - InputDir=data.get('InputDir'), - OutputDir=data.get('OutputDir', './stubs'), - InputFiles=data.get('InputFiles', []), - IncludePatterns=data.get('IncludePatterns', ['*.h', '*.c', '*.py']), - ExcludePatterns=data.get('ExcludePatterns', []), - TypeMappings=data.get('TypeMappings', {}), - PreserveStructure=data.get('PreserveStructure', True), - GenerateGuards=data.get('GenerateGuards', True), - verbose=data.get('verbose', False), - DryRun=data.get('DryRun', False), - ) - - @classmethod - def from_file(cls, FilePath: str) -> 'StubGenConfig': - """从 JSON 文件加载配置""" - with open(FilePath, 'r', encoding='utf-8') as f: - data = json.load(f) - return cls.from_dict(data) +"""StubGen 配置模块""" +from __future__ import annotations +import json +from dataclasses import dataclass, field +from typing import List, Dict, Optional + + +@dataclass +class StubGenConfig: + """存根生成器配置""" + InputDir: Optional[str] = None + OutputDir: str = "./stubs" + InputFiles: List[str] = field(default_factory=list) + IncludePatterns: List[str] = field(default_factory=lambda: ["*.h", "*.c", "*.py"]) + ExcludePatterns: List[str] = field(default_factory=list) + TypeMappings: Dict[str, str] = field(default_factory=dict) + PreserveStructure: bool = True # 保持目录结构 + GenerateGuards: bool = True # 生成宏守卫 + verbose: bool = False + DryRun: bool = False + + @classmethod + def from_dict(cls, data: dict) -> StubGenConfig: + """从字典创建配置""" + return cls( + InputDir=data.get('InputDir'), + OutputDir=data.get('OutputDir', './stubs'), + InputFiles=data.get('InputFiles', []), + IncludePatterns=data.get('IncludePatterns', ['*.h', '*.c', '*.py']), + ExcludePatterns=data.get('ExcludePatterns', []), + TypeMappings=data.get('TypeMappings', {}), + PreserveStructure=data.get('PreserveStructure', True), + GenerateGuards=data.get('GenerateGuards', True), + verbose=data.get('verbose', False), + DryRun=data.get('DryRun', False), + ) + + @classmethod + def from_file(cls, FilePath: str) -> StubGenConfig: + """从 JSON 文件加载配置""" + with open(FilePath, 'r', encoding='utf-8') as f: + data: dict = json.load(f) + return cls.from_dict(data) \ No newline at end of file diff --git a/lib/StubGen/Converter.py b/lib/StubGen/Converter.py index a808713..17fdcda 100644 --- a/lib/StubGen/Converter.py +++ b/lib/StubGen/Converter.py @@ -1,7 +1,10 @@ """StubGen 转换器模块 - 将 Python 文件转换为存根格式""" +from __future__ import annotations import ast import re +import fnmatch from typing import List, Dict, Optional, Tuple +from lib.core.SymbolUtils import IsListAnnotation class PythonToStubConverter: @@ -17,24 +20,23 @@ class PythonToStubConverter: MacroExcludeList: List[str] = [] @classmethod - def SetIncludeAliasMap(cls, alias_map: Dict[str, str]): + def SetIncludeAliasMap(cls, alias_map: Dict[str, str]) -> None: """设置 __include 别名映射表""" cls.IncludeAliasMap = alias_map @classmethod - def SetVarExcludeList(cls, exclude_list: List[str]): + def SetVarExcludeList(cls, exclude_list: List[str]) -> None: """设置变量排除列表""" cls.VarExcludeList = exclude_list @classmethod - def SetMacroExcludeList(cls, exclude_list: List[str]): + def SetMacroExcludeList(cls, exclude_list: List[str]) -> None: """设置宏排除列表""" cls.MacroExcludeList = exclude_list @classmethod def _ShouldExcludeVar(cls, VarName: str) -> bool: """检查变量是否应该被排除""" - import fnmatch for pattern in cls.VarExcludeList: if fnmatch.fnmatch(VarName, pattern): return True @@ -43,7 +45,6 @@ class PythonToStubConverter: @classmethod def _ShouldExcludeMacro(cls, MacroName: str) -> bool: """检查宏是否应该被排除""" - import fnmatch for pattern in cls.MacroExcludeList: if fnmatch.fnmatch(MacroName, pattern): return True @@ -52,8 +53,8 @@ class PythonToStubConverter: @staticmethod def convert(PyContent: str, ModuleName: str) -> str: """将 Python 代码转换为存根格式""" - lines = PyContent.split('\n') - StubLines = [] + lines: list[str] = PyContent.split('\n') + StubLines: list[str] = [] # 添加文件头 StubLines.append('"""') @@ -63,11 +64,10 @@ class PythonToStubConverter: StubLines.append('') # 解析 Python 代码,检查是否已经导入了 t 和 c - import ast - HasImportT = False - HasImportC = False + HasImportT: bool = False + HasImportC: bool = False try: - tree = ast.parse(PyContent) + tree: ast.Module = ast.parse(PyContent) for node in tree.body: if isinstance(node, ast.Import): for alias in node.names: @@ -103,24 +103,24 @@ class PythonToStubConverter: tree = ast.parse(PyContent) # 第一遍扫描:收集 Postdefinition 变量 - PostdefVars = {} # {ClassName: [(VarName, TypeStr, node), ...]} + PostdefVars: dict[str, list[tuple[str, str, ast.AnnAssign]]] = {} # {ClassName: [(VarName, TypeStr, node), ...]} for node in tree.body: if isinstance(node, ast.AnnAssign) and isinstance(node.target, ast.Name): - TypeStr = PythonToStubConverter._GetTypeString(node.annotation) + TypeStr: str = PythonToStubConverter._GetTypeString(node.annotation) # 检查是否是 Postdefinition 类型 if 't.Postdefinition' in TypeStr: # 提取引用的类名 - ClassName = PythonToStubConverter._ExtractPostdefClass(node.annotation) + ClassName: str | None = PythonToStubConverter._ExtractPostdefClass(node.annotation) if ClassName: if ClassName not in PostdefVars: PostdefVars[ClassName] = [] PostdefVars[ClassName].append((node.target.id, TypeStr, node)) # 按原始顺序处理节点,保持代码的原始顺序 - PrevType = None # 记录前一个节点的类型 + PrevType: str | None = None # 记录前一个节点的类型 for node in tree.body: - CurrentType = None + CurrentType: str | None = None if isinstance(node, ast.ClassDef): CurrentType = 'class' @@ -128,8 +128,8 @@ class PythonToStubConverter: if PrevType is not None and PrevType != 'class': StubLines.append('') # 检查是否有对应的 Postdefinition 变量 - ClassPostdefs = PostdefVars.get(node.name, []) - ClassLines = PythonToStubConverter._ConvertClass( + ClassPostdefs: list[tuple[str, str, ast.AnnAssign]] = PostdefVars.get(node.name, []) + ClassLines: list[str] = PythonToStubConverter._ConvertClass( node, SourceLines=lines, PostdefVars=ClassPostdefs ) StubLines.extend(ClassLines) @@ -138,7 +138,7 @@ class PythonToStubConverter: # 如果前一个是类或者是第一个函数,添加空行分隔 if PrevType == 'class' or (PrevType is not None and PrevType != 'function'): StubLines.append('') - FuncLines = PythonToStubConverter._ConvertFunction(node, SourceLines=lines) + FuncLines: list[str] = PythonToStubConverter._ConvertFunction(node, SourceLines=lines) StubLines.extend(FuncLines) StubLines.append('') # 函数后空行 elif isinstance(node, ast.AnnAssign): @@ -148,11 +148,11 @@ class PythonToStubConverter: if 't.Postdefinition' in TypeStr: continue # 检查是否带有 t.CStatic 标志,如果有则不排除 - HasStatic = 't.CStatic' in TypeStr + HasStatic: bool = 't.CStatic' in TypeStr # 检查变量是否应该被排除 - ShouldExclude = False + ShouldExclude: bool = False if isinstance(node.target, ast.Name) and not HasStatic: - VarName = node.target.id + VarName: str = node.target.id if PythonToStubConverter._ShouldExcludeVar(VarName): ShouldExclude = True if ShouldExclude: @@ -160,14 +160,14 @@ class PythonToStubConverter: # 如果前一个不是变量,添加空行分隔 if PrevType is not None and PrevType != 'variable': StubLines.append('') - VarLines = PythonToStubConverter._ConvertVariable(node, SourceLines=lines) + VarLines: list[str] = PythonToStubConverter._ConvertVariable(node, SourceLines=lines) # 移除多余的空行 VarLines = [line for line in VarLines if line.strip()] StubLines.extend(VarLines) elif isinstance(node, ast.Import): # 处理导入语句 CurrentType = 'import' - ImportStr = PythonToStubConverter._GetImportString(node, SourceLines=lines) + ImportStr: str = PythonToStubConverter._GetImportString(node, SourceLines=lines) if ImportStr: if PrevType is not None and PrevType != 'import': StubLines.append('') @@ -177,7 +177,7 @@ class PythonToStubConverter: # 处理模块级别的全局变量(无类型标注) if PrevType is not None and PrevType != 'variable': StubLines.append('') - AssignLines = PythonToStubConverter._ConvertGlobalAssign(node) + AssignLines: list[str] = PythonToStubConverter._ConvertGlobalAssign(node) StubLines.extend(AssignLines) elif isinstance(node, ast.ImportFrom): # 处理 from ... import ... 语句 @@ -189,14 +189,14 @@ class PythonToStubConverter: StubLines.append(ImportStr) elif isinstance(node, ast.Expr): # 处理模块级别的宏调用,如 c.CIf(...), c.CEndif() - ExprStr = PythonToStubConverter._GetExprString(node.value) + ExprStr: str = PythonToStubConverter._GetExprString(node.value) if ExprStr: CurrentType = 'macro' StubLines.append(ExprStr) StubLines.append('') # 宏后空行 elif isinstance(node, ast.If): # 处理模块级别的 if 宏条件,如 if c.CIf(FF_MULTI_PARTITION): - IfStr = PythonToStubConverter._GetModuleIfMacroString(node) + IfStr: str = PythonToStubConverter._GetModuleIfMacroString(node) if IfStr: CurrentType = 'macro' StubLines.append(IfStr) @@ -220,7 +220,7 @@ class PythonToStubConverter: return '\n'.join(StubLines) @staticmethod - def _ConvertClass(node: ast.ClassDef, SourceLines: List[str] = None, PostdefVars: List[Tuple[str, str, ast.AnnAssign]] = None, indent: int = 0) -> List[str]: + def _ConvertClass(node: ast.ClassDef, SourceLines: list[str] | None = None, PostdefVars: list[tuple[str, str, ast.AnnAssign]] | None = None, indent: int = 0) -> list[str]: """转换类定义 Args: @@ -229,24 +229,24 @@ class PythonToStubConverter: PostdefVars: Postdefinition 变量列表 [(VarName, TypeStr, node), ...] indent: 缩进级别(用于嵌套类) """ - lines = [] + lines: list[str] = [] PostdefVars = PostdefVars or [] - IndentStr = ' ' * indent + IndentStr: str = ' ' * indent # 处理类装饰器 for decorator in node.decorator_list: - DecoratorStr = PythonToStubConverter._GetDecoratorString(decorator) + DecoratorStr: str = PythonToStubConverter._GetDecoratorString(decorator) if DecoratorStr: lines.append(f'{IndentStr}@{DecoratorStr}') # 检查是否是结构体、联合体或枚举 - BaseNames = [base.attr if isinstance(base, ast.Attribute) else base.id + BaseNames: list[str] = [base.attr if isinstance(base, ast.Attribute) else base.id for base in node.bases if isinstance(base, (ast.Name, ast.Attribute))] # 保留原始基类 if node.bases: - BaseStrs = [] + BaseStrs: list[str] = [] for base in node.bases: if isinstance(base, ast.Name): BaseStrs.append(base.id) @@ -255,9 +255,9 @@ class PythonToStubConverter: elif isinstance(base, ast.Subscript): # 处理泛型类型,如 memory_block_t[MAX_ORDER + 1] BaseStrs.append(PythonToStubConverter._GetTypeString(base)) - ClassTypeParamStr = '' + ClassTypeParamStr: str = '' if hasattr(node, 'type_params') and node.type_params: - param_names = [tp.name for tp in node.type_params] + param_names: list[str] = [tp.name for tp in node.type_params] ClassTypeParamStr = f'[{", ".join(param_names)}]' if BaseStrs: lines.append(f'{IndentStr}class {node.name}{ClassTypeParamStr}({", ".join(BaseStrs)}):') @@ -271,12 +271,12 @@ class PythonToStubConverter: lines.append(f'{IndentStr}class {node.name}{ClassTypeParamStr}:') # 处理类成员 - HasMembers = False - seen_member_names = set() + HasMembers: bool = False + seen_member_names: set[str] = set() for item in node.body: if isinstance(item, ast.AnnAssign) and isinstance(item.target, ast.Name): seen_member_names.add(item.target.id) - init_members = [] + init_members: list[ast.AnnAssign] = [] for item in node.body: if isinstance(item, ast.FunctionDef) and item.name == '__init__': for stmt in item.body: @@ -285,7 +285,7 @@ class PythonToStubConverter: and isinstance(stmt.target.value, ast.Name) and stmt.target.value.id == 'self'): init_members.append(stmt) - untyped_self_members = [] + untyped_self_members: list[ast.Assign] = [] for m_name in [m.target.attr for m in init_members if isinstance(m.target, ast.Attribute)]: seen_member_names.add(m_name) for item in node.body: @@ -296,7 +296,7 @@ class PythonToStubConverter: and isinstance(stmt.targets[0], ast.Attribute) and isinstance(stmt.targets[0].value, ast.Name) and stmt.targets[0].value.id == 'self'): - attr_name = stmt.targets[0].attr + attr_name: str = stmt.targets[0].attr if attr_name not in seen_member_names: seen_member_names.add(attr_name) untyped_self_members.append(stmt) @@ -307,11 +307,11 @@ class PythonToStubConverter: and isinstance(item.targets[0].value, ast.Name) and item.targets[0].value.id == 'self'): HasMembers = True - MemberIndent = IndentStr + ' ' + MemberIndent: str = IndentStr + ' ' attr_name = item.targets[0].attr if attr_name in seen_member_names: continue - InferredType = 'int' + InferredType: str = 'int' if item.value and isinstance(item.value, ast.Constant): if isinstance(item.value.value, float): InferredType = 'float' @@ -324,86 +324,95 @@ class PythonToStubConverter: HasMembers = True MemberIndent = IndentStr + ' ' if SourceLines and hasattr(item, 'lineno'): - StartLine = item.lineno - 1 - EndLine = item.EndLineno if hasattr(item, 'EndLineno') and item.EndLineno else StartLine + 1 + StartLine: int = item.lineno - 1 + EndLine: int = item.end_lineno if hasattr(item, 'end_lineno') and item.end_lineno else StartLine + 1 for i in range(StartLine, min(EndLine, len(SourceLines))): lines.append(MemberIndent + SourceLines[i].lstrip()) elif isinstance(item, ast.AnnAssign): HasMembers = True - TypeStr = PythonToStubConverter._GetTypeString(item.annotation) + TypeStr: str = PythonToStubConverter._GetTypeString(item.annotation) MemberIndent = IndentStr + ' ' + # __provides__/__requires__/__require_must__ 元数据:保留值以便跨模块加载 + if isinstance(item.target, ast.Name) and item.target.id in ('__provides__', '__requires__', '__require_must__'): + if item.value is not None: + try: + value_str: str = ast.unparse(item.value) + except Exception: + value_str = '' + lines.append(f'{MemberIndent}{item.target.id}: {TypeStr} = {value_str}') + else: + lines.append(f'{MemberIndent}{item.target.id}: {TypeStr}') + continue # 检查是否是宏变量(类型包含 t.CDefine) if 't.CDefine' in TypeStr: # 检查宏变量是否应该被排除 if isinstance(item.target, ast.Name): - MacroName = item.target.id + MacroName: str = item.target.id if PythonToStubConverter._ShouldExcludeMacro(MacroName): continue # 跳过该宏 # 宏变量保持原样(包括赋值) if SourceLines and hasattr(item, 'lineno'): StartLine = item.lineno - 1 - EndLine = item.EndLineno if hasattr(item, 'EndLineno') and item.EndLineno else StartLine + 1 + EndLine = item.end_lineno if hasattr(item, 'end_lineno') and item.end_lineno else StartLine + 1 for i in range(StartLine, min(EndLine, len(SourceLines))): lines.append(MemberIndent + SourceLines[i].lstrip()) else: lines.append(f'{MemberIndent}{item.target.id}: {TypeStr}') else: if isinstance(item.target, ast.Attribute): - MemberName = item.target.attr + MemberName: str = item.target.attr else: MemberName = item.target.id - FinalTypeStr = TypeStr - if (isinstance(item.annotation, ast.Subscript) - and isinstance(item.annotation.value, ast.Name) - and item.annotation.value.id == 'list'): - slice_node = item.annotation.slice - has_size = False + FinalTypeStr: str = TypeStr + if IsListAnnotation(item.annotation): + slice_node: ast.AST = item.annotation.slice + has_size: bool = False if isinstance(slice_node, ast.Tuple) and len(slice_node.elts) == 2: - count_node = slice_node.elts[1] + count_node: ast.AST = slice_node.elts[1] if isinstance(count_node, ast.Constant) and isinstance(count_node.value, int) and count_node.value > 0: has_size = True else: try: - count_expr = ast.unparse(count_node) + count_expr: str = ast.unparse(count_node) except Exception: count_expr = '' if count_expr and count_expr != 'None': has_size = True - elem_type_str = PythonToStubConverter._GetTypeString(slice_node.elts[0]) - FinalTypeStr = f'list[{elem_type_str}, {count_expr}]' + elem_type_str: str = PythonToStubConverter._GetTypeString(slice_node.elts[0]) + FinalTypeStr = f't.CArray[{elem_type_str}, {count_expr}]' if not has_size: elem_type_str = PythonToStubConverter._GetTypeString(slice_node if not isinstance(slice_node, ast.Tuple) else slice_node.elts[0]) - init_len = 0 + init_len: int = 0 if item.value is not None: if isinstance(item.value, ast.List): init_len = len(item.value.elts) elif isinstance(item.value, ast.Constant) and isinstance(item.value.value, str): init_len = len(item.value.value) + 1 if init_len > 0: - FinalTypeStr = f'list[{elem_type_str}, {init_len}]' + FinalTypeStr = f't.CArray[{elem_type_str}, {init_len}]' else: - FinalTypeStr = f'list[{elem_type_str}, None]' + FinalTypeStr = f't.CArray[{elem_type_str}, None]' lines.append(f'{MemberIndent}{MemberName}: {FinalTypeStr}') elif isinstance(item, ast.FunctionDef): HasMembers = True - FuncStub = PythonToStubConverter._ConvertFunction(item, indent=indent+1, SourceLines=SourceLines, class_name=node.name) + FuncStub: list[str] = PythonToStubConverter._ConvertFunction(item, indent=indent+1, SourceLines=SourceLines, class_name=node.name) lines.extend(FuncStub) elif isinstance(item, ast.Expr): # 处理宏调用,如 c.CIf(...), c.CEndif(), c.CElif(), c.CElse() - ExprStr = PythonToStubConverter._GetExprString(item.value) + ExprStr: str = PythonToStubConverter._GetExprString(item.value) if ExprStr: lines.append(f'{IndentStr} {ExprStr}') elif isinstance(item, ast.If): # 处理 if c.CIf(...): 形式的宏条件 - IfStr = PythonToStubConverter._get_if_macro_string(item, indent=indent+1) + IfStr: str = PythonToStubConverter._get_if_macro_string(item, indent=indent+1) if IfStr: lines.append(IfStr) elif isinstance(item, ast.ClassDef): # 处理嵌套类 HasMembers = True - NestedClassLines = PythonToStubConverter._ConvertClass(item, SourceLines=SourceLines, PostdefVars=[], indent=indent+1) + NestedClassLines: list[str] = PythonToStubConverter._ConvertClass(item, SourceLines=SourceLines, PostdefVars=[], indent=indent+1) # 移除嵌套类的宏守卫(因为已经在父类的宏守卫内) - FilteredLines = [] + FilteredLines: list[str] = [] for line in NestedClassLines: # 跳过宏守卫相关行 if line.strip().startswith('c.CIfndef(') or line.strip().startswith('c.CEndif()'): @@ -425,15 +434,15 @@ class PythonToStubConverter: return lines @staticmethod - def _ConvertFunction(node: ast.FunctionDef, indent: int = 0, SourceLines: List[str] = None, class_name: str = None) -> List[str]: + def _ConvertFunction(node: ast.FunctionDef, indent: int = 0, SourceLines: list[str] | None = None, class_name: str | None = None) -> list[str]: """转换函数定义""" - lines = [] - IndentStr = ' ' * indent + lines: list[str] = [] + IndentStr: str = ' ' * indent # 检查是否是宏函数(返回类型包含 t.CDefine) - is_macro_func = False + is_macro_func: bool = False if node.returns: - ReturnType = PythonToStubConverter._GetTypeString(node.returns) + ReturnType: str = PythonToStubConverter._GetTypeString(node.returns) if 't.CDefine' in ReturnType: is_macro_func = True @@ -444,8 +453,8 @@ class PythonToStubConverter: # 保持原样(包括代码块) if SourceLines: - StartLine = node.lineno - 1 - EndLine = node.EndLineno if hasattr(node, 'EndLineno') and node.EndLineno else StartLine + 1 + StartLine: int = node.lineno - 1 + EndLine: int = node.end_lineno if hasattr(node, 'end_lineno') and node.end_lineno else StartLine + 1 for i in range(StartLine, min(EndLine, len(SourceLines))): lines.append(SourceLines[i]) if lines and lines[-1].strip() and not lines[-1].rstrip().endswith(':'): @@ -456,16 +465,16 @@ class PythonToStubConverter: # 处理函数装饰器 for decorator in node.decorator_list: - DecoratorStr = PythonToStubConverter._GetDecoratorString(decorator) + DecoratorStr: str = PythonToStubConverter._GetDecoratorString(decorator) if DecoratorStr: lines.append(f'{IndentStr}@{DecoratorStr}') # 构建参数列表 - params = [] + params: list[str] = [] for arg_idx, arg in enumerate(node.args.args): - ArgName = arg.arg + ArgName: str = arg.arg if arg.annotation: - TypeStr = PythonToStubConverter._GetTypeString(arg.annotation) + TypeStr: str = PythonToStubConverter._GetTypeString(arg.annotation) params.append(f'{ArgName}: {TypeStr}') elif class_name and arg_idx == 0 and ArgName == 'self': params.append(f'self: {class_name}') @@ -490,7 +499,7 @@ class PythonToStubConverter: else: params.append(f'**{ArgName}') - ParamStr = ', '.join(params) + ParamStr: str = ', '.join(params) # 返回类型 - 保持原始类型(不添加t.State) if node.returns: @@ -498,21 +507,21 @@ class PythonToStubConverter: else: ReturnType = 't.CInt' - TypeParamStr = '' + TypeParamStr: str = '' if hasattr(node, 'type_params') and node.type_params: - param_names = [tp.name for tp in node.type_params] + param_names: list[str] = [tp.name for tp in node.type_params] TypeParamStr = f'[{", ".join(param_names)}]' lines.append(f'{IndentStr}def {node.name}{TypeParamStr}({ParamStr}) -> {ReturnType}: pass') return lines @staticmethod - def _ConvertVariable(node: ast.AnnAssign, SourceLines: List[str] = None) -> List[str]: + def _ConvertVariable(node: ast.AnnAssign, SourceLines: list[str] | None = None) -> list[str]: """转换变量定义""" - lines = [] + lines: list[str] = [] if isinstance(node.target, ast.Name): - VarName = node.target.id - TypeStr = PythonToStubConverter._GetTypeString(node.annotation) + VarName: str = node.target.id + TypeStr: str = PythonToStubConverter._GetTypeString(node.annotation) # 检查是否是宏变量(类型包含 t.CDefine) if 't.CDefine' in TypeStr: # 检查宏变量是否应该被排除 @@ -520,8 +529,8 @@ class PythonToStubConverter: return lines # 返回空列表,排除该宏 # 宏变量保持原样(包括赋值) if SourceLines and hasattr(node, 'lineno'): - StartLine = node.lineno - 1 - EndLine = node.EndLineno if hasattr(node, 'EndLineno') and node.EndLineno else StartLine + 1 + StartLine: int = node.lineno - 1 + EndLine: int = node.end_lineno if hasattr(node, 'end_lineno') and node.end_lineno else StartLine + 1 for i in range(StartLine, min(EndLine, len(SourceLines))): lines.append(SourceLines[i]) else: @@ -529,9 +538,9 @@ class PythonToStubConverter: return lines # 非宏变量:不加 t.State # 含有 typedef 的变量不加 extern,普通变量需要加 extern - has_typedef = 't.CTypedef' in TypeStr or 'CTypedef' in TypeStr + has_typedef: bool = 't.CTypedef' in TypeStr or 'CTypedef' in TypeStr if has_typedef and node.value is not None: - ValueTypeStr = PythonToStubConverter._GetTypeString(node.value) + ValueTypeStr: str = PythonToStubConverter._GetTypeString(node.value) lines.append(f'{VarName}: {TypeStr} = {ValueTypeStr}') else: if not has_typedef and 't.CExtern' not in TypeStr and 't.CStatic' not in TypeStr: @@ -540,20 +549,20 @@ class PythonToStubConverter: return lines @staticmethod - def _ConvertGlobalAssign(node: ast.Assign) -> List[str]: + def _ConvertGlobalAssign(node: ast.Assign) -> list[str]: """转换模块级别的全局变量(无类型标注)""" - lines = [] + lines: list[str] = [] if not node.targets or not isinstance(node.targets[0], ast.Name): return lines - VarName = node.targets[0].id + VarName: str = node.targets[0].id # 跳过私有变量(以下划线开头) if VarName.startswith('_'): return lines # 从值推断类型 - inferred_type = PythonToStubConverter._InferTypeFromValue(node.value) + inferred_type: str | None = PythonToStubConverter._InferTypeFromValue(node.value) if inferred_type: lines.append(f'{VarName}: {inferred_type}') else: @@ -562,7 +571,7 @@ class PythonToStubConverter: return lines @staticmethod - def _InferTypeFromValue(value: ast.AST) -> str: + def _InferTypeFromValue(value: ast.AST) -> str | None: """从值推断 C 类型""" if isinstance(value, ast.Constant): if isinstance(value.value, int): @@ -580,14 +589,14 @@ class PythonToStubConverter: elif isinstance(value, ast.Name): return 't.CInt' elif isinstance(value, ast.BinOp): - left_type = PythonToStubConverter._InferTypeFromValue(value.left) + left_type: str | None = PythonToStubConverter._InferTypeFromValue(value.left) if left_type: return left_type return 't.CInt' elif isinstance(value, ast.Call): # 函数调用返回值,假设为指针类型 if isinstance(value.func, ast.Name): - func_name = value.func.id + func_name: str = value.func.id if func_name == 'malloc': return 't.CVoidPtr' elif func_name in ('ctypes.cast', 'cast'): @@ -605,26 +614,26 @@ class PythonToStubConverter: return f'{annotation.value.id}.{annotation.attr}' else: # 处理嵌套属性访问,如 t.attr.packed - ParentStr = PythonToStubConverter._GetTypeString(annotation.value) + ParentStr: str = PythonToStubConverter._GetTypeString(annotation.value) return f'{ParentStr}.{annotation.attr}' elif isinstance(annotation, ast.Subscript): - base = PythonToStubConverter._GetTypeString(annotation.value) + base: str = PythonToStubConverter._GetTypeString(annotation.value) if isinstance(annotation.slice, ast.Tuple): - slice_strs = [PythonToStubConverter._GetTypeString(e) for e in annotation.slice.elts] - SliceStr = ', '.join(slice_strs) + slice_strs: list[str] = [PythonToStubConverter._GetTypeString(e) for e in annotation.slice.elts] + SliceStr: str = ', '.join(slice_strs) else: SliceStr = PythonToStubConverter._GetTypeString(annotation.slice) return f'{base}[{SliceStr}]' elif isinstance(annotation, ast.BinOp): # 处理 BinOp,如 t.CExtern | fd_table.__set_default__(...) - left = annotation.left - right = annotation.right + left: ast.AST = annotation.left + right: ast.AST = annotation.right # 检查右侧是否是 __set_default__ 调用 if isinstance(right, ast.Call) and isinstance(right.func, ast.Attribute) and right.func.attr in ('__set_default__', '__set_default'): # 去除 __set_default__,保留左侧,右侧替换为函数名部分 - LeftStr = PythonToStubConverter._GetTypeString(left) - RightStr = PythonToStubConverter._GetTypeString(right.func.value) + LeftStr: str = PythonToStubConverter._GetTypeString(left) + RightStr: str = PythonToStubConverter._GetTypeString(right.func.value) if isinstance(annotation.op, ast.BitOr): return f'{LeftStr} | {RightStr}' @@ -644,7 +653,7 @@ class PythonToStubConverter: return f'{LeftStr} % {RightStr}' elif isinstance(annotation, ast.UnaryOp): if isinstance(annotation.op, ast.Not): - operand = PythonToStubConverter._GetTypeString(annotation.operand) + operand: str = PythonToStubConverter._GetTypeString(annotation.operand) return f'not {operand}' elif isinstance(annotation.op, ast.Invert): operand = PythonToStubConverter._GetTypeString(annotation.operand) @@ -654,9 +663,9 @@ class PythonToStubConverter: return f'-{operand}' elif isinstance(annotation, ast.Compare): # 处理比较操作,如 FF_MAX_SS != FF_MIN_SS - left = PythonToStubConverter._GetTypeString(annotation.left) - comparators = [PythonToStubConverter._GetTypeString(c) for c in annotation.comparators] - ops = [] + left: str = PythonToStubConverter._GetTypeString(annotation.left) + comparators: list[str] = [PythonToStubConverter._GetTypeString(c) for c in annotation.comparators] + ops: list[str] = [] for op in annotation.ops: if isinstance(op, ast.Eq): ops.append('==') @@ -672,7 +681,7 @@ class PythonToStubConverter: ops.append('>=') else: ops.append('?') - result = left + result: str = left for i, op in enumerate(ops): result += f' {op} {comparators[i]}' return result @@ -682,7 +691,7 @@ class PythonToStubConverter: return PythonToStubConverter._GetTypeString(annotation.value) elif isinstance(annotation, ast.List): # 处理列表,如 [MAX_FILE_DESCRIPTORS] - elements = [PythonToStubConverter._GetTypeString(elem) for elem in annotation.elts] + elements: list[str] = [PythonToStubConverter._GetTypeString(elem) for elem in annotation.elts] return f'[{", ".join(elements)}]' elif isinstance(annotation, ast.Call): # 处理函数调用形式的类型注解,如 t.Postdefinition(xxa) 或 callable(t.CVoid, app_id = t.CInt) @@ -690,10 +699,10 @@ class PythonToStubConverter: if isinstance(annotation.func, ast.Attribute) and annotation.func.attr in ('__set_default__', '__set_default'): return PythonToStubConverter._GetTypeString(annotation.func.value) - FuncStr = PythonToStubConverter._GetTypeString(annotation.func) - ArgsStr = ', '.join([PythonToStubConverter._GetTypeString(arg) for arg in annotation.args]) + FuncStr: str = PythonToStubConverter._GetTypeString(annotation.func) + ArgsStr: str = ', '.join([PythonToStubConverter._GetTypeString(arg) for arg in annotation.args]) # 处理关键字参数 - keywords_str = ', '.join([f'{kw.arg} = {PythonToStubConverter._GetTypeString(kw.value)}' for kw in annotation.keywords]) + keywords_str: str = ', '.join([f'{kw.arg} = {PythonToStubConverter._GetTypeString(kw.value)}' for kw in annotation.keywords]) # 合并位置参数和关键字参数 if ArgsStr and keywords_str: return f'{FuncStr}({ArgsStr}, {keywords_str})' @@ -704,7 +713,7 @@ class PythonToStubConverter: return 't.CVoid' @staticmethod - def _ExtractPostdefClass(annotation: ast.AST) -> Optional[str]: + def _ExtractPostdefClass(annotation: ast.AST) -> str | None: """从 Postdefinition 类型注解中提取类名 例如:t.Postdefinition(__buddy_system) -> '__buddy_system' @@ -713,21 +722,21 @@ class PythonToStubConverter: # 处理 BinOp (如: t.Postdefinition(xxx) | t.CTypedef) if isinstance(annotation, ast.BinOp): # 递归检查左操作数 - left_result = PythonToStubConverter._ExtractPostdefClass(annotation.left) + left_result: str | None = PythonToStubConverter._ExtractPostdefClass(annotation.left) if left_result: return left_result # 递归检查右操作数 - right_result = PythonToStubConverter._ExtractPostdefClass(annotation.right) + right_result: str | None = PythonToStubConverter._ExtractPostdefClass(annotation.right) if right_result: return right_result return None # 处理函数调用 (如: t.Postdefinition(__buddy_system)) if isinstance(annotation, ast.Call): - FuncStr = PythonToStubConverter._GetTypeString(annotation.func) + FuncStr: str = PythonToStubConverter._GetTypeString(annotation.func) if FuncStr == 't.Postdefinition' and annotation.args: # 提取第一个参数 - first_arg = annotation.args[0] + first_arg: ast.AST = annotation.args[0] if isinstance(first_arg, ast.Name): return first_arg.id elif isinstance(first_arg, ast.Attribute): @@ -736,20 +745,20 @@ class PythonToStubConverter: return None @staticmethod - def _GetImportString(node: ast.Import, SourceLines: List[str] = None) -> str: + def _GetImportString(node: ast.Import, SourceLines: list[str] | None = None) -> str: """获取导入语句字符串""" - parts = [] - IncludeAliasMap = PythonToStubConverter.IncludeAliasMap + parts: list[str] = [] + IncludeAliasMap: dict[str, str] = PythonToStubConverter.IncludeAliasMap for alias in node.names: - ModuleName = alias.name + ModuleName: str = alias.name # 检查是否是 __include.xxx 格式的导入 if ModuleName.startswith('__include.'): # 提取别名(xxx 部分) - SubModule = ModuleName[len('__include.'):] + SubModule: str = ModuleName[len('__include.'):] if SubModule in IncludeAliasMap: # 替换为实际模块路径 - RealModule = IncludeAliasMap[SubModule] + RealModule: str = IncludeAliasMap[SubModule] if alias.asname: parts.append(f'{RealModule} as {alias.asname}') else: @@ -766,31 +775,31 @@ class PythonToStubConverter: else: parts.append(alias.name) - result = f'import {", ".join(parts)}' + result: str = f'import {", ".join(parts)}' # 提取并保留注释 if SourceLines and hasattr(node, 'lineno'): - LineIdx = node.lineno - 1 + LineIdx: int = node.lineno - 1 if 0 <= LineIdx < len(SourceLines): - line = SourceLines[LineIdx] - CommentMatch = re.search(r'#.*$', line) + line: str = SourceLines[LineIdx] + CommentMatch: re.Match | None = re.search(r'#.*$', line) if CommentMatch: result += ' ' + CommentMatch.group(0) return result @staticmethod - def _GetImportFromString(node: ast.ImportFrom, SourceLines: List[str] = None) -> str: + def _GetImportFromString(node: ast.ImportFrom, SourceLines: list[str] | None = None) -> str: """获取 from ... import ... 语句字符串""" - module = node.module or '' - parts = [] - IncludeAliasMap = PythonToStubConverter.IncludeAliasMap + module: str = node.module or '' + parts: list[str] = [] + IncludeAliasMap: dict[str, str] = PythonToStubConverter.IncludeAliasMap # 处理相对导入 (from . import xxx 或 from ..package import xxx) if node.level > 0: if module: if node.level == 1: - full_module = f'.{module}' + full_module: str = f'.{module}' else: full_module = '.' * node.level + module else: @@ -803,22 +812,22 @@ class PythonToStubConverter: return f'from {full_module} import {", ".join(parts)}' # 提取注释(在生成结果前获取) - comment = '' + comment: str = '' if SourceLines and hasattr(node, 'lineno'): LineIdx = node.lineno - 1 if 0 <= LineIdx < len(SourceLines): line = SourceLines[LineIdx] - CommentMatch = re.search(r'#.*$', line) + CommentMatch: re.Match | None = re.search(r'#.*$', line) if CommentMatch: comment = ' ' + CommentMatch.group(0) # 检查是否是 from __include import xxx 格式 if module == '__include': for alias in node.names: - name = alias.name + name: str = alias.name if name in IncludeAliasMap: # 替换为实际模块路径 - RealModule = IncludeAliasMap[name] + RealModule: str = IncludeAliasMap[name] if alias.asname: parts.append(f'import {RealModule} as {alias.asname}{comment}') else: @@ -850,8 +859,8 @@ class PythonToStubConverter: return decorator.attr elif isinstance(decorator, ast.Call): # 处理带参数的装饰器,如 @c.Attribute(t.attr.packed) - FuncStr = PythonToStubConverter._GetDecoratorString(decorator.func) - ArgsStr = ', '.join([PythonToStubConverter._GetTypeString(arg) for arg in decorator.args]) + FuncStr: str = PythonToStubConverter._GetDecoratorString(decorator.func) + ArgsStr: str = ', '.join([PythonToStubConverter._GetTypeString(arg) for arg in decorator.args]) return f'{FuncStr}({ArgsStr})' return '' @@ -860,30 +869,30 @@ class PythonToStubConverter: """获取表达式字符串(用于宏调用)""" if isinstance(expr, ast.Call): # 处理函数调用,如 c.CIf(...), c.CEndif(), c.CUndef(...), c.CPragma(...) - FuncStr = PythonToStubConverter._GetDecoratorString(expr.func) + FuncStr: str = PythonToStubConverter._GetDecoratorString(expr.func) if FuncStr and ('CIf' in FuncStr or 'CEndif' in FuncStr or 'CElif' in FuncStr or 'CElse' in FuncStr or 'CUndef' in FuncStr or 'CPragma' in FuncStr): - ArgsStr = ', '.join([PythonToStubConverter._GetTypeString(arg) for arg in expr.args]) + ArgsStr: str = ', '.join([PythonToStubConverter._GetTypeString(arg) for arg in expr.args]) return f'{FuncStr}({ArgsStr})' if ArgsStr else f'{FuncStr}()' return '' @staticmethod def _get_if_macro_string(node: ast.If, indent: int = 1) -> str: """获取类内部的 if 宏字符串(如 if c.CIf(...):)""" - IndentStr = ' ' * indent - InnerIndent = ' ' * (indent + 1) + IndentStr: str = ' ' * indent + InnerIndent: str = ' ' * (indent + 1) # 检查条件是否是宏调用 if isinstance(node.test, ast.Call): - FuncStr = PythonToStubConverter._GetDecoratorString(node.test.func) + FuncStr: str = PythonToStubConverter._GetDecoratorString(node.test.func) if FuncStr and 'CIf' in FuncStr: - ArgsStr = ', '.join([PythonToStubConverter._GetTypeString(arg) for arg in node.test.args]) - result = [f'{IndentStr}if {FuncStr}({ArgsStr}):' if ArgsStr else f'{IndentStr}if {FuncStr}():'] + ArgsStr: str = ', '.join([PythonToStubConverter._GetTypeString(arg) for arg in node.test.args]) + result: list[str] = [f'{IndentStr}if {FuncStr}({ArgsStr}):' if ArgsStr else f'{IndentStr}if {FuncStr}():'] # 处理 if 体内的语句 for item in node.body: if isinstance(item, ast.AnnAssign): - TypeStr = PythonToStubConverter._GetTypeString(item.annotation) + TypeStr: str = PythonToStubConverter._GetTypeString(item.annotation) result.append(f'{InnerIndent}{item.target.id}: {TypeStr}') elif isinstance(item, ast.Expr): - ExprStr = PythonToStubConverter._GetExprString(item.value) + ExprStr: str = PythonToStubConverter._GetExprString(item.value) if ExprStr: result.append(f'{InnerIndent}{ExprStr}') return '\n'.join(result) @@ -897,28 +906,28 @@ class PythonToStubConverter: @staticmethod def _ProcessIfMacro(node: ast.If, indent: int = 0) -> str: """处理 if 宏节点,支持 elif 和 else""" - IndentStr = ' ' * indent + IndentStr: str = ' ' * indent # 检查条件是否是宏调用 if isinstance(node.test, ast.Call): - FuncStr = PythonToStubConverter._GetDecoratorString(node.test.func) + FuncStr: str = PythonToStubConverter._GetDecoratorString(node.test.func) if FuncStr and 'CIf' in FuncStr: - ArgsStr = ', '.join([PythonToStubConverter._GetTypeString(arg) for arg in node.test.args]) - result = [f'{IndentStr}if {FuncStr}({ArgsStr}):' if ArgsStr else f'{IndentStr}if {FuncStr}():'] + ArgsStr: str = ', '.join([PythonToStubConverter._GetTypeString(arg) for arg in node.test.args]) + result: list[str] = [f'{IndentStr}if {FuncStr}({ArgsStr}):' if ArgsStr else f'{IndentStr}if {FuncStr}():'] # 处理 if 体内的语句 for item in node.body: result.extend(PythonToStubConverter._ProcessMacroBodyItem(item, indent + 1)) # 处理 elif 和 else - current = node + current: ast.If = node while current.orelse: if len(current.orelse) == 1 and isinstance(current.orelse[0], ast.If): # elif 情况 - elif_node = current.orelse[0] + elif_node: ast.If = current.orelse[0] if isinstance(elif_node.test, ast.Call): - ElifFuncStr = PythonToStubConverter._GetDecoratorString(elif_node.test.func) + ElifFuncStr: str = PythonToStubConverter._GetDecoratorString(elif_node.test.func) if ElifFuncStr and 'CIf' in ElifFuncStr: - ElifArgsStr = ', '.join([PythonToStubConverter._GetTypeString(arg) for arg in elif_node.test.args]) + ElifArgsStr: str = ', '.join([PythonToStubConverter._GetTypeString(arg) for arg in elif_node.test.args]) result.append(f'{IndentStr}elif {ElifFuncStr}({ElifArgsStr}):' if ElifArgsStr else f'{IndentStr}elif {ElifFuncStr}():') for item in elif_node.body: result.extend(PythonToStubConverter._ProcessMacroBodyItem(item, indent + 1)) @@ -936,32 +945,32 @@ class PythonToStubConverter: return '' @staticmethod - def _ProcessMacroBodyItem(item: ast.AST, indent: int = 0) -> list: + def _ProcessMacroBodyItem(item: ast.AST, indent: int = 0) -> list[str]: """处理宏体内的单个语句""" - IndentStr = ' ' * indent - result = [] + IndentStr: str = ' ' * indent + result: list[str] = [] if isinstance(item, ast.ClassDef): - class_stub = PythonToStubConverter._ConvertClass(item) + class_stub: list[str] = PythonToStubConverter._ConvertClass(item) for line in class_stub: if line.strip(): result.append(f'{IndentStr}{line}') else: result.append(line) elif isinstance(item, ast.FunctionDef): - FuncStub = PythonToStubConverter._ConvertFunction(item, indent=indent) + FuncStub: list[str] = PythonToStubConverter._ConvertFunction(item, indent=indent) result.extend(FuncStub) elif isinstance(item, ast.AnnAssign): - TypeStr = PythonToStubConverter._GetTypeString(item.annotation) + TypeStr: str = PythonToStubConverter._GetTypeString(item.annotation) result.append(f'{IndentStr}{item.target.id}: {TypeStr}') elif isinstance(item, ast.Expr): - ExprStr = PythonToStubConverter._GetExprString(item.value) + ExprStr: str = PythonToStubConverter._GetExprString(item.value) if ExprStr: result.append(f'{IndentStr}{ExprStr}') elif isinstance(item, ast.If): # 处理嵌套的 if 宏 - NestedIf = PythonToStubConverter._ProcessIfMacro(item, indent=indent) + NestedIf: str = PythonToStubConverter._ProcessIfMacro(item, indent=indent) if NestedIf: result.append(NestedIf) - return result + return result \ No newline at end of file diff --git a/lib/StubGen/Generator.py b/lib/StubGen/Generator.py index 111b87d..01e4e41 100644 --- a/lib/StubGen/Generator.py +++ b/lib/StubGen/Generator.py @@ -1,12 +1,15 @@ """StubGen 生成器模块 - 存根生成器主类和命令行入口""" +from __future__ import annotations import sys import os import re import argparse import logging +import traceback from pathlib import Path from typing import List, Tuple +from lib.core.VLogger import get_logger as _vlog from lib.core.stub_generator import CHeaderParser, PythonStubGenerator, CTypeMapper from lib.StubGen.Config import StubGenConfig from lib.StubGen.Converter import PythonToStubConverter @@ -15,9 +18,9 @@ from lib.StubGen.Converter import PythonToStubConverter class StubGen: """存根生成器主类""" - def __init__(self, config: StubGenConfig): - self.config = config - self.logger = self._SetupLogger() + def __init__(self, config: StubGenConfig) -> None: + self.config: StubGenConfig = config + self.logger: logging.Logger = self._SetupLogger() self.GeneratedFiles: List[str] = [] self.FailedFiles: List[str] = [] @@ -27,12 +30,12 @@ class StubGen: def _SetupLogger(self) -> logging.Logger: """设置日志""" - logger = logging.getLogger('StubGen') + logger: logging.Logger = logging.getLogger('StubGen') logger.setLevel(logging.DEBUG if self.config.verbose else logging.INFO) if not logger.handlers: - handler = logging.StreamHandler(sys.stdout) - formatter = logging.Formatter( + handler: logging.StreamHandler = logging.StreamHandler(sys.stdout) + formatter: logging.Formatter = logging.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(message)s', datefmt='%H:%M:%S' ) @@ -41,26 +44,26 @@ class StubGen: return logger - def FindInputFiles(self) -> List[Tuple[str, str]]: + def FindInputFiles(self) -> list[tuple[str, str]]: """查找输入文件,返回 (文件路径, 相对路径) 列表""" - files = [] + files: list[tuple[str, str]] = [] # 添加显式指定的文件 for FilePath in self.config.InputFiles: if os.path.exists(FilePath): - RelPath = os.path.relpath(FilePath, self.config.InputDir or '.') + RelPath: str = os.path.relpath(FilePath, self.config.InputDir or '.') files.append((FilePath, RelPath)) else: self.logger.warning(f"Input file not found: {FilePath}") # 从输入目录查找 if self.config.InputDir and os.path.exists(self.config.InputDir): - InputPath = Path(self.config.InputDir) + InputPath: Path = Path(self.config.InputDir) for pattern in self.config.IncludePatterns: for FilePath in InputPath.rglob(pattern): # 检查是否在排除列表中 - excluded = False - RelPath = os.path.relpath(str(FilePath), self.config.InputDir) + excluded: bool = False + RelPath: str = os.path.relpath(str(FilePath), self.config.InputDir) for exclude_pattern in self.config.ExcludePatterns: if FilePath.match(exclude_pattern) or RelPath == exclude_pattern: @@ -71,10 +74,10 @@ class StubGen: files.append((str(FilePath), RelPath)) # 去重并保持顺序 - seen = set() - UniqueFiles = [] + seen: set[str] = set() + UniqueFiles: list[tuple[str, str]] = [] for FilePath, RelPath in files: - key = FilePath + key: str = FilePath if key not in seen: seen.add(key) UniqueFiles.append((FilePath, RelPath)) @@ -84,10 +87,10 @@ class StubGen: def _GenerateGuardName(self, FilePath: str) -> str: """生成宏守卫名称""" # 获取文件名(不含扩展名) - BaseName = os.path.splitext(os.path.basename(FilePath))[0] + BaseName: str = os.path.splitext(os.path.basename(FilePath))[0] # 转换为大写,替换特殊字符为下划线 - guard = re.sub(r'[^a-zA-Z0-9_]', '_', BaseName).upper() + guard: str = re.sub(r'[^a-zA-Z0-9_]', '_', BaseName).upper() guard = re.sub(r'_+', '_', guard) # 合并多个下划线 guard = guard.strip('_') @@ -96,12 +99,12 @@ class StubGen: def _GetOutputPath(self, RelPath: str) -> str: """获取输出文件路径""" # 更改扩展名为 .pyi (Python stub file) - BaseName = os.path.splitext(RelPath)[0] - OutputRelPath = BaseName + '.pyi' + BaseName: str = os.path.splitext(RelPath)[0] + OutputRelPath: str = BaseName + '.pyi' # 构建完整输出路径 if self.config.OutputDir: - OutputPath = os.path.join(self.config.OutputDir, OutputRelPath) + OutputPath: str = os.path.join(self.config.OutputDir, OutputRelPath) else: OutputPath = OutputRelPath @@ -113,10 +116,10 @@ class StubGen: self.logger.info(f"Processing: {InputFile}") # 确定输出文件路径 - OutputFile = self._GetOutputPath(RelPath) + OutputFile: str = self._GetOutputPath(RelPath) # 确保输出目录存在 - OutputDir = os.path.dirname(OutputFile) + OutputDir: str = os.path.dirname(OutputFile) if OutputDir and not os.path.exists(OutputDir): if not self.config.DryRun: os.makedirs(OutputDir, exist_ok=True) @@ -127,11 +130,11 @@ class StubGen: return True # 根据文件类型选择处理方式 - ext = os.path.splitext(InputFile)[1].lower() + ext: str = os.path.splitext(InputFile)[1].lower() if ext in ['.h', '.c']: # C 文件:使用 CHeaderParser - content = self._GenerateFromC(InputFile, RelPath) + content: str = self._GenerateFromC(InputFile, RelPath) elif ext == '.py': # Python 文件:使用 PythonToStubConverter content = self._GenerateFromPy(InputFile, RelPath) @@ -149,24 +152,23 @@ class StubGen: except Exception as e: self.logger.error(f"Failed to process {InputFile}: {e}") - import traceback traceback.print_exc() self.FailedFiles.append(InputFile) return False def _GenerateFromC(self, InputFile: str, RelPath: str) -> str: """从 C 文件生成存根""" - parser = CHeaderParser() + parser: CHeaderParser = CHeaderParser() parser.parse_file(InputFile) - generator = PythonStubGenerator(parser) - ModuleName = os.path.splitext(os.path.basename(InputFile))[0] - content = generator.generate(ModuleName) + generator: PythonStubGenerator = PythonStubGenerator(parser) + ModuleName: str = os.path.splitext(os.path.basename(InputFile))[0] + content: str = generator.generate(ModuleName) # 添加宏守卫(如果需要) if self.config.GenerateGuards: - guard_name = self._GenerateGuardName(InputFile) - guard_comment = f"\n# Guard: {guard_name}\n" + guard_name: str = self._GenerateGuardName(InputFile) + guard_comment: str = f"\n# Guard: {guard_name}\n" content = content + guard_comment return content @@ -174,15 +176,15 @@ class StubGen: def _GenerateFromPy(self, InputFile: str, RelPath: str) -> str: """从 Python 文件生成存根""" with open(InputFile, 'r', encoding='utf-8') as f: - PyContent = f.read() + PyContent: str = f.read() - ModuleName = os.path.splitext(os.path.basename(InputFile))[0] - content = PythonToStubConverter.convert(PyContent, ModuleName) + ModuleName: str = os.path.splitext(os.path.basename(InputFile))[0] + content: str = PythonToStubConverter.convert(PyContent, ModuleName) # 添加宏守卫(如果需要) if self.config.GenerateGuards: - guard_name = self._GenerateGuardName(InputFile) - guard_comment = f"\n# Guard: {guard_name}\n" + guard_name: str = self._GenerateGuardName(InputFile) + guard_comment: str = f"\n# Guard: {guard_name}\n" content = content + guard_comment return content @@ -194,7 +196,7 @@ class StubGen: self.logger.info("=" * 60) # 查找输入文件 - InputFiles = self.FindInputFiles() + InputFiles: list[tuple[str, str]] = self.FindInputFiles() if not InputFiles: self.logger.warning("No input files found!") @@ -205,7 +207,7 @@ class StubGen: self.logger.debug(f" - {RelPath}") # 处理每个文件 - SuccessCount = 0 + SuccessCount: int = 0 for FilePath, RelPath in InputFiles: if self.GenerateStub(FilePath, RelPath): SuccessCount += 1 @@ -222,8 +224,8 @@ class StubGen: return SuccessCount == len(InputFiles) -def main(): - parser = argparse.ArgumentParser( +def main() -> None: + parser: argparse.ArgumentParser = argparse.ArgumentParser( description='StubGen - Generate Python stub files from C/H/Py sources', formatter_class=argparse.RawDescriptionHelpFormatter, epilog=''' @@ -246,7 +248,7 @@ Examples: ) # 输入选项 - InputGroup = parser.add_mutually_exclusive_group(required=True) + InputGroup: argparse._MutuallyExclusiveGroup = parser.add_mutually_exclusive_group(required=True) InputGroup.add_argument('-c', '--config', help='Configuration file (JSON)') InputGroup.add_argument('-i', '--input', help='Input file') InputGroup.add_argument('-d', '--directory', help='Input directory') @@ -268,14 +270,14 @@ Examples: parser.add_argument('--dry-run', action='store_true', help='Dry run (do not create files)') - args = parser.parse_args() + args: argparse.Namespace = parser.parse_args() # 加载配置 if args.config: if not os.path.exists(args.config): - print(f"Error: Config file not found: {args.config}") + _vlog().error(f"配置文件未找到: {args.config}") sys.exit(1) - config = StubGenConfig.from_file(args.config) + config: StubGenConfig = StubGenConfig.from_file(args.config) else: config = StubGenConfig() config.IncludePatterns = args.include or ['*.h', '*.c', '*.py'] @@ -295,12 +297,12 @@ Examples: config.OutputDir = args.output # 创建生成器并运行 - generator = StubGen(config) + generator: StubGen = StubGen(config) # 如果指定了单个输出文件,直接处理 if args.input and args.output and not os.path.isdir(args.output): - RelPath = os.path.relpath(args.input, config.InputDir or '.') - success = generator.GenerateStub(args.input, RelPath) + RelPath: str = os.path.relpath(args.input, config.InputDir or '.') + success: bool = generator.GenerateStub(args.input, RelPath) else: success = generator.run() @@ -308,4 +310,4 @@ Examples: if __name__ == '__main__': - main() + main() \ No newline at end of file diff --git a/lib/constants/config.py b/lib/constants/config.py index beac484..250a029 100644 --- a/lib/constants/config.py +++ b/lib/constants/config.py @@ -1,11 +1,12 @@ # 常量定义 +from __future__ import annotations -DEFAULT_INPUT_FILE = 'test.py' -DEFAULT_OUTPUT_FILE = 'test.ll' +DEFAULT_INPUT_FILE: str = 'test.py' +DEFAULT_OUTPUT_FILE: str = 'test.ll' -SLICE_THRESHOLD = 50 -SLICE_LEVEL_DEFAULT = 3 -SLICE_LEVELS = { +SLICE_THRESHOLD: int = 50 +SLICE_LEVEL_DEFAULT: int = 3 +SLICE_LEVELS: dict[int | str, str] = { 0: 'no_optimize', 1: 'conservative', 2: 'moderate', @@ -13,10 +14,10 @@ SLICE_LEVELS = { 's': 'size', } -DEFAULT_COMPILE_COMMAND = 'gcc' -DEFAULT_COMPILE_FLAGS = '' +DEFAULT_COMPILE_COMMAND: str = 'gcc' +DEFAULT_COMPILE_FLAGS: str = '' -DEFAULT_METADATA = { +DEFAULT_METADATA: dict[str, str] = { 'PROJECT_NAME': 'TransPyC Project', 'AUTHOR': 'TransPyC Team', 'VERSION': '1.0.0', @@ -25,7 +26,7 @@ DEFAULT_METADATA = { 'COPYRIGHT_HOLDER': 'Galactic Vorpal Software Development Studio (e.g. GVSDS Inc.)' } -ERROR_MESSAGES = { +ERROR_MESSAGES: dict[str, str] = { 'MISSING_ARGS': 'Missing required arguments -f and/or -o', 'UNKNOWN_ARG': 'Unknown argument', 'UNSUPPORTED_TYPE': 'Unsupported file type', @@ -33,10 +34,10 @@ ERROR_MESSAGES = { 'COMPILE_FAILED': 'Compilation or execution failed' } -HELP_MESSAGE = ''' +HELP_MESSAGE: str = ''' Usage: python TransPyC.py -f InputFile -o OutputFile [-wh header_files] [-debug DebugFile] [-cc compile_command] [-cflags CompileFlags] [-run] [-args RunArgs] [-h HelperFiles] -h: Specify helper files (C or Python) to help identify structs, functions, variables, and ptrs ''' -mode = "strict" +mode: str = "strict" diff --git a/lib/core/ConstEvaluator.py b/lib/core/ConstEvaluator.py index 4a4486a..5548e68 100644 --- a/lib/core/ConstEvaluator.py +++ b/lib/core/ConstEvaluator.py @@ -15,7 +15,14 @@ ConstEvaluator 提供三个级别的求值: from __future__ import annotations import ast -from typing import Any, Optional +from typing import Any, Callable, Optional, TYPE_CHECKING + +import llvmlite.ir as ir + +from lib.core.Handles.HandlesBase import CTypeInfo + +if TYPE_CHECKING: + from lib.core.LlvmCodeGenerator import LlvmCodeGenerator class ConstEvaluator: @@ -40,7 +47,7 @@ class ConstEvaluator: # ================================================================== @staticmethod - def eval_with_symtab(node: ast.AST, symtab) -> Optional[Any]: + def eval_with_symtab(node: ast.AST, symtab: Any) -> Optional[Any]: """求值常量表达式,支持从 SymbolTable 查找 define 值。 支持: Constant, BinOp, UnaryOp, Name(define), Attribute(define) @@ -49,7 +56,7 @@ class ConstEvaluator: return node.value if isinstance(node, ast.Name): if hasattr(symtab, '__contains__') and node.id in symtab: - info = symtab[node.id] + info: CTypeInfo = symtab[node.id] if info.IsDefine and isinstance(info.DefineValue, int): return info.DefineValue return None @@ -71,7 +78,7 @@ class ConstEvaluator: if isinstance(node, ast.BoolOp): if isinstance(node.op, ast.And): for val in node.values: - result = ConstEvaluator.eval_full(val, ctx) + result: Any = ConstEvaluator.eval_full(val, ctx) if result is None: return None if not result: @@ -79,7 +86,7 @@ class ConstEvaluator: return 1 elif isinstance(node.op, ast.Or): for val in node.values: - result = ConstEvaluator.eval_full(val, ctx) + result: Any = ConstEvaluator.eval_full(val, ctx) if result is None: return None if result: @@ -89,14 +96,16 @@ class ConstEvaluator: # Compare (HandlesIf 逻辑) if isinstance(node, ast.Compare): - left = ConstEvaluator.eval_full(node.left, ctx) + left: Any = ConstEvaluator.eval_full(node.left, ctx) if left is None: return None + op: ast.cmpop + comparator: ast.AST for op, comparator in zip(node.ops, node.comparators): - right = ConstEvaluator.eval_full(comparator, ctx) + right: Any = ConstEvaluator.eval_full(comparator, ctx) if right is None: return None - result = ConstEvaluator._eval_compare_op(op, left, right) + result: bool | None = ConstEvaluator._eval_compare_op(op, left, right) if result is None: return None if not result: @@ -118,7 +127,7 @@ class ConstEvaluator: # UnaryOp if isinstance(node, ast.UnaryOp): - operand = ConstEvaluator.eval_full(node.operand, ctx) + operand: Any = ConstEvaluator.eval_full(node.operand, ctx) if operand is None: return None if isinstance(node.op, ast.Not): @@ -131,6 +140,10 @@ class ConstEvaluator: return ~operand return None + # Call — 编译时函数调用(如 ctraits.isptr(x)) + if isinstance(node, ast.Call): + return ConstEvaluator._eval_compile_time_call(node, ctx) + # BinOp return ConstEvaluator._eval_arith(node, lambda n: ConstEvaluator.eval_full(n, ctx)) @@ -139,16 +152,73 @@ class ConstEvaluator: # ================================================================== @staticmethod - def _eval_arith(node: ast.AST, recurse) -> Optional[Any]: + def _eval_compile_time_call(node: ast.Call, ctx: 'EvalContext') -> Optional[Any]: + """处理编译时函数调用,如 ctraits.isptr(x)""" + func: ast.expr = node.func + func_name: str | None = None + module_name: str | None = None + + if isinstance(func, ast.Attribute): + if isinstance(func.value, ast.Name): + module_name = func.value.id + func_name = func.attr + elif isinstance(func, ast.Name): + func_name = func.id + + # ctraits.isptr(x) — 带模块前缀 + # isptr(x) — 通过 from ctraits import isptr 导入 + is_isptr: bool = False + if module_name == 'ctraits' and func_name == 'isptr': + is_isptr = True + elif func_name == 'isptr' and not module_name: + # 检查是否通过 from ctraits import isptr 导入 + t_c_imported = getattr(ctx.translator, '_t_c_imported_names', {}) if ctx.translator else {} + if func_name in t_c_imported: + src_module, _ = t_c_imported[func_name] + if src_module == 'ctraits': + is_isptr = True + # 也检查符号表中是否有 ctraits.isptr + if not is_isptr and ctx.symtab: + sym = ctx.symtab.lookup('ctraits.isptr') if hasattr(ctx.symtab, 'lookup') else None + if sym: + is_isptr = True + + if is_isptr and node.args and ctx.translator: + try: + arg_node: ast.expr = node.args[0] + # 局部变量:优先通过 LLVM 类型判断(GetCTypeInfo 无法解析局部变量名) + if ctx.Gen and isinstance(arg_node, ast.Name): + var_name: str = arg_node.id + variables: dict = getattr(ctx.Gen, 'variables', {}) + if var_name in variables: + var_val: Any = variables[var_name] + if hasattr(var_val, 'type') and isinstance(var_val.type, ir.PointerType): + pointee: ir.Type = var_val.type.pointee + if isinstance(pointee, ir.PointerType): + return 1 + return 0 + # 类型名 / typedef:通过 TypeMergeHandler 获取 CTypeInfo + type_info = ctx.translator.TypeMergeHandler.GetCTypeInfo(arg_node) + if type_info and (type_info.IsPtr or type_info.PtrCount > 0): + return 1 + if type_info and not (type_info.IsPtr or type_info.PtrCount > 0): + return 0 + return None + except Exception: + return None + return None + + @staticmethod + def _eval_arith(node: ast.AST, recurse: Callable[[ast.AST], Any]) -> Optional[Any]: """通用算术求值:BinOp + UnaryOp""" if isinstance(node, ast.BinOp): - left = recurse(node.left) - right = recurse(node.right) + left: Any = recurse(node.left) + right: Any = recurse(node.right) if left is None or right is None: return None return ConstEvaluator._apply_binop(node.op, left, right) if isinstance(node, ast.UnaryOp): - operand = recurse(node.operand) + operand: Any = recurse(node.operand) if operand is None: return None if isinstance(node.op, ast.USub): @@ -161,7 +231,7 @@ class ConstEvaluator: return None @staticmethod - def _apply_binop(op: ast.operator, left, right) -> Optional[Any]: + def _apply_binop(op: ast.operator, left: Any, right: Any) -> Optional[Any]: """应用二元运算符""" try: if isinstance(op, ast.Add): @@ -197,7 +267,7 @@ class ConstEvaluator: return None @staticmethod - def _eval_compare_op(op, left, right) -> Optional[bool]: + def _eval_compare_op(op: ast.cmpop, left: Any, right: Any) -> Optional[bool]: """应用比较运算符""" if isinstance(op, ast.Eq): return left == right @@ -214,25 +284,27 @@ class ConstEvaluator: return None @staticmethod - def _eval_attribute_define(node: ast.Attribute, symtab) -> Optional[Any]: + def _eval_attribute_define(node: ast.Attribute, symtab: Any) -> Optional[Any]: """从 SymbolTable 查找 Attribute 形式的 define 值""" - parts = [] - current = node + parts: list[str] = [] + current: ast.AST = node while isinstance(current, ast.Attribute): parts.append(current.attr) current = current.value if isinstance(current, ast.Name): parts.append(current.id) parts.reverse() - attr_name = parts[-1] - possible_keys = [attr_name, '.'.join(parts)] + attr_name: str = parts[-1] + possible_keys: list[str] = [attr_name, '.'.join(parts)] for key in possible_keys: if hasattr(symtab, '__contains__') and key in symtab: - info = symtab[key] + info: CTypeInfo = symtab[key] if info.IsDefine and isinstance(info.DefineValue, int): return info.DefineValue # 模糊匹配 if len(parts) >= 2: + mod_key: str + mod_info: CTypeInfo for mod_key, mod_info in (symtab.items() if hasattr(symtab, 'items') else []): if mod_info.IsDefine and isinstance(mod_info.DefineValue, int): if mod_key.endswith('.' + attr_name) or mod_key == attr_name: @@ -240,7 +312,7 @@ class ConstEvaluator: return None @staticmethod - def _intify(val): + def _intify(val: Any) -> Any: """float → int 转换(仅当 float 值恰好是整数时)""" if isinstance(val, float) and val == int(val): return int(val) @@ -253,36 +325,37 @@ class EvalContext: 由调用方构造并传入 ConstEvaluator.eval_full()。 """ - def __init__(self, Gen=None, symtab=None, platform_macros: dict | None = None): - self.Gen = Gen - self.symtab = symtab - self._platform_macros = platform_macros + def __init__(self, Gen: LlvmCodeGenerator | None = None, symtab: Any = None, platform_macros: dict | None = None, translator: Any = None): + self.Gen: LlvmCodeGenerator | None = Gen + self.symtab: Any = symtab + self._platform_macros: dict | None = platform_macros + self.translator: Any = translator def lookup_name(self, name: str) -> Optional[Any]: """查找 Name 节点的值:define_constants → SymbolTable → 平台宏""" # 1. Gen._define_constants if self.Gen and hasattr(self.Gen, '_define_constants') and name in self.Gen._define_constants: - val = self.Gen._define_constants[name] + val: Any = self.Gen._define_constants[name] if isinstance(val, (int, float)): return ConstEvaluator._intify(val) # 2. Gen._DefineConstants (大写版本) if self.Gen and hasattr(self.Gen, '_DefineConstants') and name in self.Gen._DefineConstants: - val = self.Gen._DefineConstants[name] + val: Any = self.Gen._DefineConstants[name] if isinstance(val, (int, float)): return ConstEvaluator._intify(val) # 3. SymbolTable if self.symtab and name in self.symtab: - info = self.symtab[name] - val = info.value + info: CTypeInfo = self.symtab[name] + val: Any = info.value if isinstance(val, (int, float)): return ConstEvaluator._intify(val) if info.IsDefine and isinstance(info.DefineValue, (int, float)): return ConstEvaluator._intify(info.DefineValue) # 4. 平台宏 - macros = self._get_platform_macros() + macros: dict = self._get_platform_macros() if name in macros: return macros[name] @@ -290,35 +363,39 @@ class EvalContext: def lookup_attribute(self, node: ast.Attribute) -> Optional[Any]: """查找 Attribute 节点的值""" - module_name = node.value.id if isinstance(node.value, ast.Name) else None - attr_name = node.attr + module_name: str | None = node.value.id if isinstance(node.value, ast.Name) else None + attr_name: str = node.attr if module_name and attr_name: - combined_key = f"{module_name}.{attr_name}" + combined_key: str = f"{module_name}.{attr_name}" # 1. Gen._define_constants if self.Gen and hasattr(self.Gen, '_define_constants') and combined_key in self.Gen._define_constants: - val = self.Gen._define_constants[combined_key] + val: Any = self.Gen._define_constants[combined_key] if isinstance(val, (int, float)): return ConstEvaluator._intify(val) # 2. SymbolTable (精确匹配 + 后缀匹配) if self.symtab: + key: str + info: CTypeInfo for key, info in self.symtab.items(): if key.endswith(f".{combined_key}") or key == combined_key: if info.IsDefine and isinstance(info.DefineValue, (int, float)): return ConstEvaluator._intify(info.DefineValue) # 3. _all_define_constants - all_dc = self._get_all_define_constants() + all_dc: dict = self._get_all_define_constants() if combined_key in all_dc: - val = all_dc[combined_key] + val: Any = all_dc[combined_key] if isinstance(val, (int, float)): return ConstEvaluator._intify(val) if attr_name in all_dc: - val = all_dc[attr_name] + val: Any = all_dc[attr_name] if isinstance(val, (int, float)): return ConstEvaluator._intify(val) + dc_key: str + dc_val: Any for dc_key, dc_val in all_dc.items(): if dc_key == attr_name or dc_key.endswith(f".{attr_name}"): if isinstance(dc_val, (int, float)): @@ -326,23 +403,23 @@ class EvalContext: # 4. SymbolTable 短名查找 if self.symtab and attr_name in self.symtab: - info = self.symtab[attr_name] + info: CTypeInfo = self.symtab[attr_name] if info.IsDefine and isinstance(info.DefineValue, (int, float)): return ConstEvaluator._intify(info.DefineValue) # 5. Gen._define_constants 短名 if self.Gen and hasattr(self.Gen, '_define_constants') and attr_name in self.Gen._define_constants: - val = self.Gen._define_constants[attr_name] + val: Any = self.Gen._define_constants[attr_name] if isinstance(val, (int, float)): return ConstEvaluator._intify(val) # 6. 平台宏 - macros = self._get_platform_macros() - full_key = self._get_attr_full_name(node) + macros: dict = self._get_platform_macros() + full_key: str | None = self._get_attr_full_name(node) if full_key: if full_key in macros: return macros[full_key] - short_name = full_key.split('.')[-1] if '.' in full_key else full_key + short_name: str = full_key.split('.')[-1] if '.' in full_key else full_key if short_name in macros: return macros[short_name] @@ -360,9 +437,9 @@ class EvalContext: return self._platform_macros if not self.Gen: return {} - macros = {} - pi = getattr(self.Gen, '_platform_info', {}) - ptr_size = getattr(self.Gen, 'ptr_size', 8) + macros: dict[str, int] = {} + pi: dict = getattr(self.Gen, '_platform_info', {}) + ptr_size: int = getattr(self.Gen, 'ptr_size', 8) if pi.get('is_windows'): macros['_WIN32'] = 1 if not pi.get('is_32bit'): @@ -393,8 +470,8 @@ class EvalContext: @staticmethod def _get_attr_full_name(node: ast.Attribute) -> Optional[str]: """从 Attribute 节点提取完整名称 (e.g. 'module.name')""" - parts = [] - current = node + parts: list[str] = [] + current: ast.AST = node while isinstance(current, ast.Attribute): parts.append(current.attr) current = current.value diff --git a/lib/core/DecoratorPass.py b/lib/core/DecoratorPass.py index 88b93ff..69b4cc8 100644 --- a/lib/core/DecoratorPass.py +++ b/lib/core/DecoratorPass.py @@ -106,20 +106,24 @@ v4 增强版特性: """ from __future__ import annotations import llvmlite.ir as ir +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from lib.core.LlvmCodeGenerator import LlvmCodeGenerator # 栈帧局部上下文缓冲区大小(字节) -_CTX_SIZE = 32 +_CTX_SIZE: int = 32 # 装饰器处理函数的 LLVM 签名:i32 (i8*, i8*, i32, i8*, i8*, i8*) -_DECOR_HANDLER_PARAM_TYPES = None # 延迟初始化 +_DECOR_HANDLER_PARAM_TYPES: ir.FunctionType | None = None # 延迟初始化 -def _get_decor_handler_func_type(): +def _get_decor_handler_func_type() -> ir.FunctionType: """获取装饰器处理函数的 LLVM FunctionType: i32 (i8*, i8*, i32, i8*, i8*, i8*)""" global _DECOR_HANDLER_PARAM_TYPES if _DECOR_HANDLER_PARAM_TYPES is None: - i8_ptr = ir.IntType(8).as_pointer() + i8_ptr: ir.PointerType = ir.IntType(8).as_pointer() _DECOR_HANDLER_PARAM_TYPES = ir.FunctionType( ir.IntType(32), [i8_ptr, i8_ptr, ir.IntType(32), i8_ptr, i8_ptr, i8_ptr] @@ -127,27 +131,28 @@ def _get_decor_handler_func_type(): return _DECOR_HANDLER_PARAM_TYPES -def _find_or_declare_handler(module, handler_name): +def _find_or_declare_handler(module: ir.Module, handler_name: str) -> ir.Function: """在 module 中查找或声明装饰器处理函数""" + f: ir.Function for f in module.functions: if f.name == handler_name: return f - func_type = _get_decor_handler_func_type() - handler = ir.Function(module, func_type, name=handler_name) + func_type: ir.FunctionType = _get_decor_handler_func_type() + handler: ir.Function = ir.Function(module, func_type, name=handler_name) return handler -def _make_string_constant(module, text, name_prefix="decor.str"): +def _make_string_constant(module: ir.Module, text: str, name_prefix: str = "decor.str") -> ir.Constant: """在 module 中创建一个全局字符串常量,返回 i8* 指针""" - counter = getattr(_make_string_constant, '_counter', 0) + 1 + counter: int = getattr(_make_string_constant, '_counter', 0) + 1 _make_string_constant._counter = counter - const_name = f"{name_prefix}.{counter}" + const_name: str = f"{name_prefix}.{counter}" - encoded = text.encode('utf-8') + b'\x00' - const_type = ir.ArrayType(ir.IntType(8), len(encoded)) - const_val = ir.Constant(const_type, bytearray(encoded)) + encoded: bytes = text.encode('utf-8') + b'\x00' + const_type: ir.ArrayType = ir.ArrayType(ir.IntType(8), len(encoded)) + const_val: ir.Constant = ir.Constant(const_type, bytearray(encoded)) - global_var = ir.GlobalVariable(module, const_type, name=const_name) + global_var: ir.GlobalVariable = ir.GlobalVariable(module, const_type, name=const_name) global_var.global_constant = True global_var.linkage = 'private' global_var.initializer = const_val @@ -155,7 +160,7 @@ def _make_string_constant(module, text, name_prefix="decor.str"): return global_var.bitcast(ir.IntType(8).as_pointer()) -def _make_decor_args_constant(module, decorator_info): +def _make_decor_args_constant(module: ir.Module, decorator_info: dict) -> ir.Constant: """ 为带参数的装饰器生成全局常量结构体,返回 i8* 指针。 无参数装饰器返回 null。 @@ -166,37 +171,43 @@ def _make_decor_args_constant(module, decorator_info): - bool → i1 - str → i8*(全局字符串常量) """ - deco_args = decorator_info.get('args', []) - deco_kwargs = decorator_info.get('kwargs', {}) + deco_args: list = decorator_info.get('args', []) + deco_kwargs: dict = decorator_info.get('kwargs', {}) if not deco_args and not deco_kwargs: return ir.Constant(ir.IntType(8).as_pointer(), None) - field_types = [] - field_values = [] + field_types: list = [] + field_values: list = [] + arg: int | str | float | bool for arg in deco_args: + llvm_type: ir.Type | None + llvm_val: ir.Constant | None llvm_type, llvm_val = _python_value_to_llvm(module, arg) if llvm_type is None: return ir.Constant(ir.IntType(8).as_pointer(), None) field_types.append(llvm_type) field_values.append(llvm_val) + kw: str for kw in sorted(deco_kwargs.keys()): + llvm_type: ir.Type | None + llvm_val: ir.Constant | None llvm_type, llvm_val = _python_value_to_llvm(module, deco_kwargs[kw]) if llvm_type is None: return ir.Constant(ir.IntType(8).as_pointer(), None) field_types.append(llvm_type) field_values.append(llvm_val) - struct_type = ir.LiteralStructType(field_types) - struct_const = ir.Constant(struct_type, field_values) + struct_type: ir.LiteralStructType = ir.LiteralStructType(field_types) + struct_const: ir.Constant = ir.Constant(struct_type, field_values) - counter = getattr(_make_decor_args_constant, '_counter', 0) + 1 + counter: int = getattr(_make_decor_args_constant, '_counter', 0) + 1 _make_decor_args_constant._counter = counter - global_name = f"__decor_args.{counter}" + global_name: str = f"__decor_args.{counter}" - global_var = ir.GlobalVariable(module, struct_type, name=global_name) + global_var: ir.GlobalVariable = ir.GlobalVariable(module, struct_type, name=global_name) global_var.global_constant = True global_var.linkage = 'private' global_var.initializer = struct_const @@ -204,7 +215,7 @@ def _make_decor_args_constant(module, decorator_info): return global_var.bitcast(ir.IntType(8).as_pointer()) -def _python_value_to_llvm(module, value): +def _python_value_to_llvm(module: ir.Module, value: int | str | float | bool) -> tuple[ir.Type | None, ir.Constant | None]: """将 Python 值转换为 (LLVM类型, LLVM常量) 元组。""" if isinstance(value, bool): return ir.IntType(1), ir.Constant(ir.IntType(1), int(value)) @@ -222,7 +233,7 @@ def _python_value_to_llvm(module, value): return None, None -def _ZeroConstant(llvm_type): +def _ZeroConstant(llvm_type: ir.Type) -> ir.Constant | None: """为给定 LLVM 类型创建零值常量""" if isinstance(llvm_type, ir.IntType): return ir.Constant(llvm_type, 0) @@ -231,7 +242,7 @@ def _ZeroConstant(llvm_type): elif isinstance(llvm_type, ir.PointerType): return ir.Constant(llvm_type, None) elif isinstance(llvm_type, ir.ArrayType): - elem_zero = _ZeroConstant(llvm_type.element) + elem_zero: ir.Constant | None = _ZeroConstant(llvm_type.element) if elem_zero is None: return None return ir.Constant(llvm_type, [elem_zero] * llvm_type.count) @@ -239,9 +250,9 @@ def _ZeroConstant(llvm_type): return None -def _generate_single_wrapper(module, original_func, wrapper_name, func_name_str, - decorator_info, is_export=False, - is_outermost=False, true_original_func=None): +def _generate_single_wrapper(module: ir.Module, original_func: ir.Function, wrapper_name: str, func_name_str: str, + decorator_info: dict, is_export: bool = False, + is_outermost: bool = False, true_original_func: ir.Function | None = None) -> ir.Function: """ 为单个装饰器生成一层 wrapper 函数。 @@ -253,38 +264,39 @@ def _generate_single_wrapper(module, original_func, wrapper_name, func_name_str, loop.body → 从 args_struct 读回参数(支持修改),调用原函数 post → 调用 handler 后置,清除递归标志,返回结果 """ - decor_name = decorator_info['name'] - handler = _find_or_declare_handler(module, decor_name) - func_name_const = _make_string_constant(module, func_name_str, name_prefix="decor.fn") + decor_name: str = decorator_info['name'] + handler: ir.Function = _find_or_declare_handler(module, decor_name) + func_name_const: ir.Constant = _make_string_constant(module, func_name_str, name_prefix="decor.fn") - func_type = original_func.ftype - return_type = func_type.return_type - param_types = [p.type for p in original_func.args] - is_void = isinstance(return_type, ir.VoidType) + func_type: ir.FunctionType = original_func.ftype + return_type: ir.Type = func_type.return_type + param_types: list[ir.Type] = [p.type for p in original_func.args] + is_void: bool = isinstance(return_type, ir.VoidType) - wrapper_type = ir.FunctionType(return_type, param_types) - wrapper = ir.Function(module, wrapper_type, name=wrapper_name) + wrapper_type: ir.FunctionType = ir.FunctionType(return_type, param_types) + wrapper: ir.Function = ir.Function(module, wrapper_type, name=wrapper_name) # 添加 alwaysinline 属性,优化器完全内联消除调用开销 wrapper.attributes.add('alwaysinline') - i32 = ir.IntType(32) - i8 = ir.IntType(8) - i8_ptr = ir.IntType(8).as_pointer() - phase_pre = ir.Constant(i32, 0) - phase_post = ir.Constant(i32, 1) - null_ptr = ir.Constant(i8_ptr, None) - zero_i32 = ir.Constant(i32, 0) - one_i32 = ir.Constant(i32, 1) - one_i8 = ir.Constant(i8, 1) - zero_i8 = ir.Constant(i8, 0) + i32: ir.IntType = ir.IntType(32) + i8: ir.IntType = ir.IntType(8) + i8_ptr: ir.PointerType = ir.IntType(8).as_pointer() + phase_pre: ir.Constant = ir.Constant(i32, 0) + phase_post: ir.Constant = ir.Constant(i32, 1) + null_ptr: ir.Constant = ir.Constant(i8_ptr, None) + zero_i32: ir.Constant = ir.Constant(i32, 0) + one_i32: ir.Constant = ir.Constant(i32, 1) + one_i8: ir.Constant = ir.Constant(i8, 1) + zero_i8: ir.Constant = ir.Constant(i8, 0) # 递归保护:仅最外层 wrapper 生成 - rec_flag = None + rec_flag: ir.GlobalVariable | None = None if is_outermost and true_original_func is not None: - rec_flag_name = f"__decor_rec_{wrapper_name}" + rec_flag_name: str = f"__decor_rec_{wrapper_name}" # 检查是否已存在 rec_flag = None + g: ir.GlobalValue for g in module.global_values: if g.name == rec_flag_name: rec_flag = g @@ -296,8 +308,10 @@ def _generate_single_wrapper(module, original_func, wrapper_name, func_name_str, rec_flag.initializer = zero_i8 # 创建基本块 - entry_block = wrapper.append_basic_block("entry") + entry_block: ir.Block = wrapper.append_basic_block("entry") + recursive_call_block: ir.Block | None + decorated_entry_block: ir.Block | None if rec_flag is not None: recursive_call_block = wrapper.append_basic_block("recursive_call") decorated_entry_block = wrapper.append_basic_block("decorated_entry") @@ -305,24 +319,25 @@ def _generate_single_wrapper(module, original_func, wrapper_name, func_name_str, recursive_call_block = None decorated_entry_block = None - loop_header_block = wrapper.append_basic_block("loop.header") - loop_body_block = wrapper.append_basic_block("loop.body") - post_block = wrapper.append_basic_block("post") + loop_header_block: ir.Block = wrapper.append_basic_block("loop.header") + loop_body_block: ir.Block = wrapper.append_basic_block("loop.body") + post_block: ir.Block = wrapper.append_basic_block("post") # ==== Entry block ==== - builder = ir.IRBuilder(entry_block) + builder: ir.IRBuilder = ir.IRBuilder(entry_block) + loop_predecessor: ir.Block if rec_flag is not None: # 递归保护:检查标志位 - rec_val = builder.load(rec_flag, name="rec_val") - is_recursive = builder.icmp_signed('!=', rec_val, zero_i8) + rec_val: ir.LoadInstr = builder.load(rec_flag, name="rec_val") + is_recursive: ir.ICMPInstr = builder.icmp_signed('!=', rec_val, zero_i8) builder.cbranch(is_recursive, recursive_call_block, decorated_entry_block) # ==== Recursive call block ==== builder = ir.IRBuilder(recursive_call_block) # 递归调用:直接调用真正的原函数,跳过所有装饰逻辑 - rec_call_args = [arg for arg in wrapper.args] - rec_ret_val = builder.call(true_original_func, rec_call_args) + rec_call_args: list[ir.Argument] = [arg for arg in wrapper.args] + rec_ret_val: ir.CallInstr = builder.call(true_original_func, rec_call_args) if is_void: builder.ret_void() else: @@ -339,39 +354,42 @@ def _generate_single_wrapper(module, original_func, wrapper_name, func_name_str, loop_predecessor = entry_block # 1. 分配栈帧局部上下文(每次调用独立,线程安全,递归安全) - ctx_type = ir.ArrayType(ir.IntType(8), _CTX_SIZE) - ctx_alloca = builder.alloca(ctx_type, name="ctx") - ctx_ptr = builder.bitcast(ctx_alloca, i8_ptr) + ctx_type: ir.ArrayType = ir.ArrayType(ir.IntType(8), _CTX_SIZE) + ctx_alloca: ir.AllocaInstr = builder.alloca(ctx_type, name="ctx") + ctx_ptr: ir.BitCastInstr = builder.bitcast(ctx_alloca, i8_ptr) # 2. 打包函数参数到结构体(装饰器可通过 args_ptr 读写修改) - args_alloca = None - args_struct_type = None + args_alloca: ir.AllocaInstr | None = None + args_struct_type: ir.LiteralStructType | None = None if param_types: args_struct_type = ir.LiteralStructType(param_types) args_alloca = builder.alloca(args_struct_type, name="args") - zero = ir.Constant(i32, 0) + zero: ir.Constant = ir.Constant(i32, 0) + i: int + arg: ir.Argument for i, arg in enumerate(wrapper.args): - field_idx = ir.Constant(i32, i) - gep = builder.gep(args_alloca, [zero, field_idx], inbounds=True) + field_idx: ir.Constant = ir.Constant(i32, i) + gep: ir.GEPInstr = builder.gep(args_alloca, [zero, field_idx], inbounds=True) builder.store(arg, gep) - args_ptr = builder.bitcast(args_alloca, i8_ptr) + args_ptr: ir.BitCastInstr | ir.Constant = builder.bitcast(args_alloca, i8_ptr) else: args_ptr = null_ptr # 3. 分配返回值存储(零初始化,确保跳过原函数时返回安全默认值) + ret_alloca: ir.AllocaInstr | None if not is_void: ret_alloca = builder.alloca(return_type, name="ret") - zero_val = _ZeroConstant(return_type) + zero_val: ir.Constant | None = _ZeroConstant(return_type) if zero_val is not None: builder.store(zero_val, ret_alloca) else: ret_alloca = None # 4. 获取装饰器参数指针 - decor_args_ptr = _make_decor_args_constant(module, decorator_info) + decor_args_ptr: ir.Constant = _make_decor_args_constant(module, decorator_info) # 5. 前置阶段:handler 返回调用次数 - n_calls = builder.call(handler, [ctx_ptr, func_name_const, phase_pre, + n_calls: ir.CallInstr = builder.call(handler, [ctx_ptr, func_name_const, phase_pre, args_ptr, null_ptr, decor_args_ptr]) # 6. 跳转到循环头 @@ -379,30 +397,28 @@ def _generate_single_wrapper(module, original_func, wrapper_name, func_name_str, # ==== Loop header block ==== builder = ir.IRBuilder(loop_header_block) - i_phi = builder.phi(i32, "i") + i_phi: ir.PhiInstr = builder.phi(i32, "i") i_phi.add_incoming(zero_i32, loop_predecessor) - cond = builder.icmp_signed('<', i_phi, n_calls) + cond: ir.ICMPInstr = builder.icmp_signed('<', i_phi, n_calls) builder.cbranch(cond, loop_body_block, post_block) # ==== Loop body block ==== builder = ir.IRBuilder(loop_body_block) # v4: 从 args_struct 读回参数(装饰器可能在 pre-phase 中修改了参数) + call_args: list[ir.LoadInstr | ir.Argument] = [] if args_alloca is not None and args_struct_type is not None: zero = ir.Constant(i32, 0) - call_args = [] for i in range(len(param_types)): - field_idx = ir.Constant(i32, i) - gep = builder.gep(args_alloca, [zero, field_idx], inbounds=True) - Loaded_arg = builder.load(gep, name=f"arg.{i}") + field_idx: ir.Constant = ir.Constant(i32, i) + gep: ir.GEPInstr = builder.gep(args_alloca, [zero, field_idx], inbounds=True) + Loaded_arg: ir.LoadInstr = builder.load(gep, name=f"arg.{i}") call_args.append(Loaded_arg) - else: - call_args = [] - ret_val = builder.call(original_func, call_args) + ret_val: ir.CallInstr = builder.call(original_func, call_args) if ret_alloca is not None: builder.store(ret_val, ret_alloca) - i_next = builder.add(i_phi, one_i32) + i_next: ir.AddInstr = builder.add(i_phi, one_i32) i_phi.add_incoming(i_next, loop_body_block) builder.branch(loop_header_block) @@ -410,6 +426,7 @@ def _generate_single_wrapper(module, original_func, wrapper_name, func_name_str, builder = ir.IRBuilder(post_block) # 后置阶段 + ret_ptr: ir.BitCastInstr | ir.Constant if ret_alloca is not None: ret_ptr = builder.bitcast(ret_alloca, i8_ptr) else: @@ -425,13 +442,13 @@ def _generate_single_wrapper(module, original_func, wrapper_name, func_name_str, if is_void: builder.ret_void() else: - final_ret = builder.load(ret_alloca, name="final_ret") + final_ret: ir.LoadInstr = builder.load(ret_alloca, name="final_ret") builder.ret(final_ret) return wrapper -def _redirect_calls(module, old_func, new_func, skip_func_names=None): +def _redirect_calls(module: ir.Module, old_func: ir.Function, new_func: ir.Function, skip_func_names: set[str] | None = None) -> None: """ 替换 module 中所有对 old_func 的调用指令为对 new_func 的调用。 跳过 skip_func_names 中的函数(wrapper 函数内部不应被重定向)。 @@ -439,21 +456,24 @@ def _redirect_calls(module, old_func, new_func, skip_func_names=None): if skip_func_names is None: skip_func_names = set() + func: ir.Function for func in module.functions: if func.name in skip_func_names: continue if func.name == new_func.name: continue + block: ir.Block for block in func.blocks: + instr: ir.Instruction for instr in list(block.instructions): if not isinstance(instr, ir.CallInstr): continue - callee = instr.callee + callee: ir.Function = instr.callee if isinstance(callee, ir.Function) and callee is old_func: instr.callee = new_func -def run(Gen): +def run(Gen: LlvmCodeGenerator) -> None: """ 执行 DecoratorPass。 @@ -466,16 +486,19 @@ def run(Gen): if not hasattr(Gen, '_decorated_funcs') or not Gen._decorated_funcs: return - module = Gen.module - decorated = Gen._decorated_funcs.copy() + module: ir.Module = Gen.module + decorated: dict = Gen._decorated_funcs.copy() + mangled_name: str + info: dict for mangled_name, info in decorated.items(): - decorators = info['decorators'] - func_name = info['func_name'] - is_export = info['is_export'] + decorators: list = info['decorators'] + func_name: str = info['func_name'] + is_export: bool = info['is_export'] # 查找原始函数 - original_func = None + original_func: ir.Function | None = None + f: ir.Function for f in module.functions: if f.name == mangled_name: original_func = f @@ -490,14 +513,16 @@ def run(Gen): # Python 装饰器顺序:@a @b def f() => a(b(f)) # 执行顺序:先应用最靠近函数的 @b,再应用 @a - current_func = original_func - all_wrapper_names = set() + current_func: ir.Function = original_func + all_wrapper_names: set[str] = set() + i: int for i in range(len(decorators) - 1, -1, -1): - deco = decorators[i] - is_outermost = (i == 0) - deco_name = deco['name'] + deco: dict = decorators[i] + is_outermost: bool = (i == 0) + deco_name: str = deco['name'] + wrapper_name: str if is_outermost: wrapper_name = f"__decor_wrap_{mangled_name}" else: @@ -505,7 +530,7 @@ def run(Gen): all_wrapper_names.add(wrapper_name) - wrapper = _generate_single_wrapper( + wrapper: ir.Function = _generate_single_wrapper( module, current_func, wrapper_name, func_name, deco, is_export=is_export, is_outermost=is_outermost, diff --git a/lib/core/DiagnosticCollector.py b/lib/core/DiagnosticCollector.py index 0758bdc..453b7fa 100644 --- a/lib/core/DiagnosticCollector.py +++ b/lib/core/DiagnosticCollector.py @@ -15,7 +15,8 @@ from __future__ import annotations import os from dataclasses import dataclass, field from enum import Enum -from typing import List, Optional +from typing import List +from lib.core.VLogger import get_logger as _vlog class DiagnosticLevel(Enum): @@ -30,29 +31,29 @@ class Diagnostic: lineno: int message: str - def __str__(self): - short_file = os.path.basename(self.file) if self.file else "" + def __str__(self) -> str: + short_file: str = os.path.basename(self.file) if self.file else "" return f"[{self.level.value}] {short_file}:{self.lineno} — {self.message}" class DiagnosticCollector: """诊断信息收集器""" - def __init__(self): - self._diagnostics: List[Diagnostic] = [] + def __init__(self) -> None: + self._diagnostics: list[Diagnostic] = [] - def warn(self, file: str, lineno: int, message: str): + def warn(self, file: str, lineno: int, message: str) -> None: self._diagnostics.append(Diagnostic(DiagnosticLevel.WARNING, file, lineno, message)) - def error(self, file: str, lineno: int, message: str): + def error(self, file: str, lineno: int, message: str) -> None: self._diagnostics.append(Diagnostic(DiagnosticLevel.ERROR, file, lineno, message)) @property - def warnings(self) -> List[Diagnostic]: + def warnings(self) -> list[Diagnostic]: return [d for d in self._diagnostics if d.level == DiagnosticLevel.WARNING] @property - def errors(self) -> List[Diagnostic]: + def errors(self) -> list[Diagnostic]: return [d for d in self._diagnostics if d.level == DiagnosticLevel.ERROR] @property @@ -63,17 +64,17 @@ class DiagnosticCollector: def has_warnings(self) -> bool: return any(d.level == DiagnosticLevel.WARNING for d in self._diagnostics) - def report(self, min_level: DiagnosticLevel = DiagnosticLevel.WARNING): + def report(self, min_level: DiagnosticLevel = DiagnosticLevel.WARNING) -> None: """打印所有诊断信息""" for d in self._diagnostics: if d.level.value >= min_level.value: - print(d) + _vlog().debug(str(d)) - def clear(self): + def clear(self) -> None: self._diagnostics.clear() - def __len__(self): + def __len__(self) -> int: return len(self._diagnostics) - def __bool__(self): + def __bool__(self) -> bool: return len(self._diagnostics) > 0 diff --git a/lib/core/DifferenceCalculation.py b/lib/core/DifferenceCalculation.py index 1dd30f8..ba7e28a 100644 --- a/lib/core/DifferenceCalculation.py +++ b/lib/core/DifferenceCalculation.py @@ -1,3 +1,5 @@ +from __future__ import annotations + def LevenshteinDistance(s1: str, s2: str) -> int: """ 计算两个字符串的 Levenshtein 距离(编辑距离) @@ -6,13 +8,17 @@ def LevenshteinDistance(s1: str, s2: str) -> int: :return: 最少编辑操作次数(差异程度) """ # 创建二维动态规划表,dp[i][j] 表示 s1[:i] 到 s2[:j] 的编辑距离 + m: int + n: int m, n = len(s1), len(s2) - dp = [[0] * (n + 1) for _ in range(m + 1)] + dp: list[list[int]] = [[0] * (n + 1) for _ in range(m + 1)] # 初始化:空字符串到 s1[:i] 需要 i 次删除操作 + i: int for i in range(m + 1): dp[i][0] = i # 初始化:空字符串到 s2[:j] 需要 j 次插入操作 + j: int for j in range(n + 1): dp[0][j] = j @@ -39,11 +45,15 @@ def LongestCommonSubsequence(s1: str, s2: str) -> tuple[list[tuple[int, int]], s :param s2: 目标字符串 :return: (LCS 位置列表 [(S1Idx, S2Idx)], LCS 字符串) """ + m: int + n: int m, n = len(s1), len(s2) # dp[i][j] 表示 s1[:i] 和 s2[:j] 的 LCS 长度 - dp = [[0] * (n + 1) for _ in range(m + 1)] + dp: list[list[int]] = [[0] * (n + 1) for _ in range(m + 1)] # 填充 LCS 长度表 + i: int + j: int for i in range(1, m + 1): for j in range(1, n + 1): if s1[i-1] == s2[j-1]: @@ -52,8 +62,8 @@ def LongestCommonSubsequence(s1: str, s2: str) -> tuple[list[tuple[int, int]], s dp[i][j] = max(dp[i-1][j], dp[i][j-1]) # 回溯找 LCS 的具体字符和位置 - LcsChars = [] - LcsPositions = [] + LcsChars: list[str] = [] + LcsPositions: list[tuple[int, int]] = [] i, j = m, n while i > 0 and j > 0: if s1[i-1] == s2[j-1]: @@ -72,7 +82,7 @@ def LongestCommonSubsequence(s1: str, s2: str) -> tuple[list[tuple[int, int]], s return LcsPositions, ''.join(LcsChars) -def GetStringDiff(s1: str, s2: str) -> dict: +def GetStringDiff(s1: str, s2: str) -> dict[str, int | float | str | dict[str, list[tuple[int, str] | tuple[int, str, str]]]]: """ 完整对比两个字符串,返回差异详情 :param s1: 原始字符串 @@ -80,20 +90,24 @@ def GetStringDiff(s1: str, s2: str) -> dict: :return: 差异字典(包含编辑距离、LCS、差异位置/内容) """ # 1. 计算编辑距离(差异程度) - EditDist = LevenshteinDistance(s1, s2) + EditDist: int = LevenshteinDistance(s1, s2) # 2. 计算 LCS(公共部分) + LcsPos: list[tuple[int, int]] + LcsStr: str LcsPos, LcsStr = LongestCommonSubsequence(s1, s2) # 3. 定位差异位置和内容 - DiffDetails = { + DiffDetails: dict[str, list] = { "delete": [], # s1 中需要删除的字符 (索引, 字符) "insert": [], # s2 中需要插入的字符 (索引, 字符) "replace": [] # s1 中需要替换的字符 (s1索引, 原字符, 目标字符) } # 生成 s1 和 s2 的差异标记 - S1Idx = 0 - S2Idx = 0 + S1Idx: int = 0 + S2Idx: int = 0 + LcsS1Idx: int + LcsS2Idx: int for (LcsS1Idx, LcsS2Idx) in LcsPos: # 处理 s1 中需要删除的字符(LCS 前的非公共部分) while S1Idx < LcsS1Idx: @@ -116,7 +130,13 @@ def GetStringDiff(s1: str, s2: str) -> dict: S2Idx += 1 # 优化:将连续的删除+插入合并为替换(更符合直观) - ReplaceCandidates = list(zip(DiffDetails["delete"], DiffDetails["insert"])) + ReplaceCandidates: list[tuple[tuple[int, str], tuple[int, str]]] = list(zip(DiffDetails["delete"], DiffDetails["insert"])) + DelItem: tuple[int, str] + InsItem: tuple[int, str] + DelIdx: int + DelChar: str + InsIdx: int + InsChar: str for (DelItem, InsItem) in ReplaceCandidates: DelIdx, DelChar = DelItem InsIdx, InsChar = InsItem @@ -136,9 +156,9 @@ def GetStringDiff(s1: str, s2: str) -> dict: # 测试用例 if __name__ == "__main__": # 示例1:轻微差异(替换+插入) - s1 = "Hello World!" - s2 = "Hello Python!" - DiffResult = GetStringDiff(s1, s2) + s1: str = "Hello World!" + s2: str = "Hello Python!" + DiffResult: dict = GetStringDiff(s1, s2) print("=== 示例1:轻微差异 ===") print(f"编辑距离:{DiffResult['EditDistance']}") print(f"相似度:{DiffResult['similarity']:.2f}") @@ -146,9 +166,9 @@ if __name__ == "__main__": print(f"差异详情:{DiffResult['DiffDetails']}") # 示例2:完全不同 - s3 = "abc123" - s4 = "xyz789" - DiffResult2 = GetStringDiff(s3, s4) + s3: str = "abc123" + s4: str = "xyz789" + DiffResult2: dict = GetStringDiff(s3, s4) print("\n=== 示例2:完全不同 ===") print(f"编辑距离:{DiffResult2['EditDistance']}") print(f"相似度:{DiffResult2['similarity']:.2f}") @@ -156,9 +176,9 @@ if __name__ == "__main__": print(f"差异详情:{DiffResult2['DiffDetails']}") # 示例3:内容一致 - s5 = "TestString" - s6 = "TestString" - DiffResult3 = GetStringDiff(s5, s6) + s5: str = "TestString" + s6: str = "TestString" + DiffResult3: dict = GetStringDiff(s5, s6) print("\n=== 示例3:内容一致 ===") print(f"编辑距离:{DiffResult3['EditDistance']}") print(f"相似度:{DiffResult3['similarity']:.2f}") diff --git a/lib/core/Exportable.py b/lib/core/Exportable.py index 00d6c01..3b7ffc2 100644 --- a/lib/core/Exportable.py +++ b/lib/core/Exportable.py @@ -2,6 +2,7 @@ """ 导出表模块 - 用于收集和存储文件的公开符号信息 """ +from __future__ import annotations from dataclasses import dataclass, field from typing import Dict, List, Optional, Any @@ -79,25 +80,25 @@ class Exportable: def add_enum(self, name: str, lineno: int, is_public: bool = True) -> EnumInfo: """添加枚举类型""" - enum_info = EnumInfo(name=name, lineno=lineno, is_public=is_public) + enum_info: EnumInfo = EnumInfo(name=name, lineno=lineno, is_public=is_public) self.enums.append(enum_info) return enum_info def add_function(self, name: str, return_type: str, lineno: int, is_public: bool = True) -> FunctionInfo: """添加函数""" - func_info = FunctionInfo(name=name, return_type=return_type, lineno=lineno, is_public=is_public) + func_info: FunctionInfo = FunctionInfo(name=name, return_type=return_type, lineno=lineno, is_public=is_public) self.functions.append(func_info) return func_info def add_struct(self, name: str, lineno: int, is_public: bool = True) -> StructInfo: """添加结构体""" - struct_info = StructInfo(name=name, lineno=lineno, is_public=is_public) + struct_info: StructInfo = StructInfo(name=name, lineno=lineno, is_public=is_public) self.structs.append(struct_info) return struct_info def add_typedef(self, name: str, original_type: str, lineno: int, is_public: bool = True) -> TypedefInfo: """添加类型别名""" - typedef_info = TypedefInfo(name=name, original_type=original_type, lineno=lineno, is_public=is_public) + typedef_info: TypedefInfo = TypedefInfo(name=name, original_type=original_type, lineno=lineno, is_public=is_public) self.typedefs.append(typedef_info) return typedef_info @@ -167,7 +168,7 @@ class Exportable: def get_public_symbols(self) -> 'Exportable': """获取仅包含公开符号的导出表""" - result = Exportable(filename=self.filename) + result: Exportable = Exportable(filename=self.filename) result.enums = [e for e in self.enums if e.is_public] result.functions = [f for f in self.functions if f.is_public] diff --git a/lib/core/Handles/HandlesAnnAssign.py b/lib/core/Handles/HandlesAnnAssign.py index 43c19c2..f65f709 100644 --- a/lib/core/Handles/HandlesAnnAssign.py +++ b/lib/core/Handles/HandlesAnnAssign.py @@ -1,91 +1,108 @@ from __future__ import annotations -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Any if TYPE_CHECKING: from lib.core.translator import Translator -from lib.core.Handles.HandlesBase import BaseHandle, CTypeInfo -from lib.includes import t + from lib.core.LlvmCodeGenerator import LlvmCodeGenerator import ast import llvmlite.ir as ir +from lib.core.Handles.HandlesBase import BaseHandle, CTypeInfo +from lib.core.VLogger import get_logger as _vlog +from lib.constants.config import mode as _config_mode +from lib.includes import t +from lib.core.SymbolUtils import IsListAnnotation, ParseListAnnotation, FindStructNameInAnnotation class AnnAssignHandle(BaseHandle): - def _GetCTypeInfo(self, annotation): + def _GetCTypeInfo(self, annotation: ast.AST) -> CTypeInfo | None: return self.Trans.TypeMergeHandler.GetCTypeInfo(annotation) - def _StoreOrStrCopy(self, VarName, VarPtr, Value): - Gen = self.Trans.LlvmGen - DestPtr = Gen._load(VarPtr, name=VarName) + def _StoreOrStrCopy(self, VarName: str, VarPtr: ir.Value, Value: ir.Value) -> None: + Gen: LlvmCodeGenerator = self.Trans.LlvmGen + DestPtr: ir.Value = Gen._load(VarPtr, name=VarName) if isinstance(DestPtr.type, ir.PointerType) and isinstance(DestPtr.type.pointee, ir.IntType) and DestPtr.type.pointee.width == 8: if isinstance(Value.type, ir.PointerType) and isinstance(Value.type.pointee, ir.IntType) and Value.type.pointee.width == 8: if 'llvm.memcpy' not in Gen.functions: - memcpy_type = ir.FunctionType(ir.VoidType(), [ir.PointerType(ir.IntType(8)), ir.PointerType(ir.IntType(8)), ir.IntType(64), ir.IntType(32), ir.IntType(1)]) + memcpy_type: ir.FunctionType = ir.FunctionType(ir.VoidType(), [ir.PointerType(ir.IntType(8)), ir.PointerType(ir.IntType(8)), ir.IntType(64), ir.IntType(32), ir.IntType(1)]) Gen.functions['llvm.memcpy'] = ir.Function(Gen.module, memcpy_type, name='llvm.memcpy') if isinstance(DestPtr.type.pointee, ir.IntType) and not isinstance(DestPtr.type.pointee, ir.IntType(8)): DestPtr = Gen.builder.bitcast(DestPtr, ir.PointerType(ir.IntType(8)), name=f"strcpy_dst_cast_{VarName}") if isinstance(Value.type.pointee, ir.IntType) and not isinstance(Value.type.pointee, ir.IntType(8)): Value = Gen.builder.bitcast(Value, ir.PointerType(ir.IntType(8)), name=f"strcpy_src_cast_{VarName}") - size = ir.Constant(ir.IntType(64), 8) - align = ir.Constant(ir.IntType(32), 1) - isvolatile = ir.Constant(ir.IntType(1), 0) + size: ir.Constant = ir.Constant(ir.IntType(64), 8) + align: ir.Constant = ir.Constant(ir.IntType(32), 1) + isvolatile: ir.Constant = ir.Constant(ir.IntType(1), 0) Gen.builder.call(Gen.functions['llvm.memcpy'], [DestPtr, Value, size, align, isvolatile], name=f"strcpy_call_{VarName}") return try: - CastedVal = Gen.builder.bitcast(Value, VarPtr.type.pointee, name=f"cast_{VarName}") + CastedVal: ir.Value = Gen.builder.bitcast(Value, VarPtr.type.pointee, name=f"cast_{VarName}") Gen._store(CastedVal, VarPtr) except Exception: # 回退:bitcast 失败时 alloca 新变量 - NewVar = Gen._allocaEntry(Value.type, name=VarName) + NewVar: ir.AllocaInstr = Gen._allocaEntry(Value.type, name=VarName) Gen._store(Value, NewVar) Gen.variables[VarName] = NewVar - def _HandleAttributeStoreLlvm(self, Target, Value): - Gen = self.Trans.LlvmGen - AttrName = Target.attr + def _HandleAttributeStoreLlvm(self, Target: ast.Attribute, Value: ir.Value) -> None: + Gen: LlvmCodeGenerator = self.Trans.LlvmGen + AttrName: str = Target.attr if isinstance(Target.value, ast.Name) and Target.value.id == 'self': - ClassName = self._CurrentCpythonObjectClass + ClassName: str | None = self._CurrentCpythonObjectClass if not ClassName: - self_var = Gen.variables.get('self') + self_var: ir.Value | None = Gen.variables.get('self') if self_var: - var_type = self_var.type + var_type: ir.Type = self_var.type if isinstance(var_type, ir.PointerType) and isinstance(var_type.pointee, ir.PointerType): var_type = var_type.pointee if isinstance(var_type, ir.PointerType): - pointee = var_type.pointee + pointee: ir.Type = var_type.pointee for cn, st in Gen.structs.items(): if st == pointee: ClassName = cn break if ClassName and ClassName in Gen.structs: - SelfVar = Gen._get_var_ptr('self') + SelfVar: ir.Value | None = Gen._get_var_ptr('self') if SelfVar: - SelfPtr = Gen._load(SelfVar, name="self") - offset = Gen._get_member_offset(AttrName, ClassName) - MemberPtr = Gen.builder.gep(SelfPtr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=AttrName) + SelfPtr: ir.Value = Gen._load(SelfVar, name="self") + offset: int = Gen._get_member_offset(AttrName, ClassName) + MemberPtr: ir.Value = Gen.builder.gep(SelfPtr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=AttrName) self._StoreWithCoerce(Value, MemberPtr) elif isinstance(Target.value, ast.Name): - VarName = Target.value.id - ClassName = Gen.var_struct_class.get(VarName) + VarName: str = Target.value.id + + # FakeDuck: 检查是否有影子结构体 a__meta__ (str 变量的 per-instance 字段存储) + # 直接通过 a.__field__ = value 访问影子结构体字段 (语法糖) + _fd_meta_name: str = f"{VarName}__meta__" + if _fd_meta_name in Gen.variables and '_str' in Gen.structs: + _fd_offset = Gen._get_member_offset(AttrName, '_str') + if _fd_offset is not None: + _fd_meta_ptr: ir.Value = Gen.variables[_fd_meta_name] + _fd_field_ptr: ir.Value = Gen.builder.gep(_fd_meta_ptr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), _fd_offset)], name=f"{VarName}_{AttrName}_ptr") + self._StoreWithCoerce(Value, _fd_field_ptr) + return + + ClassName: str | None = Gen.var_struct_class.get(VarName) if not ClassName: for CN in Gen.structs: if VarName == CN.lower() or VarName.startswith(CN): ClassName = CN break if not ClassName and VarName in Gen.variables: - VarPtr = Gen.variables[VarName] + VarPtr: ir.Value = Gen.variables[VarName] if isinstance(VarPtr.type, ir.PointerType): - pointee = VarPtr.type.pointee + pointee: ir.Type = VarPtr.type.pointee if isinstance(pointee, ir.PointerType): pointee = pointee.pointee for CN, ST in Gen.structs.items(): if pointee == ST: ClassName = CN break - IsUnion = False - if ClassName and self.Trans.SymbolTable.has(ClassName): - TypeInfo = self.Trans.SymbolTable[ClassName] - if TypeInfo.IsUnion: - IsUnion = True + IsUnion: bool = False + if ClassName: + ClassTypeInfo: Any = self.Trans.SymbolTable.lookup(ClassName) + if ClassTypeInfo: + if ClassTypeInfo.IsUnion: + IsUnion = True if ClassName and ClassName in Gen.structs: - ObjVal = self.Trans.ExprHandler.HandleExprLlvm(Target.value) + ObjVal: ir.Value | None = self.Trans.ExprHandler.HandleExprLlvm(Target.value) if ObjVal: if isinstance(ObjVal.type, ir.PointerType) and isinstance(ObjVal.type.pointee, ir.IntType) and ObjVal.type.pointee.width == 8: ObjVal = Gen.builder.bitcast(ObjVal, ir.PointerType(Gen.structs[ClassName]), name=f"cast_{ClassName}") @@ -93,34 +110,34 @@ class AnnAssignHandle(BaseHandle): ObjVal = Gen._load(ObjVal, name=f"Load_{ClassName}") if isinstance(ObjVal.type, ir.PointerType) and ObjVal.type.pointee == Gen.structs[ClassName]: if IsUnion: - NestedStructName = f"{ClassName}_{AttrName}" + NestedStructName: str = f"{ClassName}_{AttrName}" if NestedStructName in Gen.structs: - NestedStructType = Gen.structs[NestedStructName] + NestedStructType: ir.Type = Gen.structs[NestedStructName] ObjVal = Gen.builder.bitcast(ObjVal, ir.PointerType(NestedStructType), name=f"cast_{NestedStructName}") - offset = Gen._get_member_offset(AttrName, NestedStructName) + offset: int = Gen._get_member_offset(AttrName, NestedStructName) if offset is not None and offset < len(NestedStructType.elements): - MemberPtr = Gen.builder.gep(ObjVal, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=AttrName) + MemberPtr: ir.Value = Gen.builder.gep(ObjVal, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=AttrName) self._StoreWithCoerce(Value, MemberPtr) return - offset = Gen._get_member_offset(AttrName, ClassName) - MemberPtr = Gen.builder.gep(ObjVal, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=AttrName) + offset: int = Gen._get_member_offset(AttrName, ClassName) + MemberPtr: ir.Value = Gen.builder.gep(ObjVal, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=AttrName) self._StoreWithCoerce(Value, MemberPtr) elif isinstance(Target.value, ast.Attribute): - ObjVal = self.Trans.ExprHandler.HandleExprLlvm(Target.value) + ObjVal: ir.Value | None = self.Trans.ExprHandler.HandleExprLlvm(Target.value) if ObjVal and isinstance(ObjVal.type, ir.PointerType): - pointee = ObjVal.type.pointee + pointee: ir.Type = ObjVal.type.pointee if isinstance(pointee, (ir.LiteralStructType, ir.IdentifiedStructType)): for CN, ST in Gen.structs.items(): if pointee == ST: - offset = Gen._get_member_offset(AttrName, CN) - MemberPtr = Gen.builder.gep(ObjVal, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=AttrName) + offset: int = Gen._get_member_offset(AttrName, CN) + MemberPtr: ir.Value = Gen.builder.gep(ObjVal, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=AttrName) self._StoreWithCoerce(Value, MemberPtr) break - def _StoreWithCoerce(self, Value, Ptr): - Gen = self.Trans.LlvmGen + def _StoreWithCoerce(self, Value: ir.Value, Ptr: ir.Value) -> None: + Gen: LlvmCodeGenerator = self.Trans.LlvmGen if isinstance(Ptr.type, ir.PointerType): - TargetType = Ptr.type.pointee + TargetType: ir.Type = Ptr.type.pointee if Value.type != TargetType: if isinstance(TargetType, ir.IntType) and isinstance(Value.type, ir.IntType): if TargetType.width < Value.type.width: @@ -135,30 +152,30 @@ class AnnAssignHandle(BaseHandle): Value = Gen.builder.ptrtoint(Value, TargetType, name="ptr_to_int") Gen._store(Value, Ptr) - def _HandleAnnAssignLlvm(self, Node): - Gen = self.Trans.LlvmGen + def _HandleAnnAssignLlvm(self, Node: ast.AnnAssign) -> None: + Gen: LlvmCodeGenerator = self.Trans.LlvmGen self.Trans._current_assign_node = Node try: self._HandleAnnAssignLlvmInner(Node) finally: self.Trans._current_assign_node = None - def _HandleAnnAssignLlvmInner(self, Node): - Gen = self.Trans.LlvmGen + def _HandleAnnAssignLlvmInner(self, Node: ast.AnnAssign) -> None: + Gen: LlvmCodeGenerator = self.Trans.LlvmGen if isinstance(Node.target, ast.Name): - VarName = Node.target.id - TypeInfo = self.Trans.TypeMergeHandler.GetCTypeInfo(Node.annotation) + VarName: str = Node.target.id + TypeInfo: CTypeInfo | None = self.Trans.TypeMergeHandler.GetCTypeInfo(Node.annotation) if TypeInfo is None: TypeInfo = CTypeInfo() TypeInfo.BaseType = t.CInt() - IsPtr = TypeInfo.IsPtr + IsPtr: bool = TypeInfo.IsPtr if TypeInfo.IsDefine: if Node.value and isinstance(Node.value, ast.Constant): if not hasattr(Gen, '_define_constants'): Gen._define_constants = {} Gen._define_constants[VarName] = Node.value.value - info = CTypeInfo() + info: CTypeInfo = CTypeInfo() info.IsDefine = True info.DefineValue = Node.value.value self.Trans.SymbolTable.insert(VarName, info) @@ -169,92 +186,89 @@ class AnnAssignHandle(BaseHandle): TypeInfo.BaseType = t.CChar() TypeInfo.PtrCount = 1 IsPtr = True - if isinstance(Node.annotation, ast.Subscript) and isinstance(Node.annotation.value, ast.Name) and Node.annotation.value.id == 'list': - slice_node = Node.annotation.slice - if isinstance(slice_node, ast.Tuple) and len(slice_node.elts) == 2: - elem_type_node = slice_node.elts[0] - count_node = slice_node.elts[1] - ElemTypeInfo = CTypeInfo.FromNode(elem_type_node, self.Trans.SymbolTable) - if isinstance(elem_type_node, ast.Name) and elem_type_node.id in Gen.structs: - ElemType = Gen.structs[elem_type_node.id] - else: - if isinstance(elem_type_node, ast.Name) and elem_type_node.id == 'str': - ElemType = ir.PointerType(ir.IntType(8)) - else: - ElemType = Gen._ctype_to_llvm(ElemTypeInfo) - if isinstance(ElemType, ir.VoidType): - ElemType = ir.IntType(32) - ArrayCount = 1 - if isinstance(count_node, ast.Constant) and isinstance(count_node.value, int): - ArrayCount = count_node.value - else: - eval_count = CTypeInfo.TryEvalConstExpr(count_node, self.Trans.SymbolTable) - if eval_count is not None and isinstance(eval_count, int) and eval_count > 0: - ArrayCount = eval_count - elif count_node is None or (isinstance(count_node, ast.Constant) and count_node.value is None): - if Node.value and isinstance(Node.value, ast.Constant) and isinstance(Node.value.value, str): - ArrayCount = len(Node.value.value) + 1 - VarType = ir.ArrayType(ElemType, ArrayCount) - var = Gen._allocaEntry(VarType, name=VarName) - Gen.variables[VarName] = var - Gen._record_var_signedness(VarName, False) - if Node.value and isinstance(Node.value, ast.List): - InitConstants = self.Trans._BuildArrayInitConstants(Node.value, ElemType, elem_type_node, ArrayCount, Gen) - if InitConstants: - try: - InitVal = ir.Constant(VarType, InitConstants) - Gen.builder.store(InitVal, var) - except Exception as _e: - if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": - self.Trans.LogWarning(f"异常被忽略: {_e}") - elif Node.value and isinstance(Node.value, ast.Constant) and isinstance(Node.value.value, str): - str_val = Node.value.value + '\x00' - str_bytes = bytearray(str_val, 'utf-8') - if isinstance(VarType, ir.ArrayType) and len(str_bytes) < VarType.count: - str_bytes.extend(b'\x00' * (VarType.count - len(str_bytes))) + # FakeDuck: 为 str 变量创建影子结构体 a__meta__ (栈上, per-instance) + # a 保持为 char* 用于 printf; a__meta__ 存储 __data__ 和 __mbuddy__ 字段 + # 仅对 str 类型创建,bytes 和 t.CChar|t.CPtr 不创建 + if '_str' in Gen.structs and isinstance(Node.annotation, ast.Name) and Node.annotation.id == 'str': + _meta_name: str = f"{VarName}__meta__" + _meta_var: ir.AllocaInstr = Gen._allocaEntry(Gen.structs['_str'], name=_meta_name) + Gen.variables[_meta_name] = _meta_var + # 标记指针到 str/bytes 的变量 (BinOp 注解如 str | t.CPtr) + # elem_ptr[0] 应加载/存储 8 字节 (指针), 而非 1 字节 (字符) + if isinstance(Node.annotation, ast.BinOp) and isinstance(Node.annotation.op, ast.BitOr): + Gen.var_ptr_element[VarName] = True + parse_result = ParseListAnnotation(Node.annotation) + if parse_result: + elem_type_node: ast.expr = parse_result.elem_type_node + ElemType, ElemTypeInfo = self.ResolveListElementType( + elem_type_node, Gen, + handle_str=True, void_fallback_width=32, + ) + if parse_result.is_pointer: + # 单参数 list[type] → 指针 + # 但如果有列表字面量初始化值 [a, b, c],则按数组 list[type, N] 处理 + if not (Node.value and isinstance(Node.value, ast.List)): + VarType: ir.Type = ir.PointerType(ElemType) + var: ir.AllocaInstr = Gen._allocaEntry(VarType, name=VarName) + Gen.variables[VarName] = var + Gen._record_var_signedness(VarName, False) + if self.Trans.VarScopes: + self.Trans.VarScopes[-1][VarName] = ElemTypeInfo + return + # 有列表字面量值,继续走数组路径(count_node=None 时从列表长度推断) + count_node: ast.expr | None = parse_result.count_node + ArrayCount: int = self.ParseArrayCount(count_node, Gen, Node.value, mode='local') + VarType = ir.ArrayType(ElemType, ArrayCount) + var = Gen._allocaEntry(VarType, name=VarName) + Gen.variables[VarName] = var + Gen._record_var_signedness(VarName, False) + if Node.value and isinstance(Node.value, ast.List): + InitConstants: list[ir.Constant] | None = self.Trans._BuildArrayInitConstants(Node.value, ElemType, elem_type_node, ArrayCount, Gen, byte_order=ElemTypeInfo.ByteOrder if ElemTypeInfo else '') + if InitConstants: try: - InitVal = ir.Constant(VarType, str_bytes[:VarType.count] if isinstance(VarType, ir.ArrayType) else str_bytes) + InitVal: ir.Constant = ir.Constant(VarType, InitConstants) Gen.builder.store(InitVal, var) except Exception as _e: - if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": + if _config_mode == "strict": self.Trans.LogWarning(f"异常被忽略: {_e}") - if self.Trans.VarScopes: - self.Trans.VarScopes[-1][VarName] = ElemTypeInfo - return + elif Node.value and isinstance(Node.value, ast.Constant) and isinstance(Node.value.value, str): + str_val: str = Node.value.value + '\x00' + str_bytes: bytearray = bytearray(str_val, 'utf-8') + if isinstance(VarType, ir.ArrayType) and len(str_bytes) < VarType.count: + str_bytes.extend(b'\x00' * (VarType.count - len(str_bytes))) + try: + InitVal: ir.Constant = ir.Constant(VarType, str_bytes[:VarType.count] if isinstance(VarType, ir.ArrayType) else str_bytes) + Gen.builder.store(InitVal, var) + except Exception as _e: + if _config_mode == "strict": + self.Trans.LogWarning(f"异常被忽略: {_e}") + if self.Trans.VarScopes: + self.Trans.VarScopes[-1][VarName] = ElemTypeInfo + # 记录数组元素字节序 + if ElemTypeInfo and ElemTypeInfo.ByteOrder == 'big' and isinstance(ElemType, ir.IntType) and ElemType.width in (16, 32, 64): + Gen.local_var_byteorders[VarName] = 'big' + return if TypeInfo.IsVoid and isinstance(Node.annotation, ast.BinOp): - def _find_struct_name_in_annot(node): - if isinstance(node, ast.Name) and node.id in Gen.structs: - return node.id - if isinstance(node, ast.Constant) and isinstance(node.value, str) and node.value in Gen.structs: - return node.value - if isinstance(node, ast.Attribute) and node.attr in Gen.structs: - return node.attr - if isinstance(node, ast.BinOp) and isinstance(node.op, ast.BitOr): - result = _find_struct_name_in_annot(node.left) - if result: - return result - return _find_struct_name_in_annot(node.right) - return None - found = _find_struct_name_in_annot(Node.annotation) + found: str | None = FindStructNameInAnnotation(Node.annotation, Gen.structs) if found: TypeInfo = CTypeInfo() TypeInfo.BaseType = t.CStruct(name=found) TypeInfo.PtrCount = 1 IsPtr = True elif isinstance(Node.annotation.left, ast.Attribute): - AttrTypeInfo = self.Trans.TypeMergeHandler.GetCTypeInfo(Node.annotation.left) + AttrTypeInfo: CTypeInfo | None = self.Trans.TypeMergeHandler.GetCTypeInfo(Node.annotation.left) if AttrTypeInfo and AttrTypeInfo.BaseType: TypeInfo = AttrTypeInfo TypeInfo.PtrCount = max(TypeInfo.PtrCount, 1) IsPtr = True - VarType = Gen._ctype_to_llvm(TypeInfo) + VarType: ir.Type = Gen._ctype_to_llvm(TypeInfo) if not IsPtr and TypeInfo.IsStruct and TypeInfo.Name: - stripped = TypeInfo.Name + stripped: str = TypeInfo.Name if stripped in Gen.class_vtable and stripped in Gen.structs: VarType = ir.PointerType(Gen.structs[stripped]) IsPtr = True if isinstance(VarType, ir.IdentifiedStructType): - struct_name = getattr(VarType, 'name', '') + struct_name: str = getattr(VarType, 'name', '') if struct_name and Gen.class_vtable: for cls_name in Gen.class_vtable: if struct_name.endswith(f'.{cls_name}') or struct_name == cls_name: @@ -263,38 +277,38 @@ class AnnAssignHandle(BaseHandle): break if isinstance(VarType, ir.VoidType): VarType = ir.IntType(32) - IsUnsigned = TypeInfo.IsUInt + IsUnsigned: bool = TypeInfo.IsUInt if VarName in Gen._reg_values: - OldVal = Gen._reg_values[VarName] + OldVal: ir.Value = Gen._reg_values[VarName] if isinstance(OldVal.type, ir.PointerType): - var = Gen._allocaEntry(OldVal.type, name=VarName) + var: ir.AllocaInstr = Gen._allocaEntry(OldVal.type, name=VarName) Gen._store(OldVal, var) Gen.variables[VarName] = var del Gen._reg_values[VarName] if Node.value: - InitValue = self.HandleExprLlvm(Node.value, VarType=VarType) + InitValue: ir.Value | None = self.HandleExprLlvm(Node.value, VarType=VarType) if InitValue: self._StoreOrStrCopy(VarName, var, InitValue) Gen._record_var_signedness(VarName, IsUnsigned) return del Gen._reg_values[VarName] - InitValue = None + InitValue: ir.Value | None = None if Node.value: InitValue = self.HandleExprLlvm(Node.value, VarType=VarType) if VarName in Gen._reg_values: del Gen._reg_values[VarName] if VarName in Gen.variables and Gen.variables[VarName] is not None: if InitValue and isinstance(InitValue.type, ir.PointerType): - pointee = InitValue.type.pointee + pointee: ir.Type = InitValue.type.pointee if isinstance(pointee, ir.IdentifiedStructType): - struct_name = getattr(pointee, 'name', '') - is_vtable_class = False + struct_name: str = getattr(pointee, 'name', '') + is_vtable_class: bool = False for cls_name in Gen.class_vtable: if struct_name.endswith(f'.{cls_name}') or struct_name == cls_name: is_vtable_class = True break if is_vtable_class: - var = Gen._allocaEntry(InitValue.type, name=VarName) + var: ir.AllocaInstr = Gen._allocaEntry(InitValue.type, name=VarName) Gen._store(InitValue, var) Gen.variables[VarName] = var if isinstance(Node.annotation, ast.Name) and Node.annotation.id in Gen.structs: @@ -304,9 +318,9 @@ class AnnAssignHandle(BaseHandle): return if InitValue: try: - VarPtr = Gen.variables[VarName] + VarPtr: ir.Value = Gen.variables[VarName] if isinstance(VarPtr.type, ir.PointerType): - TargetType = VarPtr.type.pointee + TargetType: ir.Type = VarPtr.type.pointee if InitValue.type != TargetType: if isinstance(InitValue.type, ir.IntType) and isinstance(TargetType, ir.IntType): if TargetType.width > InitValue.type.width: @@ -317,24 +331,24 @@ class AnnAssignHandle(BaseHandle): InitValue = Gen.builder.bitcast(InitValue, TargetType, name=f"cast_{VarName}") Gen._store(InitValue, VarPtr) except Exception as _e: - if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": + if _config_mode == "strict": self.Trans.LogWarning(f"异常被忽略: {_e}") Gen._record_var_signedness(VarName, IsUnsigned) return if VarName in Gen.global_vars: if VarName in Gen.module.globals: - GVar = Gen.module.globals[VarName] + GVar: ir.GlobalVariable = Gen.module.globals[VarName] if InitValue: Gen._store(InitValue, GVar) Gen.variables[VarName] = GVar Gen._record_var_signedness(VarName, IsUnsigned) return - var = Gen._allocaEntry(VarType, name=VarName) + var: ir.AllocaInstr = Gen._allocaEntry(VarType, name=VarName) if InitValue and isinstance(InitValue.type, ir.PointerType): - pointee = InitValue.type.pointee + pointee: ir.Type = InitValue.type.pointee if isinstance(pointee, ir.IdentifiedStructType): - struct_name = getattr(pointee, 'name', '') - is_vtable_class = False + struct_name: str = getattr(pointee, 'name', '') + is_vtable_class: bool = False for cls_name in Gen.class_vtable: if struct_name.endswith(f'.{cls_name}') or struct_name == cls_name: is_vtable_class = True @@ -373,34 +387,46 @@ class AnnAssignHandle(BaseHandle): InitValue = Gen.builder.inttoptr(InitValue, VarType, name=f"int2ptr_{VarName}") elif isinstance(VarType, ir.IntType) and isinstance(InitValue.type, ir.PointerType): InitValue = Gen.builder.ptrtoint(InitValue, VarType, name=f"ptr2int_{VarName}") + # 大端局部变量:存储时 bswap + InitValue = Gen._apply_bswap_if_big(InitValue, TypeInfo.ByteOrder, f"bswap_store_{VarName}") Gen._store(InitValue, var) except Exception as _e: - if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": + if _config_mode == "strict": self.Trans.LogWarning(f"异常被忽略: {_e}") Gen.variables[VarName] = var Gen._record_var_signedness(VarName, IsUnsigned) + # FakeDuck: 初始化影子结构体 a__meta__ 的字段 + _meta_name_check: str = f"{VarName}__meta__" + if _meta_name_check in Gen.variables and '_str' in Gen.structs: + _meta_var_init: ir.Value = Gen.variables[_meta_name_check] + _str_st: ir.Type = Gen.structs['_str'] + # __data__ 字段 = 字符串指针 + _data_off = Gen._get_member_offset('__data__', '_str') + if _data_off is not None and InitValue: + _data_ptr = Gen.builder.gep(_meta_var_init, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), _data_off)], name=f"{VarName}_meta_data") + Gen._store(InitValue, _data_ptr) + # __mbuddy__ 字段 = NULL + _mpool_off = Gen._get_member_offset('__mbuddy__', '_str') + if _mpool_off is not None: + _mpool_ptr = Gen.builder.gep(_meta_var_init, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), _mpool_off)], name=f"{VarName}_meta_mbuddy") + Gen._store(ir.Constant(ir.PointerType(ir.IntType(8)), None), _mpool_ptr) + # FakeDuck: 从 with 上下文自动注入 requires 字段(如 __mbuddy__) + self.Trans.ExprCallHandle._InjectRequiresFields(_meta_var_init, '_str', Gen) + # 记录局部变量字节序 + if TypeInfo.ByteOrder == 'big': + if isinstance(VarType, ir.IntType) and VarType.width in (16, 32, 64): + Gen.local_var_byteorders[VarName] = 'big' + elif isinstance(VarType, ir.ArrayType) and isinstance(VarType.element, ir.IntType) and VarType.element.width in (16, 32, 64): + Gen.local_var_byteorders[VarName] = 'big' if isinstance(Node.annotation, ast.BinOp) and isinstance(Node.annotation.op, ast.BitOr): - def _find_struct_in_binop(node): - if isinstance(node, ast.Name) and node.id in Gen.structs: - return node.id - if isinstance(node, ast.Constant) and isinstance(node.value, str) and node.value in Gen.structs: - return node.value - if isinstance(node, ast.Attribute) and node.attr in Gen.structs: - return node.attr - if isinstance(node, ast.BinOp) and isinstance(node.op, ast.BitOr): - result = _find_struct_in_binop(node.left) - if result: - return result - return _find_struct_in_binop(node.right) - return None - found_struct = _find_struct_in_binop(Node.annotation) + found_struct: str | None = FindStructNameInAnnotation(Node.annotation, Gen.structs) if found_struct: Gen.var_struct_class[VarName] = found_struct Gen.global_struct_class[VarName] = found_struct if InitValue and isinstance(InitValue.type, ir.PointerType): - pointee = InitValue.type.pointee + pointee: ir.Type = InitValue.type.pointee if isinstance(pointee, (ir.LiteralStructType, ir.IdentifiedStructType)): for CN, ST in Gen.structs.items(): if pointee == ST: @@ -414,47 +440,45 @@ class AnnAssignHandle(BaseHandle): if TypeInfo: self.Trans.VarScopes[-1][VarName] = TypeInfo else: - DefaultInfo = CTypeInfo() + DefaultInfo: CTypeInfo = CTypeInfo() DefaultInfo.BaseType = t.CInt self.Trans.VarScopes[-1][VarName] = DefaultInfo elif isinstance(Node.target, ast.Attribute): if isinstance(Node.target.value, ast.Name) and Node.target.value.id == 'self': if Node.value: - AttrVarType = None + AttrVarType: Any = None try: - if isinstance(Node.annotation, ast.Subscript) and isinstance(Node.annotation.value, ast.Name) and Node.annotation.value.id == 'list': - slice_node = Node.annotation.slice + if IsListAnnotation(Node.annotation): + slice_node: ast.AST = Node.annotation.slice if isinstance(slice_node, ast.Name): - AttrVarType = f'list[{slice_node.id}]' + AttrVarType = f't.CArray[{slice_node.id}]' elif isinstance(slice_node, ast.Tuple): - elts = ', '.join(getattr(e, 'id', str(e)) for e in slice_node.elts) - AttrVarType = f'list[{elts}]' + elts: str = ', '.join(getattr(e, 'id', str(e)) for e in slice_node.elts) + AttrVarType = f't.CArray[{elts}]' elif isinstance(slice_node, ast.Attribute): - AttrVarType = f'list[{ast.dump(slice_node)}]' + AttrVarType = f't.CArray[{ast.dump(slice_node)}]' if AttrVarType is None: - AttrTypeInfo = CTypeInfo.FromNode(Node.annotation, self.Trans.SymbolTable) + AttrTypeInfo: CTypeInfo | None = CTypeInfo.FromNode(Node.annotation, self.Trans.SymbolTable) if AttrTypeInfo: AttrVarType = Gen._ctype_to_llvm(AttrTypeInfo) except Exception as _e: - from lib.core.VLogger import get_logger as _vlog - from lib.constants.config import mode as _config_mode if _config_mode == "strict": raise _vlog().warning(f"解析类型失败: {_e}", "Exception") - Value = self.HandleExprLlvm(Node.value, VarType=AttrVarType) + Value: ir.Value | None = self.HandleExprLlvm(Node.value, VarType=AttrVarType) if Value: self._HandleAttributeStoreLlvm(Node.target, Value) - AttrName = Node.target.attr - len_name = f'{AttrName}__len' - ClassName = self._CurrentCpythonObjectClass + AttrName: str = Node.target.attr + len_name: str = f'{AttrName}__len' + ClassName: str | None = self._CurrentCpythonObjectClass if not ClassName: - self_var = Gen.variables.get('self') + self_var: ir.Value | None = Gen.variables.get('self') if self_var: - var_type = self_var.type + var_type: ir.Type = self_var.type if isinstance(var_type, ir.PointerType) and isinstance(var_type.pointee, ir.PointerType): var_type = var_type.pointee if isinstance(var_type, ir.PointerType): - pointee = var_type.pointee + pointee: ir.Type = var_type.pointee for cn, st in Gen.structs.items(): if st == pointee: ClassName = cn @@ -462,14 +486,14 @@ class AnnAssignHandle(BaseHandle): if ClassName and ClassName in Gen.class_members: for m_name, m_type in Gen.class_members[ClassName]: if m_name == len_name: - list_len = None + list_len: ir.Constant | None = None if isinstance(Node.value, ast.List): list_len = ir.Constant(ir.IntType(64), len(Node.value.elts)) if list_len is not None: - SelfVar = Gen._get_var_ptr('self') + SelfVar: ir.Value | None = Gen._get_var_ptr('self') if SelfVar: - SelfPtr = Gen._load(SelfVar, name="self") - offset = Gen._get_member_offset(len_name, ClassName) - LenPtr = Gen.builder.gep(SelfPtr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=len_name) + SelfPtr: ir.Value = Gen._load(SelfVar, name="self") + offset: int = Gen._get_member_offset(len_name, ClassName) + LenPtr: ir.Value = Gen.builder.gep(SelfPtr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=len_name) Gen._store(list_len, LenPtr) break \ No newline at end of file diff --git a/lib/core/Handles/HandlesAssert.py b/lib/core/Handles/HandlesAssert.py index 7b8ef64..93b0392 100644 --- a/lib/core/Handles/HandlesAssert.py +++ b/lib/core/Handles/HandlesAssert.py @@ -1,57 +1,60 @@ -from __future__ import annotations -from typing import TYPE_CHECKING -if TYPE_CHECKING: - from lib.core.translator import Translator -from lib.core.Handles.HandlesBase import BaseHandle, EXCEPTION_CODE_MAP -import ast -import llvmlite.ir as ir - -class AssertHandle(BaseHandle): - def _HandleAssertLlvm(self, Node): - Gen = self.Trans.LlvmGen - cond_val = self.HandleExprLlvm(Node.test) - if not cond_val: - return - if not isinstance(cond_val.type, ir.IntType) or cond_val.type.width != 1: - zero = ir.Constant(cond_val.type, 0) - cond_val = Gen.builder.icmp_signed('!=', cond_val, zero, name="assert_cond") - AssertFailBB = Gen.func.append_basic_block(name="assert.fail") - AssertOkBB = Gen.func.append_basic_block(name="assert.ok") - Gen.builder.cbranch(cond_val, AssertOkBB, AssertFailBB) - Gen.builder.position_at_start(AssertFailBB) - exc_code = 9 - exc_msg = None - if Node.msg: - if isinstance(Node.msg, ast.Constant) and isinstance(Node.msg.value, str): - exc_msg = self.HandleExprLlvm(Node.msg) - elif isinstance(Node.msg, ast.Call) and isinstance(Node.msg.func, ast.Name): - exc_code = EXCEPTION_CODE_MAP.get(Node.msg.func.id, 99) - if Node.msg.args: - first_arg = Node.msg.args[0] - if isinstance(first_arg, ast.Constant) and isinstance(first_arg.value, str): - exc_msg = self.HandleExprLlvm(first_arg) - elif isinstance(Node.msg, ast.Name): - exc_code = EXCEPTION_CODE_MAP.get(Node.msg.id, 99) - else: - exc_msg = self.HandleExprLlvm(Node.msg) - if Gen.eh_except_block_stack: - ExceptBB, EndBB, exception_code, eh_message = Gen.eh_except_block_stack[-1] - Gen._store(ir.Constant(ir.IntType(32), exc_code), exception_code) - if exc_msg: - Gen._store(exc_msg, eh_message) - else: - null_ptr = ir.Constant(ir.PointerType(ir.IntType(8)), None) - Gen._store(null_ptr, eh_message) - Gen.builder.branch(ExceptBB) - else: - printf_func = Gen.get_or_declare_c_func('printf', ir.FunctionType(ir.IntType(32), [ir.PointerType(ir.IntType(8))], var_arg=True)) - if exc_msg: - fmt = Gen.emit_constant("AssertionError: %s\n", 'string') - Gen.builder.call(printf_func, [fmt, exc_msg], name="assert_fail_print") - else: - fmt = Gen.emit_constant("AssertionError\n", 'string') - Gen.builder.call(printf_func, [fmt], name="assert_fail_print") - exit_func = Gen.get_or_declare_c_func('exit', ir.FunctionType(ir.VoidType(), [ir.IntType(32)])) - Gen.builder.call(exit_func, [ir.Constant(ir.IntType(32), 1)], name="call_exit") - Gen.builder.unreachable() +from __future__ import annotations +from typing import TYPE_CHECKING +if TYPE_CHECKING: + from lib.core.translator import Translator +from lib.core.Handles.HandlesBase import BaseHandle, EXCEPTION_CODE_MAP +import ast +import llvmlite.ir as ir + +class AssertHandle(BaseHandle): + def _HandleAssertLlvm(self, Node: ast.Assert) -> None: + Gen: "Translator.LlvmGen" = self.Trans.LlvmGen + cond_val: ir.Value | None = self.HandleExprLlvm(Node.test) + if not cond_val: + return + if not isinstance(cond_val.type, ir.IntType) or cond_val.type.width != 1: + zero: ir.Constant = ir.Constant(cond_val.type, 0) + cond_val = Gen.builder.icmp_signed('!=', cond_val, zero, name="assert_cond") + AssertFailBB: ir.Block = Gen.func.append_basic_block(name="assert.fail") + AssertOkBB: ir.Block = Gen.func.append_basic_block(name="assert.ok") + Gen.builder.cbranch(cond_val, AssertOkBB, AssertFailBB) + Gen.builder.position_at_start(AssertFailBB) + exc_code: int = 9 + exc_msg: ir.Value | None = None + if Node.msg: + if isinstance(Node.msg, ast.Constant) and isinstance(Node.msg.value, str): + exc_msg = self.HandleExprLlvm(Node.msg) + elif isinstance(Node.msg, ast.Call) and isinstance(Node.msg.func, ast.Name): + exc_code = EXCEPTION_CODE_MAP.get(Node.msg.func.id, 99) + if Node.msg.args: + first_arg: ast.expr = Node.msg.args[0] + if isinstance(first_arg, ast.Constant) and isinstance(first_arg.value, str): + exc_msg = self.HandleExprLlvm(first_arg) + elif isinstance(Node.msg, ast.Name): + exc_code = EXCEPTION_CODE_MAP.get(Node.msg.id, 99) + else: + exc_msg = self.HandleExprLlvm(Node.msg) + if Gen.eh_except_block_stack: + ExceptBB: ir.Block = Gen.eh_except_block_stack[-1][0] + EndBB: ir.Block | None = Gen.eh_except_block_stack[-1][1] + exception_code: ir.AllocaInstr = Gen.eh_except_block_stack[-1][2] + eh_message: ir.AllocaInstr = Gen.eh_except_block_stack[-1][3] + Gen._store(ir.Constant(ir.IntType(32), exc_code), exception_code) + if exc_msg: + Gen._store(exc_msg, eh_message) + else: + null_ptr: ir.Constant = ir.Constant(ir.PointerType(ir.IntType(8)), None) + Gen._store(null_ptr, eh_message) + Gen.builder.branch(ExceptBB) + else: + printf_func: ir.Function = Gen.get_or_declare_c_func('printf', ir.FunctionType(ir.IntType(32), [ir.PointerType(ir.IntType(8))], var_arg=True)) + if exc_msg: + fmt: ir.Value = Gen.emit_constant("AssertionError: %s\n", 'string') + Gen.builder.call(printf_func, [fmt, exc_msg], name="assert_fail_print") + else: + fmt: ir.Value = Gen.emit_constant("AssertionError\n", 'string') + Gen.builder.call(printf_func, [fmt], name="assert_fail_print") + exit_func: ir.Function = Gen.get_or_declare_c_func('exit', ir.FunctionType(ir.VoidType(), [ir.IntType(32)])) + Gen.builder.call(exit_func, [ir.Constant(ir.IntType(32), 1)], name="call_exit") + Gen.builder.unreachable() Gen.builder.position_at_start(AssertOkBB) \ No newline at end of file diff --git a/lib/core/Handles/HandlesAssign.py b/lib/core/Handles/HandlesAssign.py index a179d92..407229b 100644 --- a/lib/core/Handles/HandlesAssign.py +++ b/lib/core/Handles/HandlesAssign.py @@ -1,1570 +1,1576 @@ -from __future__ import annotations -from typing import TYPE_CHECKING -if TYPE_CHECKING: - from lib.core.translator import Translator -from lib.core.Handles.HandlesBase import BaseHandle, CTypeInfo, FuncMeta -from lib.includes import t -import ast -import llvmlite.ir as ir - -class AssignHandle: - def __init__(self, translator: "Translator"): - self.Trans = translator - self._CurrentCpythonObjectClass: str = None - - @staticmethod - def _zero_value(var_type): - if isinstance(var_type, ir.ArrayType): - elem_zv = AssignHandle._zero_value(var_type.element) - if elem_zv is None: - return None - return ir.Constant(var_type, [elem_zv] * var_type.count) - elif isinstance(var_type, ir.IntType): - return ir.Constant(var_type, 0) - elif isinstance(var_type, (ir.FloatType, ir.DoubleType)): - return ir.Constant(var_type, 0.0) - elif isinstance(var_type, ir.PointerType): - return ir.Constant(var_type, None) - elif isinstance(var_type, ir.BaseStructType): - if var_type.elements is not None and len(var_type.elements) > 0: - elem_zvs = [AssignHandle._zero_value(m) for m in var_type.elements] - if any(zv is None for zv in elem_zvs): - return None - return ir.Constant(var_type, elem_zvs) - return None - return None - - @staticmethod - def _contains_identified_struct(var_type): - if isinstance(var_type, ir.IdentifiedStructType): - return True - if isinstance(var_type, ir.ArrayType): - return AssignHandle._contains_identified_struct(var_type.element) - if isinstance(var_type, ir.PointerType): - return AssignHandle._contains_identified_struct(var_type.pointee) - if isinstance(var_type, ir.BaseStructType): - if var_type.elements: - return any(AssignHandle._contains_identified_struct(e) for e in var_type.elements) - return False - - def HandleExprLlvm(self, Node, VarType=None): - return self.Trans.ExprHandler.HandleExprLlvm(Node, VarType) - - def _HandleAssignLlvm(self, Node): - Gen = self.Trans.LlvmGen - Gen._set_node_info(Node, "Assign") - if len(Node.targets) == 1: - Target = Node.targets[0] - if isinstance(Target, ast.Name): - VarName = Target.id - if VarName in Gen.var_const_flags: - src_info = Gen._get_node_info() - print(f"[错误] 不能对 const 变量 '{VarName}' 赋值{src_info}") - import sys - sys.exit(1) - if isinstance(Node.value, ast.Attribute) and isinstance(Node.value.value, ast.Name) and Node.value.value.id == 't': - AttrName = Node.value.attr - Gen.var_type_info[VarName] = {'type': 't_type', 'name': AttrName} - Gen.var_type_assignments.setdefault(VarName, []).append({'type': 't_type', 'name': AttrName}) - from lib.includes.t import CTypeRegistry - c_type_name = '' - resolved = CTypeRegistry.ResolveName(AttrName) - if resolved is not None: - ctype_cls, ptr_level = resolved - c_type_name = CTypeRegistry.CTypeToCName(ctype_cls) - if ptr_level > 0 and c_type_name: - c_type_name = c_type_name + ' *' - if not c_type_name: - if AttrName == 'CPtr': - c_type_name = 'void *' - is_unsigned = Gen._is_type_unsigned(c_type_name) if c_type_name else False - fmt_str = "%u\n" if is_unsigned else "%d\n" - fmt_bytes = fmt_str.encode('utf-8') + b'\x00' - fmt_type = ir.ArrayType(ir.IntType(8), len(fmt_bytes)) - fmt_const = ir.Constant(fmt_type, bytearray(fmt_bytes)) - fmt_gvar = ir.GlobalVariable(Gen.module, fmt_type, name=f"str_const_{Gen.string_const_counter}") - Gen.string_const_counter += 1 - fmt_gvar.initializer = fmt_const - fmt_gvar.linkage = 'internal' - fmt_ptr = Gen.builder.bitcast(fmt_gvar, ir.PointerType(ir.IntType(8)), name=f"{VarName}_fmt") - fmt_var_name = f"__{VarName}_fmt" - if fmt_var_name not in Gen.variables: - fmt_alloca = Gen._allocaEntry(ir.PointerType(ir.IntType(8)), name=fmt_var_name) - Gen.variables[fmt_var_name] = fmt_alloca - Gen.builder.store(fmt_ptr, Gen.variables[fmt_var_name]) - kind_var_name = f"__{VarName}_kind" - if kind_var_name not in Gen.variables: - kind_alloca = Gen._allocaEntry(ir.IntType(32), name=kind_var_name) - Gen.variables[kind_var_name] = kind_alloca - Gen.builder.store(ir.Constant(ir.IntType(32), 0), Gen.variables[kind_var_name]) - if VarName not in Gen.variables: - dummy_var = Gen._alloca(ir.IntType(8), name=VarName) - Gen.variables[VarName] = dummy_var - return - if isinstance(Node.value, ast.Name) and Node.value.id in Gen.structs: - ClassName = Node.value.id - Gen.var_type_info[VarName] = {'type': 'class_cast', 'name': ClassName} - Gen.var_type_assignments.setdefault(VarName, []).append({'type': 'class_cast', 'name': ClassName}) - fmt_str = "%p\n" - fmt_bytes = fmt_str.encode('utf-8') + b'\x00' - fmt_type = ir.ArrayType(ir.IntType(8), len(fmt_bytes)) - fmt_const = ir.Constant(fmt_type, bytearray(fmt_bytes)) - fmt_gvar = ir.GlobalVariable(Gen.module, fmt_type, name=f"str_const_{Gen.string_const_counter}") - Gen.string_const_counter += 1 - fmt_gvar.initializer = fmt_const - fmt_gvar.linkage = 'internal' - fmt_ptr = Gen.builder.bitcast(fmt_gvar, ir.PointerType(ir.IntType(8)), name=f"{VarName}_fmt") - fmt_var_name = f"__{VarName}_fmt" - if fmt_var_name not in Gen.variables: - fmt_alloca = Gen._allocaEntry(ir.PointerType(ir.IntType(8)), name=fmt_var_name) - Gen.variables[fmt_var_name] = fmt_alloca - Gen.builder.store(fmt_ptr, Gen.variables[fmt_var_name]) - kind_var_name = f"__{VarName}_kind" - if kind_var_name not in Gen.variables: - kind_alloca = Gen._allocaEntry(ir.IntType(32), name=kind_var_name) - Gen.variables[kind_var_name] = kind_alloca - Gen.builder.store(ir.Constant(ir.IntType(32), 1), Gen.variables[kind_var_name]) - if VarName not in Gen.variables: - dummy_var = Gen._alloca(ir.IntType(8), name=VarName) - Gen.variables[VarName] = dummy_var - return - if isinstance(Node.value, ast.Call) and isinstance(Node.value.func, ast.Name) and Node.value.func.id == 'va_list': - va_list_ptr = Gen._allocaEntry(ir.IntType(8).as_pointer(), name="va_list") - Gen.variables[VarName] = va_list_ptr - return - IsStructCtor = (isinstance(Node.value, ast.Call) and isinstance(Node.value.func, ast.Name) - and Node.value.func.id in Gen.structs) - if IsStructCtor: - ClassName = Node.value.func.id - StructType = Gen.structs[ClassName] - - IsUnion = False - TypeInfo = self.Trans.SymbolTable.lookup(ClassName) - if TypeInfo and TypeInfo.IsUnion: - IsUnion = True - - if IsUnion: - Value = self.HandleExprLlvm(Node.value) - if Value: - var = Gen._allocaEntry(Value.type, name=VarName) - Gen._store(Value, var) - Gen.variables[VarName] = var - return - - ExistingPtr = None - if VarName in Gen.variables and Gen.variables[VarName] is not None: - VarPtr = Gen.variables[VarName] - if isinstance(VarPtr.type.pointee, ir.PointerType): - ExistingPtr = VarPtr - elif VarName in Gen._reg_values: - OldVal = Gen._reg_values[VarName] - if isinstance(OldVal.type, ir.PointerType): - var = Gen._allocaEntry(OldVal.type, name=VarName) - Gen._store(OldVal, var) - Gen.variables[VarName] = var - del Gen._reg_values[VarName] - ExistingPtr = var - elif VarName in Gen._direct_values: - OldVal = Gen._direct_values.pop(VarName) - if isinstance(OldVal.type, ir.PointerType): - var = Gen._allocaEntry(OldVal.type, name=VarName) - Gen._store(OldVal, var) - Gen.variables[VarName] = var - ExistingPtr = var - if ExistingPtr: - pointee = ExistingPtr.type.pointee - if isinstance(pointee, ir.PointerType) and pointee.pointee == StructType: - self._InitStructAtPtr(Node.value, ClassName, ExistingPtr) - return - elif isinstance(pointee, ir.PointerType) and isinstance(pointee.pointee, ir.IntType) and pointee.pointee.width == 8: - self._InitStructAtPtr(Node.value, ClassName, ExistingPtr) - Gen.var_struct_class[VarName] = ClassName - return - if isinstance(Node.value, ast.Attribute): - enum_type_name = self._CheckEnumMemberAssignment(Node.value) - if enum_type_name: - Gen.var_type_info[VarName] = {'type': 'enum', 'name': enum_type_name} - var_type_for_list = None - if isinstance(Node.value, ast.List) and VarName in Gen.var_type_info: - type_info = Gen.var_type_info[VarName] - if type_info.get('type') == 'list': - var_type_for_list = type_info.get('full_type') - Value = self.HandleExprLlvm(Node.value, VarType=var_type_for_list) - if not Value: - return - if isinstance(Value.type, ir.VoidType): - return - Gen._UnregisterTempPtr(Value) - if isinstance(Value.type, ir.PointerType) and isinstance(Value.type.pointee, (ir.LiteralStructType, ir.IdentifiedStructType)): - found_class = None - found = Gen.find_struct_by_pointee(Value.type.pointee) - if found: - CN, ST = found - found_class = CN - Gen.var_struct_class[VarName] = CN - Gen._var_to_heap_ptr[VarName] = Value - if found_class is None and isinstance(Value.type.pointee, ir.IdentifiedStructType): - pointee_name = Value.type.pointee.name - for CN, ST in Gen.structs.items(): - if isinstance(ST, ir.IdentifiedStructType) and ST.name == pointee_name: - found_class = CN - Gen.var_struct_class[VarName] = CN - Gen._var_to_heap_ptr[VarName] = Value - break - else: - if VarName in ('mctx', 's1ctx', 's2ctx', 's5ctx'): - pass - if isinstance(Value.type, ir.PointerType) and isinstance(Value.type.pointee, (ir.LiteralStructType, ir.IdentifiedStructType)): - if VarName in Gen.variables and Gen.variables[VarName] is not None: - Gen._store(Value, Gen.variables[VarName]) - else: - var = Gen._allocaEntry(Value.type, name=VarName) - Gen._store(Value, var) - Gen.variables[VarName] = var - if isinstance(Node.value, ast.Call) and isinstance(Node.value.func, ast.Name): - call_func_name = Node.value.func.id - if call_func_name in Gen.var_type_info: - type_info = Gen.var_type_info[call_func_name] - if type_info['type'] in ('t_type', 'class_cast'): - src_fmt_var = f"__{call_func_name}_fmt" - dst_fmt_var = f"__{VarName}_fmt" - if src_fmt_var in Gen.variables: - if dst_fmt_var not in Gen.variables: - dst_alloca = Gen._allocaEntry(ir.PointerType(ir.IntType(8)), name=dst_fmt_var) - Gen.variables[dst_fmt_var] = dst_alloca - src_fmt_ptr = Gen._load(Gen.variables[src_fmt_var], name=f"Load_{call_func_name}_fmt_for_{VarName}") - Gen.builder.store(src_fmt_ptr, Gen.variables[dst_fmt_var]) - src_kind_var = f"__{call_func_name}_kind" - dst_kind_var = f"__{VarName}_kind" - if src_kind_var in Gen.variables: - if dst_kind_var not in Gen.variables: - dst_kind_alloca = Gen._allocaEntry(ir.IntType(32), name=dst_kind_var) - Gen.variables[dst_kind_var] = dst_kind_alloca - src_kind_val = Gen._load(Gen.variables[src_kind_var], name=f"Load_{call_func_name}_kind_for_{VarName}") - Gen.builder.store(src_kind_val, Gen.variables[dst_kind_var]) - Gen.var_type_info[VarName] = {'type': 't_type_runtime', 'source': call_func_name} - return - if VarName in Gen.global_vars: - if VarName in Gen.module.globals: - GVar = Gen.module.globals[VarName] - Gen._store(Value, GVar) - Gen.variables[VarName] = GVar - if isinstance(Value.type, ir.PointerType) and isinstance(Value.type.pointee, (ir.LiteralStructType, ir.IdentifiedStructType)): - found = Gen.find_struct_by_pointee(Value.type.pointee) - if found: - CN, ST = found - Gen.var_struct_class[VarName] = CN - elif VarName in Gen.variables and Gen.variables[VarName] is not None: - Gen._store(Value, Gen.variables[VarName]) - return - if VarName in Gen._reg_values: - OldVal = Gen._reg_values[VarName] - var = Gen._allocaEntry(OldVal.type, name=VarName) - Gen._store(OldVal, var) - Gen.variables[VarName] = var - del Gen._reg_values[VarName] - if VarName in Gen._direct_values: - OldVal = Gen._direct_values.pop(VarName) - var = Gen._allocaEntry(OldVal.type, name=VarName) - Gen._store(OldVal, var) - Gen.variables[VarName] = var - if VarName in Gen.variables and Gen.variables[VarName] is not None: - VarPtr = Gen.variables[VarName] - TargetType = VarPtr.type.pointee if isinstance(VarPtr.type, ir.PointerType) else None - try: - types_differ = TargetType and Value.type != TargetType - except AssertionError: - types_differ = False - if isinstance(Value.type, ir.PointerType) and isinstance(Value.type.pointee, ir.PointerType): - LoadedValue = Gen._load(Value, name=f"Load_{VarName}") - try: - Loaded_differ = TargetType and LoadedValue.type != TargetType - except AssertionError: - Loaded_differ = False - if Loaded_differ: - try: - Coerced = Gen._coerce_value(LoadedValue, TargetType) - if Coerced is not None: - LoadedValue = Coerced - except AssertionError: - pass - Gen._store(LoadedValue, VarPtr) - elif types_differ: - try: - Coerced = Gen._coerce_value(Value, TargetType) - if Coerced is not None: - Gen._store(Coerced, VarPtr) - else: - Gen._store(Value, VarPtr) - except AssertionError: - Gen._store(Value, VarPtr) - else: - Gen._store(Value, VarPtr) - if VarName not in Gen.variables: - # 检查是否为模块级全局变量,避免创建局部变量遮蔽全局 - if VarName in Gen.module.globals: - GVar = Gen.module.globals[VarName] - Gen._store(Value, GVar) - Gen.variables[VarName] = GVar - elif isinstance(Value.type, ir.PointerType) and isinstance(Value.type.pointee, ir.PointerType): - LoadedValue = Gen._load(Value, name=f"Load_{VarName}") - var = Gen._allocaEntry(LoadedValue.type, name=VarName) - Gen._store(LoadedValue, var) - Gen.variables[VarName] = var - else: - var = Gen._allocaEntry(Value.type, name=VarName) - Gen._store(Value, var) - Gen.variables[VarName] = var - is_u = Gen._check_node_unsigned(Node.value) - Gen._record_var_signedness(VarName, 'unsigned int' if is_u else 'int') - if isinstance(Node.value, ast.Call) and isinstance(Node.value.func, ast.Name): - call_func_name = Node.value.func.id - if call_func_name in Gen.var_type_info: - type_info = Gen.var_type_info[call_func_name] - if type_info['type'] in ('t_type', 'class_cast'): - src_fmt_var = f"__{call_func_name}_fmt" - dst_fmt_var = f"__{VarName}_fmt" - if src_fmt_var in Gen.variables: - if dst_fmt_var not in Gen.variables: - dst_alloca = Gen._allocaEntry(ir.PointerType(ir.IntType(8)), name=dst_fmt_var) - Gen.variables[dst_fmt_var] = dst_alloca - src_fmt_ptr = Gen._load(Gen.variables[src_fmt_var], name=f"Load_{call_func_name}_fmt_for_{VarName}") - Gen.builder.store(src_fmt_ptr, Gen.variables[dst_fmt_var]) - src_kind_var = f"__{call_func_name}_kind" - dst_kind_var = f"__{VarName}_kind" - if src_kind_var in Gen.variables: - if dst_kind_var not in Gen.variables: - dst_kind_alloca = Gen._allocaEntry(ir.IntType(32), name=dst_kind_var) - Gen.variables[dst_kind_var] = dst_kind_alloca - src_kind_val = Gen._load(Gen.variables[src_kind_var], name=f"Load_{call_func_name}_kind_for_{VarName}") - Gen.builder.store(src_kind_val, Gen.variables[dst_kind_var]) - Gen.var_type_info[VarName] = {'type': 't_type_runtime', 'source': call_func_name} - else: - Gen.var_type_info[VarName] = {'type': 't_type_runtime', 'source': call_func_name} - elif isinstance(Target, ast.Attribute): - TargetType = None - AttrName = Target.attr - VarName = None - if isinstance(Target.value, ast.Name): - VarName = Target.value.id - if VarName: - ClassName = Gen.var_struct_class.get(VarName) - if not ClassName and getattr(Gen, 'global_struct_class', None): - ClassName = Gen.global_struct_class.get(VarName) - if ClassName: - Gen.var_struct_class[VarName] = ClassName - if not ClassName: - for CN in Gen.structs: - if VarName == CN.lower() or VarName.startswith(CN): - ClassName = CN - break - if ClassName and ClassName in Gen.class_members: - for m_name, m_type in Gen.class_members[ClassName]: - if m_name == AttrName: - TargetType = m_type - break - Value = self.HandleExprLlvm(Node.value, VarType=TargetType) - if Value: - self._HandleAttributeStoreLlvm(Target, Value) - elif isinstance(Target, ast.Subscript): - TargetType = None - SubVarName = None - if isinstance(Target.value, ast.Name): - SubVarName = Target.value.id - if SubVarName in Gen.var_struct_class: - ClassName = Gen.var_struct_class[SubVarName] - if ClassName in Gen.class_members: - for m_name, m_type in Gen.class_members[ClassName]: - if m_name == SubVarName: - if isinstance(m_type, ir.PointerType): - pointee = m_type.pointee - if isinstance(pointee, ir.ArrayType): - TargetType = pointee.element - elif isinstance(m_type, ir.ArrayType): - TargetType = m_type.element - break - if not TargetType and isinstance(Target.value, ast.Name): - SubVarName = Target.value.id - var_val = Gen.variables.get(SubVarName) - if var_val is None and SubVarName in Gen._direct_values: - var_val = Gen._direct_values[SubVarName] - if var_val is not None: - var_type = var_val.type - if isinstance(var_type, ir.PointerType): - pointee = var_type.pointee - if isinstance(pointee, ir.ArrayType): - TargetType = pointee.element - elif isinstance(var_type, ir.ArrayType): - TargetType = var_type.element - Value = self.HandleExprLlvm(Node.value, VarType=TargetType) - if Value: - self._HandleSubscriptStoreLlvm(Target, Value) - elif isinstance(Target, ast.Tuple): - if isinstance(Node.value, ast.Call): - FuncName = None - ModulePath = None - if isinstance(Node.value.func, ast.Name): - FuncName = Node.value.func.id - elif isinstance(Node.value.func, ast.Attribute): - FuncName = Node.value.func.attr - ModulePath = self.Trans.ExprCallHandle._get_ModulePath(Node.value.func.value) - CReturnTypes = [] - FuncDef = self.Trans.FunctionDefCache.get(FuncName) if FuncName else None - if FuncDef: - if FuncDef.returns and isinstance(FuncDef.returns, ast.Subscript): - if isinstance(FuncDef.returns.value, ast.Name) and FuncDef.returns.value.id == 'tuple': - slice_node = FuncDef.returns.slice - if isinstance(slice_node, ast.Tuple): - CReturnTypes = slice_node.elts - else: - CReturnTypes = [slice_node] - if FuncDef.decorator_list: - for decorator in FuncDef.decorator_list: - if isinstance(decorator, ast.Call) and isinstance(decorator.func, ast.Attribute): - if decorator.func.attr == 'CReturn': - for arg in decorator.args: - CReturnTypes.append(arg) - if not CReturnTypes and FuncName: - func = Gen.functions.get(FuncName) - if func: - func_ft = getattr(func, 'ftype', None) - if func_ft: - ret_type = func_ft.return_type - if isinstance(ret_type, ir.LiteralStructType): - CReturnTypes = [None] * len(ret_type.elements) - if not CReturnTypes: - sym_key = FuncName - if not self.Trans.SymbolTable.has(sym_key): - if ModulePath: - sym_key = f"{ModulePath}.{FuncName}" - sym_info = self.Trans.SymbolTable.lookup(sym_key) - if sym_info and sym_info.IsFunction: - ret_type_info = sym_info.FuncPtrReturn - param_type_infos = [pt for _, pt in (sym_info.FuncPtrParams or [])] - if ret_type_info: - if isinstance(ret_type_info, CTypeInfo) and ret_type_info.BaseType: - ret_type = ret_type_info.ToLLVM(Gen) - else: - ret_type = Gen._type_str_to_llvm(str(ret_type_info) if ret_type_info else 'i32', False) - if isinstance(ret_type, ir.LiteralStructType): - CReturnTypes = [None] * len(ret_type.elements) - if FuncName not in Gen.functions: - if isinstance(ret_type, ir.VoidType): - ret_type = ir.IntType(32) - llvm_param_types = [] - for pt in param_type_infos: - if isinstance(pt, CTypeInfo) and pt.BaseType: - lp = pt.ToLLVM(Gen) - else: - lp = Gen._type_str_to_llvm(str(pt) if pt else 'i32', '*' in str(pt) if isinstance(pt, str) else False) - if isinstance(lp, ir.VoidType): - lp = ir.IntType(8).as_pointer() - llvm_param_types.append(lp) - func_type = ir.FunctionType(ret_type, llvm_param_types) - MangledName = Gen._mangle_func_name(FuncName) - func_decl = ir.Function(Gen.module, func_type, name=MangledName) - Gen.functions[MangledName] = func_decl - Gen.functions[FuncName] = func_decl - if not CReturnTypes and FuncName: - func = Gen.functions.get(FuncName) - if func: - func_ft = getattr(func, 'ftype', None) - if func_ft: - ret_type = func_ft.return_type - if isinstance(ret_type, ir.LiteralStructType): - CReturnTypes = [None] * len(ret_type.elements) - if CReturnTypes and len(Target.elts) == len(CReturnTypes): - CallArgs = [] - for arg in Node.value.args: - ArgVal = self.HandleExprLlvm(arg) - if ArgVal: - CallArgs.append(ArgVal) - for kw in Node.value.keywords: - pass - func = Gen.functions.get(FuncName) - func_ft = getattr(func, 'ftype', None) if func else None - func_params = list(getattr(func_ft, 'args', []) or []) if func_ft else [] - while len(CallArgs) < len(func_params): - FuncDef = self.Trans.FunctionDefCache.get(FuncName) - if FuncDef and len(CallArgs) < len(FuncDef.args.args): - arg_def = FuncDef.args.defaults - arg_idx = len(CallArgs) - total_args = len(FuncDef.args.args) - default_start = total_args - len(arg_def) - if arg_idx >= default_start: - def_idx = arg_idx - default_start - if def_idx < len(arg_def): - DefVal = self.HandleExprLlvm(arg_def[def_idx]) - if DefVal: - expected_type = func_params[arg_idx] - if DefVal.type != expected_type: - if isinstance(expected_type, ir.IntType) and isinstance(DefVal.type, ir.IntType): - if DefVal.type.width < expected_type.width: - DefVal = Gen.builder.zext(DefVal, expected_type, name=f"zext_default_{arg_idx}") - elif DefVal.type.width > expected_type.width: - DefVal = Gen.builder.trunc(DefVal, expected_type, name=f"trunc_default_{arg_idx}") - CallArgs.append(DefVal) - continue - if len(CallArgs) < len(func_params): - CallArgs.append(ir.Constant(func_params[len(CallArgs)], 0)) - else: - break - adjusted = Gen._adjust_args(CallArgs, func) - call_result = Gen.builder.call(func, adjusted, name=f"call_{FuncName}") - func_ft = getattr(func, 'ftype', None) - ret_type = getattr(func_ft, 'return_type', None) if func_ft else None - for j, elt in enumerate(Target.elts): - if isinstance(elt, ast.Name): - VarName = elt.id - field_val = Gen.builder.extract_value(call_result, j, name=f"extract_{FuncName}_{j}") - if CReturnTypes[j] is not None: - ReturnTypeInfo = CTypeInfo.FromNode(CReturnTypes[j], self.Trans.SymbolTable) - if ReturnTypeInfo is None: - ReturnTypeInfo = CTypeInfo() - ReturnTypeInfo.BaseType = t.CInt() - VarType = Gen._ctype_to_llvm(ReturnTypeInfo) - elif ret_type and isinstance(ret_type, ir.LiteralStructType) and j < len(ret_type.elements): - VarType = ret_type.elements[j] - else: - VarType = field_val.type - if isinstance(VarType, ir.VoidType): - VarType = ir.IntType(32) - var = Gen._alloca(VarType, name=VarName) - Gen.variables[VarName] = var - if CReturnTypes[j] is not None: - Gen._record_var_signedness(VarName, ReturnTypeStr) - elif ret_type and isinstance(ret_type, ir.LiteralStructType) and j < len(ret_type.elements): - elem_type = ret_type.elements[j] - if isinstance(elem_type, ir.IntType): - if elem_type.width == 16: - Gen._record_var_signedness(VarName, 'unsigned short') - elif elem_type.width == 32: - Gen._record_var_signedness(VarName, 'unsigned int') - elif elem_type.width == 64: - Gen._record_var_signedness(VarName, 'unsigned long long') - Gen._store(field_val, var) - return - - def _InitStructAtPtr(self, call_node, ClassName, VarPtr): - Gen = self.Trans.LlvmGen - if ClassName not in Gen.structs: - return - StructType = Gen.structs[ClassName] - StructPtrType = ir.PointerType(StructType) - RawPtr = Gen._load(VarPtr, name=getattr(VarPtr, 'name', 'ptr')) - StructPtr = Gen.builder.bitcast(RawPtr, StructPtrType, name=ClassName) - members = Gen.class_members.get(ClassName, []) - defaults = Gen.class_member_defaults.get(ClassName, {}) - member_values = {} - for member_name, member_type in members: - if member_name in defaults: - member_values[member_name] = defaults[member_name] - if call_node.args: - for i, arg in enumerate(call_node.args): - if i < len(members): - member_name, _ = members[i] - val = self.HandleExprLlvm(arg) - if val: - member_values[member_name] = val - if call_node.keywords: - for kw in call_node.keywords: - val = self.HandleExprLlvm(kw.value) - if val: - member_values[kw.arg] = val - has_vtable = ClassName in Gen.class_vtable - base = 1 if has_vtable else 0 - for i, (member_name, member_type) in enumerate(members): - if isinstance(member_type, ir.VoidType): - continue - if member_name in member_values: - ElemPtr = Gen.builder.gep(StructPtr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), base + i)], name=f"{ClassName}_{member_name}") - try: - Gen._store(member_values[member_name], ElemPtr) - except Exception as _e: - if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": - self.Trans.LogWarning(f"异常被忽略: {_e}") - InitFuncName = f'{ClassName}.__init__' - if Gen._has_function(InitFuncName): - Args = [self.HandleExprLlvm(arg) for arg in call_node.args] - Args = [a for a in Args if a] - Gen.builder.call(Gen._get_function(InitFuncName), [StructPtr] + Args, name=f"call_{InitFuncName}") - - def _StoreOrStrCopy(self, VarName, VarPtr, Value): - Gen = self.Trans.LlvmGen - DestPtr = Gen._load(VarPtr, name=VarName) - if BaseHandle._is_char_pointer(DestPtr): - if BaseHandle._is_char_pointer(Value): - if 'strcpy' not in Gen.functions: - strcpy_type = ir.FunctionType(ir.PointerType(ir.IntType(8)), [ir.PointerType(ir.IntType(8)), ir.PointerType(ir.IntType(8))]) - Gen.functions['strcpy'] = ir.Function(Gen.module, strcpy_type, name='strcpy') - Gen.builder.call(Gen.functions['strcpy'], [DestPtr, Value]) - return - try: - CastedVal = Gen.builder.bitcast(Value, VarPtr.type.pointee, name=f"cast_{VarName}") - Gen._store(CastedVal, VarPtr) - except Exception: # 回退:bitcast 失败时 alloca 新变量 - NewVar = Gen._allocaEntry(Value.type, name=VarName) - Gen._store(Value, NewVar) - Gen.variables[VarName] = NewVar - - def _HandleAttributeStoreLlvm(self, Target, Value): - Gen = self.Trans.LlvmGen - AttrName = Target.attr - if isinstance(Target.value, ast.Name) and Target.value.id == 'self': - ClassName = self.Trans._CurrentCpythonObjectClass - if ClassName and ClassName in Gen.structs: - PropKey = f'{ClassName}.{AttrName}' - PropInfo = self.Trans.SymbolTable.lookup(PropKey) - if PropInfo and PropInfo.MetaList and FuncMeta.PROPERTY_SETTER in PropInfo.MetaList: - SelfVar = Gen._get_var_ptr('self') - if SelfVar: - SelfPtr = Gen._load(SelfVar, name="self") - SetterFunc = Gen._get_function(PropKey + '$set') - if SetterFunc and SelfPtr: - Gen.builder.call(SetterFunc, [SelfPtr, Value], name=f"prop_set_{PropKey}") - return - SelfVar = Gen._get_var_ptr('self') - if not SelfVar: - return - if SelfVar: - SelfPtr = Gen._load(SelfVar, name="self") - is_vtable_method = False - if ClassName in Gen.class_vtable or ClassName in Gen._cross_module_vtable_classes: - if ClassName in Gen.class_methods: - for mi, mn in enumerate(Gen.class_methods[ClassName]): - method_short = mn.split('.')[-1] if '.' in mn else mn - if method_short == AttrName or mn == AttrName: - is_vtable_method = True - method_idx = mi - break - if is_vtable_method: - VtableSlotPtr = Gen.builder.gep(SelfPtr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), 0)], name=f"vtable_slot_{ClassName}") - VtablePtr = Gen._load(VtableSlotPtr, name=f"vtable_ptr_{ClassName}") - methods = Gen.class_methods[ClassName] - VtableArrayType = ir.ArrayType(ir.PointerType(ir.IntType(8)), len(methods)) - ClassVtable = Gen.Vtables.get(ClassName) - if ClassVtable: - ClassVtableAddr = Gen.builder.bitcast(ClassVtable, ir.PointerType(ir.IntType(8)), name=f"class_vtable_addr_{ClassName}") - IsSameVtable = Gen.builder.icmp_unsigned('==', VtablePtr, ClassVtableAddr, name=f"is_same_vtable_{ClassName}") - CopyBlock = Gen.func.append_basic_block(name=f"vtable_copy_self_{AttrName}") - SkipBlock = Gen.func.append_basic_block(name=f"vtable_skip_self_{AttrName}") - Gen.builder.cbranch(IsSameVtable, CopyBlock, SkipBlock) - Gen.builder.position_at_end(CopyBlock) - if not hasattr(Gen, '_vtable_copy_counter'): - Gen._vtable_copy_counter = 0 - Gen._vtable_copy_counter += 1 - CopyName = f"{Gen._mangle_name(ClassName)}_vtable_copy_self_{Gen._vtable_copy_counter}" - VtableCopyGlobal = ir.GlobalVariable(Gen.module, VtableArrayType, name=CopyName) - VtableCopyGlobal.linkage = 'internal' - VtableCopyGlobal.initializer = ir.Constant(VtableArrayType, [ir.Constant(ir.PointerType(ir.IntType(8)), None)] * len(methods)) - VtableCopyTyped = Gen.builder.bitcast(VtableCopyGlobal, ir.PointerType(ir.IntType(8)), name=f"vtable_copy_typed") - SrcTyped = Gen.builder.bitcast(ClassVtable, ir.PointerType(ir.IntType(8)), name=f"src_vtable_typed") - VtableSize = len(methods) * Gen.ptr_size - MemcpyFunc = Gen._find_function('llvm.memcpy.p0i8.p0i8.i64') - if not MemcpyFunc: - MemcpyType = ir.FunctionType(ir.VoidType(), [ir.PointerType(ir.IntType(8)), ir.PointerType(ir.IntType(8)), ir.IntType(64), ir.IntType(1)]) - MemcpyFunc = ir.Function(Gen.module, MemcpyType, name='llvm.memcpy.p0i8.p0i8.i64') - Gen.functions['llvm.memcpy.p0i8.p0i8.i64'] = MemcpyFunc - Gen.builder.call(MemcpyFunc, [VtableCopyTyped, SrcTyped, ir.Constant(ir.IntType(64), VtableSize), ir.Constant(ir.IntType(1), 0)]) - VtableCopyGlobalAddr = Gen.builder.bitcast(VtableCopyGlobal, ir.PointerType(ir.IntType(8)), name=f"vtable_copy_addr") - Gen._store(VtableCopyGlobalAddr, VtableSlotPtr) - Gen.builder.branch(SkipBlock) - Gen.builder.position_at_end(SkipBlock) - VtablePtr = Gen._load(VtableSlotPtr, name=f"vtable_ptr_{ClassName}_after_copy") - VtableTyped = Gen.builder.bitcast(VtablePtr, ir.PointerType(VtableArrayType), name=f"vtable_typed_{ClassName}") - MethodPtrAddr = Gen.builder.gep(VtableTyped, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), method_idx)], name=f"vmethod_slot_{AttrName}") - FuncPtrI8 = Gen.builder.bitcast(Value, ir.PointerType(ir.IntType(8)), name=f"func_ptr_i8_{AttrName}") - Gen._store(FuncPtrI8, MethodPtrAddr) - return - offset = Gen._get_member_offset(AttrName, ClassName) - struct_type = Gen.structs[ClassName] - max_offset = len(struct_type.elements) if isinstance(struct_type, ir.IdentifiedStructType) else 0 - if offset >= max_offset: - VarName = f"self.{AttrName}" - if VarName not in Gen.variables: - NewVar = Gen._allocaEntry(Value.type, name=AttrName) - Gen.variables[VarName] = NewVar - Gen._store(Value, Gen.variables[VarName]) - return - MemberPtr = Gen.builder.gep(SelfPtr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=AttrName) - self._StoreWithCoerce(Value, MemberPtr) - elif isinstance(Target.value, ast.Name): - VarName = Target.value.id - ClassName = Gen.var_struct_class.get(VarName) - - if not ClassName and getattr(Gen, 'global_struct_class', None): - ClassName = Gen.global_struct_class.get(VarName) - if ClassName: - Gen.var_struct_class[VarName] = ClassName - - if not ClassName: - for CN in Gen.structs: - if VarName == CN.lower() or VarName.startswith(CN): - ClassName = CN - break - - if not ClassName and VarName in Gen.module.globals: - GVar = Gen.module.globals[VarName] - if isinstance(GVar.type, ir.PointerType) and isinstance(GVar.type.pointee, (ir.IdentifiedStructType, ir.LiteralStructType)): - found = Gen.find_struct_by_pointee(GVar.type.pointee) - if found: - ClassName = found[0] - Gen.var_struct_class[VarName] = ClassName - if getattr(Gen, 'global_struct_class', None): - Gen.global_struct_class[VarName] = ClassName - - if not ClassName and VarName in Gen.variables: - VarPtr = Gen.variables[VarName] - if isinstance(VarPtr.type, ir.PointerType): - pointee = VarPtr.type.pointee - if isinstance(pointee, ir.PointerType): - pointee = pointee.pointee - found = Gen.find_struct_by_pointee(pointee) - if found: - CN, ST = found - ClassName = CN - - IsUnion = False - TypeInfo = self.Trans.SymbolTable.lookup(ClassName) - if TypeInfo and TypeInfo.IsUnion: - IsUnion = True - - if ClassName and ClassName in Gen.structs: - PropKey = f'{ClassName}.{AttrName}' - PropInfo = self.Trans.SymbolTable.lookup(PropKey) - if PropInfo and PropInfo.MetaList and FuncMeta.PROPERTY_SETTER in PropInfo.MetaList: - ObjVal = self.Trans.ExprHandler.HandleExprLlvm(Target.value) - SetterFunc = Gen._get_function(PropKey + '$set') - if SetterFunc and ObjVal: - if isinstance(ObjVal.type, ir.PointerType) and isinstance(ObjVal.type.pointee, ir.PointerType): - ObjVal = Gen._load(ObjVal, name=f"Load_{ClassName}") - Gen.builder.call(SetterFunc, [ObjVal, Value], name=f"prop_set_{PropKey}") - return - ObjVal = self.Trans.ExprHandler.HandleExprLlvm(Target.value) - if ObjVal: - if BaseHandle._is_char_pointer(ObjVal): - ObjVal = Gen.builder.bitcast(ObjVal, ir.PointerType(Gen.structs[ClassName]), name=f"cast_{ClassName}") - if isinstance(ObjVal.type, ir.PointerType) and isinstance(ObjVal.type.pointee, ir.PointerType): - ObjVal = Gen._load(ObjVal, name=f"Load_{ClassName}") - if isinstance(ObjVal.type, ir.PointerType) and ObjVal.type.pointee == Gen.structs[ClassName]: - if IsUnion: - NestedStructName = f"{ClassName}_{AttrName}" - if NestedStructName in Gen.structs: - NestedStructType = Gen.structs[NestedStructName] - ObjVal = Gen.builder.bitcast(ObjVal, ir.PointerType(NestedStructType), name=f"cast_{NestedStructName}") - offset = Gen._get_member_offset(AttrName, NestedStructName) - if offset is not None and offset < len(NestedStructType.elements): - MemberPtr = Gen.builder.gep(ObjVal, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=AttrName) - self._StoreWithCoerce(Value, MemberPtr) - return - bitfield_offsets = Gen.class_member_bitoffsets.get(ClassName, {}) - if AttrName in bitfield_offsets: - self._store_bitfield_member(ObjVal, ClassName, AttrName, Value) - return - bitfields = Gen.class_member_bitfields.get(ClassName, {}) - if AttrName in bitfields and bitfields[AttrName] > 0: - if ClassName not in Gen.class_member_bitoffsets: - Gen.class_member_bitoffsets[ClassName] = {} - if AttrName not in Gen.class_member_bitoffsets[ClassName]: - bo = 0 - for bf_name, bf_width in bitfields.items(): - if bf_name == AttrName: - break - bo += bf_width - Gen.class_member_bitoffsets[ClassName][AttrName] = bo - self._store_bitfield_member(ObjVal, ClassName, AttrName, Value) - return - is_vtable_method = False - if ClassName in Gen.class_vtable or ClassName in Gen._cross_module_vtable_classes: - if ClassName in Gen.class_methods: - for mi, mn in enumerate(Gen.class_methods[ClassName]): - method_short = mn.split('.')[-1] if '.' in mn else mn - if method_short == AttrName or mn == AttrName: - is_vtable_method = True - method_idx = mi - break - if is_vtable_method: - VtableSlotPtr = Gen.builder.gep(ObjVal, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), 0)], name=f"vtable_slot_{ClassName}") - VtablePtr = Gen._load(VtableSlotPtr, name=f"vtable_ptr_{ClassName}") - methods = Gen.class_methods[ClassName] - VtableArrayType = ir.ArrayType(ir.PointerType(ir.IntType(8)), len(methods)) - ClassVtable = Gen.Vtables.get(ClassName) - if ClassVtable: - ClassVtableAddr = Gen.builder.bitcast(ClassVtable, ir.PointerType(ir.IntType(8)), name=f"class_vtable_addr_{ClassName}") - IsSameVtable = Gen.builder.icmp_unsigned('==', VtablePtr, ClassVtableAddr, name=f"is_same_vtable_{ClassName}") - CopyBlock = Gen.func.append_basic_block(name=f"vtable_copy_{AttrName}") - SkipBlock = Gen.func.append_basic_block(name=f"vtable_skip_{AttrName}") - Gen.builder.cbranch(IsSameVtable, CopyBlock, SkipBlock) - Gen.builder.position_at_end(CopyBlock) - if not hasattr(Gen, '_vtable_copy_counter'): - Gen._vtable_copy_counter = 0 - Gen._vtable_copy_counter += 1 - CopyName = f"{Gen._mangle_name(ClassName)}_vtable_copy_{Gen._vtable_copy_counter}" - VtableCopyGlobal = ir.GlobalVariable(Gen.module, VtableArrayType, name=CopyName) - VtableCopyGlobal.linkage = 'internal' - VtableCopyGlobal.initializer = ir.Constant(VtableArrayType, [ir.Constant(ir.PointerType(ir.IntType(8)), None)] * len(methods)) - VtableCopyTyped = Gen.builder.bitcast(VtableCopyGlobal, ir.PointerType(ir.IntType(8)), name=f"vtable_copy_typed") - SrcTyped = Gen.builder.bitcast(ClassVtable, ir.PointerType(ir.IntType(8)), name=f"src_vtable_typed") - VtableSize = len(methods) * Gen.ptr_size - MemcpyFunc = Gen._find_function('llvm.memcpy.p0i8.p0i8.i64') - if not MemcpyFunc: - MemcpyType = ir.FunctionType(ir.VoidType(), [ir.PointerType(ir.IntType(8)), ir.PointerType(ir.IntType(8)), ir.IntType(64), ir.IntType(1)]) - MemcpyFunc = ir.Function(Gen.module, MemcpyType, name='llvm.memcpy.p0i8.p0i8.i64') - Gen.functions['llvm.memcpy.p0i8.p0i8.i64'] = MemcpyFunc - Gen.builder.call(MemcpyFunc, [VtableCopyTyped, SrcTyped, ir.Constant(ir.IntType(64), VtableSize), ir.Constant(ir.IntType(1), 0)]) - VtableCopyGlobalAddr = Gen.builder.bitcast(VtableCopyGlobal, ir.PointerType(ir.IntType(8)), name=f"vtable_copy_addr") - Gen._store(VtableCopyGlobalAddr, VtableSlotPtr) - Gen.builder.branch(SkipBlock) - Gen.builder.position_at_end(SkipBlock) - VtablePtr = Gen._load(VtableSlotPtr, name=f"vtable_ptr_{ClassName}_after_copy") - VtableTyped = Gen.builder.bitcast(VtablePtr, ir.PointerType(VtableArrayType), name=f"vtable_typed_{ClassName}") - MethodPtrAddr = Gen.builder.gep(VtableTyped, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), method_idx)], name=f"vmethod_slot_{AttrName}") - FuncPtrI8 = Gen.builder.bitcast(Value, ir.PointerType(ir.IntType(8)), name=f"func_ptr_i8_{AttrName}") - Gen._store(FuncPtrI8, MethodPtrAddr) - return - offset = Gen._get_member_offset(AttrName, ClassName) - StructType = Gen.structs.get(ClassName) - if isinstance(StructType, ir.IdentifiedStructType) and (StructType.elements is None or len(StructType.elements) == 0): - self.Trans.ImportHandler._TryLoadStructFromStub(ClassName, Gen) - StructType = Gen.structs.get(ClassName) - if isinstance(StructType, ir.IdentifiedStructType) and (StructType.elements is None or len(StructType.elements) == 0): - return - if StructType is not None and StructType.elements is not None and isinstance(ObjVal.type, ir.PointerType) and isinstance(ObjVal.type.pointee, ir.IdentifiedStructType) and ObjVal.type.pointee.elements is None: - ObjVal = Gen.builder.bitcast(ObjVal, ir.PointerType(StructType), name=f"cast_{ClassName}") - if offset is not None and StructType is not None and StructType.elements is not None and offset < len(StructType.elements): - MemberPtr = Gen.builder.gep(ObjVal, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=AttrName) - else: - return - - byte_order = getattr(Gen, 'class_member_byteorders', {}).get(ClassName, {}).get(AttrName, "") - - if byte_order == 'big': - st = Gen.structs.get(ClassName) - if st is None or st.elements is None or len(st.elements) == 0: - return - member_type = st.elements[offset] - if isinstance(member_type, ir.IntType): - if member_type.width == 16: - Value = Gen.builder.bswap(Value, name=f"bswap_store_{AttrName}") - elif member_type.width == 32: - Value = Gen.builder.bswap(Value, name=f"bswap_store_{AttrName}") - elif member_type.width == 64: - Value = Gen.builder.bswap(Value, name=f"bswap_store_{AttrName}") - - self._StoreWithCoerce(Value, MemberPtr) - if not ClassName: - imported_modules = getattr(self.Trans, '_ImportedModules', None) - resolved_mod = self.Trans.SymbolTable.resolve_alias(VarName) - if imported_modules and (VarName in imported_modules or resolved_mod in imported_modules): - PossibleKeys = [f"{VarName}.{AttrName}", AttrName] - for mod_name in imported_modules: - if mod_name.endswith(f".{VarName}") or mod_name == VarName: - key = f"{mod_name}.{AttrName}" - if key not in PossibleKeys: - PossibleKeys.append(key) - for key in PossibleKeys: - if key in Gen.module.globals: - GVar = Gen.module.globals[key] - if isinstance(GVar, ir.Function): - return - if isinstance(GVar.type, ir.PointerType) and isinstance(GVar.type.pointee, (ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)): - return - self._StoreWithCoerce(Value, GVar) - return - ModuleSha1Map = getattr(Gen, 'ModuleSha1Map', {}) - sha1_candidates = [VarName, resolved_mod] - for mod_name in imported_modules: - if mod_name.endswith(f".{VarName}") or mod_name == VarName: - if mod_name not in sha1_candidates: - sha1_candidates.append(mod_name) - for cand in sha1_candidates: - sha1 = ModuleSha1Map.get(cand) - if sha1: - prefixed = f"{sha1}.{AttrName}" - if prefixed in Gen.module.globals: - GVar2 = Gen.module.globals[prefixed] - if isinstance(GVar2, ir.Function): - return - if isinstance(GVar2.type, ir.PointerType) and isinstance(GVar2.type.pointee, (ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)): - return - self._StoreWithCoerce(Value, GVar2) - return - elif isinstance(Target.value, ast.Attribute): - ObjVal = self.Trans.ExprHandler.HandleExprLlvm(Target.value) - if ObjVal and isinstance(ObjVal.type, ir.PointerType): - pointee = ObjVal.type.pointee - if isinstance(pointee, (ir.LiteralStructType, ir.IdentifiedStructType)): - if isinstance(pointee, ir.IdentifiedStructType) and pointee.elements is None: - for CN, ST in Gen.structs.items(): - if isinstance(ST, ir.IdentifiedStructType) and ST.name == pointee.name and ST.elements is not None: - pointee = ST - ObjVal = Gen.builder.bitcast(ObjVal, ir.PointerType(ST), name=f"cast_{CN}") - break - found_match = False - for CN, ST in Gen.structs.items(): - if pointee == ST or (isinstance(pointee, ir.IdentifiedStructType) and isinstance(ST, ir.IdentifiedStructType) and pointee.name == ST.name): - found_match = True - if ST.elements is None: - self.Trans.ImportHandler._TryLoadStructFromStub(CN, Gen) - ST = Gen.structs.get(CN, ST) - if ST.elements is not None and isinstance(ObjVal.type, ir.PointerType) and isinstance(ObjVal.type.pointee, ir.IdentifiedStructType) and ObjVal.type.pointee.elements is None: - ObjVal = Gen.builder.bitcast(ObjVal, ir.PointerType(ST), name=f"cast_{CN}") - bitfield_offsets = Gen.class_member_bitoffsets.get(CN, {}) - if AttrName in bitfield_offsets: - self._store_bitfield_member(ObjVal, CN, AttrName, Value) - return - offset = Gen._get_member_offset(AttrName, CN) - if offset is not None and ST.elements is not None and offset < len(ST.elements): - MemberPtr = Gen.builder.gep(ObjVal, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=AttrName) - self._StoreWithCoerce(Value, MemberPtr) - break - if not found_match: - if isinstance(pointee, ir.IdentifiedStructType): - matched_cn = None - for CN in Gen.class_members: - members = Gen.class_members[CN] - for mname, mtype in members: - if mname == AttrName: - matched_cn = CN - break - if matched_cn: - break - if matched_cn and matched_cn in Gen.structs: - ST = Gen.structs[matched_cn] - if isinstance(ST, ir.IdentifiedStructType) and (ST.elements is None or len(ST.elements) == 0): - self.Trans.ImportHandler._TryLoadStructFromStub(matched_cn, Gen) - ST = Gen.structs.get(matched_cn, ST) - if ST.elements is not None and isinstance(ObjVal.type, ir.PointerType) and isinstance(ObjVal.type.pointee, ir.IdentifiedStructType) and ObjVal.type.pointee.elements is None: - ObjVal = Gen.builder.bitcast(ObjVal, ir.PointerType(ST), name=f"cast_{matched_cn}") - offset = Gen._get_member_offset(AttrName, matched_cn) - if offset is not None and ST.elements is not None and offset < len(ST.elements): - MemberPtr = Gen.builder.gep(ObjVal, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=AttrName) - self._StoreWithCoerce(Value, MemberPtr) - return - elif isinstance(Target.value, ast.Call): - # Check if this is c.Deref(...) — we need the pointer, not the Loaded value - ObjVal = None - is_cderef = (isinstance(Target.value.func, ast.Attribute) and - isinstance(Target.value.func.value, ast.Name) and - Target.value.func.value.id == 'c' and - Target.value.func.attr == 'Deref' and - Target.value.args) - if is_cderef: - # Get the pointer from c.Deref argument, don't Load the value - deref_arg = Target.value.args[0] - inner_val = self.HandleExprLlvm(deref_arg) - if inner_val and isinstance(inner_val.type, ir.PointerType): - if isinstance(inner_val.type.pointee, ir.PointerType): - ObjVal = Gen._load(inner_val, name="deref_load_ptr") - else: - ObjVal = inner_val - if ObjVal is None: - ObjVal = self.Trans.ExprHandler.HandleExprLlvm(Target.value) - if ObjVal and isinstance(ObjVal.type, ir.PointerType): - pointee = ObjVal.type.pointee - if isinstance(pointee, ir.PointerType): - ObjVal = Gen._load(ObjVal, name="load_ptr_for_attr") - pointee = ObjVal.type.pointee - for CN, ST in Gen.structs.items(): - if pointee == ST or (isinstance(pointee, ir.IdentifiedStructType) and isinstance(ST, ir.IdentifiedStructType) and pointee.name == ST.name): - if isinstance(ST, ir.IdentifiedStructType) and (ST.elements is None or len(ST.elements) == 0): - self.Trans.ImportHandler._TryLoadStructFromStub(CN, Gen) - ST = Gen.structs.get(CN, ST) - if ST.elements is not None and isinstance(ObjVal.type, ir.PointerType) and isinstance(ObjVal.type.pointee, ir.IdentifiedStructType) and ObjVal.type.pointee.elements is None: - ObjVal = Gen.builder.bitcast(ObjVal, ir.PointerType(ST), name=f"cast_{CN}") - bitfield_offsets = Gen.class_member_bitoffsets.get(CN, {}) - if AttrName in bitfield_offsets: - self._store_bitfield_member(ObjVal, CN, AttrName, Value) - return - offset = Gen._get_member_offset(AttrName, CN) - if offset is not None and ST.elements is not None and offset < len(ST.elements): - MemberPtr = Gen.builder.gep(ObjVal, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=AttrName) - self._StoreWithCoerce(Value, MemberPtr) - break - elif isinstance(Target.value, ast.Subscript): - SubPtr = self.Trans.ExprAttrHandle.HandleSubscriptPtrLlvm(Target.value) - if SubPtr and isinstance(SubPtr.type, ir.PointerType): - pointee = SubPtr.type.pointee - - if isinstance(Target.value.value, ast.Attribute): - AttrNameSub = Target.value.value.attr - if AttrNameSub == 'items' and 'Item' in Gen.structs: - ObjValCast = Gen.builder.bitcast(SubPtr, ir.PointerType(Gen.structs['Item']), name=f"cast_Item") - offset = Gen._get_member_offset(AttrName, 'Item') - MemberPtr = Gen.builder.gep(ObjValCast, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=AttrName) - self._StoreWithCoerce(Value, MemberPtr) - return - - if BaseHandle._is_char_pointer(SubPtr): - for CN, ST in Gen.structs.items(): - ObjValCast = Gen.builder.bitcast(SubPtr, ir.PointerType(ST), name=f"cast_{CN}") - offset = Gen._get_member_offset(AttrName, CN) - MemberPtr = Gen.builder.gep(ObjValCast, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=AttrName) - self._StoreWithCoerce(Value, MemberPtr) - break - elif isinstance(pointee, (ir.LiteralStructType, ir.IdentifiedStructType)): - found = Gen.find_struct_by_pointee(pointee) - if found: - CN, ST = found - if isinstance(ST, ir.IdentifiedStructType) and (ST.elements is None or len(ST.elements) == 0): - self.Trans.ImportHandler._TryLoadStructFromStub(CN, Gen) - ST = Gen.structs.get(CN, ST) - if ST.elements is not None and isinstance(SubPtr.type, ir.PointerType) and isinstance(SubPtr.type.pointee, ir.IdentifiedStructType) and SubPtr.type.pointee.elements is None: - SubPtr = Gen.builder.bitcast(SubPtr, ir.PointerType(ST), name=f"cast_{CN}") - offset = Gen._get_member_offset(AttrName, CN) - if offset is not None and ST.elements is not None and offset < len(ST.elements): - MemberPtr = Gen.builder.gep(SubPtr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=AttrName) - self._StoreWithCoerce(Value, MemberPtr) - elif isinstance(pointee, ir.PointerType): - LoadedPtr = Gen._load(SubPtr, name=f"Load_{AttrName}_ptr") - if isinstance(LoadedPtr.type, ir.PointerType) and isinstance(LoadedPtr.type.pointee, (ir.IdentifiedStructType, ir.LiteralStructType)): - found = Gen.find_struct_by_pointee(LoadedPtr.type.pointee) - if found: - CN, ST = found - offset = Gen._get_member_offset(AttrName, CN) - MemberPtr = Gen.builder.gep(LoadedPtr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=AttrName) - self._StoreWithCoerce(Value, MemberPtr) - - def _HandleSubscriptStoreLlvm(self, Target, Value): - Gen = self.Trans.LlvmGen - if isinstance(Target.value, ast.Name): - SubVarName = Target.value.id - if SubVarName in Gen.var_const_flags: - src_info = Gen._get_node_info() - self.Trans.LogError(f"不能对 const 变量 '{SubVarName}' 的元素赋值{src_info}") - ClassName = self.Trans.ExprHandler._get_var_class(Target.value, Gen) - if ClassName and Gen._has_function(f'{ClassName}.__setitem__'): - obj_val = self.Trans.ExprHandler.HandleExprLlvm(Target.value) - idx_val = self.Trans.ExprHandler.HandleExprLlvm(Target.slice) - if obj_val and idx_val: - if BaseHandle._is_char_pointer(obj_val): - obj_val = Gen.builder.bitcast(obj_val, ir.PointerType(Gen.structs[ClassName]), name=f"cast_{ClassName}") - Gen.builder.call(Gen._get_function(f'{ClassName}.__setitem__'), [obj_val, idx_val, Value], name=f"call_{ClassName}.__setitem__") - return - ValueVal = self.HandleExprLlvm(Target.value) - IndexVal = self.HandleExprLlvm(Target.slice) - if not ValueVal or not IndexVal: - return - if BaseHandle._is_char_pointer(IndexVal): - Loaded_byte = Gen._load(IndexVal, name="Load_char_idx_store") - IndexVal = Gen.builder.zext(Loaded_byte, ir.IntType(32), name="char_to_int_idx_store") - if isinstance(ValueVal.type, ir.IntType): - var_ptr = self._get_int_ptr(Target.value) - if var_ptr: - i8_ptr = Gen.builder.bitcast(var_ptr, ir.PointerType(ir.IntType(8)), name="int_to_i8ptr_store") - if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width < 64: - IndexVal = Gen.builder.zext(IndexVal, ir.IntType(64), name="zext_int_index_store") - ptr = Gen.builder.gep(i8_ptr, [IndexVal], name="int_subscript_ptr_store") - self._StoreWithCoerce(Value, ptr) - return - if isinstance(ValueVal.type, ir.PointerType) and isinstance(ValueVal.type.pointee, ir.PointerType): - if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width < 64: - IndexVal = Gen.builder.zext(IndexVal, ir.IntType(64), name="zext_ptr_index_store") - ElemPtr = Gen.builder.gep(ValueVal, [IndexVal], name="subscript") - self._StoreWithCoerce(Value, ElemPtr) - return - if isinstance(ValueVal.type, ir.PointerType): - pointee = ValueVal.type.pointee - if isinstance(pointee, ir.ArrayType): - zero = ir.Constant(ir.IntType(32), 0) - if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width != 32: - if IndexVal.type.width < 32: - IndexVal = Gen.builder.zext(IndexVal, ir.IntType(32), name="zext_arr_index") - else: - IndexVal = Gen.builder.trunc(IndexVal, ir.IntType(32), name="trunc_arr_index") - ElemPtr = Gen.builder.gep(ValueVal, [zero, IndexVal], name="subscript") - else: - ElemPtr = Gen.builder.gep(ValueVal, [IndexVal], name="subscript") - self._StoreWithCoerce(Value, ElemPtr) - elif isinstance(ValueVal.type, ir.ArrayType): - zero = ir.Constant(ir.IntType(32), 0) - if isinstance(Target.value, ast.Name): - VarName = Target.value.id - if VarName in Gen.variables and Gen.variables[VarName] is not None: - VarPtr = Gen.variables[VarName] - if isinstance(VarPtr.type, ir.PointerType) and isinstance(VarPtr.type.pointee, ir.ArrayType): - if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width != 32: - if IndexVal.type.width < 32: - IndexVal = Gen.builder.zext(IndexVal, ir.IntType(32), name="zext_arr_index") - else: - IndexVal = Gen.builder.trunc(IndexVal, ir.IntType(32), name="trunc_arr_index") - ElemPtr = Gen.builder.gep(VarPtr, [zero, IndexVal], name="subscript") - self._StoreWithCoerce(Value, ElemPtr) - return - if isinstance(Target.value, ast.Subscript): - InnerPtr = self.Trans.ExprAttrHandle.HandleSubscriptPtrLlvm(Target.value) - if InnerPtr: - if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width != 32: - if IndexVal.type.width < 32: - IndexVal = Gen.builder.zext(IndexVal, ir.IntType(32), name="zext_arr_index") - else: - IndexVal = Gen.builder.trunc(IndexVal, ir.IntType(32), name="trunc_arr_index") - ElemPtr = Gen.builder.gep(InnerPtr, [zero, IndexVal], name="subscript") - self._StoreWithCoerce(Value, ElemPtr) - return - if isinstance(Target.value, ast.Attribute): - AttrPtr = self.Trans.ExprAttrHandle._get_attr_ptr(Target.value) - if AttrPtr and isinstance(AttrPtr.type, ir.PointerType) and isinstance(AttrPtr.type.pointee, ir.ArrayType): - if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width != 32: - if IndexVal.type.width < 32: - IndexVal = Gen.builder.zext(IndexVal, ir.IntType(32), name="zext_arr_index") - else: - IndexVal = Gen.builder.trunc(IndexVal, ir.IntType(32), name="trunc_arr_index") - ElemPtr = Gen.builder.gep(AttrPtr, [zero, IndexVal], name="subscript") - self._StoreWithCoerce(Value, ElemPtr) - return - arr_alloc = Gen._allocaEntry(ValueVal.type, name="arr_subscript_tmp") - Gen._store(ValueVal, arr_alloc) - ElemPtr = Gen.builder.gep(arr_alloc, [zero, IndexVal], name="subscript") - self._StoreWithCoerce(Value, ElemPtr) - ModifiedArr = Gen._load(arr_alloc, name="modified_arr") - if isinstance(Target.value, ast.Subscript): - OuterPtr = self.Trans.ExprAttrHandle.HandleSubscriptPtrLlvm(Target.value) - if OuterPtr: - Gen._store(ModifiedArr, OuterPtr) - elif isinstance(Target.value, ast.Attribute): - OuterPtr = self.Trans.ExprAttrHandle._get_attr_ptr(Target.value) - if OuterPtr: - Gen._store(ModifiedArr, OuterPtr) - - def _StoreWithCoerce(self, Value, Ptr): - Gen = self.Trans.LlvmGen - if isinstance(Ptr.type, ir.PointerType): - TargetType = Ptr.type.pointee - if Value.type != TargetType: - if isinstance(TargetType, ir.ArrayType) and isinstance(Value.type, ir.PointerType): - ElemType = TargetType.element - ElemSize = Gen._get_struct_size(ElemType) - for i in range(TargetType.count): - DstElem = Gen.builder.gep(Ptr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), i)], name=f"arr_dst_{i}") - if ElemSize == 1: - SrcPtr = Gen.builder.gep(Value, [ir.Constant(ir.IntType(32), i)], name=f"arr_src_{i}") - else: - PtrInt = Gen.builder.ptrtoint(Value, ir.IntType(64)) - Offset = ir.Constant(ir.IntType(64), i * ElemSize) - NewPtrInt = Gen.builder.add(PtrInt, Offset) - SrcPtr = Gen.builder.inttoptr(NewPtrInt, ir.PointerType(ElemType), name=f"arr_src_{i}") - SrcVal = Gen._load(SrcPtr, name=f"arr_elem_{i}") - if SrcVal.type != ElemType: - try: - SrcVal = Gen.builder.bitcast(SrcVal, ElemType, name=f"arr_cast_{i}") - except Exception: # 回退:bitcast 失败时跳过该元素 - continue - Gen._store(SrcVal, DstElem) - return - if isinstance(TargetType, ir.PointerType) and isinstance(Value, ir.Constant) and Value.constant is None: - Value = ir.Constant(TargetType, None) - elif isinstance(TargetType, ir.PointerType) and isinstance(Value.type, ir.PointerType): - try: - Value = Gen.builder.bitcast(Value, TargetType, name="null_ptr_bitcast") - except Exception: # 回退:bitcast 失败时设为 null 常量 - Value = ir.Constant(TargetType, None) - else: - Coerced = Gen._coerce_value(Value, TargetType) - if Coerced is not None: - Value = Coerced - Gen._store(Value, Ptr) - - - def _get_int_ptr(self, target): - Gen = self.Trans.LlvmGen - if isinstance(target, ast.Name): - VarName = target.id - if VarName in Gen.variables and Gen.variables[VarName] is not None: - VarPtr = Gen.variables[VarName] - if isinstance(VarPtr.type, ir.PointerType): - pointee = VarPtr.type.pointee - if isinstance(pointee, ir.ArrayType): - return Gen.builder.gep(VarPtr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), 0)], name=f"arr_start_{VarName}") - return None - - def _EmitGlobalAnnAssignLlvm(self, Node, Gen): - if isinstance(Node.target, ast.Name): - VarName = Node.target.id - EffectiveAnnotation = Node.annotation - if self.Trans.SymbolTable.has(VarName): - Info = self.Trans.SymbolTable[VarName] - if Info.get('type') == 'typedef': - return - if isinstance(EffectiveAnnotation, ast.BinOp) and isinstance(EffectiveAnnotation.op, ast.BitOr): - for side in [EffectiveAnnotation.left, EffectiveAnnotation.right]: - if isinstance(side, ast.Subscript) and isinstance(side.value, ast.Name) and side.value.id == 'list': - EffectiveAnnotation = side - break - if isinstance(EffectiveAnnotation, ast.Subscript) and isinstance(EffectiveAnnotation.value, ast.Name) and EffectiveAnnotation.value.id == 'list': - slice_node = EffectiveAnnotation.slice - if isinstance(slice_node, ast.Tuple) and len(slice_node.elts) == 2: - elem_type_node = slice_node.elts[0] - count_node = slice_node.elts[1] - if isinstance(elem_type_node, ast.Name) and elem_type_node.id in Gen.structs: - SymEntry = self.Trans.SymbolTable.lookup(elem_type_node.id) - if SymEntry and isinstance(SymEntry, CTypeInfo) and SymEntry.IsFuncPtr: - ElemType = ir.IntType(8).as_pointer() - else: - ElemType = Gen.structs[elem_type_node.id] - else: - ElemTypeInfo = CTypeInfo.FromNode(elem_type_node, self.Trans.SymbolTable) - if ElemTypeInfo and ElemTypeInfo.IsFuncPtr: - ElemType = ir.IntType(8).as_pointer() - else: - if ElemTypeInfo is None: - ElemTypeInfo = CTypeInfo() - ElemTypeInfo.BaseType = t.CInt() - ElemType = Gen._ctype_to_llvm(ElemTypeInfo) - if isinstance(ElemType, ir.VoidType): - ElemType = ir.IntType(32) - ArrayCount = 1 - if isinstance(count_node, ast.Constant) and isinstance(count_node.value, int): - ArrayCount = count_node.value - elif isinstance(count_node, ast.Name): - if self.Trans.SymbolTable.has(count_node.id): - SymInfo = self.Trans.SymbolTable[count_node.id] - if isinstance(SymInfo.value, int): - ArrayCount = SymInfo.value - if ArrayCount == 1 and count_node.id in getattr(Gen, '_define_constants', {}): - DefVal = Gen._define_constants[count_node.id] - if isinstance(DefVal, int): - ArrayCount = DefVal - elif isinstance(count_node, ast.Attribute): - ev = self._eval_global_count(count_node, Gen) - if ev is not None: - ArrayCount = ev - elif isinstance(count_node, ast.BinOp): - ev = self._eval_global_count(count_node, Gen) - if ev is not None: - ArrayCount = ev - elif count_node is None or (isinstance(count_node, ast.Constant) and count_node.value is None): - if Node.value and isinstance(Node.value, ast.List): - ArrayCount = len(Node.value.elts) - elif Node.value and isinstance(Node.value, ast.Constant) and isinstance(Node.value.value, str): - ArrayCount = len(Node.value.value) + 1 - VarType = ir.ArrayType(ElemType, ArrayCount) - if VarName not in Gen.variables and VarName not in Gen.module.globals: - GlobalVar = ir.GlobalVariable(Gen.module, VarType, name=VarName) - if isinstance(ElemType, ir.IdentifiedStructType): - GlobalVar.linkage = 'common' - elif Node.value and isinstance(Node.value, ast.Constant) and isinstance(Node.value.value, str): - str_val = Node.value.value + '\x00' - str_bytes = bytearray(str_val, 'utf-8') - if len(str_bytes) < ArrayCount: - str_bytes.extend(b'\x00' * (ArrayCount - len(str_bytes))) - try: - GlobalVar.initializer = ir.Constant(VarType, str_bytes[:ArrayCount]) - except Exception: # 回退:初始化常量失败时用零值 - GlobalVar.initializer = self._zero_value(VarType) - else: - InitConstants = self.Trans._BuildArrayInitConstants(Node.value, ElemType, elem_type_node, ArrayCount, Gen) - if InitConstants: - GlobalVar.initializer = ir.Constant(VarType, InitConstants) - elif ArrayCount > 256: - GlobalVar.linkage = 'common' - else: - if self._contains_identified_struct(VarType): - GlobalVar.linkage = 'common' - else: - GlobalVar.initializer = ir.Constant(VarType, [ir.Constant(ElemType, ir.Undefined)] * ArrayCount) - Gen.variables[VarName] = GlobalVar - if isinstance(elem_type_node, ast.Name) and elem_type_node.id in Gen.structs: - Gen.global_struct_class[VarName] = elem_type_node.id - return - if isinstance(EffectiveAnnotation, ast.Subscript) and isinstance(EffectiveAnnotation.value, ast.Name) and EffectiveAnnotation.value.id == 'list': - slice_node = EffectiveAnnotation.slice - elem_type_node = slice_node - if isinstance(elem_type_node, ast.Name) and elem_type_node.id in Gen.structs: - ElemType = Gen.structs[elem_type_node.id] - else: - ElemTypeInfo = CTypeInfo.FromNode(elem_type_node, self.Trans.SymbolTable) - if ElemTypeInfo is None: - ElemTypeInfo = CTypeInfo() - ElemTypeInfo.BaseType = t.CInt() - ElemType = Gen._ctype_to_llvm(ElemTypeInfo) - if isinstance(ElemType, ir.VoidType): - ElemType = ir.IntType(32) - VarType = ir.PointerType(ElemType) - if VarName not in Gen.variables and VarName not in Gen.module.globals: - GlobalVar = ir.GlobalVariable(Gen.module, VarType, name=VarName) - GlobalVar.initializer = ir.Constant(VarType, None) - Gen.variables[VarName] = GlobalVar - if isinstance(elem_type_node, ast.Name) and elem_type_node.id in Gen.structs: - Gen.global_struct_class[VarName] = elem_type_node.id - return - if isinstance(Node.annotation, ast.Name) and Node.annotation.id in Gen.structs: - StructName = Node.annotation.id - VarType = Gen.structs[StructName] - if VarName not in Gen.variables and VarName not in Gen.module.globals: - GlobalVar = ir.GlobalVariable(Gen.module, VarType, name=VarName) - if Node.value and isinstance(Node.value, ast.Call) and isinstance(Node.value.func, ast.Name) and Node.value.func.id == StructName: - const = self.Trans.ClassHandler._BuildStructConstant(Node.value, StructName, Gen) - if const: - GlobalVar.initializer = const - else: - GlobalVar.initializer = ir.Constant(VarType, None) - else: - GlobalVar.initializer = ir.Constant(VarType, None) - Gen.variables[VarName] = GlobalVar - Gen.global_struct_class[VarName] = StructName - return - TypeInfo = CTypeInfo.FromNode(Node.annotation, self.Trans.SymbolTable) - if not TypeInfo or not TypeInfo.BaseType: - ArrayTypeInfo = CTypeInfo._HandleArraySubscript(Node.annotation, self.Trans.SymbolTable) - if ArrayTypeInfo: - TypeInfo = ArrayTypeInfo - IsCDefine = False - if TypeInfo and TypeInfo.BaseType: - if isinstance(TypeInfo.BaseType, t._CTypedef): - return - if isinstance(TypeInfo.BaseType, t.CDefine): - IsCDefine = True - if not IsCDefine and self._IsTypedefAnnotation(Node.annotation): - IsCDefine = True - TTypeInfo = self.Trans.TypeMergeHandler.GetCTypeInfo(Node.annotation) - if TTypeInfo: - TTypeInfo.IsTypedef = True - TTypeInfo.Name = VarName - self.Trans.SymbolTable.insert(VarName, TTypeInfo) - if IsCDefine: - if Node.value: - define_constants = vars(Gen).setdefault('_define_constants', {}) - try: - const_value = self._eval_const_expr(Node.value, Gen) - if const_value is not None: - define_constants[VarName] = const_value - except Exception as _e: - if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": - self.Trans.LogWarning(f"异常被忽略: {_e}") - return - if TypeInfo is None: - TypeInfo = CTypeInfo() - TypeInfo.BaseType = t.CInt() - VarType = Gen._ctype_to_llvm(TypeInfo) - if isinstance(VarType, ir.VoidType): - VarType = ir.IntType(32) - if VarName in Gen.variables or VarName in Gen.module.globals: - return - if isinstance(VarType, (ir.IdentifiedStructType, ir.LiteralStructType)): - GlobalVar = ir.GlobalVariable(Gen.module, VarType, name=VarName) - GlobalVar.initializer = ir.Constant(VarType, None) - Gen.variables[VarName] = GlobalVar - if TypeInfo and TypeInfo.IsStruct and TypeInfo.Name: - Gen.global_struct_class[VarName] = TypeInfo.Name - return - GlobalVar = ir.GlobalVariable(Gen.module, VarType, name=VarName) - if Node.value: - if isinstance(Node.value, ast.Constant) and isinstance(Node.value.value, str) and isinstance(VarType, ir.PointerType): - str_val = Node.value.value + '\x00' - str_bytes = str_val.encode('utf-8') - arr_type = ir.ArrayType(ir.IntType(8), len(str_bytes)) - str_gv_name = VarName + '_str' - if str_gv_name not in Gen.module.globals: - str_gv = ir.GlobalVariable(Gen.module, arr_type, name=str_gv_name) - str_gv.initializer = ir.Constant(arr_type, bytearray(str_bytes)) - str_gv.linkage = 'internal' - else: - str_gv = Gen.module.globals[str_gv_name] - ptr_type = ir.PointerType(ir.IntType(8)) - if VarName not in Gen.module.globals: - ptr_gv = ir.GlobalVariable(Gen.module, ptr_type, name=VarName) - ptr_gv.initializer = ir.Constant(ptr_type, str_gv) - ptr_gv.linkage = 'internal' - else: - ptr_gv = Gen.module.globals[VarName] - Gen.variables[VarName] = ptr_gv - else: - if isinstance(VarType, ir.ArrayType) and isinstance(Node.value, (ast.List, ast.Set)): - InitConstants = self.Trans._BuildMultiDimArrayInitConstants(Node.value, VarType, Gen) - if InitConstants: - GlobalVar.initializer = ir.Constant(VarType, InitConstants) - else: - if self._contains_identified_struct(VarType): - GlobalVar.linkage = 'common' - else: - zv = self._zero_value(VarType) - if zv: - GlobalVar.initializer = zv - else: - GlobalVar.linkage = 'common' - else: - init_val = self._eval_global_const(Node.value, VarType, Gen) - if init_val: - GlobalVar.initializer = init_val - elif isinstance(VarType, ir.BaseStructType): - GlobalVar.linkage = 'common' - else: - GlobalVar.initializer = self._zero_value(VarType) - else: - if isinstance(VarType, ir.BaseStructType) or self._contains_identified_struct(VarType): - GlobalVar.linkage = 'common' - else: - GlobalVar.initializer = self._zero_value(VarType) - Gen.variables[VarName] = GlobalVar - - def _eval_global_const(self, value_node, var_type, Gen): - if isinstance(value_node, ast.Constant): - if isinstance(value_node.value, bool): - if isinstance(var_type, ir.IntType): - return ir.Constant(var_type, int(value_node.value)) - elif isinstance(value_node.value, int): - if isinstance(var_type, ir.IntType): - return ir.Constant(var_type, value_node.value) - elif isinstance(var_type, (ir.FloatType, ir.DoubleType)): - return ir.Constant(var_type, float(value_node.value)) - elif isinstance(value_node.value, float): - if isinstance(var_type, (ir.FloatType, ir.DoubleType)): - return ir.Constant(var_type, value_node.value) - elif isinstance(var_type, ir.IntType): - return ir.Constant(var_type, int(value_node.value)) - elif isinstance(value_node.value, str): - return None - # Handle type constructor calls like t.CDouble(1e-9), t.CFloat(3.14), t.CInt(42) - if isinstance(value_node, ast.Call): - inner_val = self._eval_type_ctor_const(value_node, var_type, Gen) - if inner_val is not None: - return inner_val - if isinstance(value_node, ast.UnaryOp) and isinstance(value_node.op, ast.USub): - inner = self._eval_global_const(value_node.operand, var_type, Gen) - if inner: - return ir.Constant(var_type, -inner.constant) - return None - - def _eval_type_ctor_const(self, call_node, var_type, Gen): - """Try to evaluate t.CDouble(val), t.CFloat(val), t.CInt(val) etc. as a compile-time constant.""" - if not isinstance(call_node.func, ast.Attribute): - return None - if not isinstance(call_node.func.value, ast.Name): - return None - if call_node.func.value.id != 't': - return None - if not call_node.args or len(call_node.args) != 1: - return None - arg = call_node.args[0] - # Recursively evaluate the argument as a constant - arg_val = self._eval_global_const(arg, var_type, Gen) - if arg_val is not None: - return arg_val - return None - - def _store_bitfield_member(self, struct_ptr, ClassName, field_name, Value): - Gen = self.Trans.LlvmGen - bitfield_offsets = Gen.class_member_bitoffsets.get(ClassName, {}) - bitfield_widths = Gen.class_member_bitfields.get(ClassName, {}) - if field_name not in bitfield_offsets: - return False - bit_offset = bitfield_offsets[field_name] - bit_width = bitfield_widths.get(field_name, 0) - if bit_width == 0: - return False - struct_type = Gen.structs.get(ClassName) - if struct_type is None or struct_type.elements is None or len(struct_type.elements) == 0: - return False - storage_type = struct_type.elements[0] - member_ptr = Gen.builder.gep(struct_ptr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), 0)], name=f"{field_name}_storage_ptr") - old_val = Gen._load(member_ptr, name=f"{field_name}_old_storage") - mask = (1 << bit_width) - 1 - shifted_mask = mask << bit_offset - inverted_mask = ir.Constant(storage_type, ~shifted_mask & ((1 << storage_type.width) - 1)) - cleared = Gen.builder.and_(old_val, inverted_mask, name=f"{field_name}_cleared") - if isinstance(Value.type, ir.IntType) and Value.type.width < storage_type.width: - if getattr(Value.type, 'is_signed', False): - Value = Gen.builder.sext(Value, storage_type, name=f"{field_name}_sext_store") - else: - Value = Gen.builder.zext(Value, storage_type, name=f"{field_name}_zext_store") - elif Value.type.width != storage_type.width: - Value = Gen.builder.trunc(Value, storage_type, name=f"{field_name}_trunc_store") if Value.type.width > storage_type.width else Gen.builder.zext(Value, storage_type, name=f"{field_name}_zext_store") - shifted_value = Gen.builder.shl(Value, ir.Constant(storage_type, bit_offset), name=f"{field_name}_shift_store") - masked_value = Gen.builder.and_(shifted_value, ir.Constant(storage_type, shifted_mask), name=f"{field_name}_mask_store") - new_val = Gen.builder.or_(cleared, masked_value, name=f"{field_name}_new_storage") - Gen._store(new_val, member_ptr) - return True - - def _CheckEnumMemberAssignment(self, node): - def _get_attr_path(n): - if isinstance(n, ast.Name): - return n.id - elif isinstance(n, ast.Attribute): - return f"{_get_attr_path(n.value)}.{n.attr}" - return None - attr_path = _get_attr_path(node) - if not attr_path: - return None - parts = attr_path.split('.') - if len(parts) >= 2: - enum_class_name = parts[-2] - member_name = parts[-1] - qualified_name = f"{enum_class_name}.{member_name}" - if self.Trans.SymbolTable.has(qualified_name): - info = self.Trans.SymbolTable[qualified_name] - if info.IsEnumMember and info.EnumName: - return info.EnumName - under_name = f"{enum_class_name}_{member_name}" - if self.Trans.SymbolTable.has(under_name): - info = self.Trans.SymbolTable[under_name] - if info.IsEnumMember and info.EnumName: - return info.EnumName - for key in self.Trans.SymbolTable: - if key == member_name: - info = self.Trans.SymbolTable[key] - if info.IsEnumMember and info.EnumName and info.EnumName == enum_class_name: - return enum_class_name - return None - - def _IsTypedefAnnotation(self, annotation): - if isinstance(annotation, ast.Attribute): - if annotation.attr in ('CTypedef', 'CDefine'): - return True - if isinstance(annotation, ast.BinOp) and isinstance(annotation.op, ast.BitOr): - return self._IsTypedefAnnotation(annotation.left) or self._IsTypedefAnnotation(annotation.right) - if isinstance(annotation, ast.Subscript): - return self._IsTypedefAnnotation(annotation.value) - return False - - def _EmitGlobalAssignLlvm(self, Node, Gen): - if len(Node.targets) == 1 and isinstance(Node.targets[0], ast.Name): - VarName = Node.targets[0].id - if VarName in Gen.variables or VarName in Gen.module.globals: - return - if isinstance(Node.value, ast.Call) and isinstance(Node.value.func, ast.Name): - FuncName = Node.value.func.id - if FuncName in Gen.structs: - IsUnion = False - if self.Trans.SymbolTable.has(FuncName): - TypeInfo = self.Trans.SymbolTable[FuncName] - if TypeInfo.IsUnion: - IsUnion = True - if IsUnion: - StructType = Gen.structs[FuncName] - StructPtrType = ir.PointerType(StructType) - GlobalVar = ir.GlobalVariable(Gen.module, StructPtrType, name=VarName) - GlobalVar.initializer = ir.Constant(StructPtrType, None) - Gen.variables[VarName] = GlobalVar - Gen.global_struct_class[VarName] = FuncName - return - StructName = FuncName - VarType = Gen.structs[StructName] - GlobalVar = ir.GlobalVariable(Gen.module, VarType, name=VarName) - const = self.Trans.ClassHandler._BuildStructConstant(Node.value, StructName, Gen) - if const: - GlobalVar.initializer = const - else: - GlobalVar.linkage = 'common' - Gen.variables[VarName] = GlobalVar - Gen.global_struct_class[VarName] = StructName - return - GlobalVar = ir.GlobalVariable(Gen.module, ir.IntType(32), name=VarName) - init_val = self._eval_global_const(Node.value, ir.IntType(32), Gen) - GlobalVar.initializer = init_val if init_val else ir.Constant(ir.IntType(32), 0) - Gen.variables[VarName] = GlobalVar - - def _eval_const_expr(self, node, Gen): - """计算常量表达式的值(委托到 ConstEvaluator)""" - from lib.core.ConstEvaluator import ConstEvaluator, EvalContext - ctx = EvalContext(Gen=Gen, symtab=self.Trans.SymbolTable) - return ConstEvaluator.eval_full(node, ctx) - - def _eval_global_count(self, node, Gen): - val = self._eval_const_expr(node, Gen) - if val is not None: - if isinstance(val, float): - return int(val) - if isinstance(val, int): - return val - return None +from __future__ import annotations +from typing import TYPE_CHECKING, Any +if TYPE_CHECKING: + from lib.core.translator import Translator +import ast +import sys +import llvmlite.ir as ir +from lib.core.Handles.HandlesBase import BaseHandle, CTypeInfo, FuncMeta +from lib.core.VLogger import get_logger as _vlog +from lib.core.ConstEvaluator import ConstEvaluator, EvalContext +from lib.constants.config import mode as _config_mode +from lib.includes import t +from lib.includes.t import CTypeRegistry +from lib.core.SymbolUtils import IsTModule, ParseListAnnotation + +class AssignHandle(BaseHandle): + def __init__(self, translator: "Translator") -> None: + super().__init__(translator) + self._CurrentCpythonObjectClass: str | None = None + + @staticmethod + def _contains_identified_struct(var_type: ir.Type) -> bool: + if isinstance(var_type, ir.IdentifiedStructType): + return True + if isinstance(var_type, ir.ArrayType): + return AssignHandle._contains_identified_struct(var_type.element) + if isinstance(var_type, ir.PointerType): + return AssignHandle._contains_identified_struct(var_type.pointee) + if isinstance(var_type, ir.BaseStructType): + if var_type.elements: + return any(AssignHandle._contains_identified_struct(e) for e in var_type.elements) + return False + + def HandleExprLlvm(self, Node: ast.expr, VarType: ir.Type | None = None) -> ir.Value | None: + return self.Trans.ExprHandler.HandleExprLlvm(Node, VarType) + + def _HandleAssignLlvm(self, Node: ast.Assign) -> None: + Gen: "Translator.LlvmGen" = self.Trans.LlvmGen + Gen._set_node_info(Node, "Assign") + if len(Node.targets) == 1: + Target: ast.expr = Node.targets[0] + if isinstance(Target, ast.Name): + VarName: str = Target.id + if VarName in Gen.var_const_flags: + src_info: str = Gen._get_node_info() + _vlog().error(f"不能对 const 变量 '{VarName}' 赋值{src_info}") + sys.exit(1) + if isinstance(Node.value, ast.Attribute) and isinstance(Node.value.value, ast.Name) and IsTModule(Node.value.value.id, self.Trans.SymbolTable): + AttrName: str = Node.value.attr + Gen.var_type_info[VarName] = {'type': 't_type', 'name': AttrName} + Gen.var_type_assignments.setdefault(VarName, []).append({'type': 't_type', 'name': AttrName}) + c_type_name: str = '' + resolved: tuple[type, int] | None = CTypeRegistry.ResolveName(AttrName) + if resolved is not None: + ctype_cls: type = resolved[0] + ptr_level: int = resolved[1] + c_type_name = CTypeRegistry.CTypeToName(ctype_cls) + if ptr_level > 0 and c_type_name: + c_type_name = c_type_name + ' *' + if not c_type_name: + if AttrName == 'CPtr': + c_type_name = 'void *' + is_unsigned: bool = Gen._is_type_unsigned(c_type_name) if c_type_name else False + fmt_str: str = "%u\n" if is_unsigned else "%d\n" + fmt_ptr: ir.Value = Gen._create_string_global(fmt_str) + fmt_var_name: str = f"__{VarName}_fmt" + if fmt_var_name not in Gen.variables: + fmt_alloca: ir.AllocaInstr = Gen._allocaEntry(ir.PointerType(ir.IntType(8)), name=fmt_var_name) + Gen.variables[fmt_var_name] = fmt_alloca + Gen.builder.store(fmt_ptr, Gen.variables[fmt_var_name]) + kind_var_name: str = f"__{VarName}_kind" + if kind_var_name not in Gen.variables: + kind_alloca: ir.AllocaInstr = Gen._allocaEntry(ir.IntType(32), name=kind_var_name) + Gen.variables[kind_var_name] = kind_alloca + Gen.builder.store(ir.Constant(ir.IntType(32), 0), Gen.variables[kind_var_name]) + if VarName not in Gen.variables: + dummy_var: ir.AllocaInstr = Gen._alloca(ir.IntType(8), name=VarName) + Gen.variables[VarName] = dummy_var + return + if isinstance(Node.value, ast.Name) and Node.value.id in Gen.structs: + ClassName: str = Node.value.id + Gen.var_type_info[VarName] = {'type': 'class_cast', 'name': ClassName} + Gen.var_type_assignments.setdefault(VarName, []).append({'type': 'class_cast', 'name': ClassName}) + fmt_str: str = "%p\n" + fmt_ptr: ir.Value = Gen._create_string_global(fmt_str) + fmt_var_name: str = f"__{VarName}_fmt" + if fmt_var_name not in Gen.variables: + fmt_alloca: ir.AllocaInstr = Gen._allocaEntry(ir.PointerType(ir.IntType(8)), name=fmt_var_name) + Gen.variables[fmt_var_name] = fmt_alloca + Gen.builder.store(fmt_ptr, Gen.variables[fmt_var_name]) + kind_var_name: str = f"__{VarName}_kind" + if kind_var_name not in Gen.variables: + kind_alloca: ir.AllocaInstr = Gen._allocaEntry(ir.IntType(32), name=kind_var_name) + Gen.variables[kind_var_name] = kind_alloca + Gen.builder.store(ir.Constant(ir.IntType(32), 1), Gen.variables[kind_var_name]) + if VarName not in Gen.variables: + dummy_var: ir.AllocaInstr = Gen._alloca(ir.IntType(8), name=VarName) + Gen.variables[VarName] = dummy_var + return + if isinstance(Node.value, ast.Call) and isinstance(Node.value.func, ast.Name) and Node.value.func.id == 'va_list': + va_list_ptr: ir.AllocaInstr = Gen._allocaEntry(ir.IntType(8).as_pointer(), name="va_list") + Gen.variables[VarName] = va_list_ptr + return + IsStructCtor: bool = (isinstance(Node.value, ast.Call) and isinstance(Node.value.func, ast.Name) + and Node.value.func.id in Gen.structs) + if IsStructCtor: + ClassName: str = Node.value.func.id + StructType: ir.Type = Gen.structs[ClassName] + + IsUnion: bool = False + TypeInfo: "SymbolTable.SymbolInfo | None" = self.Trans.SymbolTable.lookup(ClassName) + if TypeInfo and TypeInfo.IsUnion: + IsUnion = True + + if IsUnion: + Value: ir.Value | None = self.HandleExprLlvm(Node.value) + if Value: + var: ir.AllocaInstr = Gen._allocaEntry(Value.type, name=VarName) + Gen._store(Value, var) + Gen.variables[VarName] = var + return + + ExistingPtr: ir.Value | None = None + if VarName in Gen.variables and Gen.variables[VarName] is not None: + VarPtr: ir.Value = Gen.variables[VarName] + if isinstance(VarPtr.type.pointee, ir.PointerType): + ExistingPtr = VarPtr + elif VarName in Gen._reg_values: + OldVal: ir.Value = Gen._reg_values[VarName] + if isinstance(OldVal.type, ir.PointerType): + var: ir.AllocaInstr = Gen._allocaEntry(OldVal.type, name=VarName) + Gen._store(OldVal, var) + Gen.variables[VarName] = var + del Gen._reg_values[VarName] + ExistingPtr = var + elif VarName in Gen._direct_values: + OldVal: ir.Value = Gen._direct_values.pop(VarName) + if isinstance(OldVal.type, ir.PointerType): + var: ir.AllocaInstr = Gen._allocaEntry(OldVal.type, name=VarName) + Gen._store(OldVal, var) + Gen.variables[VarName] = var + ExistingPtr = var + if ExistingPtr: + pointee: ir.Type = ExistingPtr.type.pointee + if isinstance(pointee, ir.PointerType) and pointee.pointee == StructType: + self._InitStructAtPtr(Node.value, ClassName, ExistingPtr) + return + elif isinstance(pointee, ir.PointerType) and isinstance(pointee.pointee, ir.IntType) and pointee.pointee.width == 8: + self._InitStructAtPtr(Node.value, ClassName, ExistingPtr) + Gen.var_struct_class[VarName] = ClassName + return + if isinstance(Node.value, ast.Attribute): + enum_type_name: str | None = self._CheckEnumMemberAssignment(Node.value) + if enum_type_name: + Gen.var_type_info[VarName] = {'type': 'enum', 'name': enum_type_name} + var_type_for_list: ir.Type | None = None + if isinstance(Node.value, ast.List) and VarName in Gen.var_type_info: + type_info: dict[str, str] = Gen.var_type_info[VarName] + if type_info.get('type') == 'CArray': + var_type_for_list = type_info.get('full_type') + Value: ir.Value | None = self.HandleExprLlvm(Node.value, VarType=var_type_for_list) + if not Value: + return + if isinstance(Value.type, ir.VoidType): + return + Gen._UnregisterTempPtr(Value) + # 大端局部变量:赋值时 bswap + Value = Gen._apply_bswap_if_big(Value, getattr(Gen, 'local_var_byteorders', {}).get(VarName, ""), f"bswap_assign_{VarName}") + if isinstance(Value.type, ir.PointerType) and isinstance(Value.type.pointee, (ir.LiteralStructType, ir.IdentifiedStructType)): + found_class: str | None = None + found: tuple[str, ir.Type] | None = Gen.find_struct_by_pointee(Value.type.pointee) + if found: + CN: str = found[0] + ST: ir.Type = found[1] + found_class = CN + Gen.var_struct_class[VarName] = CN + Gen._var_to_heap_ptr[VarName] = Value + if found_class is None and isinstance(Value.type.pointee, ir.IdentifiedStructType): + pointee_name: str = Value.type.pointee.name + for CN, ST in Gen.structs.items(): + if isinstance(ST, ir.IdentifiedStructType) and ST.name == pointee_name: + found_class = CN + Gen.var_struct_class[VarName] = CN + Gen._var_to_heap_ptr[VarName] = Value + break + # 泛型类特化触发:返回类型是泛型类特化(如 list[str])但结构体尚未创建, + # 或虽然找到了结构体但它是 opaque(来自 stub 声明,尚未发射方法体) + _fd_struct_opaque: bool = False + if found_class and found_class in Gen.structs: + _fd_st: ir.IdentifiedStructType = Gen.structs[found_class] + if isinstance(_fd_st, ir.IdentifiedStructType) and (_fd_st.elements is None or len(_fd_st.elements) == 0): + _fd_struct_opaque = True + if (found_class is None or _fd_struct_opaque) and isinstance(Value.type.pointee, ir.IdentifiedStructType): + pn: str = Value.type.pointee.name + short_pn: str = pn + if '.' in pn: + pn_parts: list[str] = pn.split('.', 1) + if len(pn_parts[0]) >= 8 and all(c in '0123456789abcdef' for c in pn_parts[0]): + short_pn = pn_parts[1] + if '[' in short_pn and short_pn.endswith(']'): + gc_base: str = short_pn.split('[')[0] + gc_args_raw: str = short_pn[len(gc_base):] + gc_type_args: list[str] = [] + for gc_arg_part in gc_args_raw.split(']['): + gc_arg_part = gc_arg_part.strip('[]') + if gc_arg_part: + gc_type_args.append(gc_arg_part) + if (gc_type_args + and hasattr(self.Trans.ClassHandler, '_generic_class_templates') + and gc_base in self.Trans.ClassHandler._generic_class_templates): + gc_type_names: list[str] = [] + for gc_ta in gc_type_args: + gc_tn: str = gc_ta + if gc_ta == 'int': + gc_tn = 'CInt' + elif gc_ta == 'double': + gc_tn = 'CDouble' + elif gc_ta == 'float': + gc_tn = 'CFloat' + elif gc_ta == 'char': + gc_tn = 'CChar' + elif gc_ta == 'bool': + gc_tn = 'CBool' + gc_type_names.append(gc_tn) + gc_spec: str | None = self.Trans.ClassHandler._specialize_generic_class( + gc_base, gc_type_args, Gen, type_names=gc_type_names) + if gc_spec and gc_spec in Gen.structs: + found_class = gc_spec + Gen.var_struct_class[VarName] = gc_spec + Gen._var_to_heap_ptr[VarName] = Value + else: + if VarName in ('mctx', 's1ctx', 's2ctx', 's5ctx'): + pass + if isinstance(Value.type, ir.PointerType) and isinstance(Value.type.pointee, (ir.LiteralStructType, ir.IdentifiedStructType)): + if VarName in Gen.variables and Gen.variables[VarName] is not None: + Gen._store(Value, Gen.variables[VarName]) + else: + var: ir.AllocaInstr = Gen._allocaEntry(Value.type, name=VarName) + Gen._store(Value, var) + Gen.variables[VarName] = var + if isinstance(Node.value, ast.Call) and isinstance(Node.value.func, ast.Name): + call_func_name: str = Node.value.func.id + if call_func_name in Gen.var_type_info: + type_info: dict[str, str] = Gen.var_type_info[call_func_name] + if type_info['type'] in ('t_type', 'class_cast'): + src_fmt_var: str = f"__{call_func_name}_fmt" + dst_fmt_var: str = f"__{VarName}_fmt" + if src_fmt_var in Gen.variables: + if dst_fmt_var not in Gen.variables: + dst_alloca: ir.AllocaInstr = Gen._allocaEntry(ir.PointerType(ir.IntType(8)), name=dst_fmt_var) + Gen.variables[dst_fmt_var] = dst_alloca + src_fmt_ptr: ir.Value = Gen._load(Gen.variables[src_fmt_var], name=f"Load_{call_func_name}_fmt_for_{VarName}") + Gen.builder.store(src_fmt_ptr, Gen.variables[dst_fmt_var]) + src_kind_var: str = f"__{call_func_name}_kind" + dst_kind_var: str = f"__{VarName}_kind" + if src_kind_var in Gen.variables: + if dst_kind_var not in Gen.variables: + dst_kind_alloca: ir.AllocaInstr = Gen._allocaEntry(ir.IntType(32), name=dst_kind_var) + Gen.variables[dst_kind_var] = dst_kind_alloca + src_kind_val: ir.Value = Gen._load(Gen.variables[src_kind_var], name=f"Load_{call_func_name}_kind_for_{VarName}") + Gen.builder.store(src_kind_val, Gen.variables[dst_kind_var]) + Gen.var_type_info[VarName] = {'type': 't_type_runtime', 'source': call_func_name} + return + if VarName in Gen.global_vars: + if VarName in Gen.module.globals: + GVar: ir.GlobalVariable = Gen.module.globals[VarName] + Gen._store(Value, GVar) + Gen.variables[VarName] = GVar + if isinstance(Value.type, ir.PointerType) and isinstance(Value.type.pointee, (ir.LiteralStructType, ir.IdentifiedStructType)): + found: tuple[str, ir.Type] | None = Gen.find_struct_by_pointee(Value.type.pointee) + if found: + CN: str = found[0] + ST: ir.Type = found[1] + Gen.var_struct_class[VarName] = CN + elif VarName in Gen.variables and Gen.variables[VarName] is not None: + Gen._store(Value, Gen.variables[VarName]) + return + if VarName in Gen._reg_values: + OldVal: ir.Value = Gen._reg_values[VarName] + var: ir.AllocaInstr = Gen._allocaEntry(OldVal.type, name=VarName) + Gen._store(OldVal, var) + Gen.variables[VarName] = var + del Gen._reg_values[VarName] + if VarName in Gen._direct_values: + OldVal: ir.Value = Gen._direct_values.pop(VarName) + var: ir.AllocaInstr = Gen._allocaEntry(OldVal.type, name=VarName) + Gen._store(OldVal, var) + Gen.variables[VarName] = var + if VarName in Gen.variables and Gen.variables[VarName] is not None: + VarPtr: ir.Value = Gen.variables[VarName] + TargetType: ir.Type | None = VarPtr.type.pointee if isinstance(VarPtr.type, ir.PointerType) else None + types_differ: bool + try: + types_differ = TargetType and Value.type != TargetType + except AssertionError: + types_differ = False + if isinstance(Value.type, ir.PointerType) and isinstance(Value.type.pointee, ir.PointerType): + LoadedValue: ir.Value = Gen._load(Value, name=f"Load_{VarName}") + Loaded_differ: bool + try: + Loaded_differ = TargetType and LoadedValue.type != TargetType + except AssertionError: + Loaded_differ = False + if Loaded_differ: + try: + Coerced: ir.Value | None = Gen._coerce_value(LoadedValue, TargetType) + if Coerced is not None: + LoadedValue = Coerced + except AssertionError: + pass + Gen._store(LoadedValue, VarPtr) + elif types_differ: + try: + Coerced: ir.Value | None = Gen._coerce_value(Value, TargetType) + if Coerced is not None: + Gen._store(Coerced, VarPtr) + else: + Gen._store(Value, VarPtr) + except AssertionError: + Gen._store(Value, VarPtr) + else: + Gen._store(Value, VarPtr) + if VarName not in Gen.variables: + # 检查是否为模块级全局变量,避免创建局部变量遮蔽全局 + if VarName in Gen.module.globals: + GVar: ir.GlobalVariable = Gen.module.globals[VarName] + Gen._store(Value, GVar) + Gen.variables[VarName] = GVar + elif isinstance(Value.type, ir.PointerType) and isinstance(Value.type.pointee, ir.PointerType): + LoadedValue: ir.Value = Gen._load(Value, name=f"Load_{VarName}") + var: ir.AllocaInstr = Gen._allocaEntry(LoadedValue.type, name=VarName) + Gen._store(LoadedValue, var) + Gen.variables[VarName] = var + else: + var: ir.AllocaInstr = Gen._allocaEntry(Value.type, name=VarName) + Gen._store(Value, var) + Gen.variables[VarName] = var + is_u: bool = Gen._check_node_unsigned(Node.value) + Gen._record_var_signedness(VarName, 'unsigned int' if is_u else 'int') + if isinstance(Node.value, ast.Call) and isinstance(Node.value.func, ast.Name): + call_func_name: str = Node.value.func.id + if call_func_name in Gen.var_type_info: + type_info: dict[str, str] = Gen.var_type_info[call_func_name] + if type_info['type'] in ('t_type', 'class_cast'): + src_fmt_var: str = f"__{call_func_name}_fmt" + dst_fmt_var: str = f"__{VarName}_fmt" + if src_fmt_var in Gen.variables: + if dst_fmt_var not in Gen.variables: + dst_alloca: ir.AllocaInstr = Gen._allocaEntry(ir.PointerType(ir.IntType(8)), name=dst_fmt_var) + Gen.variables[dst_fmt_var] = dst_alloca + src_fmt_ptr: ir.Value = Gen._load(Gen.variables[src_fmt_var], name=f"Load_{call_func_name}_fmt_for_{VarName}") + Gen.builder.store(src_fmt_ptr, Gen.variables[dst_fmt_var]) + src_kind_var: str = f"__{call_func_name}_kind" + dst_kind_var: str = f"__{VarName}_kind" + if src_kind_var in Gen.variables: + if dst_kind_var not in Gen.variables: + dst_kind_alloca: ir.AllocaInstr = Gen._allocaEntry(ir.IntType(32), name=dst_kind_var) + Gen.variables[dst_kind_var] = dst_kind_alloca + src_kind_val: ir.Value = Gen._load(Gen.variables[src_kind_var], name=f"Load_{call_func_name}_kind_for_{VarName}") + Gen.builder.store(src_kind_val, Gen.variables[dst_kind_var]) + Gen.var_type_info[VarName] = {'type': 't_type_runtime', 'source': call_func_name} + else: + Gen.var_type_info[VarName] = {'type': 't_type_runtime', 'source': call_func_name} + elif isinstance(Target, ast.Attribute): + TargetType: ir.Type | None = None + AttrName: str = Target.attr + VarName: str | None = None + if isinstance(Target.value, ast.Name): + VarName = Target.value.id + if VarName: + ClassName: str | None = Gen.var_struct_class.get(VarName) + if not ClassName and getattr(Gen, 'global_struct_class', None): + ClassName = Gen.global_struct_class.get(VarName) + if ClassName: + Gen.var_struct_class[VarName] = ClassName + if not ClassName: + for CN in Gen.structs: + if VarName == CN.lower() or VarName.startswith(CN): + ClassName = CN + break + if ClassName and ClassName in Gen.class_members: + for m_name, m_type in Gen.class_members[ClassName]: + if m_name == AttrName: + TargetType = m_type + break + Value: ir.Value | None = self.HandleExprLlvm(Node.value, VarType=TargetType) + if Value: + self._HandleAttributeStoreLlvm(Target, Value) + elif isinstance(Target, ast.Subscript): + TargetType: ir.Type | None = None + SubVarName: str | None = None + if isinstance(Target.value, ast.Name): + SubVarName = Target.value.id + if SubVarName in Gen.var_struct_class: + ClassName: str = Gen.var_struct_class[SubVarName] + if ClassName in Gen.class_members: + for m_name, m_type in Gen.class_members[ClassName]: + if m_name == SubVarName: + if isinstance(m_type, ir.PointerType): + pointee: ir.Type = m_type.pointee + if isinstance(pointee, ir.ArrayType): + TargetType = pointee.element + elif isinstance(m_type, ir.ArrayType): + TargetType = m_type.element + break + if not TargetType and isinstance(Target.value, ast.Name): + SubVarName = Target.value.id + var_val: ir.Value | None = Gen.variables.get(SubVarName) + if var_val is None and SubVarName in Gen._direct_values: + var_val = Gen._direct_values[SubVarName] + if var_val is not None: + var_type: ir.Type = var_val.type + if isinstance(var_type, ir.PointerType): + pointee: ir.Type = var_type.pointee + if isinstance(pointee, ir.ArrayType): + TargetType = pointee.element + elif isinstance(var_type, ir.ArrayType): + TargetType = var_type.element + Value: ir.Value | None = self.HandleExprLlvm(Node.value, VarType=TargetType) + if Value: + self._HandleSubscriptStoreLlvm(Target, Value) + elif isinstance(Target, ast.Tuple): + if isinstance(Node.value, ast.Call): + FuncName: str | None = None + ModulePath: str | None = None + if isinstance(Node.value.func, ast.Name): + FuncName = Node.value.func.id + elif isinstance(Node.value.func, ast.Attribute): + FuncName = Node.value.func.attr + ModulePath = self.Trans.ExprCallHandle._get_ModulePath(Node.value.func.value) + CReturnTypes: list[ast.expr] = [] + FuncDef: ast.FunctionDef | None = self.Trans.FunctionDefCache.get(FuncName) if FuncName else None + if FuncDef: + if FuncDef.returns and isinstance(FuncDef.returns, ast.Subscript): + if isinstance(FuncDef.returns.value, ast.Name) and FuncDef.returns.value.id == 'tuple': + slice_node: ast.expr = FuncDef.returns.slice + if isinstance(slice_node, ast.Tuple): + CReturnTypes = slice_node.elts + else: + CReturnTypes = [slice_node] + if FuncDef.decorator_list: + for decorator in FuncDef.decorator_list: + if isinstance(decorator, ast.Call) and isinstance(decorator.func, ast.Attribute): + if decorator.func.attr == 'CReturn': + for arg in decorator.args: + CReturnTypes.append(arg) + if not CReturnTypes and FuncName: + func: ir.Function | None = Gen.functions.get(FuncName) + if func: + func_ft: ir.FunctionType | None = getattr(func, 'ftype', None) + if func_ft: + ret_type: ir.Type = func_ft.return_type + if isinstance(ret_type, ir.LiteralStructType): + CReturnTypes = [None] * len(ret_type.elements) + if not CReturnTypes: + sym_key: str = FuncName + if not self.Trans.SymbolTable.has(sym_key): + if ModulePath: + sym_key = f"{ModulePath}.{FuncName}" + sym_info: "SymbolTable.SymbolInfo | None" = self.Trans.SymbolTable.lookup(sym_key) + if sym_info and sym_info.IsFunction: + ret_type_info: CTypeInfo | None = sym_info.FuncPtrReturn + param_type_infos: list[tuple[str, CTypeInfo]] = [pt for _, pt in (sym_info.FuncPtrParams or [])] + if ret_type_info: + if isinstance(ret_type_info, CTypeInfo) and ret_type_info.BaseType: + ret_type: ir.Type = ret_type_info.ToLLVM(Gen) + else: + ret_type = Gen._type_str_to_llvm(str(ret_type_info) if ret_type_info else 'i32', False) + if isinstance(ret_type, ir.LiteralStructType): + CReturnTypes = [None] * len(ret_type.elements) + if FuncName not in Gen.functions: + if isinstance(ret_type, ir.VoidType): + ret_type = ir.IntType(32) + llvm_param_types: list[ir.Type] = [] + for pt in param_type_infos: + if isinstance(pt, CTypeInfo) and pt.BaseType: + lp: ir.Type = pt.ToLLVM(Gen) + else: + lp = Gen._type_str_to_llvm(str(pt) if pt else 'i32', '*' in str(pt) if isinstance(pt, str) else False) + if isinstance(lp, ir.VoidType): + lp = ir.IntType(8).as_pointer() + llvm_param_types.append(lp) + func_type: ir.FunctionType = ir.FunctionType(ret_type, llvm_param_types) + MangledName: str = Gen._mangle_func_name(FuncName) + func_decl: ir.Function = ir.Function(Gen.module, func_type, name=MangledName) + Gen.functions[MangledName] = func_decl + Gen.functions[FuncName] = func_decl + if not CReturnTypes and FuncName: + func: ir.Function | None = Gen.functions.get(FuncName) + if func: + func_ft: ir.FunctionType | None = getattr(func, 'ftype', None) + if func_ft: + ret_type: ir.Type = func_ft.return_type + if isinstance(ret_type, ir.LiteralStructType): + CReturnTypes = [None] * len(ret_type.elements) + if CReturnTypes and len(Target.elts) == len(CReturnTypes): + CallArgs: list[ir.Value | None] = [] + for arg in Node.value.args: + ArgVal: ir.Value | None = self.HandleExprLlvm(arg) + if ArgVal: + CallArgs.append(ArgVal) + for kw in Node.value.keywords: + pass + func: ir.Function | None = Gen.functions.get(FuncName) + func_ft: ir.FunctionType | None = getattr(func, 'ftype', None) if func else None + func_params: list[ir.Type] = list(getattr(func_ft, 'args', []) or []) if func_ft else [] + while len(CallArgs) < len(func_params): + FuncDef: ast.FunctionDef | None = self.Trans.FunctionDefCache.get(FuncName) + if FuncDef and len(CallArgs) < len(FuncDef.args.args): + arg_def: list[ast.expr] = FuncDef.args.defaults + arg_idx: int = len(CallArgs) + total_args: int = len(FuncDef.args.args) + default_start: int = total_args - len(arg_def) + if arg_idx >= default_start: + def_idx: int = arg_idx - default_start + if def_idx < len(arg_def): + DefVal: ir.Value | None = self.HandleExprLlvm(arg_def[def_idx]) + if DefVal: + expected_type: ir.Type = func_params[arg_idx] + if DefVal.type != expected_type: + if isinstance(expected_type, ir.IntType) and isinstance(DefVal.type, ir.IntType): + if DefVal.type.width < expected_type.width: + DefVal = Gen.builder.zext(DefVal, expected_type, name=f"zext_default_{arg_idx}") + elif DefVal.type.width > expected_type.width: + DefVal = Gen.builder.trunc(DefVal, expected_type, name=f"trunc_default_{arg_idx}") + CallArgs.append(DefVal) + continue + if len(CallArgs) < len(func_params): + CallArgs.append(ir.Constant(func_params[len(CallArgs)], 0)) + else: + break + adjusted: list[ir.Value] = Gen._adjust_args(CallArgs, func) + call_result: ir.Value = Gen.builder.call(func, adjusted, name=f"call_{FuncName}") + func_ft: ir.FunctionType | None = getattr(func, 'ftype', None) + ret_type: ir.Type | None = getattr(func_ft, 'return_type', None) if func_ft else None + for j, elt in enumerate(Target.elts): + if isinstance(elt, ast.Name): + VarName: str = elt.id + field_val: ir.Value = Gen.builder.extract_value(call_result, j, name=f"extract_{FuncName}_{j}") + VarType: ir.Type + if CReturnTypes[j] is not None: + ReturnTypeInfo: CTypeInfo | None = CTypeInfo.FromNode(CReturnTypes[j], self.Trans.SymbolTable) + if ReturnTypeInfo is None: + ReturnTypeInfo = CTypeInfo() + ReturnTypeInfo.BaseType = t.CInt() + VarType = Gen._ctype_to_llvm(ReturnTypeInfo) + elif ret_type and isinstance(ret_type, ir.LiteralStructType) and j < len(ret_type.elements): + VarType = ret_type.elements[j] + else: + VarType = field_val.type + if isinstance(VarType, ir.VoidType): + VarType = ir.IntType(32) + var: ir.AllocaInstr = Gen._alloca(VarType, name=VarName) + Gen.variables[VarName] = var + if CReturnTypes[j] is not None: + Gen._record_var_signedness(VarName, ReturnTypeStr) + elif ret_type and isinstance(ret_type, ir.LiteralStructType) and j < len(ret_type.elements): + elem_type: ir.Type = ret_type.elements[j] + if isinstance(elem_type, ir.IntType): + if elem_type.width == 16: + Gen._record_var_signedness(VarName, 'unsigned short') + elif elem_type.width == 32: + Gen._record_var_signedness(VarName, 'unsigned int') + elif elem_type.width == 64: + Gen._record_var_signedness(VarName, 'unsigned long long') + Gen._store(field_val, var) + return + + def _InitStructAtPtr(self, call_node: ast.Call, ClassName: str, VarPtr: ir.Value) -> None: + Gen: "Translator.LlvmGen" = self.Trans.LlvmGen + if ClassName not in Gen.structs: + return + StructType: ir.Type = Gen.structs[ClassName] + StructPtrType: ir.PointerType = ir.PointerType(StructType) + RawPtr: ir.Value = Gen._load(VarPtr, name=getattr(VarPtr, 'name', 'ptr')) + StructPtr: ir.Value = Gen.builder.bitcast(RawPtr, StructPtrType, name=ClassName) + members: list[tuple[str, ir.Type]] = Gen.class_members.get(ClassName, []) + defaults: dict[str, ir.Value] = Gen.class_member_defaults.get(ClassName, {}) + member_values: dict[str, ir.Value] = {} + for member_name, member_type in members: + if member_name in defaults: + member_values[member_name] = defaults[member_name] + if call_node.args: + for i, arg in enumerate(call_node.args): + if i < len(members): + member_name: str = members[i][0] + val: ir.Value | None = self.HandleExprLlvm(arg) + if val: + member_values[member_name] = val + if call_node.keywords: + for kw in call_node.keywords: + val: ir.Value | None = self.HandleExprLlvm(kw.value) + if val: + member_values[kw.arg] = val + has_vtable: bool = ClassName in Gen.class_vtable + base: int = 1 if has_vtable else 0 + for i, (member_name, member_type) in enumerate(members): + if isinstance(member_type, ir.VoidType): + continue + if member_name in member_values: + ElemPtr: ir.Value = Gen.builder.gep(StructPtr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), base + i)], name=f"{ClassName}_{member_name}") + try: + Gen._store(member_values[member_name], ElemPtr) + except Exception as _e: + if _config_mode == "strict": + self.Trans.LogWarning(f"异常被忽略: {_e}") + InitFuncName: str = f'{ClassName}.__init__' + if Gen._has_function(InitFuncName): + Args: list[ir.Value | None] = [self.HandleExprLlvm(arg) for arg in call_node.args] + Args = [a for a in Args if a] + Gen.builder.call(Gen._get_function(InitFuncName), [StructPtr] + Args, name=f"call_{InitFuncName}") + + def _StoreOrStrCopy(self, VarName: str, VarPtr: ir.Value, Value: ir.Value) -> None: + Gen: "Translator.LlvmGen" = self.Trans.LlvmGen + DestPtr: ir.Value = Gen._load(VarPtr, name=VarName) + if BaseHandle._is_char_pointer(DestPtr): + if BaseHandle._is_char_pointer(Value): + if 'strcpy' not in Gen.functions: + strcpy_type: ir.FunctionType = ir.FunctionType(ir.PointerType(ir.IntType(8)), [ir.PointerType(ir.IntType(8)), ir.PointerType(ir.IntType(8))]) + Gen.functions['strcpy'] = ir.Function(Gen.module, strcpy_type, name='strcpy') + Gen.builder.call(Gen.functions['strcpy'], [DestPtr, Value]) + return + try: + CastedVal: ir.Value = Gen.builder.bitcast(Value, VarPtr.type.pointee, name=f"cast_{VarName}") + Gen._store(CastedVal, VarPtr) + except Exception: # 回退:bitcast 失败时 alloca 新变量 + NewVar: ir.AllocaInstr = Gen._allocaEntry(Value.type, name=VarName) + Gen._store(Value, NewVar) + Gen.variables[VarName] = NewVar + + def _HandleAttributeStoreLlvm(self, Target: ast.Attribute, Value: ir.Value) -> None: + Gen: "Translator.LlvmGen" = self.Trans.LlvmGen + AttrName: str = Target.attr + if isinstance(Target.value, ast.Name) and Target.value.id == 'self': + ClassName: str | None = self.Trans._CurrentCpythonObjectClass + if ClassName and ClassName in Gen.structs: + PropKey: str = f'{ClassName}.{AttrName}' + PropInfo: "SymbolTable.SymbolInfo | None" = self.Trans.SymbolTable.lookup(PropKey) + if PropInfo and PropInfo.MetaList and FuncMeta.PROPERTY_SETTER in PropInfo.MetaList: + SelfVar: ir.Value | None = Gen._get_var_ptr('self') + if SelfVar: + SelfPtr: ir.Value = Gen._load(SelfVar, name="self") + SetterFunc: ir.Function | None = Gen._get_function(PropKey + '$set') + if SetterFunc and SelfPtr: + Gen.builder.call(SetterFunc, [SelfPtr, Value], name=f"prop_set_{PropKey}") + return + SelfVar: ir.Value | None = Gen._get_var_ptr('self') + if not SelfVar: + return + if SelfVar: + SelfPtr: ir.Value = Gen._load(SelfVar, name="self") + is_vtable_method: bool = False + method_idx: int = 0 + if ClassName in Gen.class_vtable or ClassName in Gen._cross_module_vtable_classes: + if ClassName in Gen.class_methods: + for mi, mn in enumerate(Gen.class_methods[ClassName]): + method_short: str = mn.split('.')[-1] if '.' in mn else mn + if method_short == AttrName or mn == AttrName: + is_vtable_method = True + method_idx = mi + break + if is_vtable_method: + VtableSlotPtr: ir.Value = Gen.builder.gep(SelfPtr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), 0)], name=f"vtable_slot_{ClassName}") + VtablePtr: ir.Value = Gen._load(VtableSlotPtr, name=f"vtable_ptr_{ClassName}") + methods: list[str] = Gen.class_methods[ClassName] + VtableArrayType: ir.ArrayType = ir.ArrayType(ir.PointerType(ir.IntType(8)), len(methods)) + ClassVtable: ir.GlobalVariable | None = Gen.Vtables.get(ClassName) + if ClassVtable: + ClassVtableAddr: ir.Value = Gen.builder.bitcast(ClassVtable, ir.PointerType(ir.IntType(8)), name=f"class_vtable_addr_{ClassName}") + IsSameVtable: ir.Value = Gen.builder.icmp_unsigned('==', VtablePtr, ClassVtableAddr, name=f"is_same_vtable_{ClassName}") + CopyBlock: ir.Block = Gen.func.append_basic_block(name=f"vtable_copy_self_{AttrName}") + SkipBlock: ir.Block = Gen.func.append_basic_block(name=f"vtable_skip_self_{AttrName}") + Gen.builder.cbranch(IsSameVtable, CopyBlock, SkipBlock) + Gen.builder.position_at_end(CopyBlock) + if not hasattr(Gen, '_vtable_copy_counter'): + Gen._vtable_copy_counter = 0 + Gen._vtable_copy_counter += 1 + CopyName: str = f"{Gen._mangle_name(ClassName)}_vtable_copy_self_{Gen._vtable_copy_counter}" + VtableCopyGlobal: ir.GlobalVariable = ir.GlobalVariable(Gen.module, VtableArrayType, name=CopyName) + VtableCopyGlobal.linkage = 'internal' + VtableCopyGlobal.initializer = ir.Constant(VtableArrayType, [ir.Constant(ir.PointerType(ir.IntType(8)), None)] * len(methods)) + VtableCopyTyped: ir.Value = Gen.builder.bitcast(VtableCopyGlobal, ir.PointerType(ir.IntType(8)), name=f"vtable_copy_typed") + SrcTyped: ir.Value = Gen.builder.bitcast(ClassVtable, ir.PointerType(ir.IntType(8)), name=f"src_vtable_typed") + VtableSize: int = len(methods) * Gen.ptr_size + MemcpyFunc: ir.Function | None = Gen._find_function('llvm.memcpy.p0i8.p0i8.i64') + if not MemcpyFunc: + MemcpyType: ir.FunctionType = ir.FunctionType(ir.VoidType(), [ir.PointerType(ir.IntType(8)), ir.PointerType(ir.IntType(8)), ir.IntType(64), ir.IntType(1)]) + MemcpyFunc = ir.Function(Gen.module, MemcpyType, name='llvm.memcpy.p0i8.p0i8.i64') + Gen.functions['llvm.memcpy.p0i8.p0i8.i64'] = MemcpyFunc + Gen.builder.call(MemcpyFunc, [VtableCopyTyped, SrcTyped, ir.Constant(ir.IntType(64), VtableSize), ir.Constant(ir.IntType(1), 0)]) + VtableCopyGlobalAddr: ir.Value = Gen.builder.bitcast(VtableCopyGlobal, ir.PointerType(ir.IntType(8)), name=f"vtable_copy_addr") + Gen._store(VtableCopyGlobalAddr, VtableSlotPtr) + Gen.builder.branch(SkipBlock) + Gen.builder.position_at_end(SkipBlock) + VtablePtr = Gen._load(VtableSlotPtr, name=f"vtable_ptr_{ClassName}_after_copy") + VtableTyped: ir.Value = Gen.builder.bitcast(VtablePtr, ir.PointerType(VtableArrayType), name=f"vtable_typed_{ClassName}") + MethodPtrAddr: ir.Value = Gen.builder.gep(VtableTyped, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), method_idx)], name=f"vmethod_slot_{AttrName}") + FuncPtrI8: ir.Value = Gen.builder.bitcast(Value, ir.PointerType(ir.IntType(8)), name=f"func_ptr_i8_{AttrName}") + Gen._store(FuncPtrI8, MethodPtrAddr) + return + offset: int = Gen._get_member_offset(AttrName, ClassName) + struct_type: ir.Type = Gen.structs[ClassName] + max_offset: int = len(struct_type.elements) if isinstance(struct_type, ir.IdentifiedStructType) else 0 + if offset >= max_offset: + VarName: str = f"self.{AttrName}" + if VarName not in Gen.variables: + NewVar: ir.AllocaInstr = Gen._allocaEntry(Value.type, name=AttrName) + Gen.variables[VarName] = NewVar + Gen._store(Value, Gen.variables[VarName]) + return + MemberPtr: ir.Value = Gen.builder.gep(SelfPtr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=AttrName) + self._StoreWithCoerce(Value, MemberPtr) + elif isinstance(Target.value, ast.Name): + VarName: str = Target.value.id + + # FakeDuck: 检查是否有影子结构体 a__meta__ (str 变量的 per-instance 字段存储) + # 直接通过 a.__field__ = value 访问影子结构体字段 (语法糖) + _fd_meta_name: str = f"{VarName}__meta__" + if _fd_meta_name in Gen.variables and '_str' in Gen.structs: + _fd_offset = Gen._get_member_offset(AttrName, '_str') + if _fd_offset is not None: + _fd_meta_ptr: ir.Value = Gen.variables[_fd_meta_name] + _fd_field_ptr: ir.Value = Gen.builder.gep(_fd_meta_ptr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), _fd_offset)], name=f"{VarName}_{AttrName}_ptr") + self._StoreWithCoerce(Value, _fd_field_ptr) + return + + ClassName: str | None = Gen.var_struct_class.get(VarName) + + if not ClassName and getattr(Gen, 'global_struct_class', None): + ClassName = Gen.global_struct_class.get(VarName) + if ClassName: + Gen.var_struct_class[VarName] = ClassName + + if not ClassName: + for CN in Gen.structs: + if VarName == CN.lower() or VarName.startswith(CN): + ClassName = CN + break + + if not ClassName and VarName in Gen.module.globals: + GVar: ir.GlobalVariable = Gen.module.globals[VarName] + if isinstance(GVar.type, ir.PointerType) and isinstance(GVar.type.pointee, (ir.IdentifiedStructType, ir.LiteralStructType)): + found: tuple[str, ir.Type] | None = Gen.find_struct_by_pointee(GVar.type.pointee) + if found: + ClassName = found[0] + Gen.var_struct_class[VarName] = ClassName + if getattr(Gen, 'global_struct_class', None): + Gen.global_struct_class[VarName] = ClassName + + if not ClassName and VarName in Gen.variables: + VarPtr: ir.Value = Gen.variables[VarName] + if isinstance(VarPtr.type, ir.PointerType): + pointee: ir.Type = VarPtr.type.pointee + if isinstance(pointee, ir.PointerType): + pointee = pointee.pointee + found: tuple[str, ir.Type] | None = Gen.find_struct_by_pointee(pointee) + if found: + CN: str = found[0] + ST: ir.Type = found[1] + ClassName = CN + + IsUnion: bool = False + TypeInfo: "SymbolTable.SymbolInfo | None" = self.Trans.SymbolTable.lookup(ClassName) + if TypeInfo and TypeInfo.IsUnion: + IsUnion = True + + if ClassName and ClassName in Gen.structs: + PropKey: str = f'{ClassName}.{AttrName}' + PropInfo: "SymbolTable.SymbolInfo | None" = self.Trans.SymbolTable.lookup(PropKey) + if PropInfo and PropInfo.MetaList and FuncMeta.PROPERTY_SETTER in PropInfo.MetaList: + ObjVal: ir.Value | None = self.Trans.ExprHandler.HandleExprLlvm(Target.value) + SetterFunc: ir.Function | None = Gen._get_function(PropKey + '$set') + if SetterFunc and ObjVal: + if isinstance(ObjVal.type, ir.PointerType) and isinstance(ObjVal.type.pointee, ir.PointerType): + ObjVal = Gen._load(ObjVal, name=f"Load_{ClassName}") + Gen.builder.call(SetterFunc, [ObjVal, Value], name=f"prop_set_{PropKey}") + return + ObjVal: ir.Value | None = self.Trans.ExprHandler.HandleExprLlvm(Target.value) + if ObjVal: + if BaseHandle._is_char_pointer(ObjVal): + ObjVal = Gen.builder.bitcast(ObjVal, ir.PointerType(Gen.structs[ClassName]), name=f"cast_{ClassName}") + if isinstance(ObjVal.type, ir.PointerType) and isinstance(ObjVal.type.pointee, ir.PointerType): + ObjVal = Gen._load(ObjVal, name=f"Load_{ClassName}") + if isinstance(ObjVal.type, ir.PointerType) and ObjVal.type.pointee == Gen.structs[ClassName]: + if IsUnion: + NestedStructName: str = f"{ClassName}_{AttrName}" + if NestedStructName in Gen.structs: + NestedStructType: ir.Type = Gen.structs[NestedStructName] + ObjVal = Gen.builder.bitcast(ObjVal, ir.PointerType(NestedStructType), name=f"cast_{NestedStructName}") + offset: int | None = Gen._get_member_offset(AttrName, NestedStructName) + if offset is not None and offset < len(NestedStructType.elements): + MemberPtr: ir.Value = Gen.builder.gep(ObjVal, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=AttrName) + self._StoreWithCoerce(Value, MemberPtr) + return + bitfield_offsets: dict[str, int] = Gen.class_member_bitoffsets.get(ClassName, {}) + if AttrName in bitfield_offsets: + self._store_bitfield_member(ObjVal, ClassName, AttrName, Value) + return + bitfields: dict[str, int] = Gen.class_member_bitfields.get(ClassName, {}) + if AttrName in bitfields and bitfields[AttrName] > 0: + if ClassName not in Gen.class_member_bitoffsets: + Gen.class_member_bitoffsets[ClassName] = {} + if AttrName not in Gen.class_member_bitoffsets[ClassName]: + bo: int = 0 + for bf_name, bf_width in bitfields.items(): + if bf_name == AttrName: + break + bo += bf_width + Gen.class_member_bitoffsets[ClassName][AttrName] = bo + self._store_bitfield_member(ObjVal, ClassName, AttrName, Value) + return + is_vtable_method: bool = False + method_idx: int = 0 + if ClassName in Gen.class_vtable or ClassName in Gen._cross_module_vtable_classes: + if ClassName in Gen.class_methods: + for mi, mn in enumerate(Gen.class_methods[ClassName]): + method_short: str = mn.split('.')[-1] if '.' in mn else mn + if method_short == AttrName or mn == AttrName: + is_vtable_method = True + method_idx = mi + break + if is_vtable_method: + VtableSlotPtr: ir.Value = Gen.builder.gep(ObjVal, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), 0)], name=f"vtable_slot_{ClassName}") + VtablePtr: ir.Value = Gen._load(VtableSlotPtr, name=f"vtable_ptr_{ClassName}") + methods: list[str] = Gen.class_methods[ClassName] + VtableArrayType: ir.ArrayType = ir.ArrayType(ir.PointerType(ir.IntType(8)), len(methods)) + ClassVtable: ir.GlobalVariable | None = Gen.Vtables.get(ClassName) + if ClassVtable: + ClassVtableAddr: ir.Value = Gen.builder.bitcast(ClassVtable, ir.PointerType(ir.IntType(8)), name=f"class_vtable_addr_{ClassName}") + IsSameVtable: ir.Value = Gen.builder.icmp_unsigned('==', VtablePtr, ClassVtableAddr, name=f"is_same_vtable_{ClassName}") + CopyBlock: ir.Block = Gen.func.append_basic_block(name=f"vtable_copy_{AttrName}") + SkipBlock: ir.Block = Gen.func.append_basic_block(name=f"vtable_skip_{AttrName}") + Gen.builder.cbranch(IsSameVtable, CopyBlock, SkipBlock) + Gen.builder.position_at_end(CopyBlock) + if not hasattr(Gen, '_vtable_copy_counter'): + Gen._vtable_copy_counter = 0 + Gen._vtable_copy_counter += 1 + CopyName: str = f"{Gen._mangle_name(ClassName)}_vtable_copy_{Gen._vtable_copy_counter}" + VtableCopyGlobal: ir.GlobalVariable = ir.GlobalVariable(Gen.module, VtableArrayType, name=CopyName) + VtableCopyGlobal.linkage = 'internal' + VtableCopyGlobal.initializer = ir.Constant(VtableArrayType, [ir.Constant(ir.PointerType(ir.IntType(8)), None)] * len(methods)) + VtableCopyTyped: ir.Value = Gen.builder.bitcast(VtableCopyGlobal, ir.PointerType(ir.IntType(8)), name=f"vtable_copy_typed") + SrcTyped: ir.Value = Gen.builder.bitcast(ClassVtable, ir.PointerType(ir.IntType(8)), name=f"src_vtable_typed") + VtableSize: int = len(methods) * Gen.ptr_size + MemcpyFunc: ir.Function | None = Gen._find_function('llvm.memcpy.p0i8.p0i8.i64') + if not MemcpyFunc: + MemcpyType: ir.FunctionType = ir.FunctionType(ir.VoidType(), [ir.PointerType(ir.IntType(8)), ir.PointerType(ir.IntType(8)), ir.IntType(64), ir.IntType(1)]) + MemcpyFunc = ir.Function(Gen.module, MemcpyType, name='llvm.memcpy.p0i8.p0i8.i64') + Gen.functions['llvm.memcpy.p0i8.p0i8.i64'] = MemcpyFunc + Gen.builder.call(MemcpyFunc, [VtableCopyTyped, SrcTyped, ir.Constant(ir.IntType(64), VtableSize), ir.Constant(ir.IntType(1), 0)]) + VtableCopyGlobalAddr: ir.Value = Gen.builder.bitcast(VtableCopyGlobal, ir.PointerType(ir.IntType(8)), name=f"vtable_copy_addr") + Gen._store(VtableCopyGlobalAddr, VtableSlotPtr) + Gen.builder.branch(SkipBlock) + Gen.builder.position_at_end(SkipBlock) + VtablePtr = Gen._load(VtableSlotPtr, name=f"vtable_ptr_{ClassName}_after_copy") + VtableTyped: ir.Value = Gen.builder.bitcast(VtablePtr, ir.PointerType(VtableArrayType), name=f"vtable_typed_{ClassName}") + MethodPtrAddr: ir.Value = Gen.builder.gep(VtableTyped, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), method_idx)], name=f"vmethod_slot_{AttrName}") + FuncPtrI8: ir.Value = Gen.builder.bitcast(Value, ir.PointerType(ir.IntType(8)), name=f"func_ptr_i8_{AttrName}") + Gen._store(FuncPtrI8, MethodPtrAddr) + return + offset: int = Gen._get_member_offset(AttrName, ClassName) + StructType: ir.Type | None = Gen.structs.get(ClassName) + if isinstance(StructType, ir.IdentifiedStructType) and (StructType.elements is None or len(StructType.elements) == 0): + self.Trans.ImportHandler._TryLoadStructFromStub(ClassName, Gen) + StructType = Gen.structs.get(ClassName) + if isinstance(StructType, ir.IdentifiedStructType) and (StructType.elements is None or len(StructType.elements) == 0): + return + if StructType is not None and StructType.elements is not None and isinstance(ObjVal.type, ir.PointerType) and isinstance(ObjVal.type.pointee, ir.IdentifiedStructType) and ObjVal.type.pointee.elements is None: + ObjVal = Gen.builder.bitcast(ObjVal, ir.PointerType(StructType), name=f"cast_{ClassName}") + if offset is not None and StructType is not None and StructType.elements is not None and offset < len(StructType.elements): + MemberPtr: ir.Value = Gen.builder.gep(ObjVal, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=AttrName) + else: + return + + byte_order: str = getattr(Gen, 'class_member_byteorders', {}).get(ClassName, {}).get(AttrName, "") + + if byte_order == 'big': + st: ir.Type | None = Gen.structs.get(ClassName) + if st is None or st.elements is None or len(st.elements) == 0: + return + member_type: ir.Type = st.elements[offset] + if isinstance(member_type, ir.IntType): + Value = Gen._apply_bswap_if_big(Value, byte_order, f"bswap_store_{AttrName}") + + self._StoreWithCoerce(Value, MemberPtr) + if not ClassName: + imported_modules: list[str] | None = getattr(self.Trans, '_ImportedModules', None) + resolved_mod: str = self.Trans.SymbolTable.resolve_alias(VarName) + if imported_modules and (VarName in imported_modules or resolved_mod in imported_modules): + PossibleKeys: list[str] = [f"{VarName}.{AttrName}", AttrName] + for mod_name in imported_modules: + if mod_name.endswith(f".{VarName}") or mod_name == VarName: + key: str = f"{mod_name}.{AttrName}" + if key not in PossibleKeys: + PossibleKeys.append(key) + for key in PossibleKeys: + if key in Gen.module.globals: + GVar: ir.GlobalVariable = Gen.module.globals[key] + if isinstance(GVar, ir.Function): + return + if isinstance(GVar.type, ir.PointerType) and isinstance(GVar.type.pointee, (ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)): + return + self._StoreWithCoerce(Value, GVar) + return + ModuleSha1Map: dict[str, str] = getattr(Gen, 'ModuleSha1Map', {}) + sha1_candidates: list[str] = [VarName, resolved_mod] + for mod_name in imported_modules: + if mod_name.endswith(f".{VarName}") or mod_name == VarName: + if mod_name not in sha1_candidates: + sha1_candidates.append(mod_name) + for cand in sha1_candidates: + sha1: str | None = ModuleSha1Map.get(cand) + if sha1: + prefixed: str = f"{sha1}.{AttrName}" + if prefixed in Gen.module.globals: + GVar2: ir.GlobalVariable = Gen.module.globals[prefixed] + if isinstance(GVar2, ir.Function): + return + if isinstance(GVar2.type, ir.PointerType) and isinstance(GVar2.type.pointee, (ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)): + return + self._StoreWithCoerce(Value, GVar2) + return + elif isinstance(Target.value, ast.Attribute): + ObjVal: ir.Value | None = self.Trans.ExprHandler.HandleExprLlvm(Target.value) + if ObjVal and isinstance(ObjVal.type, ir.PointerType): + pointee: ir.Type = ObjVal.type.pointee + if isinstance(pointee, (ir.LiteralStructType, ir.IdentifiedStructType)): + if isinstance(pointee, ir.IdentifiedStructType) and pointee.elements is None: + for CN, ST in Gen.structs.items(): + if isinstance(ST, ir.IdentifiedStructType) and ST.name == pointee.name and ST.elements is not None: + pointee = ST + ObjVal = Gen.builder.bitcast(ObjVal, ir.PointerType(ST), name=f"cast_{CN}") + break + found_match: bool = False + for CN, ST in Gen.structs.items(): + if pointee == ST or (isinstance(pointee, ir.IdentifiedStructType) and isinstance(ST, ir.IdentifiedStructType) and pointee.name == ST.name): + found_match = True + if ST.elements is None: + self.Trans.ImportHandler._TryLoadStructFromStub(CN, Gen) + ST = Gen.structs.get(CN, ST) + if ST.elements is not None and isinstance(ObjVal.type, ir.PointerType) and isinstance(ObjVal.type.pointee, ir.IdentifiedStructType) and ObjVal.type.pointee.elements is None: + ObjVal = Gen.builder.bitcast(ObjVal, ir.PointerType(ST), name=f"cast_{CN}") + bitfield_offsets: dict[str, int] = Gen.class_member_bitoffsets.get(CN, {}) + if AttrName in bitfield_offsets: + self._store_bitfield_member(ObjVal, CN, AttrName, Value) + return + offset: int = Gen._get_member_offset(AttrName, CN) + if offset is not None and ST.elements is not None and offset < len(ST.elements): + MemberPtr: ir.Value = Gen.builder.gep(ObjVal, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=AttrName) + self._StoreWithCoerce(Value, MemberPtr) + break + if not found_match: + if isinstance(pointee, ir.IdentifiedStructType): + matched_cn: str | None = None + for CN in Gen.class_members: + members: list[tuple[str, ir.Type]] = Gen.class_members[CN] + for mname, mtype in members: + if mname == AttrName: + matched_cn = CN + break + if matched_cn: + break + if matched_cn and matched_cn in Gen.structs: + ST: ir.Type = Gen.structs[matched_cn] + if isinstance(ST, ir.IdentifiedStructType) and (ST.elements is None or len(ST.elements) == 0): + self.Trans.ImportHandler._TryLoadStructFromStub(matched_cn, Gen) + ST = Gen.structs.get(matched_cn, ST) + if ST.elements is not None and isinstance(ObjVal.type, ir.PointerType) and isinstance(ObjVal.type.pointee, ir.IdentifiedStructType) and ObjVal.type.pointee.elements is None: + ObjVal = Gen.builder.bitcast(ObjVal, ir.PointerType(ST), name=f"cast_{matched_cn}") + offset: int = Gen._get_member_offset(AttrName, matched_cn) + if offset is not None and ST.elements is not None and offset < len(ST.elements): + MemberPtr: ir.Value = Gen.builder.gep(ObjVal, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=AttrName) + self._StoreWithCoerce(Value, MemberPtr) + return + elif isinstance(Target.value, ast.Call): + # Check if this is c.Deref(...) — we need the pointer, not the Loaded value + ObjVal: ir.Value | None = None + is_cderef: bool = (isinstance(Target.value.func, ast.Attribute) and + isinstance(Target.value.func.value, ast.Name) and + Target.value.func.value.id == 'c' and + Target.value.func.attr == 'Deref' and + Target.value.args) + if is_cderef: + # Get the pointer from c.Deref argument, don't Load the value + deref_arg: ast.expr = Target.value.args[0] + inner_val: ir.Value | None = self.HandleExprLlvm(deref_arg) + if inner_val and isinstance(inner_val.type, ir.PointerType): + if isinstance(inner_val.type.pointee, ir.PointerType): + ObjVal = Gen._load(inner_val, name="deref_load_ptr") + else: + ObjVal = inner_val + if ObjVal is None: + ObjVal = self.Trans.ExprHandler.HandleExprLlvm(Target.value) + if ObjVal and isinstance(ObjVal.type, ir.PointerType): + pointee: ir.Type = ObjVal.type.pointee + if isinstance(pointee, ir.PointerType): + ObjVal = Gen._load(ObjVal, name="load_ptr_for_attr") + pointee = ObjVal.type.pointee + for CN, ST in Gen.structs.items(): + if pointee == ST or (isinstance(pointee, ir.IdentifiedStructType) and isinstance(ST, ir.IdentifiedStructType) and pointee.name == ST.name): + if isinstance(ST, ir.IdentifiedStructType) and (ST.elements is None or len(ST.elements) == 0): + self.Trans.ImportHandler._TryLoadStructFromStub(CN, Gen) + ST = Gen.structs.get(CN, ST) + if ST.elements is not None and isinstance(ObjVal.type, ir.PointerType) and isinstance(ObjVal.type.pointee, ir.IdentifiedStructType) and ObjVal.type.pointee.elements is None: + ObjVal = Gen.builder.bitcast(ObjVal, ir.PointerType(ST), name=f"cast_{CN}") + bitfield_offsets: dict[str, int] = Gen.class_member_bitoffsets.get(CN, {}) + if AttrName in bitfield_offsets: + self._store_bitfield_member(ObjVal, CN, AttrName, Value) + return + offset: int = Gen._get_member_offset(AttrName, CN) + if offset is not None and ST.elements is not None and offset < len(ST.elements): + MemberPtr: ir.Value = Gen.builder.gep(ObjVal, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=AttrName) + self._StoreWithCoerce(Value, MemberPtr) + break + elif isinstance(Target.value, ast.Subscript): + SubPtr: ir.Value | None = self.Trans.ExprAttrHandle.HandleSubscriptPtrLlvm(Target.value) + if SubPtr and isinstance(SubPtr.type, ir.PointerType): + pointee: ir.Type = SubPtr.type.pointee + + if isinstance(Target.value.value, ast.Attribute): + AttrNameSub: str = Target.value.value.attr + if AttrNameSub == 'items' and 'Item' in Gen.structs: + ObjValCast: ir.Value = Gen.builder.bitcast(SubPtr, ir.PointerType(Gen.structs['Item']), name=f"cast_Item") + offset: int = Gen._get_member_offset(AttrName, 'Item') + MemberPtr: ir.Value = Gen.builder.gep(ObjValCast, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=AttrName) + self._StoreWithCoerce(Value, MemberPtr) + return + + if BaseHandle._is_char_pointer(SubPtr): + for CN, ST in Gen.structs.items(): + ObjValCast: ir.Value = Gen.builder.bitcast(SubPtr, ir.PointerType(ST), name=f"cast_{CN}") + offset: int = Gen._get_member_offset(AttrName, CN) + MemberPtr: ir.Value = Gen.builder.gep(ObjValCast, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=AttrName) + self._StoreWithCoerce(Value, MemberPtr) + break + elif isinstance(pointee, (ir.LiteralStructType, ir.IdentifiedStructType)): + found: tuple[str, ir.Type] | None = Gen.find_struct_by_pointee(pointee) + if found: + CN: str = found[0] + ST: ir.Type = found[1] + if isinstance(ST, ir.IdentifiedStructType) and (ST.elements is None or len(ST.elements) == 0): + self.Trans.ImportHandler._TryLoadStructFromStub(CN, Gen) + ST = Gen.structs.get(CN, ST) + if ST.elements is not None and isinstance(SubPtr.type, ir.PointerType) and isinstance(SubPtr.type.pointee, ir.IdentifiedStructType) and SubPtr.type.pointee.elements is None: + SubPtr = Gen.builder.bitcast(SubPtr, ir.PointerType(ST), name=f"cast_{CN}") + offset: int = Gen._get_member_offset(AttrName, CN) + if offset is not None and ST.elements is not None and offset < len(ST.elements): + MemberPtr: ir.Value = Gen.builder.gep(SubPtr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=AttrName) + self._StoreWithCoerce(Value, MemberPtr) + elif isinstance(pointee, ir.PointerType): + LoadedPtr: ir.Value = Gen._load(SubPtr, name=f"Load_{AttrName}_ptr") + if isinstance(LoadedPtr.type, ir.PointerType) and isinstance(LoadedPtr.type.pointee, (ir.IdentifiedStructType, ir.LiteralStructType)): + found: tuple[str, ir.Type] | None = Gen.find_struct_by_pointee(LoadedPtr.type.pointee) + if found: + CN: str = found[0] + ST: ir.Type = found[1] + offset: int = Gen._get_member_offset(AttrName, CN) + MemberPtr: ir.Value = Gen.builder.gep(LoadedPtr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=AttrName) + self._StoreWithCoerce(Value, MemberPtr) + + def _StoreArrElemWithCoerceBswap(self, Value: ir.Value, Ptr: ir.Value, arr_byte_order: str) -> None: + """对数组元素存储应用 bswap 后再 coerce 存储""" + Gen: "Translator.LlvmGen" = self.Trans.LlvmGen + Value = Gen._apply_bswap_if_big(Value, arr_byte_order, "bswap_arr_store") + self._StoreWithCoerce(Value, Ptr) + + def _HandleSubscriptStoreLlvm(self, Target: ast.Subscript, Value: ir.Value) -> None: + Gen: "Translator.LlvmGen" = self.Trans.LlvmGen + # 查询数组元素字节序 + arr_byte_order: str = '' + if isinstance(Target.value, ast.Name) and Target.value.id in Gen.local_var_byteorders: + arr_byte_order = Gen.local_var_byteorders[Target.value.id] + if isinstance(Target.value, ast.Name): + SubVarName: str = Target.value.id + if SubVarName in Gen.var_const_flags: + src_info: str = Gen._get_node_info() + self.Trans.LogError(f"不能对 const 变量 '{SubVarName}' 的元素赋值{src_info}") + ClassName: str | None = self.Trans.ExprHandler._get_var_class(Target.value, Gen) + if ClassName and Gen._has_function(f'{ClassName}.__setitem__'): + obj_val: ir.Value | None = self.Trans.ExprHandler.HandleExprLlvm(Target.value) + idx_val: ir.Value | None = self.Trans.ExprHandler.HandleExprLlvm(Target.slice) + if obj_val and idx_val: + if BaseHandle._is_char_pointer(obj_val): + obj_val = Gen.builder.bitcast(obj_val, ir.PointerType(Gen.structs[ClassName]), name=f"cast_{ClassName}") + setitem_args: list[ir.Value] = [obj_val, idx_val, Value] + setitem_func_name: str = f'{ClassName}.__setitem__' + setitem_args = Gen._apply_auto_addr(setitem_func_name, setitem_args) + setitem_func: ir.Function = Gen._get_function(setitem_func_name) + setitem_args = Gen._adjust_args(setitem_args, setitem_func) + Gen.builder.call(setitem_func, setitem_args, name=f"call_{setitem_func_name}") + return + ValueVal: ir.Value | None = self.HandleExprLlvm(Target.value) + IndexVal: ir.Value | None = self.HandleExprLlvm(Target.slice) + if not ValueVal or not IndexVal: + return + if BaseHandle._is_char_pointer(IndexVal): + Loaded_byte: ir.Value = Gen._load(IndexVal, name="Load_char_idx_store") + IndexVal = Gen.builder.zext(Loaded_byte, ir.IntType(32), name="char_to_int_idx_store") + if isinstance(ValueVal.type, ir.IntType): + var_ptr: ir.Value | None = self._get_int_ptr(Target.value) + if var_ptr: + i8_ptr: ir.Value = Gen.builder.bitcast(var_ptr, ir.PointerType(ir.IntType(8)), name="int_to_i8ptr_store") + if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width < 64: + IndexVal = Gen.builder.zext(IndexVal, ir.IntType(64), name="zext_int_index_store") + ptr: ir.Value = Gen.builder.gep(i8_ptr, [IndexVal], name="int_subscript_ptr_store") + self._StoreWithCoerce(Value, ptr) + return + if isinstance(ValueVal.type, ir.PointerType) and isinstance(ValueVal.type.pointee, ir.PointerType): + if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width < 64: + IndexVal = Gen.builder.zext(IndexVal, ir.IntType(64), name="zext_ptr_index_store") + ElemPtr: ir.Value = Gen.builder.gep(ValueVal, [IndexVal], name="subscript") + self._StoreArrElemWithCoerceBswap(Value, ElemPtr, arr_byte_order) + return + if isinstance(ValueVal.type, ir.PointerType): + pointee: ir.Type = ValueVal.type.pointee + if isinstance(pointee, ir.ArrayType): + zero: ir.Constant = ir.Constant(ir.IntType(32), 0) + if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width != 32: + if IndexVal.type.width < 32: + IndexVal = Gen.builder.zext(IndexVal, ir.IntType(32), name="zext_arr_index") + else: + IndexVal = Gen.builder.trunc(IndexVal, ir.IntType(32), name="trunc_arr_index") + ElemPtr: ir.Value = Gen.builder.gep(ValueVal, [zero, IndexVal], name="subscript") + elif (isinstance(pointee, ir.IntType) and pointee.width == 8 + and isinstance(Target.value, ast.Name) + and getattr(Gen, 'var_ptr_element', {}).get(Target.value.id, False)): + # 指针到 str/bytes 的变量 (BinOp 注解如 str | t.CPtr) + # elem_ptr 是 i8* 但实际指向 i8* (字符串指针), elem_ptr[0] = item 应存储 8 字节 + CastedPtrPtr: ir.Value = Gen.builder.bitcast(ValueVal, ir.PointerType(ir.PointerType(ir.IntType(8))), name="cast_pp_str_store") + if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width < 64: + IndexVal = Gen.builder.zext(IndexVal, ir.IntType(64), name="zext_pp_str_index_store") + ElemPtr = Gen.builder.gep(CastedPtrPtr, [IndexVal], name="subscript") + self._StoreArrElemWithCoerceBswap(Value, ElemPtr, arr_byte_order) + return + else: + ElemPtr: ir.Value = Gen.builder.gep(ValueVal, [IndexVal], name="subscript") + self._StoreArrElemWithCoerceBswap(Value, ElemPtr, arr_byte_order) + elif isinstance(ValueVal.type, ir.ArrayType): + zero: ir.Constant = ir.Constant(ir.IntType(32), 0) + if isinstance(Target.value, ast.Name): + VarName: str = Target.value.id + if VarName in Gen.variables and Gen.variables[VarName] is not None: + VarPtr: ir.Value = Gen.variables[VarName] + if isinstance(VarPtr.type, ir.PointerType) and isinstance(VarPtr.type.pointee, ir.ArrayType): + if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width != 32: + if IndexVal.type.width < 32: + IndexVal = Gen.builder.zext(IndexVal, ir.IntType(32), name="zext_arr_index") + else: + IndexVal = Gen.builder.trunc(IndexVal, ir.IntType(32), name="trunc_arr_index") + ElemPtr: ir.Value = Gen.builder.gep(VarPtr, [zero, IndexVal], name="subscript") + self._StoreArrElemWithCoerceBswap(Value, ElemPtr, arr_byte_order) + return + if isinstance(Target.value, ast.Subscript): + InnerPtr: ir.Value | None = self.Trans.ExprAttrHandle.HandleSubscriptPtrLlvm(Target.value) + if InnerPtr: + if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width != 32: + if IndexVal.type.width < 32: + IndexVal = Gen.builder.zext(IndexVal, ir.IntType(32), name="zext_arr_index") + else: + IndexVal = Gen.builder.trunc(IndexVal, ir.IntType(32), name="trunc_arr_index") + ElemPtr: ir.Value = Gen.builder.gep(InnerPtr, [zero, IndexVal], name="subscript") + self._StoreArrElemWithCoerceBswap(Value, ElemPtr, arr_byte_order) + return + if isinstance(Target.value, ast.Attribute): + AttrPtr: ir.Value | None = self.Trans.ExprAttrHandle._get_attr_ptr(Target.value) + if AttrPtr and isinstance(AttrPtr.type, ir.PointerType) and isinstance(AttrPtr.type.pointee, ir.ArrayType): + if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width != 32: + if IndexVal.type.width < 32: + IndexVal = Gen.builder.zext(IndexVal, ir.IntType(32), name="zext_arr_index") + else: + IndexVal = Gen.builder.trunc(IndexVal, ir.IntType(32), name="trunc_arr_index") + ElemPtr: ir.Value = Gen.builder.gep(AttrPtr, [zero, IndexVal], name="subscript") + self._StoreArrElemWithCoerceBswap(Value, ElemPtr, arr_byte_order) + return + arr_alloc: ir.AllocaInstr = Gen._allocaEntry(ValueVal.type, name="arr_subscript_tmp") + Gen._store(ValueVal, arr_alloc) + ElemPtr: ir.Value = Gen.builder.gep(arr_alloc, [zero, IndexVal], name="subscript") + self._StoreArrElemWithCoerceBswap(Value, ElemPtr, arr_byte_order) + ModifiedArr: ir.Value = Gen._load(arr_alloc, name="modified_arr") + if isinstance(Target.value, ast.Subscript): + OuterPtr: ir.Value | None = self.Trans.ExprAttrHandle.HandleSubscriptPtrLlvm(Target.value) + if OuterPtr: + Gen._store(ModifiedArr, OuterPtr) + elif isinstance(Target.value, ast.Attribute): + OuterPtr: ir.Value | None = self.Trans.ExprAttrHandle._get_attr_ptr(Target.value) + if OuterPtr: + Gen._store(ModifiedArr, OuterPtr) + + def _StoreWithCoerce(self, Value: ir.Value, Ptr: ir.Value) -> None: + Gen: "Translator.LlvmGen" = self.Trans.LlvmGen + if isinstance(Ptr.type, ir.PointerType): + TargetType: ir.Type = Ptr.type.pointee + if Value.type != TargetType: + if isinstance(TargetType, ir.ArrayType) and isinstance(Value.type, ir.PointerType): + ElemType: ir.Type = TargetType.element + ElemSize: int = Gen._get_struct_size(ElemType) + for i in range(TargetType.count): + DstElem: ir.Value = Gen.builder.gep(Ptr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), i)], name=f"arr_dst_{i}") + SrcPtr: ir.Value + if ElemSize == 1: + SrcPtr = Gen.builder.gep(Value, [ir.Constant(ir.IntType(32), i)], name=f"arr_src_{i}") + else: + PtrInt: ir.Value = Gen.builder.ptrtoint(Value, ir.IntType(64)) + Offset: ir.Constant = ir.Constant(ir.IntType(64), i * ElemSize) + NewPtrInt: ir.Value = Gen.builder.add(PtrInt, Offset) + SrcPtr = Gen.builder.inttoptr(NewPtrInt, ir.PointerType(ElemType), name=f"arr_src_{i}") + SrcVal: ir.Value = Gen._load(SrcPtr, name=f"arr_elem_{i}") + if SrcVal.type != ElemType: + try: + SrcVal = Gen.builder.bitcast(SrcVal, ElemType, name=f"arr_cast_{i}") + except Exception: # 回退:bitcast 失败时跳过该元素 + continue + Gen._store(SrcVal, DstElem) + return + if isinstance(TargetType, ir.PointerType) and isinstance(Value, ir.Constant) and Value.constant is None: + Value = ir.Constant(TargetType, None) + elif isinstance(TargetType, ir.PointerType) and isinstance(Value.type, ir.PointerType): + try: + Value = Gen.builder.bitcast(Value, TargetType, name="null_ptr_bitcast") + except Exception: # 回退:bitcast 失败时设为 null 常量 + Value = ir.Constant(TargetType, None) + else: + Coerced: ir.Value | None = Gen._coerce_value(Value, TargetType) + if Coerced is not None: + Value = Coerced + Gen._store(Value, Ptr) + + + def _get_int_ptr(self, target: ast.expr) -> ir.Value | None: + Gen: "Translator.LlvmGen" = self.Trans.LlvmGen + if isinstance(target, ast.Name): + VarName: str = target.id + if VarName in Gen.variables and Gen.variables[VarName] is not None: + VarPtr: ir.Value = Gen.variables[VarName] + if isinstance(VarPtr.type, ir.PointerType): + pointee: ir.Type = VarPtr.type.pointee + if isinstance(pointee, ir.ArrayType): + return Gen.builder.gep(VarPtr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), 0)], name=f"arr_start_{VarName}") + return None + + def _EmitGlobalAnnAssignLlvm(self, Node: ast.AnnAssign, Gen: "Translator.LlvmGen") -> None: + if isinstance(Node.target, ast.Name): + VarName: str = Node.target.id + Info: "SymbolTable.SymbolInfo | None" = self.Trans.SymbolTable.lookup(VarName) + if Info: + if Info.get('type') == 'typedef': + return + parse_result = ParseListAnnotation(Node.annotation) + if parse_result: + elem_type_node: ast.expr = parse_result.elem_type_node + ElemType, ElemTypeInfo = self.ResolveListElementType( + elem_type_node, Gen, + check_func_ptr=True, void_fallback_width=32, fallback_to_cint=True, + ) + if parse_result.is_pointer: + # 单参数 list[type] → 指针 + VarType: ir.Type = ir.PointerType(ElemType) + if VarName not in Gen.variables and VarName not in Gen.module.globals: + GlobalVar: ir.GlobalVariable = ir.GlobalVariable(Gen.module, VarType, name=VarName) + GlobalVar.initializer = ir.Constant(VarType, None) + Gen.variables[VarName] = GlobalVar + if isinstance(elem_type_node, ast.Name) and elem_type_node.id in Gen.structs: + Gen.global_struct_class[VarName] = elem_type_node.id + return + count_node: ast.expr | None = parse_result.count_node + ArrayCount: int = self.ParseArrayCount(count_node, Gen, Node.value, mode='global') + VarType = ir.ArrayType(ElemType, ArrayCount) + if VarName not in Gen.variables and VarName not in Gen.module.globals: + GlobalVar = ir.GlobalVariable(Gen.module, VarType, name=VarName) + if isinstance(ElemType, ir.IdentifiedStructType): + GlobalVar.linkage = 'common' + elif Node.value and isinstance(Node.value, ast.Constant) and isinstance(Node.value.value, str): + str_val: str = Node.value.value + '\x00' + str_bytes: bytearray = bytearray(str_val, 'utf-8') + if len(str_bytes) < ArrayCount: + str_bytes.extend(b'\x00' * (ArrayCount - len(str_bytes))) + try: + GlobalVar.initializer = ir.Constant(VarType, str_bytes[:ArrayCount]) + except Exception: # 回退:初始化常量失败时用零值 + GlobalVar.initializer = Gen._zero_value_for_type(VarType) + else: + InitConstants: list[ir.Constant] | None = self.Trans._BuildArrayInitConstants(Node.value, ElemType, elem_type_node, ArrayCount, Gen, byte_order=ElemTypeInfo.ByteOrder if ElemTypeInfo else '') + if InitConstants: + GlobalVar.initializer = ir.Constant(VarType, InitConstants) + elif ArrayCount > 256: + GlobalVar.linkage = 'common' + else: + if self._contains_identified_struct(VarType): + GlobalVar.linkage = 'common' + else: + GlobalVar.initializer = ir.Constant(VarType, [ir.Constant(ElemType, ir.Undefined)] * ArrayCount) + Gen.variables[VarName] = GlobalVar + if isinstance(elem_type_node, ast.Name) and elem_type_node.id in Gen.structs: + Gen.global_struct_class[VarName] = elem_type_node.id + return + if isinstance(Node.annotation, ast.Name) and Node.annotation.id in Gen.structs: + StructName: str = Node.annotation.id + VarType: ir.Type = Gen.structs[StructName] + if VarName not in Gen.variables and VarName not in Gen.module.globals: + GlobalVar: ir.GlobalVariable = ir.GlobalVariable(Gen.module, VarType, name=VarName) + if Node.value and isinstance(Node.value, ast.Call) and isinstance(Node.value.func, ast.Name) and Node.value.func.id == StructName: + const: ir.Constant | None = self.Trans.ClassHandler._BuildStructConstant(Node.value, StructName, Gen) + if const: + GlobalVar.initializer = const + else: + GlobalVar.initializer = ir.Constant(VarType, None) + else: + GlobalVar.initializer = ir.Constant(VarType, None) + Gen.variables[VarName] = GlobalVar + Gen.global_struct_class[VarName] = StructName + return + TypeInfo: CTypeInfo | None = CTypeInfo.FromNode(Node.annotation, self.Trans.SymbolTable) + if not TypeInfo or not TypeInfo.BaseType: + ArrayTypeInfo: CTypeInfo | None = CTypeInfo._HandleArraySubscript(Node.annotation, self.Trans.SymbolTable) + if ArrayTypeInfo: + TypeInfo = ArrayTypeInfo + IsCDefine: bool = False + if TypeInfo and TypeInfo.BaseType: + if isinstance(TypeInfo.BaseType, t._CTypedef): + return + if isinstance(TypeInfo.BaseType, t.CDefine): + IsCDefine = True + if not IsCDefine and self._IsTypedefAnnotation(Node.annotation): + IsCDefine = True + TTypeInfo: CTypeInfo | None = self.Trans.TypeMergeHandler.GetCTypeInfo(Node.annotation) + if TTypeInfo: + TTypeInfo.IsTypedef = True + TTypeInfo.Name = VarName + self.Trans.SymbolTable.insert(VarName, TTypeInfo) + if IsCDefine: + if Node.value: + define_constants: dict[str, int | float] = vars(Gen).setdefault('_define_constants', {}) + try: + const_value: int | float | None = self._eval_const_expr(Node.value, Gen) + if const_value is not None: + define_constants[VarName] = const_value + except Exception as _e: + if _config_mode == "strict": + self.Trans.LogWarning(f"异常被忽略: {_e}") + return + if TypeInfo is None: + TypeInfo = CTypeInfo() + TypeInfo.BaseType = t.CInt() + VarType: ir.Type = Gen._ctype_to_llvm(TypeInfo) + if isinstance(VarType, ir.VoidType): + VarType = ir.IntType(32) + if VarName in Gen.variables or VarName in Gen.module.globals: + return + if isinstance(VarType, (ir.IdentifiedStructType, ir.LiteralStructType)): + GlobalVar: ir.GlobalVariable = ir.GlobalVariable(Gen.module, VarType, name=VarName) + GlobalVar.initializer = ir.Constant(VarType, None) + Gen.variables[VarName] = GlobalVar + if TypeInfo and TypeInfo.IsStruct and TypeInfo.Name: + Gen.global_struct_class[VarName] = TypeInfo.Name + return + GlobalVar: ir.GlobalVariable = ir.GlobalVariable(Gen.module, VarType, name=VarName) + if Node.value: + if isinstance(Node.value, ast.Constant) and isinstance(Node.value.value, str) and isinstance(VarType, ir.PointerType): + str_val: str = Node.value.value + '\x00' + str_bytes: bytes = str_val.encode('utf-8') + arr_type: ir.ArrayType = ir.ArrayType(ir.IntType(8), len(str_bytes)) + str_gv_name: str = VarName + '_str' + str_gv: ir.GlobalVariable + if str_gv_name not in Gen.module.globals: + str_gv = ir.GlobalVariable(Gen.module, arr_type, name=str_gv_name) + str_gv.initializer = ir.Constant(arr_type, bytearray(str_bytes)) + str_gv.linkage = 'internal' + else: + str_gv = Gen.module.globals[str_gv_name] + ptr_type: ir.PointerType = ir.PointerType(ir.IntType(8)) + ptr_gv: ir.GlobalVariable + if VarName not in Gen.module.globals: + ptr_gv = ir.GlobalVariable(Gen.module, ptr_type, name=VarName) + ptr_gv.initializer = ir.Constant(ptr_type, str_gv) + ptr_gv.linkage = 'internal' + else: + ptr_gv = Gen.module.globals[VarName] + Gen.variables[VarName] = ptr_gv + else: + if isinstance(VarType, ir.ArrayType) and isinstance(Node.value, (ast.List, ast.Set)): + InitConstants: list[ir.Constant] | None = self.Trans._BuildMultiDimArrayInitConstants(Node.value, VarType, Gen) + if InitConstants: + GlobalVar.initializer = ir.Constant(VarType, InitConstants) + else: + if self._contains_identified_struct(VarType): + GlobalVar.linkage = 'common' + else: + zv: ir.Constant | None = Gen._zero_value_for_type(VarType) + if zv: + GlobalVar.initializer = zv + else: + GlobalVar.linkage = 'common' + else: + init_val: ir.Constant | None = self._eval_global_const(Node.value, VarType, Gen) + if init_val: + GlobalVar.initializer = init_val + elif isinstance(VarType, ir.BaseStructType): + GlobalVar.linkage = 'common' + else: + GlobalVar.initializer = Gen._zero_value_for_type(VarType) + else: + if isinstance(VarType, ir.BaseStructType) or self._contains_identified_struct(VarType): + GlobalVar.linkage = 'common' + else: + GlobalVar.initializer = Gen._zero_value_for_type(VarType) + Gen.variables[VarName] = GlobalVar + + def _eval_global_const(self, value_node: ast.expr, var_type: ir.Type, Gen: "Translator.LlvmGen") -> ir.Constant | None: + if isinstance(value_node, ast.Constant): + if isinstance(value_node.value, bool): + if isinstance(var_type, ir.IntType): + return ir.Constant(var_type, int(value_node.value)) + elif isinstance(value_node.value, int): + if isinstance(var_type, ir.IntType): + return ir.Constant(var_type, value_node.value) + elif isinstance(var_type, (ir.FloatType, ir.DoubleType)): + return ir.Constant(var_type, float(value_node.value)) + elif isinstance(value_node.value, float): + if isinstance(var_type, (ir.FloatType, ir.DoubleType)): + return ir.Constant(var_type, value_node.value) + elif isinstance(var_type, ir.IntType): + return ir.Constant(var_type, int(value_node.value)) + elif isinstance(value_node.value, str): + return None + # Handle type constructor calls like t.CDouble(1e-9), t.CFloat(3.14), t.CInt(42) + if isinstance(value_node, ast.Call): + inner_val: ir.Constant | None = self._eval_type_ctor_const(value_node, var_type, Gen) + if inner_val is not None: + return inner_val + if isinstance(value_node, ast.UnaryOp) and isinstance(value_node.op, ast.USub): + inner: ir.Constant | None = self._eval_global_const(value_node.operand, var_type, Gen) + if inner: + return ir.Constant(var_type, -inner.constant) + return None + + def _eval_type_ctor_const(self, call_node: ast.Call, var_type: ir.Type, Gen: "Translator.LlvmGen") -> ir.Constant | None: + """Try to evaluate t.CDouble(val), t.CFloat(val), t.CInt(val) etc. as a compile-time constant.""" + if not isinstance(call_node.func, ast.Attribute): + return None + if not isinstance(call_node.func.value, ast.Name): + return None + if call_node.func.value.id != 't': + return None + if not call_node.args or len(call_node.args) != 1: + return None + arg: ast.expr = call_node.args[0] + # Recursively evaluate the argument as a constant + arg_val: ir.Constant | None = self._eval_global_const(arg, var_type, Gen) + if arg_val is not None: + return arg_val + return None + + def _store_bitfield_member(self, struct_ptr: ir.Value, ClassName: str, field_name: str, Value: ir.Value) -> bool: + Gen: "Translator.LlvmGen" = self.Trans.LlvmGen + bitfield_offsets: dict[str, int] = Gen.class_member_bitoffsets.get(ClassName, {}) + bitfield_widths: dict[str, int] = Gen.class_member_bitfields.get(ClassName, {}) + if field_name not in bitfield_offsets: + return False + bit_offset: int = bitfield_offsets[field_name] + bit_width: int = bitfield_widths.get(field_name, 0) + if bit_width == 0: + return False + struct_type: ir.Type | None = Gen.structs.get(ClassName) + if struct_type is None or struct_type.elements is None or len(struct_type.elements) == 0: + return False + storage_type: ir.Type = struct_type.elements[0] + member_ptr: ir.Value = Gen.builder.gep(struct_ptr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), 0)], name=f"{field_name}_storage_ptr") + old_val: ir.Value = Gen._load(member_ptr, name=f"{field_name}_old_storage") + mask: int = (1 << bit_width) - 1 + shifted_mask: int = mask << bit_offset + inverted_mask: ir.Constant = ir.Constant(storage_type, ~shifted_mask & ((1 << storage_type.width) - 1)) + cleared: ir.Value = Gen.builder.and_(old_val, inverted_mask, name=f"{field_name}_cleared") + if isinstance(Value.type, ir.IntType) and Value.type.width < storage_type.width: + if getattr(Value.type, 'is_signed', False): + Value = Gen.builder.sext(Value, storage_type, name=f"{field_name}_sext_store") + else: + Value = Gen.builder.zext(Value, storage_type, name=f"{field_name}_zext_store") + elif Value.type.width != storage_type.width: + Value = Gen.builder.trunc(Value, storage_type, name=f"{field_name}_trunc_store") if Value.type.width > storage_type.width else Gen.builder.zext(Value, storage_type, name=f"{field_name}_zext_store") + shifted_value: ir.Value = Gen.builder.shl(Value, ir.Constant(storage_type, bit_offset), name=f"{field_name}_shift_store") + masked_value: ir.Value = Gen.builder.and_(shifted_value, ir.Constant(storage_type, shifted_mask), name=f"{field_name}_mask_store") + new_val: ir.Value = Gen.builder.or_(cleared, masked_value, name=f"{field_name}_new_storage") + Gen._store(new_val, member_ptr) + return True + + def _CheckEnumMemberAssignment(self, node: ast.expr) -> str | None: + def _get_attr_path(n: ast.expr) -> str | None: + if isinstance(n, ast.Name): + return n.id + elif isinstance(n, ast.Attribute): + return f"{_get_attr_path(n.value)}.{n.attr}" + return None + attr_path: str | None = _get_attr_path(node) + if not attr_path: + return None + parts: list[str] = attr_path.split('.') + if len(parts) >= 2: + enum_class_name: str = parts[-2] + member_name: str = parts[-1] + qualified_name: str = f"{enum_class_name}.{member_name}" + info: "SymbolTable.SymbolInfo | None" = self.Trans.SymbolTable.lookup(qualified_name) + if info: + if info.IsEnumMember and info.EnumName: + return info.EnumName + under_name: str = f"{enum_class_name}_{member_name}" + if self.Trans.SymbolTable.has(under_name): + info: "SymbolTable.SymbolInfo" = self.Trans.SymbolTable[under_name] + if info.IsEnumMember and info.EnumName: + return info.EnumName + for key in self.Trans.SymbolTable: + if key == member_name: + info: "SymbolTable.SymbolInfo" = self.Trans.SymbolTable[key] + if info.IsEnumMember and info.EnumName and info.EnumName == enum_class_name: + return enum_class_name + return None + + def _IsTypedefAnnotation(self, annotation: ast.expr) -> bool: + if isinstance(annotation, ast.Attribute): + if annotation.attr in ('CTypedef', 'CDefine'): + return True + if isinstance(annotation, ast.BinOp) and isinstance(annotation.op, ast.BitOr): + return self._IsTypedefAnnotation(annotation.left) or self._IsTypedefAnnotation(annotation.right) + if isinstance(annotation, ast.Subscript): + return self._IsTypedefAnnotation(annotation.value) + return False + + def _EmitGlobalAssignLlvm(self, Node: ast.Assign, Gen: "Translator.LlvmGen") -> None: + if len(Node.targets) == 1 and isinstance(Node.targets[0], ast.Name): + VarName: str = Node.targets[0].id + if VarName in Gen.variables or VarName in Gen.module.globals: + return + if isinstance(Node.value, ast.Call) and isinstance(Node.value.func, ast.Name): + FuncName: str = Node.value.func.id + if FuncName in Gen.structs: + IsUnion: bool = False + TypeInfo: "SymbolTable.SymbolInfo | None" = self.Trans.SymbolTable.lookup(FuncName) + if TypeInfo: + if TypeInfo.IsUnion: + IsUnion = True + if IsUnion: + StructType: ir.Type = Gen.structs[FuncName] + StructPtrType: ir.PointerType = ir.PointerType(StructType) + GlobalVar: ir.GlobalVariable = ir.GlobalVariable(Gen.module, StructPtrType, name=VarName) + GlobalVar.initializer = ir.Constant(StructPtrType, None) + Gen.variables[VarName] = GlobalVar + Gen.global_struct_class[VarName] = FuncName + return + StructName: str = FuncName + VarType: ir.Type = Gen.structs[StructName] + GlobalVar: ir.GlobalVariable = ir.GlobalVariable(Gen.module, VarType, name=VarName) + const: ir.Constant | None = self.Trans.ClassHandler._BuildStructConstant(Node.value, StructName, Gen) + if const: + GlobalVar.initializer = const + else: + GlobalVar.linkage = 'common' + Gen.variables[VarName] = GlobalVar + Gen.global_struct_class[VarName] = StructName + return + GlobalVar: ir.GlobalVariable = ir.GlobalVariable(Gen.module, ir.IntType(32), name=VarName) + init_val: ir.Constant | None = self._eval_global_const(Node.value, ir.IntType(32), Gen) + GlobalVar.initializer = init_val if init_val else ir.Constant(ir.IntType(32), 0) + Gen.variables[VarName] = GlobalVar + + def _eval_const_expr(self, node: ast.expr, Gen: "Translator.LlvmGen") -> int | float | None: + """计算常量表达式的值(委托到 ConstEvaluator)""" + ctx: EvalContext = EvalContext(Gen=Gen, symtab=self.Trans.SymbolTable, translator=self.Trans) + return ConstEvaluator.eval_full(node, ctx) + + def _eval_global_count(self, node: ast.expr, Gen: "Translator.LlvmGen") -> int | None: + val: int | float | None = self._eval_const_expr(node, Gen) + if val is not None: + if isinstance(val, float): + return int(val) + if isinstance(val, int): + return val + return None \ No newline at end of file diff --git a/lib/core/Handles/HandlesAugAssign.py b/lib/core/Handles/HandlesAugAssign.py index a8cf11d..4aa3c7a 100644 --- a/lib/core/Handles/HandlesAugAssign.py +++ b/lib/core/Handles/HandlesAugAssign.py @@ -1,212 +1,217 @@ -from __future__ import annotations -from typing import TYPE_CHECKING -if TYPE_CHECKING: - from lib.core.translator import Translator -from lib.core.Handles.HandlesBase import BaseHandle -import ast -import llvmlite.ir as ir - - -class AugAssignHandle(BaseHandle): - _AUGOP_MAP = { - ast.Add: '__iadd__', ast.Sub: '__isub__', ast.Mult: '__imul__', - ast.Div: '__itruediv__', ast.FloorDiv: '__ifloordiv__', ast.Mod: '__imod__', ast.Pow: '__ipow__', - } - _AUGOP_FALLBACK = { - ast.Add: '__add__', ast.Sub: '__sub__', ast.Mult: '__mul__', - ast.Div: '__truediv__', ast.FloorDiv: '__floordiv__', ast.Mod: '__mod__', ast.Pow: '__pow__', - } - - def _is_aug_unsigned(self, Node, OldVal, Value): - """判断增量赋值操作是否应使用无符号指令""" - Gen = self.Trans.LlvmGen - if isinstance(Node.target, ast.Name): - if Gen._check_node_unsigned(Node.target): - return True - elif isinstance(Node.target, ast.Attribute): - if Gen._check_node_unsigned(Node.target): - return True - elif isinstance(Node.target, ast.Subscript): - if Gen._check_node_unsigned(Node.target): - return True - if Node.value is not None and Gen._check_node_unsigned(Node.value): - return True - return False - - def _HandleAugAssignLlvm(self, Node): - Gen = self.Trans.LlvmGen - if isinstance(Node.target, ast.Name): - VarName = Node.target.id - if VarName in Gen.var_const_flags: - src_info = Gen._get_node_info() - print(f"[错误] 不能对 const 变量 '{VarName}' 增量赋值{src_info}") - import sys - sys.exit(1) - ClassName = Gen.var_struct_class.get(VarName) - iop_name = self._AUGOP_MAP.get(type(Node.op)) - if ClassName and iop_name: - iFuncName = f'{ClassName}.{iop_name}' - FuncName = f'{ClassName}.{self._AUGOP_FALLBACK.get(type(Node.op), "")}' - if iFuncName in Gen.functions or FuncName in Gen.functions: - OldVal = self.Trans.ExprHandler.HandleExprLlvm(ast.Name(id=VarName, ctx=ast.Load())) - Value = self.HandleExprLlvm(Node.value) - if OldVal and Value: - if iFuncName in Gen.functions: - result = self.Trans.ExprHandler._try_operator_overLoad(ClassName, iop_name, OldVal, Gen, Value) - else: - result = self.Trans.ExprHandler._try_operator_overLoad(ClassName, self._AUGOP_FALLBACK[type(Node.op)], OldVal, Gen, Value) - if result is not None: - if VarName in Gen.variables and Gen.variables[VarName] is not None: - VarPtr = Gen.variables[VarName] - if VarPtr.type.pointee == result.type: - Gen._store(result, VarPtr) - elif isinstance(VarPtr.type.pointee, ir.PointerType) and isinstance(result.type, ir.PointerType): - CastedVal = Gen.builder.bitcast(result, VarPtr.type.pointee, name=f"cast_{VarName}") - Gen._store(CastedVal, VarPtr) - else: - NewVar = Gen._allocaEntry(result.type, name=VarName) - Gen._store(result, NewVar) - Gen.variables[VarName] = NewVar - else: - Gen._reg_values[VarName] = result - Gen.variables[VarName] = None - return - Value = self.HandleExprLlvm(Node.value) - if not Value: - return - is_unsigned = self._is_aug_unsigned(Node, None, Value) - if isinstance(Node.target, ast.Name): - VarName = Node.target.id - Op = self.Trans.ExprHandler.GetOpSymbol(Node.op) - if VarName in Gen.global_vars and VarName in Gen.module.globals: - GVar = Gen.module.globals[VarName] - Gen.variables[VarName] = GVar - OldVal = Gen._load(GVar, name=VarName) - NewVal = Gen.emit_binary_op(Op, OldVal, Value, is_unsigned=is_unsigned) - Gen._store(NewVal, GVar) - return - if VarName in Gen._reg_values: - OldVal = Gen._reg_values[VarName] - saved_block = Gen.builder.block - entry_block = Gen.func.entry_basic_block - Gen.builder.position_at_start(entry_block) - var = Gen.builder.alloca(OldVal.type, name=VarName) - Gen._store(OldVal, var) - Gen.builder.position_at_end(saved_block) - Gen.variables[VarName] = var - del Gen._reg_values[VarName] - if VarName in Gen._direct_values: - OldVal = Gen._direct_values.pop(VarName) - saved_block = Gen.builder.block - entry_block = Gen.func.entry_basic_block - Gen.builder.position_at_start(entry_block) - var = Gen.builder.alloca(OldVal.type, name=VarName) - Gen._store(OldVal, var) - Gen.builder.position_at_end(saved_block) - Gen.variables[VarName] = var - if Gen.builder.block.is_terminated: - return - if VarName in Gen.variables and Gen.variables[VarName] is not None: - OldVal = Gen._load(Gen.variables[VarName], name=VarName) - store_ptr = Gen.variables[VarName] - if isinstance(OldVal.type, ir.PointerType) and isinstance(Value.type, ir.IntType): - if Value.type.width != 64: - Value = Gen.builder.zext(Value, ir.IntType(64), name="zext_ptr_offset") - if Op == '-' or Op == '+': - if Op == '-': - NegValue = Gen.builder.neg(Value, name="neg_ptr_offset") - NewVal = Gen.builder.gep(OldVal, [NegValue], name="ptr_sub") - else: - NewVal = Gen.builder.gep(OldVal, [Value], name="ptr_add") - else: - ptr_val = OldVal - OldVal = Gen._load(OldVal, name="deref_ptr_for_op") - orig_type = OldVal.type - if isinstance(OldVal.type, ir.IntType) and isinstance(Value.type, ir.IntType): - if OldVal.type.width < Value.type.width: - OldVal = Gen.builder.zext(OldVal, Value.type, name="zext_left") - elif OldVal.type.width > Value.type.width: - Value = Gen.builder.zext(Value, OldVal.type, name="zext_right") - NewVal = Gen.emit_binary_op(Op, OldVal, Value, is_unsigned=is_unsigned) - if isinstance(NewVal.type, ir.IntType) and isinstance(orig_type, ir.IntType): - if NewVal.type.width > orig_type.width: - NewVal = Gen.builder.trunc(NewVal, orig_type, name="trunc_result") - store_ptr = ptr_val - else: - if isinstance(OldVal.type, ir.IntType) and isinstance(Value.type, ir.IntType): - if OldVal.type.width < Value.type.width: - OldVal = Gen.builder.zext(OldVal, Value.type, name="zext_left") - elif OldVal.type.width > Value.type.width: - Value = Gen.builder.zext(Value, OldVal.type, name="zext_right") - elif isinstance(OldVal.type, ir.PointerType) and isinstance(Value.type, ir.IntType): - if Op in ('+', '-'): - if Value.type.width < 64: - Value = Gen.builder.zext(Value, ir.IntType(64), name="zext_ptr_offset_aug") - if Op == '-': - NegValue = Gen.builder.neg(Value, name="neg_ptr_offset_aug") - NewVal = Gen.builder.gep(OldVal, [NegValue], name="ptr_sub_aug") - else: - NewVal = Gen.builder.gep(OldVal, [Value], name="ptr_add_aug") - Gen._store(NewVal, store_ptr) - return - NewVal = Gen.emit_binary_op(Op, OldVal, Value, is_unsigned=is_unsigned) - if isinstance(store_ptr.type, ir.PointerType): - TargetType = store_ptr.type.pointee - if NewVal.type != TargetType: - Coerced = Gen._coerce_value(NewVal, TargetType) - if Coerced is not None: - NewVal = Coerced - Gen._store(NewVal, store_ptr) - elif VarName == 'pos': - var = Gen._allocaEntry(Value.type, name=VarName) - Gen.variables[VarName] = var - OldVal = Gen._load(var, name=VarName) - NewVal = Gen.emit_binary_op(Op, OldVal, Value, is_unsigned=is_unsigned) - Gen._store(NewVal, var) - elif isinstance(Node.target, ast.Attribute): - AttrName = Node.target.attr - OldVal = self.Trans.ExprHandler.HandleExprLlvm(Node.target) - if OldVal: - def _deref_if_ptr(val): - if isinstance(val.type, ir.PointerType): - pointee = val.type.pointee - if isinstance(pointee, (ir.IntType, ir.FloatType, ir.DoubleType)): - return Gen._load(val, name="deref_aug") - return val - OldVal = _deref_if_ptr(OldVal) - Op = self.Trans.ExprHandler.GetOpSymbol(Node.op) - if isinstance(OldVal.type, ir.IntType) and isinstance(Value.type, ir.IntType): - if OldVal.type.width < Value.type.width: - OldVal = Gen.builder.zext(OldVal, Value.type, name="zext_left_attr") - elif OldVal.type.width > Value.type.width: - Value = Gen.builder.zext(Value, OldVal.type, name="zext_right_attr") - NewVal = Gen.emit_binary_op(Op, OldVal, Value, is_unsigned=is_unsigned) - self.Trans.AssignHandler._HandleAttributeStoreLlvm(Node.target, NewVal) - elif isinstance(Node.target, ast.Subscript): - SubTarget = Node.target - ElemPtr = self.Trans.ExprAttrHandle.HandleSubscriptPtrLlvm(SubTarget) - if ElemPtr: - if isinstance(ElemPtr.type, ir.PointerType): - OldVal = Gen._load(ElemPtr, name="old_subscript_val") - Op = self.Trans.ExprHandler.GetOpSymbol(Node.op) - if isinstance(OldVal.type, ir.IntType) and isinstance(Value.type, ir.IntType): - if OldVal.type.width < Value.type.width: - OldVal = Gen.builder.zext(OldVal, Value.type, name="zext_left_sub") - elif OldVal.type.width > Value.type.width: - Value = Gen.builder.zext(Value, OldVal.type, name="zext_right_sub") - elif isinstance(OldVal.type, ir.PointerType) and isinstance(Value.type, ir.IntType): - if Op in ('+', '-'): - if Value.type.width < 64: - Value = Gen.builder.zext(Value, ir.IntType(64), name="zext_ptr_offset_sub") - if Op == '-': - NegValue = Gen.builder.neg(Value, name="neg_ptr_offset_sub") - NewVal = Gen.builder.gep(OldVal, [NegValue], name="ptr_sub_sub") - else: - NewVal = Gen.builder.gep(OldVal, [Value], name="ptr_add_sub") - Gen._store(NewVal, ElemPtr) - return - NewVal = Gen.emit_binary_op(Op, OldVal, Value, is_unsigned=is_unsigned) - if isinstance(NewVal.type, ir.IntType) and isinstance(ElemPtr.type.pointee, ir.IntType): - if NewVal.type.width > ElemPtr.type.pointee.width: - NewVal = Gen.builder.trunc(NewVal, ElemPtr.type.pointee, name="trunc_sub_result") - Gen._store(NewVal, ElemPtr) +from __future__ import annotations +from typing import TYPE_CHECKING +import ast +import sys +import llvmlite.ir as ir +if TYPE_CHECKING: + from lib.core.translator import Translator +from lib.core.VLogger import get_logger as _vlog +from lib.core.Handles.HandlesBase import BaseHandle + + +class AugAssignHandle(BaseHandle): + _AUGOP_MAP: dict[type, str] = { + ast.Add: '__iadd__', ast.Sub: '__isub__', ast.Mult: '__imul__', + ast.Div: '__itruediv__', ast.FloorDiv: '__ifloordiv__', ast.Mod: '__imod__', ast.Pow: '__ipow__', + } + _AUGOP_FALLBACK: dict[type, str] = { + ast.Add: '__add__', ast.Sub: '__sub__', ast.Mult: '__mul__', + ast.Div: '__truediv__', ast.FloorDiv: '__floordiv__', ast.Mod: '__mod__', ast.Pow: '__pow__', + } + + def _is_aug_unsigned(self, Node: ast.AugAssign, OldVal: ir.Value | None, Value: ir.Value) -> bool: + """判断增量赋值操作是否应使用无符号指令""" + Gen: "Translator.LlvmGen" = self.Trans.LlvmGen + if isinstance(Node.target, ast.Name): + if Gen._check_node_unsigned(Node.target): + return True + elif isinstance(Node.target, ast.Attribute): + if Gen._check_node_unsigned(Node.target): + return True + elif isinstance(Node.target, ast.Subscript): + if Gen._check_node_unsigned(Node.target): + return True + if Node.value is not None and Gen._check_node_unsigned(Node.value): + return True + return False + + def _HandleAugAssignLlvm(self, Node: ast.AugAssign) -> None: + Gen: "Translator.LlvmGen" = self.Trans.LlvmGen + if isinstance(Node.target, ast.Name): + VarName: str = Node.target.id + if VarName in Gen.var_const_flags: + src_info: str = Gen._get_node_info() + _vlog().error(f"不能对 const 变量 '{VarName}' 增量赋值{src_info}") + sys.exit(1) + ClassName: str | None = Gen.var_struct_class.get(VarName) + iop_name: str | None = self._AUGOP_MAP.get(type(Node.op)) + if ClassName and iop_name: + iFuncName: str = f'{ClassName}.{iop_name}' + FuncName: str = f'{ClassName}.{self._AUGOP_FALLBACK.get(type(Node.op), "")}' + if iFuncName in Gen.functions or FuncName in Gen.functions: + OldVal: ir.Value | None = self.Trans.ExprHandler.HandleExprLlvm(ast.Name(id=VarName, ctx=ast.Load())) + Value: ir.Value | None = self.HandleExprLlvm(Node.value) + if OldVal and Value: + result: ir.Value | None + if iFuncName in Gen.functions: + result = self.Trans.ExprHandler._try_operator_overLoad(ClassName, iop_name, OldVal, Gen, Value) + else: + result = self.Trans.ExprHandler._try_operator_overLoad(ClassName, self._AUGOP_FALLBACK[type(Node.op)], OldVal, Gen, Value) + if result is not None: + if VarName in Gen.variables and Gen.variables[VarName] is not None: + VarPtr: ir.Value = Gen.variables[VarName] + if VarPtr.type.pointee == result.type: + Gen._store(result, VarPtr) + elif isinstance(VarPtr.type.pointee, ir.PointerType) and isinstance(result.type, ir.PointerType): + CastedVal: ir.Value = Gen.builder.bitcast(result, VarPtr.type.pointee, name=f"cast_{VarName}") + Gen._store(CastedVal, VarPtr) + else: + NewVar: ir.AllocaInstr = Gen._allocaEntry(result.type, name=VarName) + Gen._store(result, NewVar) + Gen.variables[VarName] = NewVar + else: + Gen._reg_values[VarName] = result + Gen.variables[VarName] = None + return + Value: ir.Value | None = self.HandleExprLlvm(Node.value) + if not Value: + return + is_unsigned: bool = self._is_aug_unsigned(Node, None, Value) + if isinstance(Node.target, ast.Name): + VarName: str = Node.target.id + Op: str = self.Trans.ExprHandler.GetOpSymbol(Node.op) + if VarName in Gen.global_vars and VarName in Gen.module.globals: + GVar: ir.GlobalVariable = Gen.module.globals[VarName] + Gen.variables[VarName] = GVar + OldVal: ir.Value = Gen._load(GVar, name=VarName) + NewVal: ir.Value = Gen.emit_binary_op(Op, OldVal, Value, is_unsigned=is_unsigned) + Gen._store(NewVal, GVar) + return + if VarName in Gen._reg_values: + OldVal: ir.Value = Gen._reg_values[VarName] + saved_block: ir.Block = Gen.builder.block + entry_block: ir.Block = Gen.func.entry_basic_block + Gen.builder.position_at_start(entry_block) + var: ir.AllocaInstr = Gen.builder.alloca(OldVal.type, name=VarName) + Gen._store(OldVal, var) + Gen.builder.position_at_end(saved_block) + Gen.variables[VarName] = var + del Gen._reg_values[VarName] + if VarName in Gen._direct_values: + OldVal: ir.Value = Gen._direct_values.pop(VarName) + saved_block: ir.Block = Gen.builder.block + entry_block: ir.Block = Gen.func.entry_basic_block + Gen.builder.position_at_start(entry_block) + var: ir.AllocaInstr = Gen.builder.alloca(OldVal.type, name=VarName) + Gen._store(OldVal, var) + Gen.builder.position_at_end(saved_block) + Gen.variables[VarName] = var + if Gen.builder.block.is_terminated: + return + if VarName in Gen.variables and Gen.variables[VarName] is not None: + OldVal: ir.Value = Gen._load(Gen.variables[VarName], name=VarName) + store_ptr: ir.Value = Gen.variables[VarName] + if isinstance(OldVal.type, ir.PointerType) and isinstance(Value.type, ir.IntType): + if Value.type.width != 64: + Value = Gen.builder.zext(Value, ir.IntType(64), name="zext_ptr_offset") + NewVal: ir.Value + if Op == '-' or Op == '+': + if Op == '-': + NegValue: ir.Value = Gen.builder.neg(Value, name="neg_ptr_offset") + NewVal = Gen.builder.gep(OldVal, [NegValue], name="ptr_sub") + else: + NewVal = Gen.builder.gep(OldVal, [Value], name="ptr_add") + else: + ptr_val: ir.Value = OldVal + OldVal = Gen._load(OldVal, name="deref_ptr_for_op") + orig_type: ir.Type = OldVal.type + if isinstance(OldVal.type, ir.IntType) and isinstance(Value.type, ir.IntType): + if OldVal.type.width < Value.type.width: + OldVal = Gen.builder.zext(OldVal, Value.type, name="zext_left") + elif OldVal.type.width > Value.type.width: + Value = Gen.builder.zext(Value, OldVal.type, name="zext_right") + NewVal = Gen.emit_binary_op(Op, OldVal, Value, is_unsigned=is_unsigned) + if isinstance(NewVal.type, ir.IntType) and isinstance(orig_type, ir.IntType): + if NewVal.type.width > orig_type.width: + NewVal = Gen.builder.trunc(NewVal, orig_type, name="trunc_result") + store_ptr = ptr_val + else: + if isinstance(OldVal.type, ir.IntType) and isinstance(Value.type, ir.IntType): + if OldVal.type.width < Value.type.width: + OldVal = Gen.builder.zext(OldVal, Value.type, name="zext_left") + elif OldVal.type.width > Value.type.width: + Value = Gen.builder.zext(Value, OldVal.type, name="zext_right") + elif isinstance(OldVal.type, ir.PointerType) and isinstance(Value.type, ir.IntType): + if Op in ('+', '-'): + if Value.type.width < 64: + Value = Gen.builder.zext(Value, ir.IntType(64), name="zext_ptr_offset_aug") + NewVal: ir.Value + if Op == '-': + NegValue: ir.Value = Gen.builder.neg(Value, name="neg_ptr_offset_aug") + NewVal = Gen.builder.gep(OldVal, [NegValue], name="ptr_sub_aug") + else: + NewVal = Gen.builder.gep(OldVal, [Value], name="ptr_add_aug") + Gen._store(NewVal, store_ptr) + return + NewVal: ir.Value = Gen.emit_binary_op(Op, OldVal, Value, is_unsigned=is_unsigned) + if isinstance(store_ptr.type, ir.PointerType): + TargetType: ir.Type = store_ptr.type.pointee + if NewVal.type != TargetType: + Coerced: ir.Value | None = Gen._coerce_value(NewVal, TargetType) + if Coerced is not None: + NewVal = Coerced + Gen._store(NewVal, store_ptr) + elif VarName == 'pos': + var: ir.AllocaInstr = Gen._allocaEntry(Value.type, name=VarName) + Gen.variables[VarName] = var + OldVal: ir.Value = Gen._load(var, name=VarName) + NewVal: ir.Value = Gen.emit_binary_op(Op, OldVal, Value, is_unsigned=is_unsigned) + Gen._store(NewVal, var) + elif isinstance(Node.target, ast.Attribute): + AttrName: str = Node.target.attr + OldVal: ir.Value | None = self.Trans.ExprHandler.HandleExprLlvm(Node.target) + if OldVal: + def _deref_if_ptr(val: ir.Value) -> ir.Value: + if isinstance(val.type, ir.PointerType): + pointee: ir.Type = val.type.pointee + if isinstance(pointee, (ir.IntType, ir.FloatType, ir.DoubleType)): + return Gen._load(val, name="deref_aug") + return val + OldVal = _deref_if_ptr(OldVal) + Op: str = self.Trans.ExprHandler.GetOpSymbol(Node.op) + if isinstance(OldVal.type, ir.IntType) and isinstance(Value.type, ir.IntType): + if OldVal.type.width < Value.type.width: + OldVal = Gen.builder.zext(OldVal, Value.type, name="zext_left_attr") + elif OldVal.type.width > Value.type.width: + Value = Gen.builder.zext(Value, OldVal.type, name="zext_right_attr") + NewVal: ir.Value = Gen.emit_binary_op(Op, OldVal, Value, is_unsigned=is_unsigned) + self.Trans.AssignHandler._HandleAttributeStoreLlvm(Node.target, NewVal) + elif isinstance(Node.target, ast.Subscript): + SubTarget: ast.Subscript = Node.target + ElemPtr: ir.Value | None = self.Trans.ExprAttrHandle.HandleSubscriptPtrLlvm(SubTarget) + if ElemPtr: + if isinstance(ElemPtr.type, ir.PointerType): + OldVal: ir.Value = Gen._load(ElemPtr, name="old_subscript_val") + Op: str = self.Trans.ExprHandler.GetOpSymbol(Node.op) + if isinstance(OldVal.type, ir.IntType) and isinstance(Value.type, ir.IntType): + if OldVal.type.width < Value.type.width: + OldVal = Gen.builder.zext(OldVal, Value.type, name="zext_left_sub") + elif OldVal.type.width > Value.type.width: + Value = Gen.builder.zext(Value, OldVal.type, name="zext_right_sub") + elif isinstance(OldVal.type, ir.PointerType) and isinstance(Value.type, ir.IntType): + if Op in ('+', '-'): + if Value.type.width < 64: + Value = Gen.builder.zext(Value, ir.IntType(64), name="zext_ptr_offset_sub") + NewVal: ir.Value + if Op == '-': + NegValue: ir.Value = Gen.builder.neg(Value, name="neg_ptr_offset_sub") + NewVal = Gen.builder.gep(OldVal, [NegValue], name="ptr_sub_sub") + else: + NewVal = Gen.builder.gep(OldVal, [Value], name="ptr_add_sub") + Gen._store(NewVal, ElemPtr) + return + NewVal: ir.Value = Gen.emit_binary_op(Op, OldVal, Value, is_unsigned=is_unsigned) + if isinstance(NewVal.type, ir.IntType) and isinstance(ElemPtr.type.pointee, ir.IntType): + if NewVal.type.width > ElemPtr.type.pointee.width: + NewVal = Gen.builder.trunc(NewVal, ElemPtr.type.pointee, name="trunc_sub_result") + Gen._store(NewVal, ElemPtr) \ No newline at end of file diff --git a/lib/core/Handles/HandlesBase.py b/lib/core/Handles/HandlesBase.py index 2e7f6f6..5dcc256 100644 --- a/lib/core/Handles/HandlesBase.py +++ b/lib/core/Handles/HandlesBase.py @@ -1,618 +1,894 @@ -from __future__ import annotations -from typing import TYPE_CHECKING, Dict, Tuple -if TYPE_CHECKING: - from lib.core.translator import Translator -from lib.constants import config as _config -from lib.includes import t - -import ast -from typing import List, Dict +from __future__ import annotations +from typing import TYPE_CHECKING, Dict, Tuple, List, Any, Set +if TYPE_CHECKING: + from lib.core.translator import Translator + from lib.core.LlvmCodeGenerator import LlvmCodeGenerator + +import ast from enum import IntFlag, auto -from lib.core.TypeSpec import TypeSpec, SymbolMeta, FIELD_ROUTES - - -EXCEPTION_CODE_MAP = { - 'ValueError': 1, 'TypeError': 2, 'RuntimeError': 3, - 'ZeroDivisionError': 4, 'IndexError': 5, 'KeyError': 6, - 'IOError': 7, 'OSError': 8, 'AssertionError': 9, 'Exception': 99, -} - - -class FuncMeta(IntFlag): - NONE = 0 - STATIC_METHOD = auto() - PROPERTY_GETTER = auto() - PROPERTY_SETTER = auto() - PROPERTY_DELETER = auto() - CLASS_METHOD = auto() - ABSTRACT = auto() - - -class CTypeInfo: - """ - C 类型信息对象 - 统一符号表条目和类型计算 - - 设计原则: - - BaseType 是 CType 实例(来自 t 模块),永远不使用硬编码字符串 - - 描述符分为两种: - - VarConst/VarVolatile: 变量本身(指针)的限定符,如 int * const - - DataConst/DataVolatile: 指向数据的限定符,如 const int * - - 属性(类型计算): - - BaseType: t.CType - 基础类型实例 (如 t.CInt(), t.CVoid()) - - PtrCount: int - 指针层数 - - VarConst: bool - 变量本身(指针)是否 const,如 int * const - - VarVolatile: bool - 变量本身(指针)是否 volatile - - DataConst: bool - 指向的数据是否 const,如 const int * - - DataVolatile: bool - 指向的数据是否 volatile - - ArrayDims: List[str] - 数组维度 - - Storage: t.CType - 存储类 (static, extern 等) - - IsFuncPtr: bool - 是否函数指针 - - FuncPtrParams: List[Tuple[str, CTypeInfo]] - 函数指针参数列表,每个元素是 (参数名, 参数类型) - - FuncPtrReturn: CTypeInfo - 函数指针返回类型 - - IsBitField: bool - 是否位域 - - BitWidth: int - 位域宽度 - - IsTypedef/IsStruct/IsEnum/IsUnion: bool - 类型种类 - - 属性(符号表元数据): - - Name: str - 名称(struct/enum/union/typedef 名) - - Members: Dict[str, CTypeInfo] - 成员字典(用于 struct/union) - - OriginalType: str - typedef 的原始类型 - - DeclaredType: str - 声明类型 - - CreturnTypes: list - C 返回类型列表 - - Lineno: int - 定义行号 - - IsAnonymous: bool - 是否匿名类型 - - IsCpythonObject: bool - 是否 CPython 对象 - - IsEnumMember: bool - 是否枚举成员 - """ - - def __init__(self): - object.__setattr__(self, '_ts', TypeSpec()) - sm = SymbolMeta() - sm.meta_list = FuncMeta.NONE - object.__setattr__(self, '_sm', sm) - - # --- 新公共 API:供新代码直接访问 TypeSpec / SymbolMeta / SymbolKind --- - @property - def ts(self) -> TypeSpec: - """TypeSpec — 纯类型描述(只读)""" - return self._ts - - @property - def sm(self) -> SymbolMeta: - """SymbolMeta — 符号表元数据(只读)""" - return self._sm - - @property - def kind(self) -> 'SymbolKind': - """SymbolKind — 符号类型种类枚举""" - return self._sm.kind - - def __setattr__(self, name, value): - """属性设置路由 — 将旧字段名委托到 _ts/_sm/_kind_flags""" - if name == 'BaseType': - # BaseType 有复杂的 property setter(自动设置 IsStruct/IsEnum/IsUnion) - CTypeInfo.BaseType.fset(self, value) - return - if name in ('_ts', '_sm', 'ts', 'sm', 'kind'): - # _ts/_sm 内部字段直接设置;ts/sm/kind 是只读 property,禁止设置 - if name in ('ts', 'sm', 'kind'): - raise AttributeError(f"'CTypeInfo' attribute '{name}' is read-only") - object.__setattr__(self, name, value) - return - if name in FIELD_ROUTES: - target, field = FIELD_ROUTES[name] - if target == 'ts': - setattr(self._ts, field, value) - elif target == 'sm': - setattr(self._sm, field, value) - elif target == 'kf': - self._sm._kind_flags[field] = value - return - object.__setattr__(self, name, value) - - def __getattr__(self, name): - """属性读取路由 — 将旧字段名委托到 _ts/_sm/_kind_flags""" - try: - ts = object.__getattribute__(self, '_ts') - sm = object.__getattribute__(self, '_sm') - except AttributeError: - raise AttributeError(f"'CTypeInfo' object has no attribute '{name}'") - if name in FIELD_ROUTES: - target, field = FIELD_ROUTES[name] - if target == 'ts': - return getattr(ts, field) - elif target == 'sm': - return getattr(sm, field) - elif target == 'kf': - return sm._kind_flags.get(field, False) - raise AttributeError(f"'CTypeInfo' object has no attribute '{name}'") - - - - @property - def BaseType(self) -> t.CType | tuple: - return self._ts._base_type - - @BaseType.setter - def BaseType(self, value: t.CType | type | tuple | List): - """设置 BaseType,接受以下类型: - - - None: 清空 - - t.CType 实例: 单个类型,自动设置 IsStruct/IsEnum/IsUnion 标志 - - type (CType 子类): 如 t.CStruct,自动实例化 - - tuple/list of t.CType: 多个组合类型 - """ - ts = self._ts - kf = self._sm._kind_flags - - if value is None: - ts._base_type = None - kf['IsStruct'] = False - kf['IsEnum'] = False - kf['IsUnion'] = False - kf['IsRenum'] = False - return - - if isinstance(value, (tuple, list)): - ts._base_type = tuple(value) - for v in value: - if isinstance(v, t.CStruct): - kf['IsStruct'] = True - elif isinstance(v, t.CEnum): - kf['IsEnum'] = True - elif isinstance(v, t.CUnion): - kf['IsUnion'] = True - elif isinstance(v, t.REnum): - kf['IsRenum'] = True - kf['IsEnum'] = True - return - - if isinstance(value, type) and issubclass(value, t.CType): - ts._base_type = value() - return - - if isinstance(value, t.CType): - ts._base_type = value - if isinstance(value, t.CStruct): - kf['IsStruct'] = True - kf['IsEnum'] = False - kf['IsUnion'] = False - kf['IsRenum'] = False - elif isinstance(value, t.REnum): - kf['IsRenum'] = True - kf['IsEnum'] = True - kf['IsStruct'] = False - kf['IsUnion'] = False - elif isinstance(value, t.CEnum): - kf['IsEnum'] = True - kf['IsStruct'] = False - kf['IsUnion'] = False - kf['IsRenum'] = False - elif isinstance(value, t.CUnion): - kf['IsUnion'] = True - kf['IsStruct'] = False - kf['IsEnum'] = False - kf['IsRenum'] = False - return - - raise TypeError(f"BaseType must be t.CType instance, type subclass, or tuple of t.CType, got {type(value)}") - - @property - def TypeCls(self): - """获取 CType 类(从 BaseType 推断)""" - bt = self._ts._base_type - if bt: - return type(bt) - kf = self._sm._kind_flags - if kf.get('IsStruct'): - return t.CStruct - if kf.get('IsEnum'): - return t.CEnum - if kf.get('IsUnion'): - return t.CUnion - if kf.get('IsTypedef'): - return t._CTypedef - return None - - @property - def IsPtr(self) -> bool: - return self._ts.ptr_count > 0 - - @property - def IsVoid(self) -> bool: - return isinstance(self._ts._base_type, t.CVoid) - - @property - def IsStr(self) -> bool: - return isinstance(self._ts._base_type, t.CChar) and self._ts.ptr_count > 0 - - @property - def IsInt(self) -> bool: - bt = self._ts._base_type - return isinstance(bt, t.CType) and getattr(bt, 'IsSigned', None) is not None and bt.IsSigned is True and not isinstance(bt, t.CVoid) - - @property - def IsUInt(self) -> bool: - bt = self._ts._base_type - return isinstance(bt, t.CType) and getattr(bt, 'IsSigned', None) is False - - @property - def IsFloat(self) -> bool: - bt = self._ts._base_type - return isinstance(bt, t.CType) and getattr(bt, 'IsSigned', None) is None and getattr(bt, 'Size', 0) in (32, 64, 128) and not isinstance(bt, t.CVoid) - - @property - def IsDouble(self) -> bool: - bt = self._ts._base_type - return isinstance(bt, t.CDouble) or isinstance(bt, t.CFloat64T) - - @property - def IsPointerToChar(self) -> bool: - return isinstance(self._ts._base_type, t.CChar) and self._ts.ptr_count > 0 - - def ToString(self) -> str: - ts = self._ts - sm = self._sm - kf = sm._kind_flags - bt = ts._base_type - - if ts.is_func_ptr: - return 'Callable' - parts = [] - - if ts.storage and not isinstance(ts.storage, t.CExport): - parts.append(ts.storage.CName) - - if ts.data_const or ts.data_volatile: - qualifiers = [] - if ts.data_const: - qualifiers.append("const") - if ts.data_volatile: - qualifiers.append("volatile") - parts.append("_".join(qualifiers)) - - if kf.get('IsTypedef') and sm.name: - return sm.name - elif kf.get('IsRenum') and sm.name: - base_name = sm.name - elif bt: - base_name = getattr(bt, 'CName', None) or (bt if isinstance(bt, str) else str(bt)) - else: - base_name = "void" - - if ts.is_array_ptr: - ptr_str = "" - if ts.ptr_count > 0: - ptr_str = "*" * ts.ptr_count - if ts.array_ptr: - inner = ts.array_ptr.ToString() - if ptr_str: - parts.append(f"{base_name} {ptr_str}({inner})") - else: - parts.append(f"{base_name} ({inner})") - else: - if ptr_str: - parts.append(f"{base_name} {ptr_str}()") - else: - parts.append(f"{base_name} ()") - elif ts.array_ptr: - inner = ts.array_ptr.ToString() - if ts.ptr_count > 0: - parts.append(f"{base_name} {'*' * ts.ptr_count}({inner})") - else: - parts.append(f"{base_name} ({inner})") - else: - parts.append(base_name) - if ts.ptr_count > 0: - parts.append("*" * ts.ptr_count) - if ts.var_const: - parts.append("const") - if ts.var_volatile: - parts.append("volatile") - - for dim in ts.array_dims: - if dim: - parts.append(f"[{dim}]") - else: - parts.append("[]") - - return " ".join(parts) if parts else "void" - - @staticmethod - def CreateFromTypeName(TypeName: str) -> "CTypeInfo": - """从类型名字符串创建 CTypeInfo(兼容旧 API)""" - info = CTypeInfo() - if TypeName.startswith('struct '): - info.BaseType = t.CStruct(name=TypeName[7:].strip()) if TypeName[7:].strip() else t.CStruct() - elif TypeName.startswith('enum '): - info.BaseType = t.CEnum(name=TypeName[5:].strip()) if TypeName[5:].strip() else t.CEnum() - elif TypeName.startswith('union '): - info.BaseType = t.CUnion(name=TypeName[6:].strip()) if TypeName[6:].strip() else t.CUnion() - else: - info.BaseType = t.CStruct(name=TypeName) - return info - - # LLVM primitive type name → (CTypeClass, PtrCount) mapping - # Used when generic type inference produces LLVM type names like 'i64', 'double', etc. - _LLVM_PRIMITIVE_MAP = None - - @classmethod - def _get_llvm_primitive_map(cls): - if cls._LLVM_PRIMITIVE_MAP is not None: - return cls._LLVM_PRIMITIVE_MAP - from lib.includes import t as _t - cls._LLVM_PRIMITIVE_MAP = { - 'void': (_t.CVoid, 0), - 'i1': (_t.CInt, 0), - 'i8': (_t.CChar, 0), - 'i16': (_t.CShort, 0), - 'i32': (_t.CInt, 0), - 'i64': (_t.CLong, 0), - 'i128': (_t.CInt, 0), - 'float': (_t.CFloat, 0), - 'double': (_t.CDouble, 0), - 'fp128': (_t.CFloat128T, 0), - } - return cls._LLVM_PRIMITIVE_MAP - - @staticmethod - def FromTypeName(TypeName: str) -> "CTypeInfo": - """从简单类型名构造 CTypeInfo(不经过 FromStr 字符串解析)""" - from lib.core.TypeAnnotationResolver import TypeAnnotationResolver - return TypeAnnotationResolver.from_type_name(TypeName) - - # FromStr 已移除 - 类型解析不再经过中间字符串格式 - # typedef 展开直接走 CTypeInfo 对象,不经过字符串解析 - - @staticmethod - def TryEvalConstExpr(node, SymbolTable): - from lib.core.TypeAnnotationResolver import TypeAnnotationResolver - return TypeAnnotationResolver.try_eval_const_expr(node, SymbolTable) - - @classmethod - def FromNode(cls, Node: ast.AST, SymbolTable: dict) -> "CTypeInfo": - """从 AST 节点解析 CTypeInfo(类方法) - - Args: - Node: AST 节点(如 ast.Name, ast.Attribute 等) - SymbolTable: 符号表字典 - """ - from lib.core.TypeAnnotationResolver import TypeAnnotationResolver - return TypeAnnotationResolver.from_node(Node, SymbolTable) - - - def Copy(self) -> "CTypeInfo": - NewInfo = CTypeInfo() - NewInfo._ts = self._ts.copy() - NewInfo._sm = self._sm.copy() - # CTypeInfo 引用字段需要深拷贝 - if isinstance(NewInfo._ts.func_ptr_return, CTypeInfo): - NewInfo._ts.func_ptr_return = NewInfo._ts.func_ptr_return.Copy() - if isinstance(NewInfo._ts.original_type, CTypeInfo): - NewInfo._ts.original_type = NewInfo._ts.original_type.Copy() - if NewInfo._ts.array_ptr: - NewInfo._ts.array_ptr = NewInfo._ts.array_ptr.Copy() - return NewInfo - - def get(self, key, default=None): - """获取额外属性""" - return self._sm._extra.get(key, default) - - def set(self, key, value): - """设置额外属性""" - self._sm._extra[key] = value - - @staticmethod - def VoidTypeInfo() -> "CTypeInfo": - info = CTypeInfo() - info.BaseType = t.CVoid() - return info - - def ToLLVM(self, Gen): - from llvmlite import ir as _ir - if Gen is None: - return _ir.IntType(32) - return Gen._ctype_to_llvm(self) - - def ToLLVMBase(self, Gen): - from llvmlite import ir as _ir - if Gen is None: - return _ir.IntType(32) - return Gen._base_ctype_to_llvm(self.BaseType, self) - - def __str__(self) -> str: - return self.ToString() - - def __repr__(self) -> str: - ts = self._ts - kf = self._sm._kind_flags - return f"CTypeInfo(BaseType={ts._base_type}, PtrCount={ts.ptr_count}, IsTypedef={kf.get('IsTypedef', False)}, OriginalType={ts.original_type!r}, VarConst={ts.var_const}, DataConst={ts.data_const})" - - -class CTypeHelper: - - @staticmethod - def GetTModuleCType(TypeName: str): - from lib.includes.t import CTypeRegistry - result = CTypeRegistry.GetClassByName(TypeName) - if result is not None: - return result - TypeClass = getattr(t, TypeName, None) - if TypeClass and isinstance(TypeClass, type) and issubclass(TypeClass, t.CType): - return TypeClass - FallbackClass = getattr(t, f'_{TypeName}', None) - if FallbackClass and isinstance(FallbackClass, type) and issubclass(FallbackClass, t.CType): - return FallbackClass - return None - - @staticmethod - def GetCName(type_or_name) -> str: - from lib.includes.t import CTypeRegistry - if isinstance(type_or_name, str): - cls = CTypeRegistry.GetClassByName(type_or_name) - if cls is None: - cls = CTypeHelper.GetTModuleCType(type_or_name) - if cls: - return CTypeRegistry.CTypeToCName(cls) or type_or_name - return type_or_name - elif isinstance(type_or_name, type) and issubclass(type_or_name, t.CType): - return CTypeRegistry.CTypeToCName(type_or_name) or '' - return '' - - @staticmethod - def StripTypePrefix(TypeStr: str) -> str: - for prefix in ('struct ', 'enum ', 'union '): - if TypeStr.startswith(prefix): - return TypeStr[len(prefix):].strip() - return TypeStr - - @staticmethod - def IsVoidType(TypeStr: str) -> bool: - from lib.includes.t import CTypeRegistry - cls = CTypeRegistry.GetClassByName(TypeStr) or CTypeRegistry.CNameToClass(TypeStr) - if cls: - return CTypeRegistry.CTypeToLLVM(cls) == 'void' - return TypeStr == 'void' or TypeStr == 'struct void' or TypeStr == 'union void' - - @staticmethod - def IsStrType(TypeStr: str) -> bool: - from lib.includes.t import CTypeRegistry - resolved = CTypeRegistry.ResolveName(TypeStr) - if resolved: - ctype_cls, ptr_level = resolved - if CTypeRegistry.CTypeToLLVM(ctype_cls) == 'i8' and ptr_level > 0: - return True - return TypeStr in ('str', 'bytes', 'struct str', 'union str', 'c_char') - - -class BuiltinTypeMap: - """ - 内置类型映射表 - 字符串到 (CType类, PtrCount) 的映射 - - 用法:BuiltinTypeMap.Get('int') -> (t.CInt, 0) - BuiltinTypeMap.Get('BYTEPTR') -> (t.CUnsignedChar, 1) - """ - - _map = None - - @classmethod - def _build_map(cls): - if cls._map is not None: - return cls._map - from lib.includes.t import CTypeRegistry - CTypeRegistry._build() - cls._map = {} - for cname, ctype_cls in CTypeRegistry._cname_to_class.items(): - cls._map[cname] = (ctype_cls, 0) - for pyname, ctype_cls in CTypeRegistry._name_to_class.items(): - pos = getattr(ctype_cls, 'position', frozenset()) - if t.CType.POINTER in pos and t.CType.BASE not in pos: - cls._map[pyname] = (ctype_cls, 1) - elif pyname not in cls._map: - cls._map[pyname] = (ctype_cls, 0) - _SPECIAL = { - 'str': (t.CChar, 1), 'bytes': (t.CChar, 1), 'unsigned': (t.CUnsigned, 0), - 'signed': (t.CInt, 0), 'signed int': (t.CInt, 0), - 'signed char': (t.CSignedChar, 0), 'bool': (t.CBool, 0), - 'void': (t.CVoid, 0), 'Void': (t.CVoid, 0), - } - for k, v in _SPECIAL.items(): - if k not in cls._map: - cls._map[k] = v - _PTR_ALIASES = { - 'INTPTR': (t.CInt, 1), 'UINTPTR': (t.CUnsignedInt, 1), - 'VOIDPTR': (t.CVoid, 1), 'BYTEPTR': (t.CUnsignedChar, 1), - 'CHAR8PTR': (t.CChar8T, 1), 'CHAR16PTR': (t.CChar16T, 1), - 'CHAR32PTR': (t.CChar32T, 1), - } - for k, v in _PTR_ALIASES.items(): - if k not in cls._map: - cls._map[k] = v - _FLOAT_ALIASES = { - 'FLOAT8': (t.CFloat8T, 0), 'FLOAT16': (t.CFloat16T, 0), - 'FLOAT32': (t.CFloat32T, 0), 'FLOAT64': (t.CFloat64T, 0), - 'FLOAT128': (t.CFloat128T, 0), - } - for k, v in _FLOAT_ALIASES.items(): - if k not in cls._map: - cls._map[k] = v - return cls._map - - @classmethod - def Get(cls, type_name: str): - """获取类型类和指针层级""" - return cls._build_map().get(type_name) - - -class BaseHandle: - def __init__(self, translator: "Translator") -> None: - self.Trans: Translator = translator - self._CurrentCpythonObjectClass: str = None - - @staticmethod - def _attr(obj, name, default=None): - if obj is None: - return default - return getattr(obj, name, default) - - @staticmethod - def _is_char_pointer(val): - """检查值是否为 char* (i8*) 指针""" - from llvmlite import ir - if not isinstance(val.type, ir.PointerType): - return False - pointee = val.type.pointee - return isinstance(pointee, ir.IntType) and pointee.width == 8 - - def HandleExprLlvm(self, Node, VarType=None): - return self.Trans.ExprHandler.HandleExprLlvm(Node, VarType) - - def HandleBodyLlvm(self, Body): - return self.Trans.BodyHandler.HandleBodyLlvm(Body) - - def _get_int_ptr(self, Node): - import ast - from llvmlite import ir - Gen = self.Trans.LlvmGen - if isinstance(Node, ast.Name): - if Node.id in Gen.variables: - return Gen.variables[Node.id] - elif isinstance(Node, ast.Attribute): - obj_val = self.HandleExprLlvm(Node.value) - if not obj_val: - return None - if isinstance(obj_val.type, ir.PointerType): - pointee = obj_val.type.pointee - if isinstance(pointee, (ir.IdentifiedStructType, ir.LiteralStructType)): - StructName = None - if isinstance(pointee, ir.IdentifiedStructType): - StructName = pointee.name - if not StructName: - for ClassName, struct_type in Gen.structs.items(): - if struct_type == pointee: - StructName = ClassName - break - if StructName and StructName in Gen.structs: - offset = self.Trans.ExprHandler._get_llvm_member_offset(Node.attr, StructName, Gen) - member_ptr = Gen.builder.gep(obj_val, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=f"{Node.attr}_ptr") - return member_ptr - return None - - def _IsTModuleType(self, TypeName: str) -> bool: - if TypeName in ('t', 'State', 'Bit', 'Anonymous', 'Postdefinition'): - return True - TypeClass = getattr(t, TypeName, None) - if TypeClass and isinstance(TypeClass, type): - if issubclass(TypeClass, t.CType): - return True - FallbackClass = getattr(t, f'_{TypeName}', None) - if FallbackClass and isinstance(FallbackClass, type): - if issubclass(FallbackClass, t.CType): - return True - return False - - -StrictMode = _config.mode == 'strict' - - + +from llvmlite import ir as _ir + +from lib.constants import config as _config +from lib.includes import t +from lib.includes.t import CTypeRegistry +from lib.core.TypeSpec import TypeSpec, SymbolMeta, FIELD_ROUTES, SymbolKind +from lib.core.VLogger import get_logger as _vlog + + +EXCEPTION_CODE_MAP: dict[str, int] = { + 'ValueError': 1, 'TypeError': 2, 'RuntimeError': 3, + 'ZeroDivisionError': 4, 'IndexError': 5, 'KeyError': 6, + 'IOError': 7, 'OSError': 8, 'AssertionError': 9, 'Exception': 99, +} + + +class FuncMeta(IntFlag): + NONE = 0 + STATIC_METHOD = auto() + PROPERTY_GETTER = auto() + PROPERTY_SETTER = auto() + PROPERTY_DELETER = auto() + CLASS_METHOD = auto() + ABSTRACT = auto() + + +class CTypeInfo: + """ + C 类型信息对象 - 统一符号表条目和类型计算 + + 设计原则: + - BaseType 是 CType 实例(来自 t 模块),永远不使用硬编码字符串 + - 描述符分为两种: + - VarConst/VarVolatile: 变量本身(指针)的限定符,如 int * const + - DataConst/DataVolatile: 指向数据的限定符,如 const int * + + 属性(类型计算): + - BaseType: t.CType - 基础类型实例 (如 t.CInt(), t.CVoid()) + - PtrCount: int - 指针层数 + - VarConst: bool - 变量本身(指针)是否 const,如 int * const + - VarVolatile: bool - 变量本身(指针)是否 volatile + - DataConst: bool - 指向的数据是否 const,如 const int * + - DataVolatile: bool - 指向的数据是否 volatile + - ArrayDims: List[str] - 数组维度 + - Storage: t.CType - 存储类 (static, extern 等) + - IsFuncPtr: bool - 是否函数指针 + - FuncPtrParams: List[Tuple[str, CTypeInfo]] - 函数指针参数列表,每个元素是 (参数名, 参数类型) + - FuncPtrReturn: CTypeInfo - 函数指针返回类型 + - IsBitField: bool - 是否位域 + - BitWidth: int - 位域宽度 + - IsTypedef/IsStruct/IsEnum/IsUnion: bool - 类型种类 + + 属性(符号表元数据): + - Name: str - 名称(struct/enum/union/typedef 名) + - Members: Dict[str, CTypeInfo] - 成员字典(用于 struct/union) + - OriginalType: str - typedef 的原始类型 + - DeclaredType: str - 声明类型 + - CreturnTypes: list - C 返回类型列表 + - Lineno: int - 定义行号 + - IsAnonymous: bool - 是否匿名类型 + - IsCpythonObject: bool - 是否 CPython 对象 + - IsEnumMember: bool - 是否枚举成员 + """ + + def __init__(self) -> None: + object.__setattr__(self, '_ts', TypeSpec()) + sm: SymbolMeta = SymbolMeta() + sm.meta_list = FuncMeta.NONE + object.__setattr__(self, '_sm', sm) + + # --- 新公共 API:供新代码直接访问 TypeSpec / SymbolMeta / SymbolKind --- + @property + def ts(self) -> TypeSpec: + """TypeSpec — 纯类型描述(只读)""" + return self._ts + + @property + def sm(self) -> SymbolMeta: + """SymbolMeta — 符号表元数据(只读)""" + return self._sm + + @property + def kind(self) -> 'SymbolKind': + """SymbolKind — 符号类型种类枚举""" + return self._sm.kind + + def __setattr__(self, name: str, value: Any) -> None: + """属性设置路由 — 将旧字段名委托到 _ts/_sm/_kind_flags""" + if name == 'BaseType': + # BaseType 有复杂的 property setter(自动设置 IsStruct/IsEnum/IsUnion) + CTypeInfo.BaseType.fset(self, value) + return + if name in ('_ts', '_sm', 'ts', 'sm', 'kind'): + # _ts/_sm 内部字段直接设置;ts/sm/kind 是只读 property,禁止设置 + if name in ('ts', 'sm', 'kind'): + raise AttributeError(f"'CTypeInfo' attribute '{name}' is read-only") + object.__setattr__(self, name, value) + return + if name in FIELD_ROUTES: + target: str + field: str + target, field = FIELD_ROUTES[name] + if target == 'ts': + setattr(self._ts, field, value) + elif target == 'sm': + setattr(self._sm, field, value) + elif target == 'kf': + self._sm._kind_flags[field] = value + return + object.__setattr__(self, name, value) + + def __getattr__(self, name: str) -> Any: + """属性读取路由 — 将旧字段名委托到 _ts/_sm/_kind_flags""" + try: + ts: TypeSpec = object.__getattribute__(self, '_ts') + sm: SymbolMeta = object.__getattribute__(self, '_sm') + except AttributeError: + raise AttributeError(f"'CTypeInfo' object has no attribute '{name}'") + if name in FIELD_ROUTES: + target: str + field: str + target, field = FIELD_ROUTES[name] + if target == 'ts': + return getattr(ts, field) + elif target == 'sm': + return getattr(sm, field) + elif target == 'kf': + return sm._kind_flags.get(field, False) + raise AttributeError(f"'CTypeInfo' object has no attribute '{name}'") + + + + @property + def BaseType(self) -> t.CType | tuple | None: + return self._ts._base_type + + @BaseType.setter + def BaseType(self, value: t.CType | type | tuple | List | None) -> None: + """设置 BaseType,接受以下类型: + + - None: 清空 + - t.CType 实例: 单个类型,自动设置 IsStruct/IsEnum/IsUnion 标志 + - type (CType 子类): 如 t.CStruct,自动实例化 + - tuple/list of t.CType: 多个组合类型 + """ + ts: TypeSpec = self._ts + kf: dict[str, bool] = self._sm._kind_flags + + if value is None: + ts._base_type = None + kf['IsStruct'] = False + kf['IsEnum'] = False + kf['IsUnion'] = False + kf['IsRenum'] = False + return + + if isinstance(value, (tuple, list)): + ts._base_type = tuple(value) + for v in value: + if isinstance(v, t.CStruct): + kf['IsStruct'] = True + elif isinstance(v, t.CEnum): + kf['IsEnum'] = True + elif isinstance(v, t.CUnion): + kf['IsUnion'] = True + elif isinstance(v, t.REnum): + kf['IsRenum'] = True + kf['IsEnum'] = True + return + + if isinstance(value, type) and issubclass(value, t.CType): + ts._base_type = value() + return + + if isinstance(value, t.CType): + ts._base_type = value + if isinstance(value, t.CStruct): + kf['IsStruct'] = True + kf['IsEnum'] = False + kf['IsUnion'] = False + kf['IsRenum'] = False + elif isinstance(value, t.REnum): + kf['IsRenum'] = True + kf['IsEnum'] = True + kf['IsStruct'] = False + kf['IsUnion'] = False + elif isinstance(value, t.CEnum): + kf['IsEnum'] = True + kf['IsStruct'] = False + kf['IsUnion'] = False + kf['IsRenum'] = False + elif isinstance(value, t.CUnion): + kf['IsUnion'] = True + kf['IsStruct'] = False + kf['IsEnum'] = False + kf['IsRenum'] = False + return + + raise TypeError(f"BaseType must be t.CType instance, type subclass, or tuple of t.CType, got {type(value)}") + + @property + def TypeCls(self) -> type | None: + """获取 CType 类(从 BaseType 推断)""" + bt: t.CType | tuple | None = self._ts._base_type + if bt: + return type(bt) + kf: dict[str, bool] = self._sm._kind_flags + if kf.get('IsStruct'): + return t.CStruct + if kf.get('IsEnum'): + return t.CEnum + if kf.get('IsUnion'): + return t.CUnion + if kf.get('IsTypedef'): + return t._CTypedef + return None + + @property + def IsPtr(self) -> bool: + return self._ts.ptr_count > 0 + + @property + def IsVoid(self) -> bool: + return isinstance(self._ts._base_type, t.CVoid) + + @property + def IsStr(self) -> bool: + return isinstance(self._ts._base_type, t.CChar) and self._ts.ptr_count > 0 + + @property + def IsInt(self) -> bool: + bt: t.CType | tuple | None = self._ts._base_type + return isinstance(bt, t.CType) and getattr(bt, 'IsSigned', None) is not None and bt.IsSigned is True and not isinstance(bt, t.CVoid) + + @property + def IsUInt(self) -> bool: + bt: t.CType | tuple | None = self._ts._base_type + return isinstance(bt, t.CType) and getattr(bt, 'IsSigned', None) is False + + @property + def IsFloat(self) -> bool: + bt: t.CType | tuple | None = self._ts._base_type + return isinstance(bt, t.CType) and getattr(bt, 'IsSigned', None) is None and getattr(bt, 'Size', 0) in (32, 64, 128) and not isinstance(bt, t.CVoid) + + @property + def IsDouble(self) -> bool: + bt: t.CType | tuple | None = self._ts._base_type + return isinstance(bt, t.CDouble) or isinstance(bt, t.CFloat64T) + + @property + def IsPointerToChar(self) -> bool: + return isinstance(self._ts._base_type, t.CChar) and self._ts.ptr_count > 0 + + def ToString(self) -> str: + ts: TypeSpec = self._ts + sm: SymbolMeta = self._sm + kf: dict[str, bool] = sm._kind_flags + bt: t.CType | tuple | None = ts._base_type + + if ts.is_func_ptr: + return 'Callable' + parts: list[str] = [] + + if ts.storage and not isinstance(ts.storage, t.CExport): + parts.append(type(ts.storage).__name__) + + if ts.data_const or ts.data_volatile: + qualifiers: list[str] = [] + if ts.data_const: + qualifiers.append("const") + if ts.data_volatile: + qualifiers.append("volatile") + parts.append("_".join(qualifiers)) + + if kf.get('IsTypedef') and sm.name: + return sm.name + elif kf.get('IsRenum') and sm.name: + base_name: str = sm.name + elif bt: + if isinstance(bt, str): + base_name = bt + elif isinstance(bt, type) and issubclass(bt, t.CType): + base_name = bt.__name__ + elif isinstance(bt, t.CType): + base_name = type(bt).__name__ + else: + base_name = str(bt) + else: + base_name = "void" + + if ts.is_array_ptr: + ptr_str: str = "" + if ts.ptr_count > 0: + ptr_str = "*" * ts.ptr_count + if ts.array_ptr: + inner: str = ts.array_ptr.ToString() + if ptr_str: + parts.append(f"{base_name} {ptr_str}({inner})") + else: + parts.append(f"{base_name} ({inner})") + else: + if ptr_str: + parts.append(f"{base_name} {ptr_str}()") + else: + parts.append(f"{base_name} ()") + elif ts.array_ptr: + inner = ts.array_ptr.ToString() + if ts.ptr_count > 0: + parts.append(f"{base_name} {'*' * ts.ptr_count}({inner})") + else: + parts.append(f"{base_name} ({inner})") + else: + parts.append(base_name) + if ts.ptr_count > 0: + parts.append("*" * ts.ptr_count) + if ts.var_const: + parts.append("const") + if ts.var_volatile: + parts.append("volatile") + + for dim in ts.array_dims: + if dim: + parts.append(f"[{dim}]") + else: + parts.append("[]") + + return " ".join(parts) if parts else "void" + + @staticmethod + def CreateFromTypeName(TypeName: str) -> "CTypeInfo": + """从类型名字符串创建 CTypeInfo(兼容旧 API)""" + info: CTypeInfo = CTypeInfo() + if TypeName.startswith('struct '): + info.BaseType = t.CStruct(name=TypeName[7:].strip()) if TypeName[7:].strip() else t.CStruct() + elif TypeName.startswith('enum '): + info.BaseType = t.CEnum(name=TypeName[5:].strip()) if TypeName[5:].strip() else t.CEnum() + elif TypeName.startswith('union '): + info.BaseType = t.CUnion(name=TypeName[6:].strip()) if TypeName[6:].strip() else t.CUnion() + else: + info.BaseType = t.CStruct(name=TypeName) + return info + + # LLVM primitive type name → (CTypeClass, PtrCount) mapping + # Used when generic type inference produces LLVM type names like 'i64', 'double', etc. + _LLVM_PRIMITIVE_MAP: dict[str, tuple[type, int]] | None = None + + @classmethod + def _get_llvm_primitive_map(cls) -> dict[str, tuple[type, int]]: + if cls._LLVM_PRIMITIVE_MAP is not None: + return cls._LLVM_PRIMITIVE_MAP + cls._LLVM_PRIMITIVE_MAP = { + 'void': (t.CVoid, 0), + 'i1': (t.CInt, 0), + 'i8': (t.CChar, 0), + 'i16': (t.CShort, 0), + 'i32': (t.CInt, 0), + 'i64': (t.CLong, 0), + 'i128': (t.CInt, 0), + 'float': (t.CFloat, 0), + 'double': (t.CDouble, 0), + 'fp128': (t.CFloat128T, 0), + } + return cls._LLVM_PRIMITIVE_MAP + + @staticmethod + def FromTypeName(TypeName: str) -> "CTypeInfo": + """从简单类型名构造 CTypeInfo(不经过 FromStr 字符串解析)""" + from lib.core.TypeAnnotationResolver import TypeAnnotationResolver + return TypeAnnotationResolver.from_type_name(TypeName) + + # FromStr 已移除 - 类型解析不再经过中间字符串格式 + # typedef 展开直接走 CTypeInfo 对象,不经过字符串解析 + + @staticmethod + def TryEvalConstExpr(node: ast.AST, SymbolTable: Any) -> Any: + from lib.core.TypeAnnotationResolver import TypeAnnotationResolver + return TypeAnnotationResolver.try_eval_const_expr(node, SymbolTable) + + @classmethod + def FromNode(cls, Node: ast.AST, SymbolTable: Any) -> "CTypeInfo": + """从 AST 节点解析 CTypeInfo(类方法) + + Args: + Node: AST 节点(如 ast.Name, ast.Attribute 等) + SymbolTable: 符号表字典 + """ + from lib.core.TypeAnnotationResolver import TypeAnnotationResolver + return TypeAnnotationResolver.from_node(Node, SymbolTable) + + + def Copy(self) -> "CTypeInfo": + NewInfo: CTypeInfo = CTypeInfo() + NewInfo._ts = self._ts.copy() + NewInfo._sm = self._sm.copy() + # CTypeInfo 引用字段需要深拷贝 + if isinstance(NewInfo._ts.func_ptr_return, CTypeInfo): + NewInfo._ts.func_ptr_return = NewInfo._ts.func_ptr_return.Copy() + if isinstance(NewInfo._ts.original_type, CTypeInfo): + NewInfo._ts.original_type = NewInfo._ts.original_type.Copy() + if NewInfo._ts.array_ptr: + NewInfo._ts.array_ptr = NewInfo._ts.array_ptr.Copy() + return NewInfo + + def get(self, key: str, default: Any = None) -> Any: + """获取额外属性""" + return self._sm._extra.get(key, default) + + def set(self, key: str, value: Any) -> None: + """设置额外属性""" + self._sm._extra[key] = value + + @staticmethod + def VoidTypeInfo() -> "CTypeInfo": + info: CTypeInfo = CTypeInfo() + info.BaseType = t.CVoid() + return info + + def ToLLVM(self, Gen: LlvmCodeGenerator) -> _ir.Type: + if Gen is None: + return _ir.IntType(32) + return Gen._ctype_to_llvm(self) + + def ToLLVMBase(self, Gen: LlvmCodeGenerator) -> _ir.Type: + if Gen is None: + return _ir.IntType(32) + return Gen._base_ctype_to_llvm(self.BaseType, self) + + def __str__(self) -> str: + return self.ToString() + + def __repr__(self) -> str: + ts: TypeSpec = self._ts + kf: dict[str, bool] = self._sm._kind_flags + return f"CTypeInfo(BaseType={ts._base_type}, PtrCount={ts.ptr_count}, IsTypedef={kf.get('IsTypedef', False)}, OriginalType={ts.original_type!r}, VarConst={ts.var_const}, DataConst={ts.data_const})" + + +class CTypeHelper: + + @staticmethod + def GetTModuleCType(TypeName: str) -> type | None: + result: type | None = CTypeRegistry.GetClassByName(TypeName) + if result is not None: + return result + TypeClass: type | None = getattr(t, TypeName, None) + if TypeClass and isinstance(TypeClass, type) and issubclass(TypeClass, t.CType): + return TypeClass + FallbackClass: type | None = getattr(t, f'_{TypeName}', None) + if FallbackClass and isinstance(FallbackClass, type) and issubclass(FallbackClass, t.CType): + return FallbackClass + return None + + @staticmethod + def GetCName(type_or_name: str | type) -> str: + if isinstance(type_or_name, str): + cls: type | None = CTypeRegistry.GetClassByName(type_or_name) + if cls is None: + cls = CTypeHelper.GetTModuleCType(type_or_name) + if cls: + return cls.__name__ + return type_or_name + elif isinstance(type_or_name, type) and issubclass(type_or_name, t.CType): + return type_or_name.__name__ + return '' + + @staticmethod + def StripTypePrefix(TypeStr: str) -> str: + for prefix in ('struct ', 'enum ', 'union '): + if TypeStr.startswith(prefix): + return TypeStr[len(prefix):].strip() + return TypeStr + + @staticmethod + def IsVoidType(TypeStr: str) -> bool: + resolved: tuple[type, int] | None = CTypeRegistry.ResolveName(TypeStr) + if resolved: + return CTypeRegistry.CTypeToLLVM(resolved[0]) == 'void' + return TypeStr == 'void' or TypeStr == 'struct void' or TypeStr == 'union void' + + @staticmethod + def IsStrType(TypeStr: str) -> bool: + resolved: tuple[type, int] | None = CTypeRegistry.ResolveName(TypeStr) + if resolved: + ctype_cls: type + ptr_level: int + ctype_cls, ptr_level = resolved + if CTypeRegistry.CTypeToLLVM(ctype_cls) == 'i8' and ptr_level > 0: + return True + return TypeStr in ('str', 'bytes', 'struct str', 'union str', 'c_char') + + +class BuiltinTypeMap: + """ + 内置类型映射表 - 字符串到 (CType类, PtrCount) 的映射 + + 用法:BuiltinTypeMap.Get('int') -> (t.CInt, 0) + BuiltinTypeMap.Get('BYTEPTR') -> (t.CUnsignedChar, 1) + """ + + _map: dict[str, tuple[type, int]] | None = None + + @classmethod + def _build_map(cls) -> dict[str, tuple[type, int]]: + if cls._map is not None: + return cls._map + CTypeRegistry._build() + cls._map = {} + # 仅使用 Python 类名 → (CType 类, ptr_level) 映射。 + # C 类型名(如 'int'、'int32_t')不再通过 _cname_to_class 提供。 + # C 头文件 stub 生成器使用独立的硬编码表(CTypeMapper._CNAME_TO_PY)。 + for pyname, ctype_cls in CTypeRegistry._name_to_class.items(): + pos: frozenset = getattr(ctype_cls, 'position', frozenset()) + if t.CType.POINTER in pos and t.CType.BASE not in pos: + cls._map[pyname] = (ctype_cls, 1) + else: + cls._map[pyname] = (ctype_cls, 0) + # 保留一些常用的字符串速记(这些不是 CName,而是硬编码的便捷别名)。 + # 包含 Python 内置类型名(int/float/bool)和 C 类型名速记(char/short/long 等)。 + _SPECIAL: dict[str, tuple[type, int]] = { + # Python 内置类型名 + 'str': (t.CChar, 1), 'bytes': (t.CChar, 1), + 'int': (t.CInt, 0), 'float': (t.CFloat, 0), 'bool': (t.CBool, 0), + # C 类型名速记 + 'char': (t.CChar, 0), 'short': (t.CShort, 0), + 'long': (t.CLong, 0), 'long long': (t.CLongLong, 0), + 'double': (t.CDouble, 0), + 'unsigned': (t.CUnsigned, 0), + 'signed': (t.CInt, 0), 'signed int': (t.CInt, 0), + 'signed char': (t.CSignedChar, 0), + 'void': (t.CVoid, 0), 'Void': (t.CVoid, 0), + } + for k, v in _SPECIAL.items(): + if k not in cls._map: + cls._map[k] = v + _PTR_ALIASES: dict[str, tuple[type, int]] = { + 'INTPTR': (t.CInt, 1), 'UINTPTR': (t.CUnsignedInt, 1), + 'VOIDPTR': (t.CVoid, 1), 'BYTEPTR': (t.CUnsignedChar, 1), + 'CHAR8PTR': (t.CChar8T, 1), 'CHAR16PTR': (t.CChar16T, 1), + 'CHAR32PTR': (t.CChar32T, 1), + } + for k, v in _PTR_ALIASES.items(): + if k not in cls._map: + cls._map[k] = v + _FLOAT_ALIASES: dict[str, tuple[type, int]] = { + 'FLOAT8': (t.CFloat8T, 0), 'FLOAT16': (t.CFloat16T, 0), + 'FLOAT32': (t.CFloat32T, 0), 'FLOAT64': (t.CFloat64T, 0), + 'FLOAT128': (t.CFloat128T, 0), + } + for k, v in _FLOAT_ALIASES.items(): + if k not in cls._map: + cls._map[k] = v + return cls._map + + @classmethod + def Get(cls, type_name: str) -> tuple[type, int] | None: + """获取类型类和指针层级""" + return cls._build_map().get(type_name) + + +class BaseHandle: + def __init__(self, translator: "Translator") -> None: + self.Trans: Translator = translator + self._CurrentCpythonObjectClass: str | None = None + + @staticmethod + def _attr(obj: Any, name: str, default: Any = None) -> Any: + if obj is None: + return default + return getattr(obj, name, default) + + @staticmethod + def _is_char_pointer(val: _ir.Value) -> bool: + """检查值是否为 char* (i8*) 指针""" + if not isinstance(val.type, _ir.PointerType): + return False + pointee: _ir.Type = val.type.pointee + return isinstance(pointee, _ir.IntType) and pointee.width == 8 + + def HandleExprLlvm(self, Node: ast.AST, VarType: _ir.Type | str | None = None) -> _ir.Value | None: + return self.Trans.ExprHandler.HandleExprLlvm(Node, VarType) + + def HandleBodyLlvm(self, Body: ast.AST | list[ast.stmt]) -> Any: + return self.Trans.BodyHandler.HandleBodyLlvm(Body) + + def _get_int_ptr(self, Node: ast.AST) -> _ir.Value | None: + Gen: LlvmCodeGenerator = self.Trans.LlvmGen + if isinstance(Node, ast.Name): + if Node.id in Gen.variables: + return Gen.variables[Node.id] + elif isinstance(Node, ast.Attribute): + obj_val: Any = self.HandleExprLlvm(Node.value) + if not obj_val: + return None + if isinstance(obj_val.type, _ir.PointerType): + pointee: _ir.Type = obj_val.type.pointee + if isinstance(pointee, (_ir.IdentifiedStructType, _ir.LiteralStructType)): + StructName: str | None = None + if isinstance(pointee, _ir.IdentifiedStructType): + StructName = pointee.name + if not StructName: + for ClassName, struct_type in Gen.structs.items(): + if struct_type == pointee: + StructName = ClassName + break + if StructName and StructName in Gen.structs: + offset: int = self.Trans.ExprHandler._get_llvm_member_offset(Node.attr, StructName, Gen) + member_ptr: Any = Gen.builder.gep(obj_val, [_ir.Constant(_ir.IntType(32), 0), _ir.Constant(_ir.IntType(32), offset)], name=f"{Node.attr}_ptr") + return member_ptr + return None + + def _IsTModuleType(self, TypeName: str) -> bool: + if TypeName in ('t', 'State', 'Bit', 'Anonymous', 'Postdefinition'): + return True + TypeClass: type | None = getattr(t, TypeName, None) + if TypeClass and isinstance(TypeClass, type): + if issubclass(TypeClass, t.CType): + return True + FallbackClass: type | None = getattr(t, f'_{TypeName}', None) + if FallbackClass and isinstance(FallbackClass, type): + if issubclass(FallbackClass, t.CType): + return True + return False + + def ResolveListElementType( + self, + elem_type_node: ast.expr, + Gen: Any, + *, + check_func_ptr: bool = False, + handle_str: bool = False, + void_fallback_width: int = 32, + fallback_to_cint: bool = False, + ) -> tuple[Any, CTypeInfo | None]: + """解析 list 元素类型,返回 (LLVM类型, CTypeInfo|None)。 + + 统一处理结构体、str、函数指针、VoidType 回退等变体。 + + Args: + check_func_ptr: 是否检查函数指针(全局变量路径需要) + handle_str: 是否处理 str → i8*(局部变量路径需要) + void_fallback_width: VoidType 回退宽度 (32 或 8) + fallback_to_cint: 无类型信息时回退到 CInt + """ + elem_type_info: CTypeInfo | None = CTypeInfo.FromNode(elem_type_node, self.Trans.SymbolTable) + + # 结构体类型 + if isinstance(elem_type_node, ast.Name) and elem_type_node.id in Gen.structs: + if check_func_ptr: + sym_entry: CTypeInfo | None = self.Trans.SymbolTable.lookup(elem_type_node.id) + if sym_entry and isinstance(sym_entry, CTypeInfo) and sym_entry.IsFuncPtr: + return _ir.IntType(8).as_pointer(), elem_type_info + return Gen.structs[elem_type_node.id], elem_type_info + + # str → i8* + if handle_str and isinstance(elem_type_node, ast.Name) and elem_type_node.id == 'str': + return _ir.PointerType(_ir.IntType(8)), elem_type_info + + # 函数指针检查 + if check_func_ptr and elem_type_info and elem_type_info.IsFuncPtr: + return _ir.IntType(8).as_pointer(), elem_type_info + + # 回退到 CInt + if elem_type_info is None and fallback_to_cint: + elem_type_info = CTypeInfo() + elem_type_info.BaseType = t.CInt() + + elem_type: Any = Gen._ctype_to_llvm(elem_type_info) + if isinstance(elem_type, _ir.VoidType): + elem_type = _ir.IntType(void_fallback_width) + + return elem_type, elem_type_info + + def ParseArrayCount( + self, + count_node: ast.expr | None, + Gen: Any, + value_node: ast.expr | None = None, + *, + mode: str = 'global', + ) -> int: + """解析数组计数,返回计数(默认 1)。 + + 统一处理 Constant/Name/Attribute/BinOp/None 等形式。 + None 或 Constant(None) 时从 value_node 推断(List 长度或 str 长度+1)。 + + Args: + count_node: 计数 AST 节点 + value_node: 赋值右侧值节点(用于 count_node 为 None 时推断) + mode: 'global' 使用 _eval_global_count + SymbolTable + _define_constants; + 'local' 使用 TryEvalConstExpr + """ + # None 或 Constant(None) → 从 value_node 推断 + if count_node is None or (isinstance(count_node, ast.Constant) and count_node.value is None): + if value_node and isinstance(value_node, ast.List): + return len(value_node.elts) + if value_node and isinstance(value_node, ast.Constant) and isinstance(value_node.value, str): + return len(value_node.value) + 1 + return 1 + + # Constant(int) + if isinstance(count_node, ast.Constant) and isinstance(count_node.value, int): + return count_node.value + + if mode == 'global': + # Name → SymbolTable + _define_constants + if isinstance(count_node, ast.Name): + ArrayCount: int = 1 + if self.Trans.SymbolTable.has(count_node.id): + sym_info: Any = self.Trans.SymbolTable[count_node.id] + if isinstance(sym_info.value, int): + ArrayCount = sym_info.value + if ArrayCount == 1 and count_node.id in getattr(Gen, '_define_constants', {}): + def_val: Any = Gen._define_constants[count_node.id] + if isinstance(def_val, int): + ArrayCount = def_val + return ArrayCount + # Attribute / BinOp → _eval_global_count + if isinstance(count_node, (ast.Attribute, ast.BinOp)): + eval_fn: Any = getattr(self, '_eval_global_count', None) + if eval_fn is not None: + ev: int | None = eval_fn(count_node, Gen) + if ev is not None: + return ev + return 1 + else: + # local mode → TryEvalConstExpr + eval_count: Any = CTypeInfo.TryEvalConstExpr(count_node, self.Trans.SymbolTable) + if eval_count is not None and isinstance(eval_count, int) and eval_count > 0: + return eval_count + return 1 + + return 1 + + def ResolveAnnotationType(self, annotation: ast.expr) -> CTypeInfo | None: + """解析注解类型,BinOp(BitOr) 优先使用 MergeTypes,其他使用 FromNode。 + + 统一处理函数返回类型和参数类型的 BinOp 联合类型解析。 + """ + if isinstance(annotation, ast.BinOp) and isinstance(annotation.op, ast.BitOr): + merger: Any = getattr(self.Trans, 'TypeMergeHandler', None) + if merger: + info: CTypeInfo | None = merger.MergeTypes(annotation) + if info is not None and isinstance(info, CTypeInfo): + return info + return CTypeInfo.FromNode(annotation, self.Trans.SymbolTable) + + def CollectAnnAssignMember( + self, item: ast.AST, Gen: Any + ) -> tuple[str, _ir.Type, CTypeInfo | None] | None: + """从 ast.AnnAssign 节点解析成员信息。 + + 返回 (VarName, MemberType, TypeInfo);TypeInfo 为 None 表示解析回退到 i32。 + 非 AnnAssign/Name 目标时返回 None。 + """ + if not isinstance(item, ast.AnnAssign) or not isinstance(item.target, ast.Name): + return None + VarName: str = item.target.id + try: + TypeInfo: CTypeInfo | None = CTypeInfo.FromNode(item.annotation, self.Trans.SymbolTable) + if TypeInfo is None: + TypeInfo = CTypeInfo() + TypeInfo.BaseType = t.CInt() + MemberType: _ir.Type = Gen._ctype_to_llvm(TypeInfo) + if isinstance(MemberType, _ir.VoidType): + MemberType = _ir.PointerType(_ir.IntType(8)) + return VarName, MemberType, TypeInfo + except Exception as e: + _vlog().warning(f"HandlesBase: 忽略异常 {e}", exc_info=e) + return VarName, _ir.IntType(32), None + + def LookupFunctionSymbol(self, name: str, *, module_path: str | None = None) -> CTypeInfo | None: + """查找函数符号,先尝试 module_path.name,再回退到 name。 + + 统一处理 HandlesExprCall / HandlesAssign 中重复的二级查找模式。 + 返回 CTypeInfo(不限定 IsFunction),由调用方检查标志位。 + """ + st = self.Trans.SymbolTable + if module_path: + sym: CTypeInfo | None = st.lookup(f'{module_path}.{name}') + if sym: + return sym + return st.lookup(name) + + def BuildLLVMFuncTypeFromSig( + self, + sym_info: CTypeInfo, + Gen: Any, + *, + mangled_name: str | None = None, + use_infer_fallback: bool = False, + ) -> tuple[Any, list[Any], bool] | None: + """从 CTypeInfo 函数签名构建 LLVM 函数类型。 + + 返回 (ret_type, llvm_param_types, is_variadic),非函数返回 None。 + 统一处理 FuncPtrReturn/FuncPtrParams → ToLLVM 转换、VoidType 回退。 + + Args: + mangled_name: 用于 _infer_return_type + stub 查找回退 + use_infer_fallback: 为 True 时启用 _infer_return_type + stub 查找回退链 + """ + if not sym_info.IsFunction: + return None + is_variadic: bool = sym_info.IsVariadic + ret_type_info = sym_info.FuncPtrReturn + if isinstance(ret_type_info, CTypeInfo) and ret_type_info.BaseType: + ret_type: Any = ret_type_info.ToLLVM(Gen) + elif use_infer_fallback and mangled_name: + inferred: Any = Gen._infer_return_type(mangled_name) + if isinstance(inferred, _ir.IntType) and inferred.width == 32: + try: + stub_ft: Any = self.Trans.ImportHandler._LookupStubFuncType(mangled_name, Gen) + if stub_ft and hasattr(stub_ft, 'return_type'): + inferred = stub_ft.return_type + except Exception: + pass + ret_type = inferred + else: + ret_type = Gen._CType2LLVM('i32', False) + param_type_infos = [pt for _, pt in (sym_info.FuncPtrParams or [])] + if isinstance(ret_type, _ir.VoidType): + ret_type = _ir.IntType(32) + llvm_param_types: list[Any] = [] + for pt in param_type_infos: + if isinstance(pt, CTypeInfo) and pt.BaseType: + lp: Any = pt.ToLLVM(Gen) + else: + lp = Gen._CType2LLVM(pt if isinstance(pt, str) else 'i32', '*' in pt if isinstance(pt, str) else False) + if isinstance(lp, _ir.VoidType): + lp = _ir.IntType(8).as_pointer() + llvm_param_types.append(lp) + return ret_type, llvm_param_types, is_variadic + + def GetOrCreateFuncDecl( + self, + name: str, + ret_type: Any, + param_types: list[Any], + Gen: Any, + *, + is_variadic: bool = False, + replace_name: str | None = None, + ) -> Any: + """创建或替换 LLVM 函数声明。 + + 若 name 已存在且类型不匹配,通过 _replace_function_decl 替换。 + replace_name 传递给 _replace_function_decl(通常为未 mangle 的 func_name)。 + """ + if name not in Gen.functions: + func_type = _ir.FunctionType(ret_type, param_types, var_arg=is_variadic) + func_decl = _ir.Function(Gen.module, func_type, name=name) + Gen.functions[name] = func_decl + else: + existing = Gen.functions[name] + existing_type = getattr(existing, 'ftype', None) + new_type = _ir.FunctionType(ret_type, param_types, var_arg=is_variadic) + if existing_type and existing_type != new_type: + replaced = self.Trans.FunctionHandler._replace_function_decl(Gen, replace_name or name, new_type) + if replaced and replaced != existing: + Gen.functions[name] = replaced + return Gen.functions[name] + + def GetOrCreateStubFuncDecl( + self, + decl_name: str, + stub_func_type: Any, + Gen: Any, + *, + alias: str | None = None, + check_existing: bool = True, + ) -> Any: + """创建 stub 函数声明,可选注册别名。 + + check_existing=False 时跳过存在性检查(用于确定不存在的场景)。 + """ + if check_existing and decl_name in Gen.functions: + func_decl = Gen.functions[decl_name] + else: + func_decl = _ir.Function(Gen.module, stub_func_type, name=decl_name) + Gen.functions[decl_name] = func_decl + if alias and alias != decl_name: + if not check_existing or alias not in Gen.functions: + Gen.functions[alias] = func_decl + return func_decl + + +StrictMode: bool = _config.mode == 'strict' \ No newline at end of file diff --git a/lib/core/Handles/HandlesBody.py b/lib/core/Handles/HandlesBody.py index e236783..8adbe5d 100644 --- a/lib/core/Handles/HandlesBody.py +++ b/lib/core/Handles/HandlesBody.py @@ -1,76 +1,77 @@ -from __future__ import annotations -from typing import TYPE_CHECKING -if TYPE_CHECKING: - from lib.core.translator import Translator -from lib.core.Handles.HandlesBase import BaseHandle -import ast - - -class BodyHandle(BaseHandle): - def __init__(self, translator: "Translator"): - super().__init__(translator) - - def HandleBodyLlvm(self, Body): - Gen = self.Trans.LlvmGen - for Node in Body: - if Gen.builder and Gen.builder.block.is_terminated: - break - Gen._set_node_info(Node) - try: - if isinstance(Node, ast.Expr): - self.HandleExprLlvm(Node.value) - elif isinstance(Node, ast.Return): - self.Trans.ReturnHandler._HandleReturnLlvm(Node) - elif isinstance(Node, ast.Assign): - self.Trans.AssignHandler._HandleAssignLlvm(Node) - elif isinstance(Node, ast.AugAssign): - self.Trans.AugAssignHandler._HandleAugAssignLlvm(Node) - elif isinstance(Node, ast.AnnAssign): - self.Trans.AnnAssignHandler._HandleAnnAssignLlvm(Node) - elif isinstance(Node, ast.If): - self.Trans.IfHandler._HandleIfLlvm(Node) - elif isinstance(Node, ast.For): - self.Trans.ForHandler._HandleForLlvm(Node) - elif isinstance(Node, ast.While): - self.Trans.WhileHandler._HandleWhileLlvm(Node) - elif isinstance(Node, ast.Break): - if Gen.loop_break_targets: - Gen.builder.branch(Gen.loop_break_targets[-1]) - elif isinstance(Node, ast.Continue): - if Gen.loop_continue_targets: - Gen.builder.branch(Gen.loop_continue_targets[-1]) - elif isinstance(Node, ast.With): - self.Trans.WithHandler._HandleWithLlvm(Node) - elif isinstance(Node, ast.ClassDef): - pass - elif getattr(ast, 'Match', None) and isinstance(Node, ast.Match): - self.Trans.MatchHandler._HandleMatchLlvm(Node) - elif isinstance(Node, ast.Try): - self.Trans.TryHandler._HandleTryLlvm(Node) - elif isinstance(Node, ast.Raise): - self.Trans.RaiseHandler._HandleRaiseLlvm(Node) - elif isinstance(Node, ast.Assert): - self.Trans.AssertHandler._HandleAssertLlvm(Node) - elif isinstance(Node, ast.Global): - self.Trans.ForHandler._HandleGlobalLlvm(Node) - elif isinstance(Node, ast.FunctionDef): - self.Trans.ForHandler._HandleNestedFunctionLlvm(Node) - elif isinstance(Node, ast.Nonlocal): - self.Trans.ForHandler._HandleNonlocalLlvm(Node) - elif isinstance(Node, ast.Delete): - self.Trans.DeleteHandler._HandleDeleteLlvm(Node) - except Exception as e: - lineno = getattr(Node, 'lineno', 0) - source_line = Gen._get_source_line(lineno) - src_file = getattr(Gen, '_current_source_file', '') - src_path = src_file if src_file else 'unknown' - line_info = "源代码 (%s, line %d)" % (src_path, lineno) - if source_line: - line_info += ":\n %d | %s" % (lineno, source_line) - self.Trans._ErrorStack.append((type(e).__name__, str(e), line_info)) - raise - if Gen.builder and not Gen.builder.block.is_terminated: - Gen._EmitTempFrees() - - def HandleExprLlvm(self, Node, VarType=None): - return self.Trans.ExprHandler.HandleExprLlvm(Node, VarType) +from __future__ import annotations +from typing import TYPE_CHECKING +if TYPE_CHECKING: + from lib.core.translator import Translator +from lib.core.Handles.HandlesBase import BaseHandle +import ast +import llvmlite.ir as ir + + +class BodyHandle(BaseHandle): + def __init__(self, translator: "Translator") -> None: + super().__init__(translator) + + def HandleBodyLlvm(self, Body: list[ast.stmt]) -> None: + Gen: "Translator.LlvmGen" = self.Trans.LlvmGen + for Node in Body: + if Gen.builder and Gen.builder.block.is_terminated: + break + Gen._set_node_info(Node) + try: + if isinstance(Node, ast.Expr): + self.HandleExprLlvm(Node.value) + elif isinstance(Node, ast.Return): + self.Trans.ReturnHandler._HandleReturnLlvm(Node) + elif isinstance(Node, ast.Assign): + self.Trans.AssignHandler._HandleAssignLlvm(Node) + elif isinstance(Node, ast.AugAssign): + self.Trans.AugAssignHandler._HandleAugAssignLlvm(Node) + elif isinstance(Node, ast.AnnAssign): + self.Trans.AnnAssignHandler._HandleAnnAssignLlvm(Node) + elif isinstance(Node, ast.If): + self.Trans.IfHandler._HandleIfLlvm(Node) + elif isinstance(Node, ast.For): + self.Trans.ForHandler._HandleForLlvm(Node) + elif isinstance(Node, ast.While): + self.Trans.WhileHandler._HandleWhileLlvm(Node) + elif isinstance(Node, ast.Break): + if Gen.loop_break_targets: + Gen.builder.branch(Gen.loop_break_targets[-1]) + elif isinstance(Node, ast.Continue): + if Gen.loop_continue_targets: + Gen.builder.branch(Gen.loop_continue_targets[-1]) + elif isinstance(Node, ast.With): + self.Trans.WithHandler._HandleWithLlvm(Node) + elif isinstance(Node, ast.ClassDef): + pass + elif getattr(ast, 'Match', None) and isinstance(Node, ast.Match): + self.Trans.MatchHandler._HandleMatchLlvm(Node) + elif isinstance(Node, ast.Try): + self.Trans.TryHandler._HandleTryLlvm(Node) + elif isinstance(Node, ast.Raise): + self.Trans.RaiseHandler._HandleRaiseLlvm(Node) + elif isinstance(Node, ast.Assert): + self.Trans.AssertHandler._HandleAssertLlvm(Node) + elif isinstance(Node, ast.Global): + self.Trans.ForHandler._HandleGlobalLlvm(Node) + elif isinstance(Node, ast.FunctionDef): + self.Trans.ForHandler._HandleNestedFunctionLlvm(Node) + elif isinstance(Node, ast.Nonlocal): + self.Trans.ForHandler._HandleNonlocalLlvm(Node) + elif isinstance(Node, ast.Delete): + self.Trans.DeleteHandler._HandleDeleteLlvm(Node) + except Exception as e: + lineno: int = getattr(Node, 'lineno', 0) + source_line: str | None = Gen._get_source_line(lineno) + src_file: str = getattr(Gen, '_current_source_file', '') + src_path: str = src_file if src_file else 'unknown' + line_info: str = "源代码 (%s, line %d)" % (src_path, lineno) + if source_line: + line_info += ":\n %d | %s" % (lineno, source_line) + self.Trans._ErrorStack.append((type(e).__name__, str(e), line_info)) + raise + if Gen.builder and not Gen.builder.block.is_terminated: + Gen._EmitTempFrees() + + def HandleExprLlvm(self, Node: ast.expr, VarType: ir.Type | None = None) -> ir.Value | None: + return self.Trans.ExprHandler.HandleExprLlvm(Node, VarType) \ No newline at end of file diff --git a/lib/core/Handles/HandlesClassDef.py b/lib/core/Handles/HandlesClassDef.py index 2391a86..543961f 100644 --- a/lib/core/Handles/HandlesClassDef.py +++ b/lib/core/Handles/HandlesClassDef.py @@ -2,14 +2,21 @@ from __future__ import annotations from typing import TYPE_CHECKING if TYPE_CHECKING: from lib.core.translator import Translator -from lib.core.Handles.HandlesBase import BaseHandle, CTypeInfo, FuncMeta -from lib.includes import t + from lib.core.Translator.LlvmGenerator import LlvmGeneratorMixin import ast +import copy import llvmlite.ir as ir +from lib.core.Exportable import EnumMember as ExportEnumMember +from lib.core.Handles.HandlesBase import BaseHandle, CTypeInfo, FuncMeta +from lib.core.SymbolUtils import IsTModule, FindStructNameInAnnotation +from lib.core.VLogger import get_logger as _vlog +from lib.constants.config import mode as _config_mode +from lib.includes import t +from lib.includes.t import CTypeRegistry class ClassHandle(BaseHandle): - def _is_exception_class(self, Node): + def _is_exception_class(self, Node: ast.ClassDef) -> bool: if not Node.bases: return False for base in Node.bases: @@ -25,7 +32,7 @@ class ClassHandle(BaseHandle): return True return False - def _get_exception_parent(self, Node): + def _get_exception_parent(self, Node: ast.ClassDef) -> str | None: if not Node.bases: return None for base in Node.bases: @@ -37,35 +44,34 @@ class ClassHandle(BaseHandle): return base.attr return None - def _RegisterExceptionClass(self, Node): - ClassName = Node.name + def _RegisterExceptionClass(self, Node: ast.ClassDef) -> None: + ClassName: str = Node.name if ClassName in self.Trans.exception_registry: return - code = self.Trans._next_exception_code + code: int = self.Trans._next_exception_code self.Trans._next_exception_code += 1 self.Trans.exception_registry[ClassName] = code - parent = self._get_exception_parent(Node) + parent: str | None = self._get_exception_parent(Node) if parent: self.Trans.exception_parents[ClassName] = parent - ExcTypeInfo = CTypeInfo() + ExcTypeInfo: CTypeInfo = CTypeInfo() ExcTypeInfo.Name = ClassName ExcTypeInfo.IsExceptionClass = True ExcTypeInfo.value = code self.Trans.SymbolTable.insert(ClassName, ExcTypeInfo) - def _is_generic_class(self, Node): + def _is_generic_class(self, Node: ast.ClassDef) -> bool: if hasattr(Node, 'type_params') and Node.type_params: return True return False - def _mangle_generic_class_name(self, class_name, type_args): - from lib.includes.t import CTypeRegistry - mangled_args = [] + def _mangle_generic_class_name(self, class_name: str, type_args: list[str]) -> str: + mangled_args: list[str] = [] for ta in type_args: - llvm_str = CTypeRegistry.NameToLLVM(ta) + llvm_str: str | None = CTypeRegistry.NameToLLVM(ta) if llvm_str: if llvm_str in ('float', 'double', 'half', 'fp128'): - mangled = 'f' + str(CTypeRegistry.GetClassByName(ta)().Size) + mangled: str = 'f' + str(CTypeRegistry.GetClassByName(ta)().Size) else: mangled = llvm_str else: @@ -73,21 +79,21 @@ class ClassHandle(BaseHandle): mangled_args.append(mangled) return class_name + '[' + ']['.join(mangled_args) + ']' - def _specialize_generic_class(self, ClassName, type_args, Gen, type_names=None): + def _specialize_generic_class(self, ClassName: str, type_args: list[str], Gen: LlvmGeneratorMixin, type_names: list[str] | None = None, declare_only: bool = False) -> str | None: if not hasattr(self, '_generic_class_templates') or ClassName not in self._generic_class_templates: return None - template = self._generic_class_templates[ClassName] - Node = template['node'] - type_param_names = template['type_params'] + template: dict = self._generic_class_templates[ClassName] + Node: ast.ClassDef = template['node'] + type_param_names: list[str] = template['type_params'] if len(type_args) != len(type_param_names): return None - spec_key = ClassName + '<' + ','.join(type_args) + '>' + spec_key: str = ClassName + '<' + ','.join(type_args) + '>' if not hasattr(self, '_generic_class_specializations'): self._generic_class_specializations = {} if spec_key in self._generic_class_specializations: return self._generic_class_specializations[spec_key] - spec_name = self._mangle_generic_class_name(ClassName, type_args) - type_map = {} + spec_name: str = self._mangle_generic_class_name(ClassName, type_args) + type_map: dict[str, str] = {} for i, tp_name in enumerate(type_param_names): if type_names and i < len(type_names): type_map[tp_name] = type_names[i] @@ -99,8 +105,7 @@ class ClassHandle(BaseHandle): for tn in type_names: if tn not in self.Trans._t_c_imported_names: self.Trans._t_c_imported_names[tn] = ('t', tn) - import copy - SpecNode = copy.deepcopy(Node) + SpecNode: ast.ClassDef = copy.deepcopy(Node) SpecNode.type_params = [] SpecNode.name = spec_name for item in SpecNode.body: @@ -114,18 +119,18 @@ class ClassHandle(BaseHandle): if item.returns: item.returns = self.Trans.FunctionHandler._replace_type_in_annotation(item.returns, type_map) self.Trans.FunctionHandler._apply_type_map_to_body(item.body, type_map) - saved_builder = Gen.builder - saved_func = Gen.func - saved_variables = dict(Gen.variables) if Gen.variables else {} - saved_direct_values = dict(Gen._direct_values) if Gen._direct_values else {} - saved_var_type_info = dict(Gen.var_type_info) if Gen.var_type_info else {} - saved_var_signedness = dict(Gen.var_signedness) if Gen.var_signedness else {} - saved_global_vars = set(Gen.global_vars) if Gen.global_vars else set() - saved_var_scopes = [dict(s) for s in self.Trans.VarScopes] if self.Trans.VarScopes else [] - saved_block = None + saved_builder: ir.IRBuilder = Gen.builder + saved_func: ir.Function = Gen.func + saved_variables: dict = dict(Gen.variables) if Gen.variables else {} + saved_direct_values: dict = dict(Gen._direct_values) if Gen._direct_values else {} + saved_var_type_info: dict = dict(Gen.var_type_info) if Gen.var_type_info else {} + saved_var_signedness: dict = dict(Gen.var_signedness) if Gen.var_signedness else {} + saved_global_vars: set = set(Gen.global_vars) if Gen.global_vars else set() + saved_var_scopes: list = [dict(s) for s in self.Trans.VarScopes] if self.Trans.VarScopes else [] + saved_block: ir.Block | None = None if Gen.builder and Gen.builder.block and not Gen.builder.block.is_terminated: saved_block = Gen.builder.block - self._EmitClassLlvm(SpecNode, Gen) + self._EmitClassLlvm(SpecNode, Gen, declare_only=declare_only) Gen.builder = saved_builder if saved_block is not None and Gen.builder is not None: Gen.builder.position_at_end(saved_block) @@ -144,56 +149,96 @@ class ClassHandle(BaseHandle): Gen._struct_sha1_map[spec_name] = self.Trans._module_sha1 return spec_name - def _EmitClassLlvm(self, Node, Gen): - ClassName = Node.name - if self._is_generic_class(Node): - if not hasattr(self, '_generic_class_templates'): - self._generic_class_templates = {} - type_params = [tp.name for tp in Node.type_params] - self._generic_class_templates[ClassName] = { - 'node': Node, - 'type_params': type_params, - } - return - if self._is_exception_class(Node): - self._RegisterExceptionClass(Node) - return - IsCenum = False - IsCunion = False - IsRenum = False - if Node.bases: - for base in Node.bases: - if hasattr(base, 'attr'): - if base.attr == 'CEnum' or base.attr == 'Enum': - IsCenum = True - break - elif base.attr == 'CUnion': - IsCunion = True - elif base.attr == 'REnum': - IsRenum = True - elif hasattr(base, 'id'): - if base.id == 'CEnum' or base.id == 'Enum': - IsCenum = True - break - elif base.id == 'CUnion': - IsCunion = True - elif base.id == 'REnum': - IsRenum = True - if IsCenum: - self._RegisterEnumMembers(Node) - return - if IsCunion: - self._EmitUnionLlvm(Node, Gen) - return - if IsRenum: - self._EmitREnumLlvm(Node, Gen) - return - IsCpythonObject = False - IsCVTable = False + def _resolve_base_kind(self, base_name: str, Gen: LlvmGeneratorMixin) -> str | None: + """解析基类名称的类型种类 + + 查询顺序: + 1. _t_type_symbols(from t import CEnum as en) + 2. t 模块属性(t.CEnum / t.CUnion / t.CStruct / t.REnum) + 3. 返回 None 表示不是已知标记基类 + + Returns: + 'enum' | 'union' | 'renum' | 'struct' | None + """ + # 1) 查 _t_type_symbols(别名导入) + symtab: object = self.Trans.SymbolTable + cls: type | None = symtab._t_type_symbols.get(base_name) + if cls is not None: + if issubclass(cls, (t.CEnum, t.REnum)): + return 'renum' if issubclass(cls, t.REnum) else 'enum' + if issubclass(cls, t.CUnion): + return 'union' + if issubclass(cls, t.CStruct): + return 'struct' + + # 2) 查 t 模块属性(直接引用 t.CEnum 等) + t_cls: type | None = getattr(t, base_name, None) + if isinstance(t_cls, type) and issubclass(t_cls, t.CType): + if issubclass(t_cls, (t.CEnum, t.REnum)): + return 'renum' if issubclass(t_cls, t.REnum) else 'enum' + if issubclass(t_cls, t.CUnion): + return 'union' + if issubclass(t_cls, t.CStruct): + return 'struct' + + return None + + def _resolve_decorator_kind(self, Node: ast.ClassDef, Gen: LlvmGeneratorMixin) -> str | None: + """从装饰器列表中解析结构体类型种类 + + 支持 @t.CStruct, @t.CUnion, @t.CEnum, @t.REnum + 也支持 from t import CStruct 等别名形式 + + Returns: + 'enum' | 'union' | 'renum' | 'struct' | None + """ + if not hasattr(Node, 'decorator_list') or not Node.decorator_list: + return None + symtab: object = self.Trans.SymbolTable + for decorator in Node.decorator_list: + attr_name: str | None = None + # @t.CStruct 形式 + if isinstance(decorator, ast.Attribute) and isinstance(decorator.value, ast.Name): + if IsTModule(decorator.value.id, symtab): + attr_name = decorator.attr + # @CStruct 形式 (from t import CStruct) + elif isinstance(decorator, ast.Name): + cls: type | None = getattr(t, decorator.id, None) + if cls is None and hasattr(symtab, '_t_type_symbols'): + cls = symtab._t_type_symbols.get(decorator.id) + if cls is not None and isinstance(cls, type) and issubclass(cls, t.CType): + attr_name = cls.__name__ + if attr_name: + # 查 _t_type_symbols 和 t 模块属性以确定种类 + resolved_cls: type | None = None + if hasattr(symtab, '_t_type_symbols'): + resolved_cls = symtab._t_type_symbols.get(attr_name) + if resolved_cls is None: + resolved_cls = getattr(t, attr_name, None) + if resolved_cls is not None and isinstance(resolved_cls, type): + if issubclass(resolved_cls, t.REnum): + return 'renum' + if issubclass(resolved_cls, t.CEnum): + return 'enum' + if issubclass(resolved_cls, t.CUnion): + return 'union' + if issubclass(resolved_cls, t.CStruct): + return 'struct' + return None + + def _resolve_class_flags(self, Node: ast.ClassDef, Gen: LlvmGeneratorMixin) -> tuple[bool, bool, str | None]: + """解析类的 Object/CVTable 标志和父类信息 + + Returns: + tuple: (IsCpythonObject, IsCVTable, ParentClassName) + """ + ClassName: str = Node.name + IsCpythonObject: bool = False + IsCVTable: bool = False if hasattr(Node, 'decorator_list') and Node.decorator_list: for decorator in Node.decorator_list: if isinstance(decorator, ast.Attribute): - if hasattr(decorator.value, 'id') and decorator.value.id == 't': + if hasattr(decorator.value, 'id') and IsTModule(decorator.value.id, self.Trans.SymbolTable): if decorator.attr == 'Object': IsCpythonObject = True elif decorator.attr == 'CVTable': @@ -210,22 +255,35 @@ class ClassHandle(BaseHandle): for arg in decorator.args: if isinstance(arg, ast.Attribute): if isinstance(arg.value, ast.Attribute): - if getattr(arg.value.value, 'id', None) == 't' and arg.value.attr == 'attr' and arg.attr == 'packed': + if IsTModule(getattr(arg.value.value, 'id', ''), self.Trans.SymbolTable) and arg.value.attr == 'attr' and arg.attr == 'packed': Gen.class_packed.add(ClassName) - HasMethods = any(isinstance(item, ast.FunctionDef) for item in Node.body) - if HasMethods and not IsCpythonObject: - IsCpythonObject = True - HasParentClass = False - ParentClassName = None + class_graph: dict = getattr(Gen, '_class_graph', {}) + if class_graph.get(ClassName, {}).get('has_methods', False): + if not IsCpythonObject: + IsCpythonObject = True + # 仅当该类作为其他类的基类时,才启用 CVTable + # 检查 _class_graph 中是否有任何类将此类作为基类 + is_base_of_any: bool = False + for other_cls, info in class_graph.items(): + if ClassName in info.get('bases', []): + is_base_of_any = True + break + if is_base_of_any: + IsCVTable = True + HasParentClass: bool = False + ParentClassName: str | None = None if Node.bases: for base in Node.bases: - base_name = None + base_name: str | None = None if hasattr(base, 'id'): base_name = base.id elif hasattr(base, 'attr'): base_name = base.attr - if base_name and base_name not in ('CEnum', 'Enum', 'CUnion', 'CStruct', 'Object', 'CVTable', 'Exception'): - if base_name in Gen.class_members or base_name in Gen.structs: + if base_name: + kind: str | None = self._resolve_base_kind(base_name, Gen) + if kind is not None or base_name in t._MARKER_BASES: + continue # 标记基类,跳过 + if base_name in class_graph or base_name in Gen.class_members or base_name in Gen.structs: HasParentClass = True ParentClassName = base_name break @@ -233,8 +291,82 @@ class ClassHandle(BaseHandle): IsCVTable = True if IsCVTable: Gen.class_vtable.add(ClassName) - if ParentClassName: - Gen.class_vtable.add(ParentClassName) + # 沿继承链向上传播,将所有祖先类加入 vtable + visited: set[str] = {ClassName} + ancestor: str | None = ParentClassName + while ancestor and ancestor not in visited: + visited.add(ancestor) + Gen.class_vtable.add(ancestor) + # 查询祖先类的父类 + ancestor_info: dict | None = class_graph.get(ancestor) + if ancestor_info: + ancestor_bases: list = ancestor_info.get('bases', []) + next_ancestor: str | None = None + for ab in ancestor_bases: + if ab not in t._MARKER_BASES and ab not in visited: + next_ancestor = ab + break + ancestor = next_ancestor + else: + # 类图中没有,尝试从 class_parent 查询 + ancestor = Gen.class_parent.get(ancestor) + return IsCpythonObject, IsCVTable, ParentClassName + + def _EmitClassLlvm(self, Node: ast.ClassDef, Gen: LlvmGeneratorMixin, declare_only: bool = False) -> None: + ClassName: str = Node.name + if self._is_generic_class(Node): + if not hasattr(self, '_generic_class_templates'): + self._generic_class_templates = {} + type_params: list[str] = [tp.name for tp in Node.type_params] + self._generic_class_templates[ClassName] = { + 'node': Node, + 'type_params': type_params, + } + return + if self._is_exception_class(Node): + self._RegisterExceptionClass(Node) + return + IsCenum: bool = False + IsCunion: bool = False + IsRenum: bool = False + # 先检查装饰器形式(@t.CStruct / @t.CEnum / @t.CUnion / @t.REnum) + deco_kind: str | None = self._resolve_decorator_kind(Node, Gen) + if deco_kind == 'enum': + IsCenum = True + elif deco_kind == 'union': + IsCunion = True + elif deco_kind == 'renum': + IsRenum = True + # 再检查基类继承形式(class X(t.CStruct):),与装饰器合并 + if not IsCenum and not IsCunion and not IsRenum and Node.bases: + for base in Node.bases: + base_name: str | None = None + if hasattr(base, 'attr'): + base_name = base.attr + elif hasattr(base, 'id'): + base_name = base.id + if base_name: + kind: str | None = self._resolve_base_kind(base_name, Gen) + if kind == 'enum': + IsCenum = True + break + elif kind == 'union': + IsCunion = True + elif kind == 'renum': + IsRenum = True + if IsCenum: + self._RegisterEnumMembers(Node) + return + if IsCunion: + self._EmitUnionLlvm(Node, Gen) + return + if IsRenum: + self._EmitREnumLlvm(Node, Gen) + return + IsCpythonObject: bool + IsCVTable: bool + ParentClassName: str | None + IsCpythonObject, IsCVTable, ParentClassName = self._resolve_class_flags(Node, Gen) if ClassName not in Gen.class_methods: Gen.class_methods[ClassName] = [] # 当前文件定义的类是权威定义,覆盖之前导入阶段可能添加的外部声明 @@ -244,26 +376,28 @@ class ClassHandle(BaseHandle): Gen.class_member_bitfields[ClassName] = {} Gen.class_member_byteorders[ClassName] = {} Gen.class_member_bitoffsets[ClassName] = {} - ParentClass = None + ParentClass: str | None = None if Node.bases: + class_graph: dict = getattr(Gen, '_class_graph', {}) for base in Node.bases: if hasattr(base, 'id'): base_name = base.id - if base_name in Gen.class_members and base_name != ClassName: - ParentClass = base_name - break elif hasattr(base, 'attr'): base_name = base.attr - if base_name in Gen.class_members and base_name != ClassName: - ParentClass = base_name - break + else: + continue + if base_name == ClassName: + continue + if base_name in class_graph or base_name in Gen.class_members: + ParentClass = base_name + break if ParentClass: Gen.class_parent[ClassName] = ParentClass if ParentClass: - parent_members = list(Gen.class_members[ParentClass]) - parent_defaults = dict(Gen.class_member_defaults.get(ParentClass, {})) - existing_names = {m[0] for m in Gen.class_members[ClassName]} - inherited = [] + parent_members: list = list(Gen.class_members[ParentClass]) + parent_defaults: dict = dict(Gen.class_member_defaults.get(ParentClass, {})) + existing_names: set = {m[0] for m in Gen.class_members[ClassName]} + inherited: list[tuple] = [] for pm_name, pm_type in parent_members: if pm_name not in existing_names: inherited.append((pm_name, pm_type)) @@ -271,67 +405,66 @@ class ClassHandle(BaseHandle): Gen.class_member_defaults[ClassName][pm_name] = parent_defaults[pm_name] Gen.class_members[ClassName] = inherited + Gen.class_members[ClassName] if ParentClass in Gen.class_methods: - parent_methods = list(Gen.class_methods[ParentClass]) + parent_methods: list = list(Gen.class_methods[ParentClass]) for pm in parent_methods: - method_name = pm.split('.')[-1] if '.' in pm else pm - child_method = f"{ClassName}.{method_name}" + method_name: str = pm.split('.')[-1] if '.' in pm else pm + child_method: str = f"{ClassName}.{method_name}" if child_method not in Gen.class_methods[ClassName]: Gen.class_methods[ClassName].append(child_method) Gen.register_method(ClassName, child_method) + # 解析 __provides__/__requires__/__require_must__ 编译期元数据 for item in Node.body: if isinstance(item, ast.AnnAssign) and isinstance(item.target, ast.Name): - VarName = item.target.id - try: - TypeInfo = CTypeInfo.FromNode(item.annotation, self.Trans.SymbolTable) - if TypeInfo is None: - TypeInfo = CTypeInfo() - TypeInfo.BaseType = t.CInt() - IsPtr = TypeInfo.IsPtr - MemberType = Gen._ctype_to_llvm(TypeInfo) - if isinstance(MemberType, ir.VoidType): - MemberType = ir.PointerType(ir.IntType(8)) - Gen.class_members[ClassName].append((VarName, MemberType)) + field_name: str = item.target.id + if field_name in ('__provides__', '__requires__', '__require_must__') and item.value: + values: list[str] = [] + if isinstance(item.value, ast.List): + for elt in item.value.elts: + if isinstance(elt, ast.Constant) and isinstance(elt.value, str): + values.append(elt.value) + if field_name == '__provides__': + Gen.class_provides[ClassName] = values + elif field_name == '__requires__': + Gen.class_requires[ClassName] = values + elif field_name == '__require_must__': + Gen.class_require_must[ClassName] = values + for item in Node.body: + # 跳过编译期元数据字段(__provides__/__requires__/__require_must__) + if isinstance(item, ast.AnnAssign) and isinstance(item.target, ast.Name): + if item.target.id in ('__provides__', '__requires__', '__require_must__'): + continue + parsed = self.CollectAnnAssignMember(item, Gen) + if parsed: + VarName, MemberType, TypeInfo = parsed + Gen.class_members[ClassName].append((VarName, MemberType)) + if TypeInfo: if isinstance(MemberType, ir.PointerType) and isinstance(MemberType.pointee, ir.IntType) and MemberType.pointee.width == 8: if isinstance(item.annotation, ast.BinOp) and isinstance(item.annotation.op, ast.BitOr): - def _find_struct_in_annot(node): - if isinstance(node, ast.Name) and node.id in Gen.structs: - return node.id - if isinstance(node, ast.Constant) and isinstance(node.value, str) and node.value in Gen.structs: - return node.value - if isinstance(node, ast.Attribute) and node.attr in Gen.structs: - return node.attr - if isinstance(node, ast.BinOp) and isinstance(node.op, ast.BitOr): - result = _find_struct_in_annot(node.left) - if result: - return result - return _find_struct_in_annot(node.right) - return None - element_class = _find_struct_in_annot(item.annotation) + element_class: str | None = FindStructNameInAnnotation(item.annotation, Gen.structs) if element_class: if ClassName not in Gen.class_member_element_class: Gen.class_member_element_class[ClassName] = {} Gen.class_member_element_class[ClassName][VarName] = element_class - if TypeInfo and hasattr(TypeInfo.BaseType, 'IsSigned'): + if hasattr(TypeInfo.BaseType, 'IsSigned'): Gen.class_member_signeds[ClassName][VarName] = TypeInfo.BaseType.IsSigned else: Gen.class_member_signeds[ClassName][VarName] = None - if TypeInfo and TypeInfo.IsBitField: + if TypeInfo.IsBitField: Gen.class_member_bitfields[ClassName][VarName] = TypeInfo.BitWidth else: Gen.class_member_bitfields[ClassName][VarName] = 0 - if TypeInfo and TypeInfo.ByteOrder: + if TypeInfo.ByteOrder: Gen.class_member_byteorders[ClassName][VarName] = TypeInfo.ByteOrder else: Gen.class_member_byteorders[ClassName][VarName] = "" if item.value: - const = self._BuildScalarConstant(item.value, MemberType) + const: ir.Constant | None = self._BuildScalarConstant(item.value, MemberType, Gen) if const: Gen.class_member_defaults[ClassName][VarName] = const - except Exception: # 回退:类成员类型解析失败时使用默认 i32 - Gen.class_members[ClassName].append((VarName, ir.IntType(32))) + else: Gen.class_member_signeds[ClassName][VarName] = None Gen.class_member_bitfields[ClassName][VarName] = 0 - existing_members = {m[0] for m in Gen.class_members[ClassName]} + existing_members: set[str] = {m[0] for m in Gen.class_members[ClassName]} for item in Node.body: if isinstance(item, ast.FunctionDef): self._current_method_args = {} @@ -342,10 +475,10 @@ class ClassHandle(BaseHandle): self._current_method_args = {} for item in Node.body: if isinstance(item, ast.FunctionDef): - MethodName = item.name - FullMethodName = f"{ClassName}.{MethodName}" + MethodName: str = item.name + FullMethodName: str = f"{ClassName}.{MethodName}" # property setter/deleter 使用不同的函数名后缀 - item_meta = self.Trans.FunctionHandler._ExtractFuncMeta(item.decorator_list) + item_meta: FuncMeta = self.Trans.FunctionHandler._ExtractFuncMeta(item.decorator_list) if FuncMeta.PROPERTY_SETTER in item_meta: FullMethodName = FullMethodName + '$set' elif FuncMeta.PROPERTY_DELETER in item_meta: @@ -362,41 +495,42 @@ class ClassHandle(BaseHandle): for item in Node.body: if isinstance(item, ast.FunctionDef): self.Trans.FunctionHandler._EmitFunctionForwardDeclLlvm(item, Gen, ClassName=ClassName) - for item in Node.body: - if isinstance(item, ast.FunctionDef): - self.Trans.FunctionHandler._EmitFunctionLlvm(item, Gen, ClassName=ClassName) + if not declare_only: + for item in Node.body: + if isinstance(item, ast.FunctionDef): + self.Trans.FunctionHandler._EmitFunctionLlvm(item, Gen, ClassName=ClassName) if IsCVTable and ClassName in Gen.Vtables: self._fill_vtable_with_methods(ClassName, Gen) # Generate wrapper functions for inherited methods that are not overridden if ParentClass: self._generate_inherited_method_wrappers(ClassName, Gen) - def _generate_inherited_method_wrappers(self, ClassName, Gen): + def _generate_inherited_method_wrappers(self, ClassName: str, Gen: LlvmGeneratorMixin) -> None: """为子类继承但未覆写的方法生成包装函数,使跨模块调用能正确链接。 例如 Label 继承 Widget.place,生成 Label.place 函数, 内部将 self 从 Label* bitcast 为 Widget*,然后调用 Widget.place。 """ - methods = Gen.class_methods.get(ClassName, []) + methods: list = Gen.class_methods.get(ClassName, []) if not methods: return if ClassName not in Gen.structs: return for method_name in methods: - method_short = method_name.split('.')[-1] if '.' in method_name else method_name - child_full = f"{ClassName}.{method_short}" + method_short: str = method_name.split('.')[-1] if '.' in method_name else method_name + child_full: str = f"{ClassName}.{method_short}" # 如果子类已经有该方法的实现,跳过 if Gen._find_function(child_full): continue # 沿继承链查找父类实现 - parent_func = None - parent_class = None - p = Gen.class_parent.get(ClassName) + parent_func: ir.Function | None = None + parent_class: str | None = None + p: str | None = Gen.class_parent.get(ClassName) while p: - parent_full = f"{p}.{method_short}" + parent_full: str = f"{p}.{method_short}" parent_func = Gen._find_function(parent_full) if parent_func: parent_class = p @@ -411,17 +545,17 @@ class ClassHandle(BaseHandle): continue # 构造子类包装函数签名:与父类函数相同,但 self 参数类型为子类指针 - parent_ftype = parent_func.function_type - parent_ret_type = parent_ftype.return_type - parent_param_types = list(parent_ftype.args) - is_vararg = parent_ftype.var_arg + parent_ftype: ir.FunctionType = parent_func.function_type + parent_ret_type: ir.Type = parent_ftype.return_type + parent_param_types: list[ir.Type] = list(parent_ftype.args) + is_vararg: bool = parent_ftype.var_arg # 判断父类方法是否是静态方法: # 如果第一个参数类型是父类指针,说明是实例方法;否则是静态方法 - parent_struct_ptr_type = ir.PointerType(Gen.structs[parent_class]) if parent_class in Gen.structs else None - is_static = True + parent_struct_ptr_type: ir.PointerType | None = ir.PointerType(Gen.structs[parent_class]) if parent_class in Gen.structs else None + is_static: bool = True if parent_param_types and parent_struct_ptr_type: - first_param = parent_param_types[0] + first_param: ir.Type = parent_param_types[0] # 检查第一个参数是否是父类指针(或可以 bitcast 为父类指针的指针类型) if isinstance(first_param, ir.PointerType): if isinstance(first_param.pointee, ir.IdentifiedStructType): @@ -433,8 +567,8 @@ class ClassHandle(BaseHandle): if is_static: # 静态方法:签名与父类完全一致,不需要 self 参数 - child_param_types = list(parent_param_types) - child_struct_ptr = None + child_param_types: list[ir.Type] = list(parent_param_types) + child_struct_ptr: ir.PointerType | None = None else: # 实例方法:替换第一个参数(self)的类型为子类指针 child_struct_ptr = ir.PointerType(Gen.structs[ClassName]) @@ -443,20 +577,20 @@ class ClassHandle(BaseHandle): else: child_param_types = [child_struct_ptr] - child_func_type = ir.FunctionType(parent_ret_type, child_param_types, var_arg=is_vararg) - child_mangled = Gen._mangle_func_name(child_full) - child_func = Gen._get_or_declare_function(child_mangled, child_func_type) + child_func_type: ir.FunctionType = ir.FunctionType(parent_ret_type, child_param_types, var_arg=is_vararg) + child_mangled: str = Gen._mangle_func_name(child_full) + child_func: ir.Function = Gen._get_or_declare_function(child_mangled, child_func_type) Gen.functions[child_full] = child_func # 生成函数体 - entry_block = child_func.append_basic_block(name="entry") - saved_builder = Gen.builder - saved_func = Gen.func + entry_block: ir.Block = child_func.append_basic_block(name="entry") + saved_builder: ir.IRBuilder = Gen.builder + saved_func: ir.Function = Gen.func Gen.builder = ir.IRBuilder(entry_block) Gen.func = child_func # 准备参数 - call_args = [] + call_args: list[ir.Value] = [] if is_static: # 静态方法:参数直接传递,不做 bitcast for arg in child_func.args: @@ -465,13 +599,13 @@ class ClassHandle(BaseHandle): # 实例方法:bitcast self,其余参数直接传递 for i, arg in enumerate(child_func.args): if i == 0 and parent_param_types: - actual_self_type = parent_param_types[0] - casted_self = Gen.builder.bitcast(arg, actual_self_type, name="self_cast") + actual_self_type: ir.Type = parent_param_types[0] + casted_self: ir.Value = Gen.builder.bitcast(arg, actual_self_type, name="self_cast") call_args.append(casted_self) else: call_args.append(arg) - result = Gen.builder.call(parent_func, call_args, name="inherited_call") + result: ir.Value = Gen.builder.call(parent_func, call_args, name="inherited_call") if isinstance(parent_ret_type, ir.VoidType): Gen.builder.ret_void() @@ -481,21 +615,21 @@ class ClassHandle(BaseHandle): Gen.builder = saved_builder Gen.func = saved_func - def _fill_vtable_with_methods(self, ClassName, Gen): - methods = Gen.class_methods.get(ClassName, []) + def _fill_vtable_with_methods(self, ClassName: str, Gen: LlvmGeneratorMixin) -> None: + methods: list = Gen.class_methods.get(ClassName, []) if not methods or ClassName not in Gen.Vtables: return - Vtable = Gen.Vtables[ClassName] - VtableType = Vtable.type.pointee - null_i8ptr = ir.Constant(ir.PointerType(ir.IntType(8)), None) - initializers = [] + Vtable: ir.GlobalVariable = Gen.Vtables[ClassName] + VtableType: ir.Type = Vtable.type.pointee + null_i8ptr: ir.Constant = ir.Constant(ir.PointerType(ir.IntType(8)), None) + initializers: list[ir.Constant] = [] for mi, method_name in enumerate(methods): - method_short = method_name.split('.')[-1] if '.' in method_name else method_name - func = Gen._find_function(f"{ClassName}.{method_short}") + method_short: str = method_name.split('.')[-1] if '.' in method_name else method_name + func: ir.Function | None = Gen._find_function(f"{ClassName}.{method_short}") if not func: func = Gen._find_function(f"{ClassName}.{method_short}__") if not func: - p = Gen.class_parent.get(ClassName) + p: str | None = Gen.class_parent.get(ClassName) while p: func = Gen._find_function(f"{p}.{method_short}") if not func: @@ -510,26 +644,27 @@ class ClassHandle(BaseHandle): if initializers: Vtable.initializer = ir.Constant(VtableType, initializers) - def _scan_method_body_for_self_members(self, body, ClassName, existing_members, Gen): + def _scan_method_body_for_self_members(self, body: list[ast.AST], ClassName: str, existing_members: set[str], Gen: LlvmGeneratorMixin) -> None: for stmt in body: self._scan_node_for_self_assign(stmt, ClassName, existing_members, Gen) - def _scan_node_for_self_assign(self, node, ClassName, existing_members, Gen): + def _scan_node_for_self_assign(self, node: ast.AST, ClassName: str, existing_members: set[str], Gen: LlvmGeneratorMixin) -> None: if isinstance(node, ast.AnnAssign): if (isinstance(node.target, ast.Attribute) and isinstance(node.target.value, ast.Name) and node.target.value.id == 'self'): - VarName = node.target.attr + VarName: str = node.target.attr if VarName not in existing_members: try: - TypeInfo = CTypeInfo.FromNode(node.annotation, self.Trans.SymbolTable) + TypeInfo: CTypeInfo | None = CTypeInfo.FromNode(node.annotation, self.Trans.SymbolTable) if TypeInfo is None: TypeInfo = CTypeInfo() TypeInfo.BaseType = t.CInt() - MemberType = Gen._ctype_to_llvm(TypeInfo) + MemberType: ir.Type = Gen._ctype_to_llvm(TypeInfo) if isinstance(MemberType, ir.VoidType): MemberType = ir.IntType(32) - except Exception: # 回退:成员类型解析失败时使用默认 i32 + except Exception as e: # 回退:成员类型解析失败时使用默认 i32 + _vlog().warning(f"HandlesClassDef: 忽略异常 {e}", exc_info=e) MemberType = ir.IntType(32) Gen.class_members[ClassName].append((VarName, MemberType)) Gen.class_member_signeds[ClassName][VarName] = None @@ -583,7 +718,7 @@ class ClassHandle(BaseHandle): if node.value.func.attr == 'len': MemberType = ir.IntType(32) except Exception as _e: - if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": + if _config_mode == "strict": self.Trans.LogWarning(f"异常被忽略: {_e}") Gen.class_members[ClassName].append((VarName, MemberType)) Gen.class_member_signeds[ClassName][VarName] = None @@ -596,123 +731,106 @@ class ClassHandle(BaseHandle): continue self._scan_node_for_self_assign(child, ClassName, existing_members, Gen) - def _EmitUnionLlvm(self, Node, Gen): - ClassName = Node.name - union_member_types = [] - for item in Node.body: - if isinstance(item, ast.ClassDef): - nested_class_name = item.name - nested_member_types = [] - for nested_item in item.body: - if isinstance(nested_item, ast.AnnAssign) and isinstance(nested_item.target, ast.Name): - VarName = nested_item.target.id - try: - TypeInfo = CTypeInfo.FromNode(nested_item.annotation, self.Trans.SymbolTable) - if TypeInfo is None: - TypeInfo = CTypeInfo() - TypeInfo.BaseType = t.CInt() - MemberType = Gen._ctype_to_llvm(TypeInfo) - if isinstance(MemberType, ir.VoidType): - MemberType = ir.PointerType(ir.IntType(8)) - nested_member_types.append(MemberType) - except Exception: # 回退:嵌套成员类型解析失败时使用默认 i32 - nested_member_types.append(ir.IntType(32)) - if nested_member_types: - nested_struct_type = ir.IdentifiedStructType(Gen.module, f"{ClassName}_{nested_class_name}") - nested_struct_type.set_body(*nested_member_types) - Gen.structs[f"{ClassName}_{nested_class_name}"] = nested_struct_type - union_member_types.append(nested_struct_type) - nested_class_full_name = f"{ClassName}_{nested_class_name}" - if nested_class_full_name not in Gen.class_members: - Gen.class_members[nested_class_full_name] = [] - if nested_class_full_name not in Gen.class_member_signeds: - Gen.class_member_signeds[nested_class_full_name] = {} - for nested_item in item.body: - if isinstance(nested_item, ast.AnnAssign) and isinstance(nested_item.target, ast.Name): - VarName = nested_item.target.id - try: - TypeInfo = CTypeInfo.FromNode(nested_item.annotation, self.Trans.SymbolTable) - if TypeInfo is None: - TypeInfo = CTypeInfo() - TypeInfo.BaseType = t.CInt() - MemberType = Gen._ctype_to_llvm(TypeInfo) - if isinstance(MemberType, ir.VoidType): - MemberType = ir.PointerType(ir.IntType(8)) - Gen.class_members[nested_class_full_name].append((VarName, MemberType)) - if TypeInfo and hasattr(TypeInfo.BaseType, 'IsSigned'): - Gen.class_member_signeds[nested_class_full_name][VarName] = TypeInfo.BaseType.IsSigned - else: - Gen.class_member_signeds[nested_class_full_name][VarName] = None - except Exception: # 回退:嵌套类成员类型解析失败时使用默认 i32 - Gen.class_members[nested_class_full_name].append((VarName, ir.IntType(32))) + def _EmitUnionLlvm(self, Node: ast.ClassDef, Gen: LlvmGeneratorMixin) -> None: + ClassName: str = Node.name + union_member_types: list[ir.Type] = [] + for item in Node.body: + if isinstance(item, ast.ClassDef): + nested_class_name: str = item.name + nested_member_types: list[ir.Type] = [] + for nested_item in item.body: + parsed = self.CollectAnnAssignMember(nested_item, Gen) + if parsed: + nested_member_types.append(parsed[1]) + if nested_member_types: + nested_struct_type: ir.IdentifiedStructType = ir.IdentifiedStructType(Gen.module, f"{ClassName}_{nested_class_name}") + nested_struct_type.set_body(*nested_member_types) + Gen.structs[f"{ClassName}_{nested_class_name}"] = nested_struct_type + union_member_types.append(nested_struct_type) + nested_class_full_name: str = f"{ClassName}_{nested_class_name}" + if nested_class_full_name not in Gen.class_members: + Gen.class_members[nested_class_full_name] = [] + if nested_class_full_name not in Gen.class_member_signeds: + Gen.class_member_signeds[nested_class_full_name] = {} + for nested_item in item.body: + parsed = self.CollectAnnAssignMember(nested_item, Gen) + if parsed: + VarName, MemberType, TypeInfo = parsed + Gen.class_members[nested_class_full_name].append((VarName, MemberType)) + if TypeInfo and hasattr(TypeInfo.BaseType, 'IsSigned'): + Gen.class_member_signeds[nested_class_full_name][VarName] = TypeInfo.BaseType.IsSigned + else: Gen.class_member_signeds[nested_class_full_name][VarName] = None if union_member_types: - max_size = 0 + max_size: int = 0 for member_type in union_member_types: try: - size = member_type.get_abi_size(ir.DataLayout(Gen.module.data_layout)) - except Exception: # 回退:获取类型大小失败时使用默认值 8 + size: int = member_type.get_abi_size(ir.DataLayout(Gen.module.data_layout)) + except Exception as e: # 回退:获取类型大小失败时使用默认值 8 + _vlog().warning(f"HandlesClassDef: 忽略异常 {e}", exc_info=e) size = 8 max_size = max(max_size, size) - union_type = ir.IdentifiedStructType(Gen.module, ClassName) + union_type: ir.IdentifiedStructType = ir.IdentifiedStructType(Gen.module, ClassName) union_type.set_body(ir.ArrayType(ir.IntType(8), max_size)) Gen.structs[ClassName] = union_type - UnionNode = CTypeInfo() + UnionNode: CTypeInfo = CTypeInfo() UnionNode.Name = ClassName UnionNode.IsUnion = True self.Trans.SymbolTable.insert(ClassName, UnionNode) - def _EmitREnumLlvm(self, Node, Gen): - ClassName = Node.name - variant_info = [] - variant_names = [] - variant_index = 0 + def _EmitREnumLlvm(self, Node: ast.ClassDef, Gen: LlvmGeneratorMixin) -> None: + ClassName: str = Node.name + variant_info: list[tuple] = [] + variant_names: list[str] = [] + + # 第一遍:收集显式赋值的 tag 值,确定起始索引 + explicit_values: dict[str, int] = {} + for item in Node.body: + if isinstance(item, ast.Assign): + for target in item.targets: + if isinstance(target, ast.Name): + if item.value and isinstance(item.value, ast.Constant): + explicit_values[target.id] = item.value.value + # 类变体从 max(explicit_values, default=-1) + 1 开始 + next_class_tag: int = max(explicit_values.values()) + 1 if explicit_values else 0 + variant_index: int = 0 + for item in Node.body: if isinstance(item, ast.ClassDef): - VariantName = item.name + VariantName: str = item.name variant_names.append(VariantName) - member_types = [] - member_names = [] - member_annotations = [] + member_types: list[ir.Type] = [] + member_names: list[str] = [] + member_annotations: list[ast.AST | None] = [] for nested_item in item.body: - if isinstance(nested_item, ast.AnnAssign) and isinstance(nested_item.target, ast.Name): - VarName = nested_item.target.id - try: - TypeInfo = CTypeInfo.FromNode(nested_item.annotation, self.Trans.SymbolTable) - if TypeInfo is None: - TypeInfo = CTypeInfo() - TypeInfo.BaseType = t.CInt() - MemberType = Gen._ctype_to_llvm(TypeInfo) - if isinstance(MemberType, ir.VoidType): - MemberType = ir.PointerType(ir.IntType(8)) - member_types.append(MemberType) - member_names.append(VarName) - member_annotations.append(nested_item.annotation) - except Exception: # 回退:成员类型解析失败时使用默认 i32 - member_types.append(ir.IntType(32)) - member_names.append(VarName) - member_annotations.append(None) - variant_info.append((VariantName, member_types, member_names, member_annotations, item.lineno, variant_index)) - variant_index += 1 + parsed = self.CollectAnnAssignMember(nested_item, Gen) + if parsed: + VarName, MemberType, TypeInfo = parsed + member_types.append(MemberType) + member_names.append(VarName) + member_annotations.append(nested_item.annotation if TypeInfo else None) + # 类变体使用专用计数器,避免与显式值冲突 + tag: int = next_class_tag + next_class_tag += 1 + variant_info.append((VariantName, member_types, member_names, member_annotations, item.lineno, tag)) elif isinstance(item, ast.Assign): for target in item.targets: if isinstance(target, ast.Name): VarName = target.id variant_names.append(VarName) - value = None + value: int | None = None if item.value and isinstance(item.value, ast.Constant): value = item.value.value - variant_index = value + 1 else: value = variant_index variant_index += 1 variant_info.append((VarName, [], [], [], item.lineno, value)) - max_variant_struct = None - max_variant_size = 0 + max_variant_struct: list[ir.Type] | None = None + max_variant_size: int = 0 for _, member_types, _, _, _, _ in variant_info: if member_types: - full_types = [ir.IntType(32)] + member_types - size = 4 + full_types: list[ir.Type] = [ir.IntType(32)] + member_types + size: int = 4 for mt in full_types: if isinstance(mt, ir.IntType): size += mt.width // 8 @@ -734,14 +852,14 @@ class ClassHandle(BaseHandle): max_variant_struct = full_types if max_variant_struct is None: max_variant_struct = [ir.IntType(32), ir.IntType(32)] - renum_type = ir.IdentifiedStructType(Gen.module, ClassName) + renum_type: ir.IdentifiedStructType = ir.IdentifiedStructType(Gen.module, ClassName) renum_type.set_body(*max_variant_struct) Gen.structs[ClassName] = renum_type for VariantName, member_types, member_names, member_annotations, lineno, tag_value in variant_info: - NestedStructName = f"{ClassName}_{VariantName}" + NestedStructName: str = f"{ClassName}_{VariantName}" if member_types: - padded_member_types = list(max_variant_struct) - nested_struct_type = ir.IdentifiedStructType(Gen.module, NestedStructName) + padded_member_types: list[ir.Type] = list(max_variant_struct) + nested_struct_type: ir.IdentifiedStructType = ir.IdentifiedStructType(Gen.module, NestedStructName) nested_struct_type.set_body(*padded_member_types) Gen.structs[NestedStructName] = nested_struct_type if NestedStructName not in Gen.class_members: @@ -753,14 +871,15 @@ class ClassHandle(BaseHandle): for i, (mname, mtype) in enumerate(zip(member_names, member_types)): Gen.class_members[NestedStructName].append((mname, mtype)) try: - ti = CTypeInfo.FromNode(member_annotations[i], self.Trans.SymbolTable) + ti: CTypeInfo | None = CTypeInfo.FromNode(member_annotations[i], self.Trans.SymbolTable) if ti and hasattr(ti.BaseType, 'IsSigned'): Gen.class_member_signeds[NestedStructName][mname] = ti.BaseType.IsSigned else: Gen.class_member_signeds[NestedStructName][mname] = None - except Exception: # 回退:签名信息解析失败时设为 None + except Exception as e: # 回退:签名信息解析失败时设为 None + _vlog().warning(f"HandlesClassDef: 忽略异常 {e}", exc_info=e) Gen.class_member_signeds[NestedStructName][mname] = None - MemberNode = CTypeInfo() + MemberNode: CTypeInfo = CTypeInfo() MemberNode.Name = VariantName MemberNode.BaseType = t.CEnum(ClassName) MemberNode.value = tag_value @@ -768,7 +887,7 @@ class ClassHandle(BaseHandle): MemberNode.Lineno = lineno MemberNode.IsEnumMember = True self.Trans.SymbolTable.insert(VariantName, MemberNode) - RenumTypeInfo = CTypeInfo() + RenumTypeInfo: CTypeInfo = CTypeInfo() RenumTypeInfo.Name = ClassName RenumTypeInfo.BaseType = t.REnum(ClassName) RenumTypeInfo.IsRenum = True @@ -776,26 +895,25 @@ class ClassHandle(BaseHandle): RenumTypeInfo.RenumVariants = variant_names self.Trans.SymbolTable.insert(ClassName, RenumTypeInfo) - def _RegisterEnumMembers(self, Node): - ClassName = Node.name - EnumTypeInfo = CTypeInfo() + def _RegisterEnumMembers(self, Node: ast.ClassDef) -> None: + ClassName: str = Node.name + EnumTypeInfo: CTypeInfo = CTypeInfo() EnumTypeInfo.Name = ClassName EnumTypeInfo.BaseType = t.CEnum(ClassName) EnumTypeInfo.IsEnum = True self.Trans.SymbolTable.insert(ClassName, EnumTypeInfo) - from lib.core.Exportable import EnumMember as ExportEnumMember enum_export = self.Trans.Exportable.add_enum( name=ClassName, lineno=Node.lineno, is_public=True ) - next_enum_value = 0 + next_enum_value: int = 0 for item in Node.body: if isinstance(item, ast.Assign): for target in item.targets: if isinstance(target, ast.Name): - VarName = target.id - value = None + VarName: str = target.id + value: int | str | None = None if item.value: if isinstance(item.value, ast.Constant): value = item.value.value @@ -806,14 +924,14 @@ class ClassHandle(BaseHandle): next_enum_value = value + 1 elif isinstance(item.value, ast.Name): value = item.value.id - if self.Trans.SymbolTable.has(value): - ref_info = self.Trans.SymbolTable[value] + ref_info: CTypeInfo | None = self.Trans.SymbolTable.lookup(value) + if ref_info: if ref_info.value is not None and isinstance(ref_info.value, int): next_enum_value = ref_info.value + 1 else: value = next_enum_value next_enum_value += 1 - MemberNode = CTypeInfo() + MemberNode: CTypeInfo = CTypeInfo() MemberNode.Name = VarName MemberNode.BaseType = t.CEnum(ClassName) MemberNode.value = value @@ -840,14 +958,14 @@ class ClassHandle(BaseHandle): next_enum_value = value + 1 elif isinstance(item.value, ast.Name): value = item.value.id - if self.Trans.SymbolTable.has(value): - ref_info = self.Trans.SymbolTable[value] + ref_info: CTypeInfo | None = self.Trans.SymbolTable.lookup(value) + if ref_info: if ref_info.value is not None and isinstance(ref_info.value, int): next_enum_value = ref_info.value + 1 else: value = next_enum_value next_enum_value += 1 - MemberNode = CTypeInfo() + MemberNode: CTypeInfo = CTypeInfo() MemberNode.Name = VarName MemberNode.BaseType = t.CEnum(ClassName) MemberNode.value = value @@ -861,85 +979,66 @@ class ClassHandle(BaseHandle): lineno=item.lineno )) - def _EmitNewFunctionLlvm(self, ClassName, Gen, IsCVTable=False, IsCpythonObject=False): - NewFuncName = f'{ClassName}.__before_init__' - existing_func = Gen.functions.get(NewFuncName) + def _EmitNewFunctionLlvm(self, ClassName: str, Gen: LlvmGeneratorMixin, IsCVTable: bool = False, IsCpythonObject: bool = False) -> None: + NewFuncName: str = f'{ClassName}.__before_init__' + existing_func: ir.Function | None = Gen.functions.get(NewFuncName) if existing_func and len(existing_func.blocks) > 0: return - MangledName = Gen._mangle_name(NewFuncName) - StructType = Gen.structs[ClassName] + MangledName: str = Gen._mangle_name(NewFuncName) + StructType: ir.Type = Gen.structs[ClassName] if isinstance(StructType, ir.IdentifiedStructType) and (StructType.elements is None or len(StructType.elements) == 0): self.Trans.ImportHandler._TryLoadStructFromStub(ClassName, Gen) StructType = Gen.structs.get(ClassName, StructType) - StructPtrType = ir.PointerType(StructType) - FuncType = ir.FunctionType(ir.VoidType(), [StructPtrType]) + StructPtrType: ir.PointerType = ir.PointerType(StructType) + FuncType: ir.FunctionType = ir.FunctionType(ir.VoidType(), [StructPtrType]) if existing_func: - func = existing_func + func: ir.Function = existing_func else: func = Gen._get_or_declare_function(MangledName, FuncType) Gen.functions[NewFuncName] = func - EntryBlock = func.append_basic_block(name="entry") - saved_builder = Gen.builder - saved_func = Gen.func + EntryBlock: ir.Block = func.append_basic_block(name="entry") + saved_builder: ir.IRBuilder = Gen.builder + saved_func: ir.Function = Gen.func Gen.builder = ir.IRBuilder(EntryBlock) Gen.func = func - StructPtr = func.args[0] + StructPtr: ir.Argument = func.args[0] if IsCVTable: - base = 1 + base: int = 1 if ClassName in Gen.Vtables: - VtablePtr = Gen.builder.gep(StructPtr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), 0)], name="vtable_slot") - VtableAddr = Gen.builder.bitcast(Gen.Vtables[ClassName], ir.PointerType(ir.IntType(8)), name="vtable_addr") + VtablePtr: ir.Value = Gen.builder.gep(StructPtr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), 0)], name="vtable_slot") + VtableAddr: ir.Value = Gen.builder.bitcast(Gen.Vtables[ClassName], ir.PointerType(ir.IntType(8)), name="vtable_addr") Gen.builder.store(VtableAddr, VtablePtr) - members = Gen.class_members.get(ClassName, []) - defaults = Gen.class_member_defaults.get(ClassName, {}) + members: list[tuple] = Gen.class_members.get(ClassName, []) + defaults: dict = Gen.class_member_defaults.get(ClassName, {}) for i, (member_name, member_type) in enumerate(members): - ElemPtr = Gen.builder.gep(StructPtr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), base + i)], name=f"{ClassName}_{member_name}") + ElemPtr: ir.Value = Gen.builder.gep(StructPtr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), base + i)], name=f"{ClassName}_{member_name}") if member_name in defaults: try: - val = defaults[member_name] + val: ir.Constant = defaults[member_name] if not isinstance(val, ir.Constant): val = ir.Constant(ElemPtr.type.pointee, val) Gen.builder.store(val, ElemPtr) except Exception as _e: - if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": + if _config_mode == "strict": self.Trans.LogWarning(f"异常被忽略: {_e}") Gen.builder.ret_void() Gen.builder = saved_builder Gen.func = saved_func - def _BuildScalarConstant(self, node, llvm_type): - if isinstance(node, ast.Constant): - if isinstance(node.value, bool): - try: - return ir.Constant(llvm_type, 1 if node.value else 0) - except Exception: # 回退:常量创建失败 - return None - elif isinstance(node.value, int): - try: - return ir.Constant(llvm_type, node.value) - except Exception: # 回退:常量创建失败 - return None - elif isinstance(node.value, float): - try: - return ir.Constant(llvm_type, node.value) - except Exception: # 回退:常量创建失败 - return None - elif isinstance(node, ast.UnaryOp) and isinstance(node.op, ast.USub): - if isinstance(node.operand, ast.Constant) and isinstance(node.operand.value, int): - try: - return ir.Constant(llvm_type, -node.operand.value) - except Exception: # 回退:常量创建失败 - return None - return None + def _BuildScalarConstant(self, node: ast.AST, llvm_type: ir.Type, Gen: LlvmGeneratorMixin | None = None) -> ir.Constant | None: + """构建标量常量,委托给统一的 _BuildScalarConstantUnified 方法。""" + if Gen is None: + Gen = self.Trans.LlvmGen + return self.Trans._BuildScalarConstantUnified(node, llvm_type, Gen) - def _BuildStructConstant(self, call_node, StructName, Gen): - struct_type = Gen.structs[StructName] - members = Gen.class_members.get(StructName, []) - defaults = Gen.class_member_defaults.get(StructName, {}) - member_values = [] + def _BuildStructConstant(self, call_node: ast.Call, StructName: str, Gen: LlvmGeneratorMixin) -> ir.Constant | None: + struct_type: ir.Type = Gen.structs[StructName] + members: list[tuple] = Gen.class_members.get(StructName, []) + defaults: dict = Gen.class_member_defaults.get(StructName, {}) + member_values: list[ir.Constant] = [] for member_name, member_type in members: if member_name in defaults: - val = defaults[member_name] + val: ir.Constant = defaults[member_name] if not isinstance(val, ir.Constant): try: val = ir.Constant(member_type, val) @@ -958,7 +1057,7 @@ class ClassHandle(BaseHandle): for i, arg in enumerate(call_node.args): if i < len(members): _, member_type = members[i] - const = self._BuildScalarConstant(arg, member_type) + const: ir.Constant | None = self._BuildScalarConstant(arg, member_type, Gen) if const is not None: member_values[i] = const try: diff --git a/lib/core/Handles/HandlesDelete.py b/lib/core/Handles/HandlesDelete.py index 64119e2..649fcad 100644 --- a/lib/core/Handles/HandlesDelete.py +++ b/lib/core/Handles/HandlesDelete.py @@ -1,96 +1,96 @@ -from __future__ import annotations -from typing import TYPE_CHECKING -if TYPE_CHECKING: - from lib.core.translator import Translator -from lib.core.Handles.HandlesBase import BaseHandle, FuncMeta -import ast -import llvmlite.ir as ir - - -class DeleteHandle(BaseHandle): - def _HandleDeleteLlvm(self, Node): - Gen = self.Trans.LlvmGen - for target in Node.targets: - if isinstance(target, ast.Subscript): - ClassName = self.Trans.ExprHandler._get_var_class(target.value, Gen) - if ClassName and Gen._has_function(f'{ClassName}.__delitem__'): - obj_val = self.Trans.ExprHandler.HandleExprLlvm(target.value) - idx_val = self.Trans.ExprHandler.HandleExprLlvm(target.slice) - if obj_val and idx_val: - if isinstance(obj_val.type, ir.PointerType) and isinstance(obj_val.type.pointee, ir.IntType) and obj_val.type.pointee.width == 8: - obj_val = Gen.builder.bitcast(obj_val, ir.PointerType(Gen.structs[ClassName]), name=f"cast_{ClassName}") - Gen.builder.call(Gen._get_function(f'{ClassName}.__delitem__'), [obj_val, idx_val], name=f"call_{ClassName}.__delitem__") - elif isinstance(target, ast.Name): - ClassName = Gen.var_struct_class.get(target.id) - if ClassName and Gen._has_function(f'{ClassName}.__delete__'): - obj_val = self.Trans.ExprHandler.HandleExprLlvm(target) - if obj_val: - if isinstance(obj_val.type, ir.PointerType) and isinstance(obj_val.type.pointee, ir.IntType) and obj_val.type.pointee.width == 8: - obj_val = Gen.builder.bitcast(obj_val, ir.PointerType(Gen.structs[ClassName]), name=f"cast_{ClassName}") - Gen.builder.call(Gen._get_function(f'{ClassName}.__delete__'), [obj_val], name=f"call_{ClassName}.__delete__") - elif isinstance(target, ast.Attribute): - # 检查 property deleter - AttrName = target.attr - ClassName = None - obj_val_for_prop = None - - if isinstance(target.value, ast.Name) and target.value.id == 'self': - # del self.attr — 检查当前类的 property deleter - ClassName = self.Trans._CurrentCpythonObjectClass - if ClassName: - PropKey = f'{ClassName}.{AttrName}' - PropInfo = self.Trans.SymbolTable.lookup(PropKey) - if PropInfo and PropInfo.MetaList and FuncMeta.PROPERTY_DELETER in PropInfo.MetaList: - SelfVar = Gen._get_var_ptr('self') - if SelfVar: - SelfPtr = Gen._load(SelfVar, name="self") - DeleterFunc = Gen._get_function(PropKey + '$del') - if DeleterFunc and SelfPtr: - Gen.builder.call(DeleterFunc, [SelfPtr], name=f"prop_del_{PropKey}") - continue - else: - # del obj.attr — 检查 obj 类的 property deleter - ClassName = self.Trans.ExprHandler._get_var_class(target.value, Gen) - if ClassName: - PropKey = f'{ClassName}.{AttrName}' - PropInfo = self.Trans.SymbolTable.lookup(PropKey) - if PropInfo and PropInfo.MetaList and FuncMeta.PROPERTY_DELETER in PropInfo.MetaList: - obj_val = self.Trans.ExprHandler.HandleExprLlvm(target.value) - if obj_val: - DeleterFunc = Gen._get_function(PropKey + '$del') - if DeleterFunc: - Gen.builder.call(DeleterFunc, [obj_val], name=f"prop_del_{PropKey}") - continue - - # 原有的 __del__ 处理逻辑 - obj_val = self.Trans.ExprHandler.HandleExprLlvm(target) - if obj_val: - if isinstance(obj_val.type, ir.PointerType) and isinstance(obj_val.type.pointee, ir.PointerType): - obj_val = Gen._load(obj_val, name="Load_del_ptr") - ClassName = None - if isinstance(obj_val.type, ir.PointerType) and isinstance(obj_val.type.pointee, (ir.LiteralStructType, ir.IdentifiedStructType)): - for CN, ST in Gen.structs.items(): - if obj_val.type.pointee == ST: - ClassName = CN - break - elif isinstance(obj_val.type, ir.PointerType) and isinstance(obj_val.type.pointee, ir.IntType) and obj_val.type.pointee.width == 8: - if isinstance(target.value, ast.Name) and target.value.id == 'self': - AttrName = target.attr - SelfClassName = self.Trans._CurrentCpythonObjectClass - if SelfClassName and SelfClassName in Gen.class_members: - for member_name, member_type in Gen.class_members[SelfClassName]: - if member_name == AttrName: - for CN in Gen.structs: - if CN == AttrName or Gen._has_function(f'{CN}.__del__'): - ClassName = CN - break - break - if not ClassName: - for CN, ST in Gen.structs.items(): - if Gen._has_function(f'{CN}.__del__'): - ClassName = CN - break - if ClassName and Gen._has_function(f'{ClassName}.__del__'): - if isinstance(obj_val.type, ir.PointerType) and isinstance(obj_val.type.pointee, ir.IntType) and obj_val.type.pointee.width == 8: - obj_val = Gen.builder.bitcast(obj_val, ir.PointerType(Gen.structs[ClassName]), name=f"cast_{ClassName}") +from __future__ import annotations +from typing import TYPE_CHECKING +if TYPE_CHECKING: + from lib.core.translator import Translator +from lib.core.Handles.HandlesBase import BaseHandle, FuncMeta +import ast +import llvmlite.ir as ir + + +class DeleteHandle(BaseHandle): + def _HandleDeleteLlvm(self, Node: ast.Delete) -> None: + Gen: "Translator.LlvmGen" = self.Trans.LlvmGen + for target in Node.targets: + if isinstance(target, ast.Subscript): + ClassName: str | None = self.Trans.ExprHandler._get_var_class(target.value, Gen) + if ClassName and Gen._has_function(f'{ClassName}.__delitem__'): + obj_val: ir.Value | None = self.Trans.ExprHandler.HandleExprLlvm(target.value) + idx_val: ir.Value | None = self.Trans.ExprHandler.HandleExprLlvm(target.slice) + if obj_val and idx_val: + if isinstance(obj_val.type, ir.PointerType) and isinstance(obj_val.type.pointee, ir.IntType) and obj_val.type.pointee.width == 8: + obj_val = Gen.builder.bitcast(obj_val, ir.PointerType(Gen.structs[ClassName]), name=f"cast_{ClassName}") + Gen.builder.call(Gen._get_function(f'{ClassName}.__delitem__'), [obj_val, idx_val], name=f"call_{ClassName}.__delitem__") + elif isinstance(target, ast.Name): + ClassName: str | None = Gen.var_struct_class.get(target.id) + if ClassName and Gen._has_function(f'{ClassName}.__delete__'): + obj_val: ir.Value | None = self.Trans.ExprHandler.HandleExprLlvm(target) + if obj_val: + if isinstance(obj_val.type, ir.PointerType) and isinstance(obj_val.type.pointee, ir.IntType) and obj_val.type.pointee.width == 8: + obj_val = Gen.builder.bitcast(obj_val, ir.PointerType(Gen.structs[ClassName]), name=f"cast_{ClassName}") + Gen.builder.call(Gen._get_function(f'{ClassName}.__delete__'), [obj_val], name=f"call_{ClassName}.__delete__") + elif isinstance(target, ast.Attribute): + # 检查 property deleter + AttrName: str = target.attr + ClassName: str | None = None + obj_val_for_prop: ir.Value | None = None + + if isinstance(target.value, ast.Name) and target.value.id == 'self': + # del self.attr — 检查当前类的 property deleter + ClassName = self.Trans._CurrentCpythonObjectClass + if ClassName: + PropKey: str = f'{ClassName}.{AttrName}' + PropInfo: "SymbolTable.SymbolInfo | None" = self.Trans.SymbolTable.lookup(PropKey) + if PropInfo and PropInfo.MetaList and FuncMeta.PROPERTY_DELETER in PropInfo.MetaList: + SelfVar: ir.Value | None = Gen._get_var_ptr('self') + if SelfVar: + SelfPtr: ir.Value = Gen._load(SelfVar, name="self") + DeleterFunc: ir.Function | None = Gen._get_function(PropKey + '$del') + if DeleterFunc and SelfPtr: + Gen.builder.call(DeleterFunc, [SelfPtr], name=f"prop_del_{PropKey}") + continue + else: + # del obj.attr — 检查 obj 类的 property deleter + ClassName = self.Trans.ExprHandler._get_var_class(target.value, Gen) + if ClassName: + PropKey: str = f'{ClassName}.{AttrName}' + PropInfo: "SymbolTable.SymbolInfo | None" = self.Trans.SymbolTable.lookup(PropKey) + if PropInfo and PropInfo.MetaList and FuncMeta.PROPERTY_DELETER in PropInfo.MetaList: + obj_val: ir.Value | None = self.Trans.ExprHandler.HandleExprLlvm(target.value) + if obj_val: + DeleterFunc: ir.Function | None = Gen._get_function(PropKey + '$del') + if DeleterFunc: + Gen.builder.call(DeleterFunc, [obj_val], name=f"prop_del_{PropKey}") + continue + + # 原有的 __del__ 处理逻辑 + obj_val: ir.Value | None = self.Trans.ExprHandler.HandleExprLlvm(target) + if obj_val: + if isinstance(obj_val.type, ir.PointerType) and isinstance(obj_val.type.pointee, ir.PointerType): + obj_val = Gen._load(obj_val, name="Load_del_ptr") + ClassName = None + if isinstance(obj_val.type, ir.PointerType) and isinstance(obj_val.type.pointee, (ir.LiteralStructType, ir.IdentifiedStructType)): + for CN, ST in Gen.structs.items(): + if obj_val.type.pointee == ST: + ClassName = CN + break + elif isinstance(obj_val.type, ir.PointerType) and isinstance(obj_val.type.pointee, ir.IntType) and obj_val.type.pointee.width == 8: + if isinstance(target.value, ast.Name) and target.value.id == 'self': + AttrName = target.attr + SelfClassName: str | None = self.Trans._CurrentCpythonObjectClass + if SelfClassName and SelfClassName in Gen.class_members: + for member_name, member_type in Gen.class_members[SelfClassName]: + if member_name == AttrName: + for CN in Gen.structs: + if CN == AttrName or Gen._has_function(f'{CN}.__del__'): + ClassName = CN + break + break + if not ClassName: + for CN, ST in Gen.structs.items(): + if Gen._has_function(f'{CN}.__del__'): + ClassName = CN + break + if ClassName and Gen._has_function(f'{ClassName}.__del__'): + if isinstance(obj_val.type, ir.PointerType) and isinstance(obj_val.type.pointee, ir.IntType) and obj_val.type.pointee.width == 8: + obj_val = Gen.builder.bitcast(obj_val, ir.PointerType(Gen.structs[ClassName]), name=f"cast_{ClassName}") Gen.builder.call(Gen._get_function(f'{ClassName}.__del__'), [obj_val], name=f"call_{ClassName}.__del__") \ No newline at end of file diff --git a/lib/core/Handles/HandlesExpr.py b/lib/core/Handles/HandlesExpr.py index 5b85f16..6b7b8bd 100644 --- a/lib/core/Handles/HandlesExpr.py +++ b/lib/core/Handles/HandlesExpr.py @@ -1,429 +1,442 @@ -from __future__ import annotations -from typing import TYPE_CHECKING -if TYPE_CHECKING: - from lib.core.translator import Translator -from lib.core.Handles.HandlesBase import BaseHandle -import ast -import llvmlite.ir as ir - - -class ExprHandle(BaseHandle): - def __init__(self, translator: "Translator"): - super().__init__(translator) - - def GetOpSymbol(self, Op): - return self.Trans.ExprUtils.GetOpSymbol(Op) - - def GetUnaryOpSymbol(self, Op): - return self.Trans.ExprUtils.GetUnaryOpSymbol(Op) - - def GetComparatorSymbol(self, Op): - return self.Trans.ExprUtils.GetComparatorSymbol(Op) - - def _get_var_class(self, node, Gen): - return self.Trans.ExprUtils._get_var_class(node, Gen) - - def _try_operator_overLoad(self, ClassName, op_name, obj_val, Gen, other_val=None): - return self.Trans.ExprUtils._try_operator_overLoad(ClassName, op_name, obj_val, Gen, other_val) - - def _get_llvm_member_offset(self, field_name, ClassName, Gen): - return self.Trans.ExprAttrHandle._get_llvm_member_offset(field_name, ClassName, Gen) - - def HandleExprLlvm(self, Node, VarType=None): - Gen = self.Trans.LlvmGen - if not Gen or not Gen.builder: - return None - if isinstance(Node, ast.Constant): - return self._HandleConstantLlvm(Node, VarType) - elif isinstance(Node, ast.Name): - return self._HandleNameLlvm(Node, VarType) - elif isinstance(Node, ast.BinOp): - return self.Trans.ExprOpsHandle._HandleBinOpLlvm(Node, VarType) - elif isinstance(Node, ast.BoolOp): - return self.Trans.ExprOpsHandle._HandleBoolOpLlvm(Node) - elif isinstance(Node, ast.UnaryOp): - return self.Trans.ExprOpsHandle._HandleUnaryOpLlvm(Node) - elif isinstance(Node, ast.Call): - return self.Trans.ExprCallHandle._HandleCallLlvm(Node) - elif isinstance(Node, ast.Compare): - return self.Trans.ExprOpsHandle._HandleCompareLlvm(Node) - elif isinstance(Node, ast.Attribute): - return self.Trans.ExprAttrHandle._HandleAttributeLlvm(Node) - elif isinstance(Node, ast.Subscript): - return self.Trans.ExprAttrHandle._HandleSubscriptLlvm(Node) - elif isinstance(Node, ast.IfExp): - return self.Trans.ExprLambdaHandle._HandleIfExpLlvm(Node) - elif isinstance(Node, ast.NamedExpr): - return self.Trans.ExprLambdaHandle._HandleNamedExprLlvm(Node) - elif isinstance(Node, ast.JoinedStr): - in_str_method = getattr(Gen, 'func', None) and getattr(Gen.func, 'name', '').endswith('.__str__') - return self.Trans.ExprFormatHandle._HandleJoinedStrLlvm(Node, return_str=in_str_method) - elif isinstance(Node, ast.Lambda): - return self.Trans.ExprLambdaHandle._HandleLambdaLlvm(Node) - elif isinstance(Node, ast.List): - return self._HandleListLlvm(Node, VarType) - return ir.Constant(ir.IntType(32), 0) - - def _HandleListLlvm(self, Node, VarType=None): - Gen = self.Trans.LlvmGen - elements = Node.elts - if not elements: - return ir.Constant(ir.IntType(8).as_pointer(), None) - - array_len = len(elements) - elem_type = 'i8' - - if VarType and isinstance(VarType, str) and 'list[' in VarType: - import re - match = re.search(r'list\[([^,\]]+)(?:,\s*(\d+))?\]', VarType) - if match: - type_str = match.group(1).strip() - if match.group(2): - array_len = int(match.group(2)) - if 'CChar' in type_str or 'char' in type_str.lower(): - elem_type = 'i8' - elif 'CFloat' in type_str or type_str.lower() == 'float': - elem_type = 'float' - elif 'CDouble' in type_str or type_str.lower() == 'double': - elem_type = 'double' - elif 'CInt' in type_str or ('int' in type_str.lower() and 'unsigned' not in type_str.lower()): - elem_type = 'i32' - elif 'CUnsignedInt' in type_str or 'unsigned' in type_str.lower(): - elem_type = 'i32' - elif 'CUnsignedChar' in type_str or 'unsigned char' in type_str.lower(): - elem_type = 'i8' - elif 'CShort' in type_str or 'short' in type_str.lower(): - elem_type = 'i16' - elif 'CUnsignedShort' in type_str: - elem_type = 'i16' - elif elements and all(isinstance(e, (ast.Constant,)) and isinstance(getattr(e, 'value', None), float) for e in elements): - elem_type = 'float' - - alloc_size = array_len - if elem_type == 'i32': - alloc_size *= 4 - elif elem_type == 'i16': - alloc_size *= 2 - elif elem_type == 'float': - alloc_size *= 4 - elif elem_type == 'double': - alloc_size *= 8 - - malloc_fn = None - malloc_arg_type = ir.IntType(64) - for fn in Gen.module.global_values: - if fn.name == 'malloc': - malloc_fn = fn - func_ftype = getattr(fn, 'ftype', None) - if func_ftype and getattr(func_ftype, 'args', None): - if func_ftype.args: - malloc_arg_type = fn.ftype.args[0] - break - - if not malloc_fn: - try: - malloc_fn_type = ir.FunctionType(ir.PointerType(ir.IntType(8)), [ir.IntType(64)]) - malloc_fn = ir.Function(Gen.module, malloc_fn_type, name='malloc') - Gen.functions['malloc'] = malloc_fn - except Exception: # 回退:malloc 函数创建失败时返回 null - return ir.Constant(ir.IntType(8).as_pointer(), None) - - alloc_ptr = Gen.builder.call(malloc_fn, [ir.Constant(malloc_arg_type, alloc_size)]) - cast_ptr = Gen.builder.bitcast(alloc_ptr, ir.PointerType(ir.IntType(8))) - - for i, elem in enumerate(elements): - if i >= array_len: - break - - elem_val = self.HandleExprLlvm(elem, VarType=elem_type) - if elem_val is None: - continue - - byte_offset = i - if elem_type == 'i32': - byte_offset = i * 4 - elif elem_type == 'i16': - byte_offset = i * 2 - elif elem_type == 'float': - byte_offset = i * 4 - elif elem_type == 'double': - byte_offset = i * 8 - - ptr_as_int = Gen.builder.ptrtoint(cast_ptr, ir.IntType(64)) - new_ptr_val = Gen.builder.add(ptr_as_int, ir.Constant(ir.IntType(64), byte_offset)) - if elem_type == 'i32': - elem_ptr = Gen.builder.inttoptr(new_ptr_val, ir.PointerType(ir.IntType(32))) - elif elem_type == 'i16': - elem_ptr = Gen.builder.inttoptr(new_ptr_val, ir.PointerType(ir.IntType(16))) - elif elem_type == 'float': - elem_ptr = Gen.builder.inttoptr(new_ptr_val, ir.PointerType(ir.FloatType())) - elif elem_type == 'double': - elem_ptr = Gen.builder.inttoptr(new_ptr_val, ir.PointerType(ir.DoubleType())) - else: - elem_ptr = Gen.builder.inttoptr(new_ptr_val, ir.PointerType(ir.IntType(8))) - - if elem_type == 'i8': - if isinstance(elem_val.type, ir.IntType) and elem_val.type.width > 8: - elem_val = Gen.builder.trunc(elem_val, ir.IntType(8), name=f"trunc_elem_{i}") - elif isinstance(elem_val.type, ir.PointerType): - elem_val = Gen.builder.ptrtoint(elem_val, ir.IntType(64), name=f"ptrtoint_elem_{i}") - elem_val = Gen.builder.trunc(elem_val, ir.IntType(8), name=f"trunc_elem_{i}") - elif elem_type == 'i32': - if isinstance(elem_val.type, ir.IntType): - if elem_val.type.width < 32: - elem_val = Gen.builder.zext(elem_val, ir.IntType(32), name=f"zext_elem_{i}") - elif elem_val.type.width > 32: - elem_val = Gen.builder.trunc(elem_val, ir.IntType(32), name=f"trunc_elem_{i}") - elif isinstance(elem_val.type, ir.PointerType): - elem_val = Gen.builder.ptrtoint(elem_val, ir.IntType(32), name=f"ptrtoint_elem_{i}") - elif elem_type == 'i16': - if isinstance(elem_val.type, ir.IntType): - if elem_val.type.width < 16: - elem_val = Gen.builder.zext(elem_val, ir.IntType(16), name=f"zext_elem_{i}") - elif elem_val.type.width > 16: - elem_val = Gen.builder.trunc(elem_val, ir.IntType(16), name=f"trunc_elem_{i}") - elif elem_type == 'float': - if isinstance(elem_val.type, ir.DoubleType): - elem_val = Gen.builder.fptrunc(elem_val, ir.FloatType(), name=f"fptrunc_elem_{i}") - elif isinstance(elem_val.type, ir.IntType): - elem_val = Gen.builder.sitofp(elem_val, ir.FloatType(), name=f"sitofp_elem_{i}") - elif elem_type == 'double': - if isinstance(elem_val.type, ir.FloatType): - elem_val = Gen.builder.fpext(elem_val, ir.DoubleType(), name=f"fpext_elem_{i}") - elif isinstance(elem_val.type, ir.IntType): - elem_val = Gen.builder.sitofp(elem_val, ir.DoubleType(), name=f"sitofp_elem_{i}") - - Gen.builder.store(elem_val, elem_ptr) - - if elem_type == 'float': - return Gen.builder.bitcast(alloc_ptr, ir.PointerType(ir.FloatType()), name="list_float_ptr") - elif elem_type == 'double': - return Gen.builder.bitcast(alloc_ptr, ir.PointerType(ir.DoubleType()), name="list_double_ptr") - return cast_ptr - - def _HandleConstantLlvm(self, Node, VarType=None): - Gen = self.Trans.LlvmGen - Value = Node.value - if Value is None: - if VarType is not None and isinstance(VarType, ir.PointerType): - return ir.Constant(VarType, None) - return ir.Constant(ir.IntType(8).as_pointer(), None) - elif isinstance(Value, bool): - return ir.Constant(ir.IntType(32), 1 if Value else 0) - elif isinstance(Value, int): - if VarType is not None: - if isinstance(VarType, ir.IntType): - return ir.Constant(VarType, Value & ((1 << VarType.width) - 1)) - if isinstance(VarType, ir.PointerType): - return ir.Constant(ir.IntType(64), Value) - if isinstance(VarType, (ir.FloatType, ir.DoubleType)): - return ir.Constant(VarType, float(Value)) - if isinstance(VarType, str) and '*' in VarType: - return ir.Constant(ir.IntType(64), Value) - if isinstance(VarType, str): - from lib.includes.t import CTypeRegistry as _CR - resolved = _CR.ResolveName(VarType) or _CR.CNameToClass(VarType) or _CR.LLVMToCType(VarType) - if resolved: - ctype_cls = resolved[0] if isinstance(resolved, tuple) else resolved - inst = ctype_cls() - size = getattr(inst, 'Size', 32) - is_unsigned = getattr(inst, 'IsSigned', True) is False - mask = (1 << size) - 1 - return ir.Constant(ir.IntType(size), Value & mask) - llvm_match = __import__('re').match(r'^i(\d+)$', VarType) - if llvm_match: - width = int(llvm_match.group(1)) - return ir.Constant(ir.IntType(width), Value & ((1 << width) - 1)) - if Value < 0 or Value > 0xFFFFFFFF: - return ir.Constant(ir.IntType(64), Value) - return ir.Constant(ir.IntType(32), Value & 0xFFFFFFFF) - elif isinstance(Value, float): - if VarType and isinstance(VarType, ir.FloatType): - return ir.Constant(VarType, Value) - elif VarType and isinstance(VarType, ir.DoubleType): - return ir.Constant(VarType, Value) - return ir.Constant(ir.DoubleType(), Value) - elif isinstance(Value, str): - is_wide = getattr(Node, 'kind', None) == 'u' - if len(Value) == 1 and not is_wide: - if VarType is not None and isinstance(VarType, ir.PointerType): - pass - elif isinstance(VarType, ir.IntType): - return ir.Constant(VarType, ord(Value[0])) - elif isinstance(VarType, str): - from lib.includes.t import CTypeRegistry as _CR - resolved = _CR.ResolveName(VarType) or _CR.CNameToClass(VarType) or _CR.LLVMToCType(VarType) - if resolved: - ctype_cls = resolved[0] if isinstance(resolved, tuple) else resolved - inst = ctype_cls() - size = getattr(inst, 'Size', 32) - return ir.Constant(ir.IntType(size), ord(Value[0])) - llvm_match = __import__('re').match(r'^i(\d+)$', VarType) - if llvm_match: - return ir.Constant(ir.IntType(int(llvm_match.group(1))), ord(Value[0])) - elif VarType is not None: - return ir.Constant(ir.IntType(8), ord(Value[0])) - if is_wide: - str_value = Value + '\x00' - wide_chars = [ord(c) for c in str_value] - target_count = len(wide_chars) - str_type = ir.ArrayType(ir.IntType(16), target_count) - gv_name = f"str_const_{Gen.string_const_counter}" - gv = ir.GlobalVariable(Gen.module, str_type, name=gv_name) - gv.initializer = ir.Constant(str_type, wide_chars) - gv.linkage = 'internal' - Gen.string_const_counter += 1 - ptr = Gen.builder.gep(gv, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), 0)], name=f"{gv_name}_cast") - return ptr - else: - str_value = Value + '\x00' - str_bytes = str_value.encode('utf-8') - target_count = len(str_bytes) - if isinstance(VarType, ir.ArrayType) and isinstance(VarType.element, ir.IntType) and VarType.element.width == 8: - target_count = VarType.count - if len(str_bytes) < target_count: - str_bytes = str_bytes + b'\x00' * (target_count - len(str_bytes)) - else: - str_bytes = str_bytes[:target_count] - str_type = ir.ArrayType(ir.IntType(8), target_count) - gv_name = f"str_const_{Gen.string_const_counter}" - gv = ir.GlobalVariable(Gen.module, str_type, name=gv_name) - gv.initializer = ir.Constant(str_type, bytearray(str_bytes)) - gv.linkage = 'internal' - Gen.string_const_counter += 1 - ptr = Gen.builder.gep(gv, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), 0)], name=f"{gv_name}_cast") - return ptr - return ir.Constant(ir.IntType(32), 0) - - def _HandleNameLlvm(self, Node, VarType=None): - Gen = self.Trans.LlvmGen - VarName = Node.id - define_constants = getattr(Gen, '_define_constants', {}) - if VarName in define_constants: - val = define_constants[VarName] - if isinstance(val, int): - # Use VarType hint if available to avoid unnecessary type mismatch - if VarType is not None and isinstance(VarType, ir.IntType): - return ir.Constant(VarType, val & ((1 << VarType.width) - 1)) - if VarName in Gen.var_signedness and Gen.var_signedness[VarName]: - if val < -(1 << 31) or val > 0xFFFFFFFF: - return ir.Constant(ir.IntType(64), val & 0xFFFFFFFFFFFFFFFF) - return ir.Constant(ir.IntType(32), val & 0xFFFFFFFF) - if val < -(1 << 31) or val > 0xFFFFFFFF: - return ir.Constant(ir.IntType(64), val) - return ir.Constant(ir.IntType(32), val & 0xFFFFFFFF) - elif isinstance(val, float): - return ir.Constant(ir.DoubleType(), val) - elif isinstance(val, str): - str_value = val + '\x00' - str_bytes = str_value.encode('utf-8') - str_type = ir.ArrayType(ir.IntType(8), len(str_bytes)) - gv_name = f"str_const_{Gen.string_const_counter}" - gv = ir.GlobalVariable(Gen.module, str_type, name=gv_name) - gv.initializer = ir.Constant(str_type, bytearray(str_bytes)) - gv.linkage = 'internal' - Gen.string_const_counter += 1 - ptr = Gen.builder.gep(gv, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), 0)], name=f"{gv_name}_cast") - return ptr - # 如果 _define_constants 中没有,尝试从符号表查找 - if VarName not in getattr(Gen, '_define_constants', {}): - try: - sym_info = self.translator.SymbolTable.lookup(VarName) - if sym_info and sym_info.IsDefine and sym_info.DefineValue is not None: - val = sym_info.DefineValue - if isinstance(val, int): - # Use VarType hint if available - if VarType is not None and isinstance(VarType, ir.IntType): - return ir.Constant(VarType, val & ((1 << VarType.width) - 1)) - if val < -(1 << 31) or val > 0xFFFFFFFF: - return ir.Constant(ir.IntType(64), val) - return ir.Constant(ir.IntType(32), val & 0xFFFFFFFF) - elif isinstance(val, float): - return ir.Constant(ir.DoubleType(), val) - elif isinstance(val, str): - str_value = val + '\x00' - str_bytes = str_value.encode('utf-8') - str_type = ir.ArrayType(ir.IntType(8), len(str_bytes)) - gv_name = f"str_const_{Gen.string_const_counter}" - gv = ir.GlobalVariable(Gen.module, str_type, name=gv_name) - gv.initializer = ir.Constant(str_type, bytearray(str_bytes)) - gv.linkage = 'internal' - Gen.string_const_counter += 1 - ptr = Gen.builder.gep(gv, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), 0)], name=f"{gv_name}_cast") - return ptr - except Exception as _e: - if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": - self.Trans.LogWarning(f"异常被忽略: {_e}") - # 优先检查 variables(alloca),因为变量可能已被 += 等操作迁移到 variables - if VarName in Gen.variables and Gen.variables[VarName] is not None: - VarPtr = Gen.variables[VarName] - if isinstance(VarPtr, ir.GlobalVariable) and isinstance(VarPtr.type, ir.PointerType) and isinstance(VarPtr.type.pointee, (ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)): - if VarName in Gen.global_struct_class: - Gen.var_struct_class[VarName] = Gen.global_struct_class[VarName] - return VarPtr - if isinstance(VarPtr.type, ir.PointerType) and isinstance(VarPtr.type.pointee, (ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)): - if VarName in Gen.global_struct_class: - Gen.var_struct_class[VarName] = Gen.global_struct_class[VarName] - return VarPtr - return Gen._load(VarPtr, name=VarName) - if VarName in Gen._reg_values: - return Gen._reg_values[VarName] - if VarName in Gen._direct_values: - return Gen._direct_values[VarName] - if VarName in Gen.global_vars and VarName in Gen.module.globals: - GVar = Gen.module.globals[VarName] - Gen.variables[VarName] = GVar - if isinstance(GVar, ir.Function): - return GVar - if isinstance(GVar.type, ir.PointerType) and isinstance(GVar.type.pointee, (ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)): - return GVar - return Gen._load(GVar, name=VarName) - if VarName in Gen.module.globals: - GVar = Gen.module.globals[VarName] - Gen.variables[VarName] = GVar - if isinstance(GVar, ir.Function): - return GVar - if VarName in Gen.global_struct_class: - Gen.var_struct_class[VarName] = Gen.global_struct_class[VarName] - if isinstance(GVar.type, ir.PointerType) and isinstance(GVar.type.pointee, (ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)): - return GVar - return Gen._load(GVar, name=VarName) - if VarName == 'self': - return Gen.GetVarPtr('self') - if Gen._has_function(VarName): - func = Gen._get_function(VarName) - if func: - return Gen.builder.bitcast(func, ir.IntType(8).as_pointer(), name=f"funcptr_{VarName}") - if VarName in Gen.class_methods: - return ir.Constant(ir.IntType(8).as_pointer(), None) - if VarName == 'True' or VarName == 'False': - return ir.Constant(ir.IntType(32), 1 if VarName == 'True' else 0) - if self.Trans.SymbolTable.has(VarName): - SymInfo = self.Trans.SymbolTable[VarName] - if SymInfo.IsEnumMember and isinstance(SymInfo.value, int): - return ir.Constant(ir.IntType(32), SymInfo.value) - if SymInfo.IsFunction or SymInfo.IsFuncPtr: - MangledName = Gen._mangle_func_name(VarName) - if MangledName in Gen.module.globals: - g = Gen.module.globals[MangledName] - if isinstance(g, ir.Function): - Gen.functions[VarName] = g - return Gen.builder.bitcast(g, ir.IntType(8).as_pointer(), name=f"funcptr_{VarName}") - for sha1 in Gen.ModuleSha1Map.values(): - prefixed = f"{sha1}.{VarName}" - if prefixed in Gen.module.globals: - g = Gen.module.globals[prefixed] - if isinstance(g, ir.Function): - Gen.functions[VarName] = g - return Gen.builder.bitcast(g, ir.IntType(8).as_pointer(), name=f"funcptr_{VarName}") - t_c_imported = getattr(self.Trans, '_t_c_imported_names', {}) - if VarName in t_c_imported: - src_module, src_name = t_c_imported[VarName] - virtual_attr = ast.Attribute( - value=ast.Name(id=src_module, ctx=ast.Load()), - attr=src_name, - ctx=ast.Load() - ) - ast.copy_location(virtual_attr, Node) - return self.Trans.ExprAttrHandle._HandleAttributeLlvm(virtual_attr) - return ir.Constant(ir.IntType(32), 0) +from __future__ import annotations +from typing import TYPE_CHECKING, Any +if TYPE_CHECKING: + from lib.core.translator import Translator + from lib.core.LlvmCodeGenerator import LlvmCodeGenerator +import ast +import re +import llvmlite.ir as ir +from lib.core.Handles.HandlesBase import BaseHandle +from lib.core.VLogger import get_logger as _vlog +from lib.constants.config import mode as _config_mode +from lib.includes import t +from lib.includes.t import CTypeRegistry as _CR + + +class ExprHandle(BaseHandle): + def __init__(self, translator: "Translator") -> None: + super().__init__(translator) + + def GetOpSymbol(self, Op: ast.cmpop | ast.operator | ast.unaryoperator) -> str | None: + return self.Trans.ExprUtils.GetOpSymbol(Op) + + def GetUnaryOpSymbol(self, Op: ast.unaryoperator) -> str | None: + return self.Trans.ExprUtils.GetUnaryOpSymbol(Op) + + def GetComparatorSymbol(self, Op: ast.cmpop) -> str | None: + return self.Trans.ExprUtils.GetComparatorSymbol(Op) + + def _get_var_class(self, node: ast.AST, Gen: LlvmCodeGenerator) -> str | None: + return self.Trans.ExprUtils._get_var_class(node, Gen) + + def _try_operator_overLoad(self, ClassName: str, op_name: str, obj_val: ir.Value, Gen: LlvmCodeGenerator, other_val: ir.Value | None = None) -> ir.Value | None: + return self.Trans.ExprUtils._try_operator_overLoad(ClassName, op_name, obj_val, Gen, other_val) + + def _get_llvm_member_offset(self, field_name: str, ClassName: str, Gen: LlvmCodeGenerator) -> int | None: + return self.Trans.ExprAttrHandle._get_llvm_member_offset(field_name, ClassName, Gen) + + def HandleExprLlvm(self, Node: ast.AST, VarType: ir.Type | str | None = None) -> ir.Value | None: + Gen: LlvmCodeGenerator = self.Trans.LlvmGen + if not Gen or not Gen.builder: + return None + if isinstance(Node, ast.Constant): + return self._HandleConstantLlvm(Node, VarType) + elif isinstance(Node, ast.Name): + return self._HandleNameLlvm(Node, VarType) + elif isinstance(Node, ast.BinOp): + return self.Trans.ExprOpsHandle._HandleBinOpLlvm(Node, VarType) + elif isinstance(Node, ast.BoolOp): + return self.Trans.ExprOpsHandle._HandleBoolOpLlvm(Node) + elif isinstance(Node, ast.UnaryOp): + return self.Trans.ExprOpsHandle._HandleUnaryOpLlvm(Node) + elif isinstance(Node, ast.Call): + return self.Trans.ExprCallHandle._HandleCallLlvm(Node) + elif isinstance(Node, ast.Compare): + return self.Trans.ExprOpsHandle._HandleCompareLlvm(Node) + elif isinstance(Node, ast.Attribute): + return self.Trans.ExprAttrHandle._HandleAttributeLlvm(Node) + elif isinstance(Node, ast.Subscript): + return self.Trans.ExprAttrHandle._HandleSubscriptLlvm(Node) + elif isinstance(Node, ast.IfExp): + return self.Trans.ExprLambdaHandle._HandleIfExpLlvm(Node) + elif isinstance(Node, ast.NamedExpr): + return self.Trans.ExprLambdaHandle._HandleNamedExprLlvm(Node) + elif isinstance(Node, ast.JoinedStr): + return self.Trans.ExprFormatHandle._HandleJoinedStrLlvm(Node) + elif isinstance(Node, ast.Lambda): + return self.Trans.ExprLambdaHandle._HandleLambdaLlvm(Node) + elif isinstance(Node, ast.List): + return self._HandleListLlvm(Node, VarType) + return ir.Constant(ir.IntType(32), 0) + + def _HandleListLlvm(self, Node: ast.List, VarType: ir.Type | str | None = None) -> ir.Value | None: + Gen: LlvmCodeGenerator = self.Trans.LlvmGen + elements: list[ast.expr] = Node.elts + if not elements: + return ir.Constant(ir.IntType(8).as_pointer(), None) + + array_len: int = len(elements) + elem_type: str = 'i8' + + if VarType and isinstance(VarType, str) and 'list[' in VarType: + match: re.Match | None = re.search(r'list\[([^,\]]+)(?:,\s*(\d+))?\]', VarType) + if match: + type_str: str = match.group(1).strip() + if match.group(2): + array_len = int(match.group(2)) + if 'CChar' in type_str or 'char' in type_str.lower(): + elem_type = 'i8' + elif 'CFloat' in type_str or type_str.lower() == 'float': + elem_type = 'float' + elif 'CDouble' in type_str or type_str.lower() == 'double': + elem_type = 'double' + elif 'CInt' in type_str or ('int' in type_str.lower() and 'unsigned' not in type_str.lower()): + elem_type = 'i32' + elif 'CUnsignedInt' in type_str or 'unsigned' in type_str.lower(): + elem_type = 'i32' + elif 'CUnsignedChar' in type_str or 'unsigned char' in type_str.lower(): + elem_type = 'i8' + elif 'CShort' in type_str or 'short' in type_str.lower(): + elem_type = 'i16' + elif 'CUnsignedShort' in type_str: + elem_type = 'i16' + elif elements and all(isinstance(e, (ast.Constant,)) and isinstance(getattr(e, 'value', None), float) for e in elements): + elem_type = 'float' + + alloc_size: int = array_len + if elem_type == 'i32': + alloc_size *= 4 + elif elem_type == 'i16': + alloc_size *= 2 + elif elem_type == 'float': + alloc_size *= 4 + elif elem_type == 'double': + alloc_size *= 8 + + malloc_fn: Any = None + malloc_arg_type: ir.IntType = ir.IntType(64) + for fn in Gen.module.global_values: + if fn.name == 'malloc': + malloc_fn = fn + func_ftype: Any = getattr(fn, 'ftype', None) + if func_ftype and getattr(func_ftype, 'args', None): + if func_ftype.args: + malloc_arg_type = fn.ftype.args[0] + break + + if not malloc_fn: + try: + malloc_fn_type: ir.FunctionType = ir.FunctionType(ir.PointerType(ir.IntType(8)), [ir.IntType(64)]) + malloc_fn = ir.Function(Gen.module, malloc_fn_type, name='malloc') + Gen.functions['malloc'] = malloc_fn + except Exception: # 回退:malloc 函数创建失败时返回 null + return ir.Constant(ir.IntType(8).as_pointer(), None) + + alloc_ptr: Any = Gen.builder.call(malloc_fn, [ir.Constant(malloc_arg_type, alloc_size)]) + cast_ptr: Any = Gen.builder.bitcast(alloc_ptr, ir.PointerType(ir.IntType(8))) + + for i, elem in enumerate(elements): + if i >= array_len: + break + + elem_val: Any = self.HandleExprLlvm(elem, VarType=elem_type) + if elem_val is None: + continue + + byte_offset: int = i + if elem_type == 'i32': + byte_offset = i * 4 + elif elem_type == 'i16': + byte_offset = i * 2 + elif elem_type == 'float': + byte_offset = i * 4 + elif elem_type == 'double': + byte_offset = i * 8 + + ptr_as_int: Any = Gen.builder.ptrtoint(cast_ptr, ir.IntType(64)) + new_ptr_val: Any = Gen.builder.add(ptr_as_int, ir.Constant(ir.IntType(64), byte_offset)) + if elem_type == 'i32': + elem_ptr: Any = Gen.builder.inttoptr(new_ptr_val, ir.PointerType(ir.IntType(32))) + elif elem_type == 'i16': + elem_ptr = Gen.builder.inttoptr(new_ptr_val, ir.PointerType(ir.IntType(16))) + elif elem_type == 'float': + elem_ptr = Gen.builder.inttoptr(new_ptr_val, ir.PointerType(ir.FloatType())) + elif elem_type == 'double': + elem_ptr = Gen.builder.inttoptr(new_ptr_val, ir.PointerType(ir.DoubleType())) + else: + elem_ptr = Gen.builder.inttoptr(new_ptr_val, ir.PointerType(ir.IntType(8))) + + if elem_type == 'i8': + if isinstance(elem_val.type, ir.IntType) and elem_val.type.width > 8: + elem_val = Gen.builder.trunc(elem_val, ir.IntType(8), name=f"trunc_elem_{i}") + elif isinstance(elem_val.type, ir.PointerType): + elem_val = Gen.builder.ptrtoint(elem_val, ir.IntType(64), name=f"ptrtoint_elem_{i}") + elem_val = Gen.builder.trunc(elem_val, ir.IntType(8), name=f"trunc_elem_{i}") + elif elem_type == 'i32': + if isinstance(elem_val.type, ir.IntType): + if elem_val.type.width < 32: + elem_val = Gen.builder.zext(elem_val, ir.IntType(32), name=f"zext_elem_{i}") + elif elem_val.type.width > 32: + elem_val = Gen.builder.trunc(elem_val, ir.IntType(32), name=f"trunc_elem_{i}") + elif isinstance(elem_val.type, ir.PointerType): + elem_val = Gen.builder.ptrtoint(elem_val, ir.IntType(32), name=f"ptrtoint_elem_{i}") + elif elem_type == 'i16': + if isinstance(elem_val.type, ir.IntType): + if elem_val.type.width < 16: + elem_val = Gen.builder.zext(elem_val, ir.IntType(16), name=f"zext_elem_{i}") + elif elem_val.type.width > 16: + elem_val = Gen.builder.trunc(elem_val, ir.IntType(16), name=f"trunc_elem_{i}") + elif elem_type == 'float': + if isinstance(elem_val.type, ir.DoubleType): + elem_val = Gen.builder.fptrunc(elem_val, ir.FloatType(), name=f"fptrunc_elem_{i}") + elif isinstance(elem_val.type, ir.IntType): + elem_val = Gen.builder.sitofp(elem_val, ir.FloatType(), name=f"sitofp_elem_{i}") + elif elem_type == 'double': + if isinstance(elem_val.type, ir.FloatType): + elem_val = Gen.builder.fpext(elem_val, ir.DoubleType(), name=f"fpext_elem_{i}") + elif isinstance(elem_val.type, ir.IntType): + elem_val = Gen.builder.sitofp(elem_val, ir.DoubleType(), name=f"sitofp_elem_{i}") + + Gen.builder.store(elem_val, elem_ptr) + + if elem_type == 'float': + return Gen.builder.bitcast(alloc_ptr, ir.PointerType(ir.FloatType()), name="list_float_ptr") + elif elem_type == 'double': + return Gen.builder.bitcast(alloc_ptr, ir.PointerType(ir.DoubleType()), name="list_double_ptr") + return cast_ptr + + def _HandleConstantLlvm(self, Node: ast.Constant, VarType: ir.Type | str | None = None) -> ir.Value: + Gen: LlvmCodeGenerator = self.Trans.LlvmGen + Value: Any = Node.value + if Value is None: + if VarType is not None and isinstance(VarType, ir.PointerType): + return ir.Constant(VarType, None) + return ir.Constant(ir.IntType(8).as_pointer(), None) + elif isinstance(Value, bool): + return ir.Constant(ir.IntType(32), 1 if Value else 0) + elif isinstance(Value, int): + if VarType is not None: + if isinstance(VarType, ir.IntType): + return ir.Constant(VarType, Value & ((1 << VarType.width) - 1)) + if isinstance(VarType, ir.PointerType): + return ir.Constant(ir.IntType(64), Value) + if isinstance(VarType, (ir.FloatType, ir.DoubleType)): + return ir.Constant(VarType, float(Value)) + if isinstance(VarType, str) and '*' in VarType: + return ir.Constant(ir.IntType(64), Value) + if isinstance(VarType, str): + resolved: Any = _CR.ResolveName(VarType) or _CR.LLVMToCType(VarType) + if resolved: + ctype_cls: type = resolved[0] if isinstance(resolved, tuple) else resolved + inst: Any = ctype_cls() + size: int = getattr(inst, 'Size', 32) + is_unsigned: bool = getattr(inst, 'IsSigned', True) is False + mask: int = (1 << size) - 1 + return ir.Constant(ir.IntType(size), Value & mask) + llvm_match: re.Match | None = re.match(r'^i(\d+)$', VarType) + if llvm_match: + width: int = int(llvm_match.group(1)) + return ir.Constant(ir.IntType(width), Value & ((1 << width) - 1)) + if Value < 0 or Value > 0xFFFFFFFF: + return ir.Constant(ir.IntType(64), Value) + return ir.Constant(ir.IntType(32), Value & 0xFFFFFFFF) + elif isinstance(Value, float): + if VarType and isinstance(VarType, ir.FloatType): + return ir.Constant(VarType, Value) + elif VarType and isinstance(VarType, ir.DoubleType): + return ir.Constant(VarType, Value) + return ir.Constant(ir.DoubleType(), Value) + elif isinstance(Value, str): + is_wide: bool = getattr(Node, 'kind', None) == 'u' + # 引号类型推断:单引号单字符 → i8,双引号/多字符/三重 → i8*,空 → 0(None) + quote_char: str | None = None + is_triple: bool = False + if not is_wide: + col_offset: int = getattr(Node, 'col_offset', 0) + node_lineno: int = getattr(Node, 'lineno', 0) + # AST 的 lineno 可能不准确(常量节点可能指向下一行), + # 因此在 lineno 和 lineno-1 两行中查找引号 + for try_lineno in (node_lineno, node_lineno - 1): + source_line: str | None = Gen._get_source_line(try_lineno) + if source_line and col_offset < len(source_line): + ch: str = source_line[col_offset] + if ch in ("'", '"'): + quote_char = ch + if col_offset + 2 < len(source_line) and source_line[col_offset:col_offset + 3] in ("'''", '"""'): + is_triple = True + break + # 空字符串 → 创建指向 \0 的全局变量 (而非 null, 避免 strcmp 解引用空指针崩溃) + # 走与非空字符串相同的路径, 由下方 else 分支处理 + # 单引号单字符(非三重)→ i8 + is_char_literal: bool = (not is_triple) and (quote_char == "'") and (len(Value) == 1) and not is_wide + if is_char_literal: + if VarType is not None and isinstance(VarType, ir.PointerType): + pass # 类型不匹配:目标是 ptr 但值是 char,走 string 路径 + elif isinstance(VarType, ir.IntType): + return ir.Constant(VarType, ord(Value[0])) + elif isinstance(VarType, str): + resolved = _CR.ResolveName(VarType) or _CR.LLVMToCType(VarType) + if resolved: + ctype_cls = resolved[0] if isinstance(resolved, tuple) else resolved + inst = ctype_cls() + size = getattr(inst, 'Size', 32) + return ir.Constant(ir.IntType(size), ord(Value[0])) + llvm_match = re.match(r'^i(\d+)$', VarType) + if llvm_match: + return ir.Constant(ir.IntType(int(llvm_match.group(1))), ord(Value[0])) + elif VarType is not None: + return ir.Constant(ir.IntType(8), ord(Value[0])) + else: + # 无类型提示:单引号单字符默认为 i8 + return ir.Constant(ir.IntType(8), ord(Value[0])) + if is_wide: + str_value: str = Value + '\x00' + wide_chars: list[int] = [ord(c) for c in str_value] + target_count: int = len(wide_chars) + str_type: ir.ArrayType = ir.ArrayType(ir.IntType(16), target_count) + gv_name: str = f"str_const_{Gen.string_const_counter}" + gv: ir.GlobalVariable = ir.GlobalVariable(Gen.module, str_type, name=gv_name) + gv.initializer = ir.Constant(str_type, wide_chars) + gv.linkage = 'internal' + Gen.string_const_counter += 1 + ptr: Any = Gen.builder.gep(gv, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), 0)], name=f"{gv_name}_cast") + return ptr + else: + str_value = Value + '\x00' + str_bytes: bytes = str_value.encode('utf-8') + target_count = len(str_bytes) + if isinstance(VarType, ir.ArrayType) and isinstance(VarType.element, ir.IntType) and VarType.element.width == 8: + target_count = VarType.count + if len(str_bytes) < target_count: + str_bytes = str_bytes + b'\x00' * (target_count - len(str_bytes)) + else: + str_bytes = str_bytes[:target_count] + str_type = ir.ArrayType(ir.IntType(8), target_count) + gv_name = f"str_const_{Gen.string_const_counter}" + gv = ir.GlobalVariable(Gen.module, str_type, name=gv_name) + gv.initializer = ir.Constant(str_type, bytearray(str_bytes)) + gv.linkage = 'internal' + Gen.string_const_counter += 1 + ptr = Gen.builder.gep(gv, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), 0)], name=f"{gv_name}_cast") + return ptr + return ir.Constant(ir.IntType(32), 0) + + def _HandleNameLlvm(self, Node: ast.Name, VarType: ir.Type | str | None = None) -> ir.Value: + Gen: LlvmCodeGenerator = self.Trans.LlvmGen + VarName: str = Node.id + define_constants: dict[str, Any] = getattr(Gen, '_define_constants', {}) + if VarName in define_constants: + val: Any = define_constants[VarName] + if isinstance(val, int): + # Use VarType hint if available to avoid unnecessary type mismatch + if VarType is not None and isinstance(VarType, ir.IntType): + return ir.Constant(VarType, val & ((1 << VarType.width) - 1)) + if VarName in Gen.var_signedness and Gen.var_signedness[VarName]: + if val < -(1 << 31) or val > 0xFFFFFFFF: + return ir.Constant(ir.IntType(64), val & 0xFFFFFFFFFFFFFFFF) + return ir.Constant(ir.IntType(32), val & 0xFFFFFFFF) + if val < -(1 << 31) or val > 0xFFFFFFFF: + return ir.Constant(ir.IntType(64), val) + return ir.Constant(ir.IntType(32), val & 0xFFFFFFFF) + elif isinstance(val, float): + return ir.Constant(ir.DoubleType(), val) + elif isinstance(val, str): + return Gen._create_string_global(val) + # 如果 _define_constants 中没有,尝试从符号表查找 + if VarName not in getattr(Gen, '_define_constants', {}): + try: + sym_info: Any = self.translator.SymbolTable.lookup(VarName) + if sym_info and sym_info.IsDefine and sym_info.DefineValue is not None: + val = sym_info.DefineValue + if isinstance(val, int): + # Use VarType hint if available + if VarType is not None and isinstance(VarType, ir.IntType): + return ir.Constant(VarType, val & ((1 << VarType.width) - 1)) + if val < -(1 << 31) or val > 0xFFFFFFFF: + return ir.Constant(ir.IntType(64), val) + return ir.Constant(ir.IntType(32), val & 0xFFFFFFFF) + elif isinstance(val, float): + return ir.Constant(ir.DoubleType(), val) + elif isinstance(val, str): + return Gen._create_string_global(val) + except Exception as _e: + if _config_mode == "strict": + self.Trans.LogWarning(f"异常被忽略: {_e}") + # 优先检查 variables(alloca),因为变量可能已被 += 等操作迁移到 variables + if VarName in Gen.variables and Gen.variables[VarName] is not None: + VarPtr: Any = Gen.variables[VarName] + if isinstance(VarPtr, ir.GlobalVariable) and isinstance(VarPtr.type, ir.PointerType) and isinstance(VarPtr.type.pointee, (ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)): + if VarName in Gen.global_struct_class: + Gen.var_struct_class[VarName] = Gen.global_struct_class[VarName] + return VarPtr + if isinstance(VarPtr.type, ir.PointerType) and isinstance(VarPtr.type.pointee, (ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)): + if VarName in Gen.global_struct_class: + Gen.var_struct_class[VarName] = Gen.global_struct_class[VarName] + return VarPtr + loaded: ir.Value = Gen._load(VarPtr, name=VarName) + # 大端局部变量:读取时 bswap 还原 + loaded = Gen._apply_bswap_if_big(loaded, getattr(Gen, 'local_var_byteorders', {}).get(VarName, ""), f"bswap_load_{VarName}") + return loaded + if VarName in Gen._reg_values: + return Gen._reg_values[VarName] + if VarName in Gen._direct_values: + return Gen._direct_values[VarName] + if VarName in Gen.global_vars and VarName in Gen.module.globals: + GVar: Any = Gen.module.globals[VarName] + Gen.variables[VarName] = GVar + if isinstance(GVar, ir.Function): + return GVar + if isinstance(GVar.type, ir.PointerType) and isinstance(GVar.type.pointee, (ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)): + return GVar + return Gen._load(GVar, name=VarName) + if VarName in Gen.module.globals: + GVar = Gen.module.globals[VarName] + Gen.variables[VarName] = GVar + if isinstance(GVar, ir.Function): + return GVar + if VarName in Gen.global_struct_class: + Gen.var_struct_class[VarName] = Gen.global_struct_class[VarName] + if isinstance(GVar.type, ir.PointerType) and isinstance(GVar.type.pointee, (ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)): + return GVar + return Gen._load(GVar, name=VarName) + if VarName == 'self': + return Gen.GetVarPtr('self') + if Gen._has_function(VarName): + func: Any = Gen._get_function(VarName) + if func: + return Gen.builder.bitcast(func, ir.IntType(8).as_pointer(), name=f"funcptr_{VarName}") + if VarName in Gen.class_methods: + return ir.Constant(ir.IntType(8).as_pointer(), None) + if VarName == 'True' or VarName == 'False': + return ir.Constant(ir.IntType(32), 1 if VarName == 'True' else 0) + SymInfo: Any = self.Trans.SymbolTable.lookup(VarName) + if SymInfo: + if SymInfo.IsEnumMember and isinstance(SymInfo.value, int): + return ir.Constant(ir.IntType(32), SymInfo.value) + if SymInfo.IsFunction or SymInfo.IsFuncPtr: + MangledName: str = Gen._mangle_func_name(VarName) + if MangledName in Gen.module.globals: + g: Any = Gen.module.globals[MangledName] + if isinstance(g, ir.Function): + Gen.functions[VarName] = g + return Gen.builder.bitcast(g, ir.IntType(8).as_pointer(), name=f"funcptr_{VarName}") + for sha1 in Gen.ModuleSha1Map.values(): + prefixed: str = f"{sha1}.{VarName}" + if prefixed in Gen.module.globals: + g = Gen.module.globals[prefixed] + if isinstance(g, ir.Function): + Gen.functions[VarName] = g + return Gen.builder.bitcast(g, ir.IntType(8).as_pointer(), name=f"funcptr_{VarName}") + t_c_imported: dict[str, tuple[str, str]] = getattr(self.Trans, '_t_c_imported_names', {}) + if VarName in t_c_imported: + src_module: str + src_name: str + src_module, src_name = t_c_imported[VarName] + virtual_attr: ast.Attribute = ast.Attribute( + value=ast.Name(id=src_module, ctx=ast.Load()), + attr=src_name, + ctx=ast.Load() + ) + ast.copy_location(virtual_attr, Node) + return self.Trans.ExprAttrHandle._HandleAttributeLlvm(virtual_attr) + return ir.Constant(ir.IntType(32), 0) \ No newline at end of file diff --git a/lib/core/Handles/HandlesExprAsm.py b/lib/core/Handles/HandlesExprAsm.py index 886933b..e61e890 100644 --- a/lib/core/Handles/HandlesExprAsm.py +++ b/lib/core/Handles/HandlesExprAsm.py @@ -1,10 +1,13 @@ from __future__ import annotations -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Any +import ast +import re +import llvmlite.ir as ir if TYPE_CHECKING: from lib.core.translator import Translator + from lib.core.LlvmCodeGenerator import LlvmCodeGenerator from lib.core.Handles.HandlesBase import BaseHandle -import ast -import llvmlite.ir as ir +from lib.core.SymbolUtils import IsTModule import t # 猴子补丁 llvmlite.ir.InlineAsm 以支持 asm_dialect 参数 @@ -37,9 +40,9 @@ if not _InlineAsmPatched: class ExprAsmHandle(BaseHandle): @staticmethod - def _format_to_dialect(asm_format): + def _format_to_dialect(asm_format: str | None) -> str | None: """将用户指定的 format 参数转换为 LLVM asm_dialect 值""" - fmt = asm_format.lower() if asm_format else 'intel' + fmt: str = asm_format.lower() if asm_format else 'intel' if fmt == 'att': return 'att' elif fmt == 'arm': @@ -47,13 +50,13 @@ class ExprAsmHandle(BaseHandle): else: return 'intel' # 默认 Intel - def _HandleAsmLlvm(self, Node): - Gen = self.Trans.LlvmGen + def _HandleAsmLlvm(self, Node: ast.Call) -> ir.Value | None: + Gen: LlvmCodeGenerator = self.Trans.LlvmGen - op_arg = None - input_arg = None - output_arg = None - asm_format = 'Intel' # 汇编格式: Intel / AT&T / ARM + op_arg: Any = None + input_arg: Any = None + output_arg: Any = None + asm_format: str = 'Intel' # 汇编格式: Intel / AT&T / ARM for kw in Node.keywords: if kw.arg == 'op': op_arg = kw.value @@ -66,7 +69,7 @@ class ExprAsmHandle(BaseHandle): asm_format = kw.value.value if len(Node.args) >= 1: - pos_op = None + pos_op: Any = None if len(Node.args) >= 2 and op_arg is None: pos_op = Node.args[1] return self._HandleAsmWithOpLlvm(Node.args[0], op_arg or pos_op, input_arg, output_arg, asm_format) @@ -74,90 +77,90 @@ class ExprAsmHandle(BaseHandle): if len(Node.args) < 2: return ir.Constant(ir.IntType(32), 1) - args = Node.args + args: list[ast.AST] = Node.args if len(args) == 4: - output_type_arg = args[0] - asm_template_arg = args[1] - constraint_arg = args[2] - clobber_arg = args[3] + output_type_arg: ast.AST = args[0] + asm_template_arg: ast.AST = args[1] + constraint_arg: ast.AST = args[2] + clobber_arg: ast.AST = args[3] - output_type = self._infer_expr_llvm_type(output_type_arg) + output_type: ir.Type | None = self._infer_expr_llvm_type(output_type_arg) if not output_type: output_type = ir.IntType(32) - asm_template = '' + asm_template: str = '' if isinstance(asm_template_arg, ast.Constant) and isinstance(asm_template_arg.value, str): asm_template = self._prepare_intel_asm(self._mangle_asm_calls(asm_template_arg.value)) - constraint = '' + constraint: str = '' if isinstance(constraint_arg, ast.Constant) and isinstance(constraint_arg.value, str): constraint = constraint_arg.value - clobber = '' + clobber: str = '' if isinstance(clobber_arg, ast.Constant) and isinstance(clobber_arg.value, str): clobber = clobber_arg.value - full_constraint = constraint - func_type = ir.FunctionType(output_type, []) - asm_dialect = self._format_to_dialect(asm_format) - inline_asm = ir.InlineAsm(func_type, asm_template, constraint, side_effect=True, asm_dialect=asm_dialect) - result = Gen.builder.call(inline_asm, [], name="asm_result") + full_constraint: str = constraint + func_type: ir.FunctionType = ir.FunctionType(output_type, []) + asm_dialect: str | None = self._format_to_dialect(asm_format) + inline_asm: ir.InlineAsm = ir.InlineAsm(func_type, asm_template, constraint, side_effect=True, asm_dialect=asm_dialect) + result: Any = Gen.builder.call(inline_asm, [], name="asm_result") return result elif len(args) >= 2: - output_type_arg = args[0] - asm_template_arg = args[1] + output_type_arg: ast.AST = args[0] + asm_template_arg: ast.AST = args[1] - output_type = self._infer_expr_llvm_type(output_type_arg) + output_type: ir.Type | None = self._infer_expr_llvm_type(output_type_arg) if not output_type: output_type = ir.IntType(32) - asm_template = '' + asm_template: str = '' if isinstance(asm_template_arg, ast.Constant) and isinstance(asm_template_arg.value, str): asm_template = self._prepare_intel_asm(self._mangle_asm_calls(asm_template_arg.value)) - output_constraints = [] - output_values = [] + output_constraints: list[str] = [] + output_values: list[Any] = [] if len(args) > 2 and isinstance(args[2], (ast.List, ast.Tuple)): for item in args[2].elts: if isinstance(item, (ast.List, ast.Tuple)) and len(item.elts) >= 2: - constraint_node = item.elts[0] - value_node = item.elts[1] + constraint_node: ast.AST = item.elts[0] + value_node: ast.AST = item.elts[1] if isinstance(constraint_node, ast.Constant) and isinstance(constraint_node.value, str): output_constraints.append(constraint_node.value) - value = self.HandleExprLlvm(value_node) + value: Any = self.HandleExprLlvm(value_node) if value: output_values.append(value) - input_constraints = [] - input_values = [] + input_constraints: list[str] = [] + input_values: list[Any] = [] if len(args) > 3 and isinstance(args[3], (ast.List, ast.Tuple)): for item in args[3].elts: if isinstance(item, (ast.List, ast.Tuple)) and len(item.elts) >= 2: - constraint_node = item.elts[0] - value_node = item.elts[1] + constraint_node: ast.AST = item.elts[0] + value_node: ast.AST = item.elts[1] if isinstance(constraint_node, ast.Constant) and isinstance(constraint_node.value, str): input_constraints.append(constraint_node.value) - value = self.HandleExprLlvm(value_node) + value: Any = self.HandleExprLlvm(value_node) if value: input_values.append(value) - clobbers = [] + clobbers: list[str] = [] if len(args) > 4 and isinstance(args[4], (ast.List, ast.Tuple)): for item in args[4].elts: if isinstance(item, ast.Constant) and isinstance(item.value, str): clobbers.append(item.value) - constraint_parts = [] + constraint_parts: list[str] = [] for oc in output_constraints: constraint_parts.append(oc) - input_start_idx = len(output_constraints) + input_start_idx: int = len(output_constraints) for ic in input_constraints: constraint_parts.append(ic) - full_constraint = ",".join(constraint_parts) + full_constraint: str = ",".join(constraint_parts) if clobbers: if full_constraint: @@ -165,18 +168,17 @@ class ExprAsmHandle(BaseHandle): for c in clobbers: full_constraint += f"~{{{c}}}" - operands = output_values + input_values - param_types = [v.type for v in operands] - func_type = ir.FunctionType(output_type, param_types) - asm_dialect = self._format_to_dialect(asm_format) - inline_asm = ir.InlineAsm(func_type, asm_template, full_constraint, side_effect=False, asm_dialect=asm_dialect) - result = Gen.builder.call(inline_asm, operands, name="asm_result") + operands: list[Any] = output_values + input_values + param_types: list[ir.Type] = [v.type for v in operands] + func_type: ir.FunctionType = ir.FunctionType(output_type, param_types) + asm_dialect: str | None = self._format_to_dialect(asm_format) + inline_asm: ir.InlineAsm = ir.InlineAsm(func_type, asm_template, full_constraint, side_effect=False, asm_dialect=asm_dialect) + result: Any = Gen.builder.call(inline_asm, operands, name="asm_result") return result return None def _prepare_intel_asm(self, template: str) -> str: - import re template = re.sub(r'%(\d+)', r'$\1', template) template = re.sub(r'%([a-zA-Z][a-zA-Z0-9]*)', r'\1', template) return template @@ -196,26 +198,26 @@ class ExprAsmHandle(BaseHandle): stripped.append('') return '\n'.join([first_line] + stripped) - def _process_joined_str_template(self, node, out_input_ops, out_input_constraints, - out_output_ops, out_output_constraints): + def _process_joined_str_template(self, node: ast.AST, out_input_ops: list[Any], out_input_constraints: list[str], + out_output_ops: list[Any], out_output_constraints: list[str]) -> str: if not isinstance(node, ast.JoinedStr): if isinstance(node, ast.Constant) and isinstance(node.value, str): return node.value return '' - raw_parts = [] + raw_parts: list[tuple[str, str | int]] = [] for value in node.values: if isinstance(value, ast.Constant) and isinstance(value.value, str): raw_parts.append(('text', value.value)) elif isinstance(value, ast.FormattedValue): - expr = value.value + expr: ast.AST = value.value if isinstance(expr, ast.Call) and isinstance(expr.func, ast.Attribute): if isinstance(expr.func.value, ast.Name) and expr.func.value.id == 'c': if expr.func.attr == 'AsmInp': if expr.args: - v = self.HandleExprLlvm(expr.args[0]) + v: Any = self.HandleExprLlvm(expr.args[0]) if v: - c = 'r' + c: str = 'r' if len(expr.args) >= 2: c = self._parse_asm_descr(expr.args[1]) if not c: @@ -225,13 +227,13 @@ class ExprAsmHandle(BaseHandle): raw_parts.append(('input', len(out_input_ops) - 1)) elif expr.func.attr == 'AsmOut': if expr.args: - target_ptr = self._get_var_ptr_for_asm(expr.args[0]) + target_ptr: Any = self._get_var_ptr_for_asm(expr.args[0]) if target_ptr: v = target_ptr else: v = self.HandleExprLlvm(expr.args[0]) if v: - c = '=r' + c: str = '=r' if len(expr.args) >= 2: c = self._parse_asm_descr(expr.args[1]) if not c: @@ -242,7 +244,7 @@ class ExprAsmHandle(BaseHandle): out_output_constraints.append(c) raw_parts.append(('output', len(out_output_ops) - 1)) else: - fallback = self.HandleExprLlvm(expr) + fallback: Any = self.HandleExprLlvm(expr) if fallback and isinstance(fallback.type, ir.IntType): out_input_ops.append(fallback) out_input_constraints.append('r') @@ -250,8 +252,8 @@ class ExprAsmHandle(BaseHandle): else: raw_parts.append(('text', '')) - num_outputs = len(out_output_ops) - parts = [] + num_outputs: int = len(out_output_ops) + parts: list[str] = [] for kind, data in raw_parts: if kind == 'text': parts.append(data) @@ -274,47 +276,46 @@ class ExprAsmHandle(BaseHandle): }) def _mangle_asm_calls(self, template: str) -> str: - import re - Gen = self.Trans.LlvmGen - sha1 = getattr(Gen, 'module_sha1', '') + Gen: LlvmCodeGenerator = self.Trans.LlvmGen + sha1: str = getattr(Gen, 'module_sha1', '') if not sha1: return template - def replace_call(m): - prefix = m.group(1) - func_name = m.group(2) + def replace_call(m: re.Match[str]) -> str: + prefix: str = m.group(1) + func_name: str = m.group(2) if func_name.lower() in self._X86_REGISTERS: return m.group(0) - mangled = Gen._mangle_func_name(func_name) + mangled: str = Gen._mangle_func_name(func_name) if '.' in mangled: return f'{prefix}\\22{mangled}\\22' return f"{prefix}{mangled}" return re.sub(r'(call\s+)(\w+)', replace_call, template) - def _HandleAsmWithOpLlvm(self, asm_template_arg, op_arg, input_arg=None, output_arg=None, asm_format='Intel'): - Gen = self.Trans.LlvmGen + def _HandleAsmWithOpLlvm(self, asm_template_arg: ast.AST, op_arg: ast.AST | None = None, input_arg: ast.AST | None = None, output_arg: ast.AST | None = None, asm_format: str = 'Intel') -> ir.Value: + Gen: LlvmCodeGenerator = self.Trans.LlvmGen - input_ops = [] - input_constraints = [] - output_ops = [] - output_constraints = [] + input_ops: list[Any] = [] + input_constraints: list[str] = [] + output_ops: list[Any] = [] + output_constraints: list[str] = [] if output_arg and isinstance(output_arg, (ast.List, ast.Tuple)): for item in output_arg.elts: if isinstance(item, ast.Call) and isinstance(item.func, ast.Attribute): if item.func.value.id == 'c' and item.func.attr == 'AsmOut': if len(item.args) >= 1: - target_ptr = self._get_var_ptr_for_asm(item.args[0]) + target_ptr: Any = self._get_var_ptr_for_asm(item.args[0]) if target_ptr: output_ops.append(target_ptr) else: - value = self.HandleExprLlvm(item.args[0]) + value: Any = self.HandleExprLlvm(item.args[0]) if value: output_ops.append(value) - constraint = '=r' + constraint: str = '=r' if len(item.args) >= 2: - base_constraint = self._parse_asm_descr(item.args[1]) + base_constraint: str = self._parse_asm_descr(item.args[1]) if base_constraint: if base_constraint.startswith('='): constraint = base_constraint @@ -322,6 +323,7 @@ class ExprAsmHandle(BaseHandle): constraint = '=' + base_constraint output_constraints.append(constraint) + raw_template: str if isinstance(asm_template_arg, ast.JoinedStr): raw_template = self._normalize_asm_template( self._process_joined_str_template( @@ -334,7 +336,8 @@ class ExprAsmHandle(BaseHandle): raw_template = '' raw_template = self._mangle_asm_calls(raw_template) - asm_dialect = self._format_to_dialect(asm_format) + asm_dialect: str | None = self._format_to_dialect(asm_format) + asm_template: str if asm_format == 'AT&T': asm_template = raw_template # AT&T 不需要转换 elif asm_format == 'ARM': @@ -347,36 +350,36 @@ class ExprAsmHandle(BaseHandle): if isinstance(item, ast.Call) and isinstance(item.func, ast.Attribute): if item.func.value.id == 'c' and item.func.attr == 'AsmInp': if len(item.args) >= 1: - value = self.HandleExprLlvm(item.args[0]) + value: Any = self.HandleExprLlvm(item.args[0]) if value: input_ops.append(value) - constraint = 'r' + constraint: str = 'r' if len(item.args) >= 2: constraint = self._parse_asm_descr(item.args[1]) if not constraint: constraint = 'r' input_constraints.append(constraint) elif isinstance(item, (ast.List, ast.Tuple)) and len(item.elts) >= 2: - value_node = item.elts[0] - descr_node = item.elts[1] - value = self.HandleExprLlvm(value_node) + value_node: ast.AST = item.elts[0] + descr_node: ast.AST = item.elts[1] + value: Any = self.HandleExprLlvm(value_node) if value: input_ops.append(value) - constraint = self._parse_asm_descr(descr_node) + constraint: str = self._parse_asm_descr(descr_node) if not constraint: constraint = 'r' input_constraints.append(constraint) - clobbers = [] + clobbers: list[str] = [] if op_arg and isinstance(op_arg, (ast.List, ast.Tuple)): for item in op_arg.elts: - clobber = self._parse_asm_descr(item) + clobber: str = self._parse_asm_descr(item) if clobber: clobbers.append(clobber) - constraint_parts = [] + constraint_parts: list[str] = [] for oc in output_constraints: - c = oc if oc.startswith('=') else ('=' + oc) + c: str = oc if oc.startswith('=') else ('=' + oc) constraint_parts.append(c) for ic in input_constraints: if ic in ('d', 'edx', 'rdx'): @@ -384,31 +387,32 @@ class ExprAsmHandle(BaseHandle): else: constraint_parts.append(ic) - full_constraint = ",".join(constraint_parts) + full_constraint: str = ",".join(constraint_parts) - constraint_to_reg = { + constraint_to_reg: dict[str, str] = { 'a': 'rax', 'b': 'rbx', 'c': 'rcx', 'd': 'rdx', 'S': 'rsi', 'D': 'rdi', 'A': 'rax', 'U': 'r8', } - used_regs = set() + used_regs: set[str] = set() for ic in input_constraints: if ic in constraint_to_reg: used_regs.add(constraint_to_reg[ic]) for oc in output_constraints: - base_oc = oc.lstrip('=').lstrip('+') + base_oc: str = oc.lstrip('=').lstrip('+') if base_oc in constraint_to_reg: used_regs.add(constraint_to_reg[base_oc]) if clobbers: - has_memory = 'memory' in clobbers + has_memory: bool = 'memory' in clobbers if has_memory and output_ops: clobbers = [c for c in clobbers if c != 'memory'] + clobber_final: list[str] if asm_format == 'ARM': # ARM 不需要 x86 的 e→r 寄存器名转换 clobber_final = [c for c in clobbers if c not in used_regs] else: - clobber_64bit = [] + clobber_64bit: list[str] = [] for c in clobbers: if c in ['eax', 'ebx', 'ecx', 'edx', 'esi', 'edi', 'ebp', 'esp']: clobber_64bit.append(c.replace('e', 'r')) @@ -421,9 +425,10 @@ class ExprAsmHandle(BaseHandle): full_constraint += ",".join([f"~{{{c}}}" for c in clobber_final]) if output_ops: - single_out = len(output_ops) == 1 + single_out: bool = len(output_ops) == 1 if single_out: - op = output_ops[0] + op: Any = output_ops[0] + ret_type: ir.Type if isinstance(op, ir.AllocaInstr): ret_type = op.type.pointee elif isinstance(op, ir.GlobalVariable): @@ -433,124 +438,122 @@ class ExprAsmHandle(BaseHandle): else: ret_type = op.type else: - def _get_ret_type(op): + def _get_ret_type(op: Any) -> ir.Type: if isinstance(op, (ir.AllocaInstr, ir.GlobalVariable)): return op.type.pointee return op.type ret_type = ir.LiteralStructType([_get_ret_type(op) for op in output_ops]) if isinstance(ret_type, ir.PointerType) and isinstance(ret_type.pointee, ir.IdentifiedStructType): ret_type = ir.IntType(64) - operands = input_ops - param_types = [op.type for op in operands] - func_type = ir.FunctionType(ret_type, param_types) - inline_asm = ir.InlineAsm(func_type, asm_template, full_constraint, side_effect=len(output_ops) == 0, asm_dialect=asm_dialect) - result = Gen.builder.call(inline_asm, operands, name="asm_result") + operands: list[Any] = input_ops + param_types: list[ir.Type] = [op.type for op in operands] + func_type: ir.FunctionType = ir.FunctionType(ret_type, param_types) + inline_asm: ir.InlineAsm = ir.InlineAsm(func_type, asm_template, full_constraint, side_effect=len(output_ops) == 0, asm_dialect=asm_dialect) + result: Any = Gen.builder.call(inline_asm, operands, name="asm_result") if single_out: - target = output_ops[0] + target: Any = output_ops[0] if isinstance(target, ir.AllocaInstr): if target.type.pointee != result.type: - i64t = ir.IntType(64) - iv = Gen.builder.ptrtoint(result, i64t) - ptr = Gen.builder.bitcast(target, ir.PointerType(i64t)) + i64t: ir.IntType = ir.IntType(64) + iv: Any = Gen.builder.ptrtoint(result, i64t) + ptr: Any = Gen.builder.bitcast(target, ir.PointerType(i64t)) Gen.builder.store(iv, ptr) else: Gen.builder.store(result, target) elif isinstance(target, (ir.GlobalVariable, ir.GEPInstr, ir.CastInstr)): - target_pointee = target.type.pointee + target_pointee: ir.Type = target.type.pointee if target_pointee != result.type: if isinstance(target_pointee, ir.PointerType) and isinstance(result, ir.Instruction) and result.type == ir.IntType(64): - ptr_val = Gen.builder.inttoptr(result, target_pointee) + ptr_val: Any = Gen.builder.inttoptr(result, target_pointee) Gen.builder.store(ptr_val, target) else: - i64t = ir.IntType(64) - iv = Gen.builder.ptrtoint(result, i64t) - ptr = Gen.builder.bitcast(target, ir.PointerType(i64t)) + i64t: ir.IntType = ir.IntType(64) + iv: Any = Gen.builder.ptrtoint(result, i64t) + ptr: Any = Gen.builder.bitcast(target, ir.PointerType(i64t)) Gen.builder.store(iv, ptr) else: Gen.builder.store(result, target) else: - dst = Gen._allocaEntry(result.type) + dst: Any = Gen._allocaEntry(result.type) Gen.builder.store(result, dst) else: for i, out_op in enumerate(output_ops): - val = Gen.builder.extract_value(result, i, name=f"asm_out_{i}") - target = out_op if isinstance(out_op, ir.AllocaInstr) else Gen._allocaEntry(val.type) + val: Any = Gen.builder.extract_value(result, i, name=f"asm_out_{i}") + target: Any = out_op if isinstance(out_op, ir.AllocaInstr) else Gen._allocaEntry(val.type) if isinstance(target, ir.AllocaInstr) and target.type.pointee != val.type: - i64t = ir.IntType(64) - iv = Gen.builder.ptrtoint(val, i64t) - ptr = Gen.builder.bitcast(target, ir.PointerType(i64t)) + i64t: ir.IntType = ir.IntType(64) + iv: Any = Gen.builder.ptrtoint(val, i64t) + ptr: Any = Gen.builder.bitcast(target, ir.PointerType(i64t)) Gen.builder.store(iv, ptr) else: Gen.builder.store(val, target) else: - operands = input_ops - param_types = [op.type for op in operands] - func_type = ir.FunctionType(ir.VoidType(), param_types) - inline_asm = ir.InlineAsm(func_type, asm_template, full_constraint, side_effect=True, asm_dialect=asm_dialect) + operands: list[Any] = input_ops + param_types: list[ir.Type] = [op.type for op in operands] + func_type: ir.FunctionType = ir.FunctionType(ir.VoidType(), param_types) + inline_asm: ir.InlineAsm = ir.InlineAsm(func_type, asm_template, full_constraint, side_effect=True, asm_dialect=asm_dialect) Gen.builder.call(inline_asm, operands, name="asm_call") return ir.Constant(ir.IntType(32), 1) - def _get_var_ptr_for_asm(self, node): - Gen = self.Trans.LlvmGen + def _get_var_ptr_for_asm(self, node: ast.AST) -> ir.Value | None: + Gen: LlvmCodeGenerator = self.Trans.LlvmGen if isinstance(node, ast.Name): - var_name = node.id + var_name: str = node.id if var_name in Gen.variables and Gen.variables[var_name] is not None: - ptr = Gen.variables[var_name] + ptr: Any = Gen.variables[var_name] if isinstance(ptr, ir.AllocaInstr): return ptr if isinstance(ptr, ir.GlobalVariable): return ptr elif isinstance(node, ast.Attribute): - obj_ptr = self._get_var_ptr_for_asm(node.value) + obj_ptr: Any = self._get_var_ptr_for_asm(node.value) if obj_ptr is not None: - obj_type = obj_ptr.type.pointee + obj_type: ir.Type = obj_ptr.type.pointee if isinstance(obj_type, ir.PointerType) and isinstance(obj_type.pointee, ir.IdentifiedStructType): - Loaded = Gen.builder.load(obj_ptr, name="asm_attr_Load") - struct_type = obj_type.pointee - class_name = Gen._resolve_class_for_var(node.value.id) if isinstance(node.value, ast.Name) else None + Loaded: Any = Gen.builder.load(obj_ptr, name="asm_attr_Load") + struct_type: ir.IdentifiedStructType = obj_type.pointee + class_name: str | None = Gen._resolve_class_for_var(node.value.id) if isinstance(node.value, ast.Name) else None if class_name: - offset = Gen._get_member_offset(node.attr, class_name) - gep = Gen.builder.gep(Loaded, [ir.Constant(ir.IntType(32), 0), + offset: int = Gen._get_member_offset(node.attr, class_name) + gep: Any = Gen.builder.gep(Loaded, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], inbounds=True) return gep for idx, elem_type in enumerate(struct_type.elements): - gep = Gen.builder.gep(Loaded, [ir.Constant(ir.IntType(32), 0), + gep: Any = Gen.builder.gep(Loaded, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), idx)], inbounds=True) return gep elif isinstance(obj_type, ir.IdentifiedStructType): - class_name = Gen._resolve_class_for_var(node.value.id) if isinstance(node.value, ast.Name) else None + class_name: str | None = Gen._resolve_class_for_var(node.value.id) if isinstance(node.value, ast.Name) else None if class_name: - offset = Gen._get_member_offset(node.attr, class_name) - gep = Gen.builder.gep(obj_ptr, [ir.Constant(ir.IntType(32), 0), + offset: int = Gen._get_member_offset(node.attr, class_name) + gep: Any = Gen.builder.gep(obj_ptr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], inbounds=True) return gep for idx, elem_type in enumerate(obj_type.elements): - gep = Gen.builder.gep(obj_ptr, [ir.Constant(ir.IntType(32), 0), + gep: Any = Gen.builder.gep(obj_ptr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), idx)], inbounds=True) return gep return None - def _parse_asm_descr(self, expr): - from lib.includes import t - + def _parse_asm_descr(self, expr: ast.AST) -> str: if isinstance(expr, ast.BinOp): - left_val = self._parse_asm_descr(expr.left) - right_val = self._parse_asm_descr(expr.right) + left_val: str = self._parse_asm_descr(expr.left) + right_val: str = self._parse_asm_descr(expr.right) return left_val + right_val elif isinstance(expr, ast.Attribute): if isinstance(expr.value, ast.Attribute): if (isinstance(expr.value.value, ast.Name) and - expr.value.value.id == 't' and + IsTModule(expr.value.value.id, self.Trans.SymbolTable) and expr.value.attr == 'ASM_DESCR'): - AttrName = expr.attr + AttrName: str = expr.attr return getattr(t.ASM_DESCR, AttrName, "") - elif isinstance(expr.value, ast.Name) and expr.value.id == 't': - AttrName = expr.attr + elif isinstance(expr.value, ast.Name) and IsTModule(expr.value.id, self.Trans.SymbolTable): + AttrName: str = expr.attr return getattr(t.ASM_DESCR, AttrName, "") elif isinstance(expr, ast.Constant): @@ -558,14 +561,13 @@ class ExprAsmHandle(BaseHandle): return "" - def _infer_expr_llvm_type(self, expr): - import llvmlite.ir as ir + def _infer_expr_llvm_type(self, expr: ast.AST) -> ir.Type | None: if isinstance(expr, ast.Name): - type_name = expr.id + type_name: str = expr.id if hasattr(t, type_name): - ctype = getattr(t, type_name) + ctype: Any = getattr(t, type_name) if isinstance(ctype, type) and issubclass(ctype, t.CType): - size = getattr(ctype, 'Size', None) + size: Any = getattr(ctype, 'Size', None) if size is not None: return ir.IntType(size) if type_name == 'CFloat': @@ -573,6 +575,6 @@ class ExprAsmHandle(BaseHandle): elif type_name == 'CDouble': return ir.DoubleType() elif isinstance(expr, ast.Attribute): - if isinstance(expr.value, ast.Name) and expr.value.id == 't': + if isinstance(expr.value, ast.Name) and IsTModule(expr.value.id, self.Trans.SymbolTable): return self._infer_expr_llvm_type(ast.Name(id=expr.attr, ctx=ast.Load())) return None diff --git a/lib/core/Handles/HandlesExprAttr.py b/lib/core/Handles/HandlesExprAttr.py index 94039df..0f2a6fb 100644 --- a/lib/core/Handles/HandlesExprAttr.py +++ b/lib/core/Handles/HandlesExprAttr.py @@ -1,7 +1,8 @@ from __future__ import annotations -from typing import TYPE_CHECKING +from typing import Any, TYPE_CHECKING if TYPE_CHECKING: from lib.core.translator import Translator + from lib.core.LlvmCodeGenerator import LlvmCodeGenerator from lib.core.Handles.HandlesBase import BaseHandle, FuncMeta import ast import llvmlite.ir as ir @@ -11,30 +12,32 @@ class ExprAttrHandle(BaseHandle): # ========== 辅助方法 ========== - def _apply_bswap_on_Load(self, val, ClassName, AttrName): - Gen = self.Trans.LlvmGen - byte_order = getattr(Gen, 'class_member_byteorders', {}).get(ClassName, {}).get(AttrName, "") - if byte_order == 'big' and isinstance(val.type, ir.IntType): - if val.type.width in (16, 32, 64): - val = Gen.builder.bswap(val, name=f"bswap_Load_{AttrName}") - return val + def _apply_bswap_on_Load(self, val: ir.Value, ClassName: str, AttrName: str) -> ir.Value: + Gen: LlvmCodeGenerator = self.Trans.LlvmGen + byte_order: str = getattr(Gen, 'class_member_byteorders', {}).get(ClassName, {}).get(AttrName, "") + return Gen._apply_bswap_if_big(val, byte_order, f"bswap_load_{AttrName}") - def _gep_and_Load_member(self, Gen, ObjVal, offset, AttrName, ClassName, ST=None): + def _load_arr_elem_with_bswap(self, Gen: LlvmCodeGenerator, ElemPtr: ir.Value, arr_byte_order: str) -> ir.Value: + """加载数组元素并按字节序应用 bswap""" + val: ir.Value = Gen._load(ElemPtr, name="arr_elem_load") + return Gen._apply_bswap_if_big(val, arr_byte_order, "bswap_arr_load") + + def _gep_and_Load_member(self, Gen: LlvmCodeGenerator, ObjVal: ir.Value, offset: int | None, AttrName: str, ClassName: str, ST: ir.Type | None = None) -> ir.Value | None: """从结构体指针通过 GEP 取成员,处理 array/struct pointer/class_members 特殊情况""" if offset is None: return None if isinstance(ObjVal.type, ir.PointerType): - pointee = ObjVal.type.pointee + pointee: Any = ObjVal.type.pointee if isinstance(pointee, ir.IdentifiedStructType) and pointee.elements is not None and offset >= len(pointee.elements): return None - MemberPtr = Gen.builder.gep(ObjVal, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=AttrName) + MemberPtr: Any = Gen.builder.gep(ObjVal, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=AttrName) if isinstance(MemberPtr.type, ir.PointerType) and isinstance(MemberPtr.type.pointee, ir.ArrayType): return MemberPtr if isinstance(MemberPtr.type, ir.PointerType) and isinstance(MemberPtr.type.pointee, ir.IdentifiedStructType): return MemberPtr # 检查 pointer-to-pointer 且实际元素是 ArrayType if isinstance(MemberPtr.type, ir.PointerType) and isinstance(MemberPtr.type.pointee, ir.PointerType): - actual_elem_type = None + actual_elem_type: Any = None if ST is not None and isinstance(ST, ir.IdentifiedStructType) and ST.elements is not None and offset < len(ST.elements): actual_elem_type = ST.elements[offset] if isinstance(actual_elem_type, ir.ArrayType): @@ -44,14 +47,14 @@ class ExprAttrHandle(BaseHandle): for member_name, member_type in Gen.class_members[ClassName]: if member_name == AttrName and isinstance(member_type, ir.ArrayType): return Gen.builder.bitcast(MemberPtr, ir.PointerType(member_type), name=f"cast_arr_{AttrName}") - val = Gen._load(MemberPtr, name=AttrName) + val: Any = Gen._load(MemberPtr, name=AttrName) return self._apply_bswap_on_Load(val, ClassName, AttrName) - def _try_Load_struct_from_stub(self, Gen, ClassName): + def _try_Load_struct_from_stub(self, Gen: LlvmCodeGenerator, ClassName: str) -> tuple[ir.Type | None, bool]: """尝试从 stub 加载结构体定义,返回 (struct_type, ok)""" if ClassName not in Gen.structs: return None, False - st = Gen.structs[ClassName] + st: Any = Gen.structs[ClassName] if isinstance(st, ir.IdentifiedStructType) and (st.elements is None or len(st.elements) == 0): self.Trans.ImportHandler._TryLoadStructFromStub(ClassName, Gen) st = Gen.structs.get(ClassName, st) @@ -59,7 +62,7 @@ class ExprAttrHandle(BaseHandle): return st, False return st, True - def _make_define_constant(self, Gen, val): + def _make_define_constant(self, Gen: LlvmCodeGenerator, val: int | float | str) -> ir.Value | None: """将 CDefine 值转为 LLVM 常量""" if isinstance(val, int): if abs(val) > 2147483647: @@ -68,109 +71,101 @@ class ExprAttrHandle(BaseHandle): elif isinstance(val, float): return ir.Constant(ir.DoubleType(), val) elif isinstance(val, str): - str_value = val + '\x00' - str_bytes = str_value.encode('utf-8') - str_type = ir.ArrayType(ir.IntType(8), len(str_bytes)) - gv_name = f"str_const_{Gen.string_const_counter}" - gv = ir.GlobalVariable(Gen.module, str_type, name=gv_name) - gv.initializer = ir.Constant(str_type, bytearray(str_bytes)) - gv.linkage = 'internal' - Gen.string_const_counter += 1 - return Gen.builder.gep(gv, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), 0)], name=f"{gv_name}_cast") + return Gen._create_string_global(val) return None - def _lookup_cdefine(self, Gen, VarName, AttrName): + def _lookup_cdefine(self, Gen: LlvmCodeGenerator, VarName: str, AttrName: str) -> ir.Value | None: """在符号表和模块中查找 CDefine 常量值""" - imported_modules = getattr(self.Trans, '_ImportedModules', None) + imported_modules: Any = getattr(self.Trans, '_ImportedModules', None) if not imported_modules: return None - PossibleKeys = [f"{VarName}.{AttrName}", AttrName] + PossibleKeys: list[str] = [f"{VarName}.{AttrName}", AttrName] for mod_name in imported_modules: if mod_name.endswith(f".{VarName}") or mod_name == VarName: - key = f"{mod_name}.{AttrName}" + key: str = f"{mod_name}.{AttrName}" if key not in PossibleKeys: PossibleKeys.append(key) for lookup_key in PossibleKeys: - SymInfo = self.Trans.SymbolTable.lookup(lookup_key) + SymInfo: Any = self.Trans.SymbolTable.lookup(lookup_key) if SymInfo and SymInfo.IsDefine and SymInfo.DefineValue is not None: return self._make_define_constant(Gen, SymInfo.DefineValue) # 也检查 _define_constants - define_constants = getattr(Gen, '_define_constants', {}) + define_constants: Any = getattr(Gen, '_define_constants', {}) for key in (f"{VarName}.{AttrName}", AttrName): if key in define_constants: return self._make_define_constant(Gen, define_constants[key]) return None - def _lookup_module_global(self, Gen, VarName, AttrName): + def _lookup_module_global(self, Gen: LlvmCodeGenerator, VarName: str, AttrName: str) -> ir.Value | None: """在模块全局变量中查找 import 的属性""" - imported_modules = getattr(self.Trans, '_ImportedModules', None) + imported_modules: Any = getattr(self.Trans, '_ImportedModules', None) if not imported_modules: return None - resolved_mod = self.Trans.SymbolTable.resolve_alias(VarName) + resolved_mod: str = self.Trans.SymbolTable.resolve_alias(VarName) if VarName not in imported_modules and resolved_mod not in imported_modules: return None - PossibleKeys = [f"{VarName}.{AttrName}", AttrName] + PossibleKeys: list[str] = [f"{VarName}.{AttrName}", AttrName] for mod_name in imported_modules: if mod_name.endswith(f".{VarName}") or mod_name == VarName: - key = f"{mod_name}.{AttrName}" + key: str = f"{mod_name}.{AttrName}" if key not in PossibleKeys: PossibleKeys.append(key) for key in PossibleKeys: if key in Gen.module.globals: - GVar = Gen.module.globals[key] + GVar: Any = Gen.module.globals[key] if isinstance(GVar, ir.Function): return GVar if isinstance(GVar.type, ir.PointerType) and isinstance(GVar.type.pointee, (ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)): return GVar return Gen._load(GVar, name=AttrName) # SHA1 前缀查找 - ModuleSha1Map = getattr(Gen, 'ModuleSha1Map', {}) - sha1_candidates = [VarName, resolved_mod] + ModuleSha1Map: Any = getattr(Gen, 'ModuleSha1Map', {}) + sha1_candidates: list[str] = [VarName, resolved_mod] for mod_name in imported_modules: if mod_name.endswith(f".{VarName}") or mod_name == VarName: if mod_name not in sha1_candidates: sha1_candidates.append(mod_name) for cand in sha1_candidates: - sha1 = ModuleSha1Map.get(cand) + sha1: str | None = ModuleSha1Map.get(cand) if sha1: - prefixed = f"{sha1}.{AttrName}" + prefixed: str = f"{sha1}.{AttrName}" if prefixed in Gen.module.globals: - GVar2 = Gen.module.globals[prefixed] + GVar2: Any = Gen.module.globals[prefixed] if isinstance(GVar2, ir.Function): return GVar2 if isinstance(GVar2.type, ir.PointerType) and isinstance(GVar2.type.pointee, (ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)): return GVar2 return Gen._load(GVar2, name=AttrName) if AttrName in Gen.module.globals: - gv = Gen.module.globals[AttrName] + gv: Any = Gen.module.globals[AttrName] if AttrName in Gen.variables and Gen.variables[AttrName] is None: - str_gv_name = AttrName + '_str' + str_gv_name: str = AttrName + '_str' if str_gv_name in Gen.module.globals: - str_gv = Gen.module.globals[str_gv_name] + str_gv: Any = Gen.module.globals[str_gv_name] return Gen.builder.gep(str_gv, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), 0)], name=f"{AttrName}_str_ptr") return Gen.builder.load(gv, name=AttrName) return None - def _resolve_var_classname(self, Gen, VarName): + def _resolve_var_classname(self, Gen: LlvmCodeGenerator, VarName: str) -> str | None: """根据变量名解析其结构体类名""" - ClassName = Gen.var_struct_class.get(VarName) + ClassName: str | None = Gen.var_struct_class.get(VarName) if not ClassName and getattr(Gen, 'global_struct_class', None): ClassName = Gen.global_struct_class.get(VarName) if ClassName: Gen.var_struct_class[VarName] = ClassName if not ClassName and VarName in Gen.module.globals: - GVar = Gen.module.globals[VarName] + GVar: Any = Gen.module.globals[VarName] if isinstance(GVar.type, ir.PointerType) and isinstance(GVar.type.pointee, (ir.IdentifiedStructType, ir.LiteralStructType)): - found = Gen.find_struct_by_pointee(GVar.type.pointee) + found: Any = Gen.find_struct_by_pointee(GVar.type.pointee) if found: ClassName = found[0] Gen.var_struct_class[VarName] = ClassName if getattr(Gen, 'global_struct_class', None): Gen.global_struct_class[VarName] = ClassName if not ClassName and VarName in Gen.variables: - VarPtr = Gen.variables[VarName] + VarPtr: Any = Gen.variables[VarName] if VarPtr is not None and isinstance(VarPtr.type, ir.PointerType): - pointee = VarPtr.type.pointee + pointee: Any = VarPtr.type.pointee if isinstance(pointee, ir.PointerType): pointee = pointee.pointee found = Gen.find_struct_by_pointee(pointee) @@ -178,12 +173,12 @@ class ExprAttrHandle(BaseHandle): ClassName = found[0] return ClassName - def _check_struct_match(self, Gen, ObjVal, ClassName): + def _check_struct_match(self, Gen: LlvmCodeGenerator, ObjVal: ir.Value, ClassName: str) -> bool: """检查 ObjVal 是否指向 ClassName 对应的结构体""" if ClassName not in Gen.structs: return False if isinstance(ObjVal.type, ir.PointerType): - ST = Gen.structs[ClassName] + ST: Any = Gen.structs[ClassName] if ObjVal.type.pointee == ST: return True if isinstance(ObjVal.type.pointee, ir.IdentifiedStructType) and isinstance(ST, ir.IdentifiedStructType) and ObjVal.type.pointee.name == ST.name: @@ -192,30 +187,30 @@ class ExprAttrHandle(BaseHandle): # ========== _HandleAttributeLlvm 子方法 ========== - def _handle_attr_self(self, Node, VarName): + def _handle_attr_self(self, Node: ast.Attribute, VarName: str) -> ir.Value | None: """处理 self.xxx 属性访问""" - Gen = self.Trans.LlvmGen - ClassName = self.Trans._CurrentCpythonObjectClass + Gen: LlvmCodeGenerator = self.Trans.LlvmGen + ClassName: str | None = self.Trans._CurrentCpythonObjectClass if not ClassName: return None # 检查 property getter - PropKey = f'{ClassName}.{Node.attr}' - PropInfo = self.Trans.SymbolTable.lookup(PropKey) + PropKey: str = f'{ClassName}.{Node.attr}' + PropInfo: Any = self.Trans.SymbolTable.lookup(PropKey) if PropInfo and PropInfo.MetaList and FuncMeta.PROPERTY_GETTER in PropInfo.MetaList: - SelfVar = Gen._get_var_ptr('self') + SelfVar: Any = Gen._get_var_ptr('self') if SelfVar: - SelfPtr = Gen._load(SelfVar, name="self") - GetterFunc = Gen._get_function(PropKey) + SelfPtr: Any = Gen._load(SelfVar, name="self") + GetterFunc: Any = Gen._get_function(PropKey) if GetterFunc and SelfPtr: return Gen.builder.call(GetterFunc, [SelfPtr], name=f"prop_{PropKey}") - offset = Gen._get_member_offset(Node.attr, ClassName) + offset: int | None = Gen._get_member_offset(Node.attr, ClassName) SelfVar = Gen._get_var_ptr('self') if not SelfVar: return None SelfPtr = Gen._load(SelfVar, name="self") if not isinstance(SelfPtr.type, ir.PointerType): return None - pointee = SelfPtr.type.pointee + pointee: Any = SelfPtr.type.pointee if isinstance(pointee, ir.IdentifiedStructType) and pointee.elements is None: for CN2, ST2 in Gen.structs.items(): if isinstance(ST2, ir.IdentifiedStructType) and ST2.name == pointee.name and ST2.elements is not None: @@ -225,34 +220,33 @@ class ExprAttrHandle(BaseHandle): if isinstance(pointee.elements[offset], ir.VoidType): return None return self._gep_and_Load_member(Gen, SelfPtr, offset, Node.attr, ClassName, pointee) - DynamicVarName = f"self.{Node.attr}" + DynamicVarName: str = f"self.{Node.attr}" if DynamicVarName in Gen.variables: return Gen._load(Gen.variables[DynamicVarName], name=Node.attr) return None - def _handle_attr_enum(self, Node, VarName): + def _handle_attr_enum(self, Node: ast.Attribute, VarName: str) -> ir.Value | None: """处理枚举成员访问 (VarName 是枚举类型名)""" - SymInfo = self.Trans.SymbolTable.lookup(VarName) + SymInfo: Any = self.Trans.SymbolTable.lookup(VarName) if not SymInfo or not SymInfo.IsEnum: return None - if self.Trans.SymbolTable.has(Node.attr): - MemberInfo = self.Trans.SymbolTable[Node.attr] - if MemberInfo.IsEnumMember and MemberInfo.EnumName == VarName: - if isinstance(MemberInfo.value, int): - return ir.Constant(ir.IntType(32), MemberInfo.value) + MemberInfo: Any = self.Trans.SymbolTable.lookup(Node.attr) + if MemberInfo and MemberInfo.IsEnumMember and MemberInfo.EnumName == VarName: + if isinstance(MemberInfo.value, int): + return ir.Constant(ir.IntType(32), MemberInfo.value) for key, info in self.Trans.SymbolTable.items(): if info.IsEnumMember and info.EnumName == VarName and key == Node.attr: if isinstance(info.value, int): return ir.Constant(ir.IntType(32), info.value) return None - def _handle_attr_name(self, Node, VarName): + def _handle_attr_name(self, Node: ast.Attribute, VarName: str) -> ir.Value | None: """处理 x.attr 形式 (x 是普通 Name)""" - Gen = self.Trans.LlvmGen - AttrName = Node.attr + Gen: LlvmCodeGenerator = self.Trans.LlvmGen + AttrName: str = Node.attr # 先尝试枚举成员 - result = self._handle_attr_enum(Node, VarName) + result: Any = self._handle_attr_enum(Node, VarName) if result is not None: return result @@ -266,37 +260,48 @@ class ExprAttrHandle(BaseHandle): if result is not None: return result + # FakeDuck: 检查是否有影子结构体 a__meta__ (str 变量的 per-instance 字段存储) + # 当 a 是 str 变量时, a 本身是 char*, 但 a__meta__ 存储了 __data__/__mbuddy__ 等字段 + # 直接通过 a.__field__ 访问影子结构体字段 (语法糖) + _fd_meta_name: str = f"{VarName}__meta__" + if _fd_meta_name in Gen.variables and '_str' in Gen.structs: + _fd_offset = Gen._get_member_offset(AttrName, '_str') + if _fd_offset is not None: + _fd_meta_ptr: ir.Value = Gen.variables[_fd_meta_name] + _fd_field_ptr: ir.Value = Gen.builder.gep(_fd_meta_ptr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), _fd_offset)], name=f"{VarName}_{AttrName}_ptr") + return Gen._load(_fd_field_ptr, name=f"{VarName}_{AttrName}_val") + # 尝试 attr 直接作为全局变量 if AttrName in Gen.module.globals: - gv = Gen.module.globals[AttrName] + gv: Any = Gen.module.globals[AttrName] if AttrName in Gen.variables and Gen.variables[AttrName] is None: - str_gv_name = AttrName + '_str' + str_gv_name: str = AttrName + '_str' if str_gv_name in Gen.module.globals: - str_gv = Gen.module.globals[str_gv_name] + str_gv: Any = Gen.module.globals[str_gv_name] return Gen.builder.gep(str_gv, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), 0)], name=f"{AttrName}_str_ptr") return Gen.builder.load(gv, name=AttrName) # 解析结构体类名并访问成员 - ClassName = self._resolve_var_classname(Gen, VarName) + ClassName: str | None = self._resolve_var_classname(Gen, VarName) if not ClassName: return None # 检查 property getter - PropKey = f'{ClassName}.{AttrName}' - PropInfo = self.Trans.SymbolTable.lookup(PropKey) + PropKey: str = f'{ClassName}.{AttrName}' + PropInfo: Any = self.Trans.SymbolTable.lookup(PropKey) if PropInfo and PropInfo.MetaList and FuncMeta.PROPERTY_GETTER in PropInfo.MetaList: - ObjVal = self.HandleExprLlvm(Node.value) - GetterFunc = Gen._get_function(PropKey) + ObjVal: Any = self.HandleExprLlvm(Node.value) + GetterFunc: Any = Gen._get_function(PropKey) if GetterFunc and ObjVal: if isinstance(ObjVal.type, ir.PointerType) and isinstance(ObjVal.type.pointee, ir.PointerType): ObjVal = Gen._load(ObjVal, name=f"Load_{VarName}") return Gen.builder.call(GetterFunc, [ObjVal], name=f"prop_{PropKey}") # 获取类型信息 - TypeInfo = self.Trans.SymbolTable.lookup(ClassName) - IsUnion = TypeInfo.IsUnion if TypeInfo else False - IsCenum = TypeInfo.IsEnum if TypeInfo else False - IsRenum = TypeInfo.IsRenum if TypeInfo else False + TypeInfo: Any = self.Trans.SymbolTable.lookup(ClassName) + IsUnion: bool = TypeInfo.IsUnion if TypeInfo else False + IsCenum: bool = TypeInfo.IsEnum if TypeInfo else False + IsRenum: bool = TypeInfo.IsRenum if TypeInfo else False # REnum 处理 if IsRenum: @@ -305,11 +310,11 @@ class ExprAttrHandle(BaseHandle): if ObjVal: if isinstance(ObjVal.type, ir.PointerType) and isinstance(ObjVal.type.pointee, ir.PointerType): ObjVal = Gen._load(ObjVal, name=f"Load_{VarName}") - tag_ptr = Gen.builder.gep(ObjVal, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), 0)], name="tag_ptr") + tag_ptr: Any = Gen.builder.gep(ObjVal, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), 0)], name="tag_ptr") return Gen._load(tag_ptr, name="tag_val") - NestedStructName = f"{ClassName}_{AttrName}" + NestedStructName: str = f"{ClassName}_{AttrName}" if NestedStructName in Gen.structs: - NestedStructType = Gen.structs[NestedStructName] + NestedStructType: Any = Gen.structs[NestedStructName] ObjVal = self.HandleExprLlvm(Node.value) if ObjVal: if isinstance(ObjVal.type, ir.PointerType) and isinstance(ObjVal.type.pointee, ir.PointerType): @@ -319,10 +324,9 @@ class ExprAttrHandle(BaseHandle): # CEnum 处理 if IsCenum: for qname in (f"{ClassName}.{AttrName}", f"{ClassName}_{AttrName}"): - if self.Trans.SymbolTable.has(qname): - info = self.Trans.SymbolTable[qname] - if info.IsEnumMember and isinstance(info.value, int): - return ir.Constant(ir.IntType(32), info.value) + info: Any = self.Trans.SymbolTable.lookup(qname) + if info and info.IsEnumMember and isinstance(info.value, int): + return ir.Constant(ir.IntType(32), info.value) for key, info in self.Trans.SymbolTable.items(): if key == AttrName: if info.IsEnumMember and info.EnumName == ClassName: @@ -354,30 +358,32 @@ class ExprAttrHandle(BaseHandle): ObjVal = Gen._load(ObjVal, name=f"Load_{VarName}") # 检查结构体匹配 - struct_match = self._check_struct_match(Gen, ObjVal, ClassName) + struct_match: bool = self._check_struct_match(Gen, ObjVal, ClassName) if not struct_match and ClassName and VarName: if VarName in Gen.var_struct_class: - CN = Gen.var_struct_class[VarName] + CN: str = Gen.var_struct_class[VarName] if CN != ClassName and CN in Gen.structs: ClassName = CN struct_match = self._check_struct_match(Gen, ObjVal, ClassName) if not struct_match: return None + st: Any + ok: bool st, ok = self._try_Load_struct_from_stub(Gen, ClassName) if not ok: return None # bitfield 处理 - bitfield_offsets = Gen.class_member_bitoffsets.get(ClassName, {}) - bitfields = Gen.class_member_bitfields.get(ClassName, {}) + bitfield_offsets: Any = Gen.class_member_bitoffsets.get(ClassName, {}) + bitfields: Any = Gen.class_member_bitfields.get(ClassName, {}) if AttrName in bitfield_offsets and bitfields.get(AttrName, 0) > 0: return self._load_bitfield_member(ObjVal, ClassName, AttrName) if AttrName in bitfields and bitfields[AttrName] > 0: if ClassName not in Gen.class_member_bitoffsets: Gen.class_member_bitoffsets[ClassName] = {} if AttrName not in Gen.class_member_bitoffsets[ClassName]: - bo = 0 + bo: int = 0 for bf_name, bf_width in bitfields.items(): if bf_name == AttrName: break @@ -388,9 +394,9 @@ class ExprAttrHandle(BaseHandle): offset = Gen._get_member_offset(AttrName, ClassName) # 检查 offset 是否超出实际结构体 if isinstance(ObjVal.type, ir.PointerType): - actual_pointee = ObjVal.type.pointee + actual_pointee: Any = ObjVal.type.pointee if isinstance(actual_pointee, ir.IdentifiedStructType): - actual_elems = actual_pointee.elements + actual_elems: Any = actual_pointee.elements if actual_elems is not None and offset is not None and offset >= len(actual_elems): self.Trans.ImportHandler._TryLoadStructFromStub(ClassName, Gen) actual_elems = actual_pointee.elements @@ -398,40 +404,42 @@ class ExprAttrHandle(BaseHandle): return None return self._gep_and_Load_member(Gen, ObjVal, offset, AttrName, ClassName, st) - def _handle_attr_nested(self, Node): + def _handle_attr_nested(self, Node: ast.Attribute) -> ir.Value | None: """处理 a.b.c 嵌套属性访问""" - Gen = self.Trans.LlvmGen + Gen: LlvmCodeGenerator = self.Trans.LlvmGen if isinstance(Node.value.value, ast.Name): - ParentVarName = Node.value.value.id - ParentAttrName = Node.value.attr - enum_result = self._try_resolve_cross_module_enum(ParentVarName, ParentAttrName, Node.attr) + ParentVarName: str = Node.value.value.id + ParentAttrName: str = Node.value.attr + enum_result: Any = self._try_resolve_cross_module_enum(ParentVarName, ParentAttrName, Node.attr) if enum_result is not None: return enum_result # 尝试跨模块子模块全局变量解析: a.b.c 其中 a.b 是已知子模块, c 是该模块的全局变量 - imported_modules = getattr(self.Trans, '_ImportedModules', None) + imported_modules: Any = getattr(self.Trans, '_ImportedModules', None) if imported_modules: - full_ModulePath = f"{ParentVarName}.{ParentAttrName}" + full_ModulePath: str = f"{ParentVarName}.{ParentAttrName}" if full_ModulePath in imported_modules: - result = self._lookup_module_global(Gen, full_ModulePath, Node.attr) + result: Any = self._lookup_module_global(Gen, full_ModulePath, Node.attr) if result is not None: return result - cdefine_result = self._try_resolve_nested_cdefine(Node) + cdefine_result: Any = self._try_resolve_nested_cdefine(Node) if cdefine_result is not None: return cdefine_result - ObjVal = self.HandleExprLlvm(Node.value) + ObjVal: Any = self.HandleExprLlvm(Node.value) if not ObjVal or not isinstance(ObjVal.type, ir.PointerType): return None - pointee = ObjVal.type.pointee + pointee: Any = ObjVal.type.pointee # char* → struct* cast + 成员访问 if isinstance(pointee, ir.IntType) and pointee.width == 8: - AttrClassName = self._get_attr_class(Node.value, Gen) + AttrClassName: str | None = self._get_attr_class(Node.value, Gen) if AttrClassName and AttrClassName in Gen.structs: + st: Any + ok: bool st, ok = self._try_Load_struct_from_stub(Gen, AttrClassName) if not isinstance(st, ir.IdentifiedStructType) or st.elements is None: return None - CastedObj = Gen.builder.bitcast(ObjVal, ir.PointerType(st), name=f"cast_{AttrClassName}") - offset = Gen._get_member_offset(Node.attr, AttrClassName) + CastedObj: Any = Gen.builder.bitcast(ObjVal, ir.PointerType(st), name=f"cast_{AttrClassName}") + offset: int | None = Gen._get_member_offset(Node.attr, AttrClassName) if offset is None: return None if offset < len(st.elements) and isinstance(st.elements[offset], ir.VoidType): @@ -445,7 +453,7 @@ class ExprAttrHandle(BaseHandle): st, ok = self._try_Load_struct_from_stub(Gen, CN) if not isinstance(st, ir.IdentifiedStructType) or st.elements is None: break - bitfield_offsets = Gen.class_member_bitoffsets.get(CN, {}) + bitfield_offsets: Any = Gen.class_member_bitoffsets.get(CN, {}) if Node.attr in bitfield_offsets: return self._load_bitfield_member(ObjVal, CN, Node.attr) offset = Gen._get_member_offset(Node.attr, CN) @@ -454,20 +462,20 @@ class ExprAttrHandle(BaseHandle): return self._gep_and_Load_member(Gen, ObjVal, offset, Node.attr, CN, st) return None - def _handle_attr_call_result(self, Node): + def _handle_attr_call_result(self, Node: ast.Attribute) -> ir.Value | None: """处理 func().attr 属性访问""" - Gen = self.Trans.LlvmGen + Gen: LlvmCodeGenerator = self.Trans.LlvmGen # Check if this is c.Deref(...) — we need the pointer, not the Loaded value - ObjVal = None - is_cderef = (isinstance(Node.value, ast.Call) and + ObjVal: Any = None + is_cderef: bool = (isinstance(Node.value, ast.Call) and isinstance(Node.value.func, ast.Attribute) and isinstance(Node.value.func.value, ast.Name) and Node.value.func.value.id == 'c' and Node.value.func.attr == 'Deref' and Node.value.args) if is_cderef: - deref_arg = Node.value.args[0] - inner_val = self.HandleExprLlvm(deref_arg) + deref_arg: ast.expr = Node.value.args[0] + inner_val: Any = self.HandleExprLlvm(deref_arg) if inner_val and isinstance(inner_val.type, ir.PointerType): if isinstance(inner_val.type.pointee, ir.PointerType): ObjVal = Gen._load(inner_val, name="deref_load_ptr") @@ -477,82 +485,96 @@ class ExprAttrHandle(BaseHandle): ObjVal = self.HandleExprLlvm(Node.value) if not ObjVal or not isinstance(ObjVal.type, ir.PointerType): return None - pointee = ObjVal.type.pointee + pointee: Any = ObjVal.type.pointee if isinstance(pointee, ir.PointerType): ObjVal = Gen._load(ObjVal, name="load_ptr_for_attr") pointee = ObjVal.type.pointee - found = Gen.find_struct_by_pointee(pointee) + found: Any = Gen.find_struct_by_pointee(pointee) if not found: return None + CN: str + ST: Any CN, ST = found + st: Any + ok: bool st, ok = self._try_Load_struct_from_stub(Gen, CN) if not isinstance(st, ir.IdentifiedStructType) or st.elements is None: return None - bitfield_offsets = Gen.class_member_bitoffsets.get(CN, {}) + bitfield_offsets: Any = Gen.class_member_bitoffsets.get(CN, {}) if Node.attr in bitfield_offsets: return self._load_bitfield_member(ObjVal, CN, Node.attr) - offset = Gen._get_member_offset(Node.attr, CN) + offset: int | None = Gen._get_member_offset(Node.attr, CN) if offset is None: return None return self._gep_and_Load_member(Gen, ObjVal, offset, Node.attr, CN, st) - def _handle_attr_subscript_result(self, Node): + def _handle_attr_subscript_result(self, Node: ast.Attribute) -> ir.Value | None: """处理 arr[i].attr 属性访问""" - Gen = self.Trans.LlvmGen - ObjVal = self.HandleExprLlvm(Node.value) + Gen: LlvmCodeGenerator = self.Trans.LlvmGen + ObjVal: Any = self.HandleExprLlvm(Node.value) if not ObjVal or not isinstance(ObjVal.type, ir.PointerType): return None - pointee = ObjVal.type.pointee + pointee: Any = ObjVal.type.pointee if not isinstance(pointee, (ir.LiteralStructType, ir.IdentifiedStructType)): return None - found = Gen.find_struct_by_pointee(pointee) + found: Any = Gen.find_struct_by_pointee(pointee) if not found: return None + CN: str + ST: Any CN, ST = found + st: Any + ok: bool st, ok = self._try_Load_struct_from_stub(Gen, CN) if not isinstance(st, ir.IdentifiedStructType) or st.elements is None: return None - offset = Gen._get_member_offset(Node.attr, CN) + offset: int | None = Gen._get_member_offset(Node.attr, CN) if offset is None: return None return self._gep_and_Load_member(Gen, ObjVal, offset, Node.attr, CN, st) - def _handle_attr_fallback(self, Node): + def _handle_attr_fallback(self, Node: ast.Attribute) -> ir.Value | None: """兜底:对任意值尝试指针解引用后查找结构体成员""" - Gen = self.Trans.LlvmGen - ObjVal = self.HandleExprLlvm(Node.value) + Gen: LlvmCodeGenerator = self.Trans.LlvmGen + ObjVal: Any = self.HandleExprLlvm(Node.value) if not ObjVal or not isinstance(ObjVal.type, ir.PointerType): return None - pointee = ObjVal.type.pointee + pointee: Any = ObjVal.type.pointee if isinstance(pointee, ir.PointerType): ObjVal = Gen._load(ObjVal, name="load_ptr_for_attr_fallback") pointee = ObjVal.type.pointee if not isinstance(pointee, (ir.IdentifiedStructType, ir.LiteralStructType)): return None - found = Gen.find_struct_by_pointee(pointee) + found: Any = Gen.find_struct_by_pointee(pointee) if not found: return None + CN: str + ST: Any CN, ST = found + st: Any + ok: bool st, ok = self._try_Load_struct_from_stub(Gen, CN) if not isinstance(st, ir.IdentifiedStructType) or st.elements is None: return None - offset = Gen._get_member_offset(Node.attr, CN) + offset: int | None = Gen._get_member_offset(Node.attr, CN) if offset is None: return None return self._gep_and_Load_member(Gen, ObjVal, offset, Node.attr, CN, st) # ========== 主入口 ========== - def _HandleAttributeLlvm(self, Node): - Gen = self.Trans.LlvmGen + def _HandleAttributeLlvm(self, Node: ast.Attribute) -> ir.Value | None: + Gen: LlvmCodeGenerator = self.Trans.LlvmGen if isinstance(Node.value, ast.Name): - VarName = Node.value.id + VarName: str = Node.value.id # 处理 t/c import 的别名重定向 - t_c_imported = getattr(self.Trans, '_t_c_imported_names', {}) + t_c_imported: Any = getattr(self.Trans, '_t_c_imported_names', {}) if VarName != 'self' and VarName in t_c_imported: + src_module: str + src_name: str src_module, src_name = t_c_imported[VarName] - virtual_attr = ast.Attribute( + virtual_attr: ast.Attribute = ast.Attribute( value=ast.Name(id=src_module, ctx=ast.Load()), attr=src_name, ctx=ast.Load() ) @@ -578,72 +600,92 @@ class ExprAttrHandle(BaseHandle): # ========== HandleSubscript 及其辅助 ========== - def _HandleSubscriptLlvm(self, Node): - Gen = self.Trans.LlvmGen - ClassName = self.Trans.ExprHandler._get_var_class(Node.value, Gen) + def _HandleSubscriptLlvm(self, Node: ast.Subscript) -> ir.Value | None: + Gen: LlvmCodeGenerator = self.Trans.LlvmGen + # 查询数组元素字节序 + arr_byte_order: str = '' + if isinstance(Node.value, ast.Name) and Node.value.id in Gen.local_var_byteorders: + arr_byte_order = Gen.local_var_byteorders[Node.value.id] + ClassName: str | None = self.Trans.ExprHandler._get_var_class(Node.value, Gen) if ClassName and Gen._has_function(f'{ClassName}.__getitem__'): - obj_val = self.HandleExprLlvm(Node.value) - idx_val = self.HandleExprLlvm(Node.slice) + obj_val: Any = self.HandleExprLlvm(Node.value) + idx_val: Any = self.HandleExprLlvm(Node.slice) if obj_val and idx_val: if isinstance(obj_val.type, ir.PointerType) and isinstance(obj_val.type.pointee, ir.IntType) and obj_val.type.pointee.width == 8: obj_val = Gen.builder.bitcast(obj_val, ir.PointerType(Gen.structs[ClassName]), name=f"cast_{ClassName}") if isinstance(idx_val.type, ir.IntType) and idx_val.type.width < 64: idx_val = Gen.builder.zext(idx_val, ir.IntType(64), name="zext_idx") - result = Gen.builder.call(Gen._get_function(f'{ClassName}.__getitem__'), [obj_val, idx_val], name=f"call_{ClassName}.__getitem__") + _getitem_func: Any = Gen._get_function(f'{ClassName}.__getitem__') + # 处理泛型特化类型不匹配:obj_val 可能是通用类型,而函数期望特化类型 + if _getitem_func.ftype.args and _getitem_func.ftype.args[0] != obj_val.type: + _expected_type = _getitem_func.ftype.args[0] + if isinstance(_expected_type, ir.PointerType) and isinstance(obj_val.type, ir.PointerType): + obj_val = Gen.builder.bitcast(obj_val, _expected_type, name=f"cast_{ClassName}_getitem") + result: Any = Gen.builder.call(_getitem_func, [obj_val, idx_val], name=f"call_{ClassName}.__getitem__") return result - ValueVal = self.HandleExprLlvm(Node.value) + ValueVal: Any = self.HandleExprLlvm(Node.value) if not ValueVal: return None - IndexVal = self.HandleExprLlvm(Node.slice) + IndexVal: Any = self.HandleExprLlvm(Node.slice) if not IndexVal: return None if isinstance(IndexVal.type, ir.PointerType) and isinstance(IndexVal.type.pointee, ir.IntType) and IndexVal.type.pointee.width == 8: - Loaded_byte = Gen._load(IndexVal, name="Load_char_idx") + Loaded_byte: Any = Gen._load(IndexVal, name="Load_char_idx") IndexVal = Gen.builder.zext(Loaded_byte, ir.IntType(32), name="char_to_int_idx") if isinstance(ValueVal.type, ir.IntType): - var_ptr = self._get_int_ptr(Node.value) + var_ptr: Any = self._get_int_ptr(Node.value) if var_ptr: - i8_ptr = Gen.builder.bitcast(var_ptr, ir.PointerType(ir.IntType(8)), name="int_to_i8ptr") + i8_ptr: Any = Gen.builder.bitcast(var_ptr, ir.PointerType(ir.IntType(8)), name="int_to_i8ptr") if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width < 64: IndexVal = Gen.builder.zext(IndexVal, ir.IntType(64), name="zext_int_index") - ptr = Gen.builder.gep(i8_ptr, [IndexVal], name="int_subscript_ptr") + ptr: Any = Gen.builder.gep(i8_ptr, [IndexVal], name="int_subscript_ptr") return Gen._load(ptr, name="int_subscript_val") return None if isinstance(ValueVal.type, ir.PointerType) and isinstance(ValueVal.type.pointee, ir.PointerType): if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width < 64: IndexVal = Gen.builder.zext(IndexVal, ir.IntType(64), name="zext_ptr_index") - ElemPtr = Gen.builder.gep(ValueVal, [IndexVal], name="subscript") + ElemPtr: Any = Gen.builder.gep(ValueVal, [IndexVal], name="subscript") if isinstance(ValueVal.type.pointee.pointee, ir.IntType) and ValueVal.type.pointee.pointee.width == 8: - return Gen._load(ElemPtr, name="subscript_val") - return Gen._load(ElemPtr, name="subscript_val") + return self._load_arr_elem_with_bswap(Gen, ElemPtr, arr_byte_order) + return self._load_arr_elem_with_bswap(Gen, ElemPtr, arr_byte_order) if isinstance(ValueVal.type, ir.PointerType): - pointee = ValueVal.type.pointee + pointee: Any = ValueVal.type.pointee if isinstance(pointee, ir.ArrayType): - zero = ir.Constant(ir.IntType(32), 0) + zero: ir.Constant = ir.Constant(ir.IntType(32), 0) if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width != 32: if IndexVal.type.width < 32: IndexVal = Gen.builder.zext(IndexVal, ir.IntType(32), name="zext_arr_index") else: IndexVal = Gen.builder.trunc(IndexVal, ir.IntType(32), name="trunc_arr_index") ElemPtr = Gen.builder.gep(ValueVal, [zero, IndexVal], name="subscript") - elem_type = pointee.element + elem_type: Any = pointee.element if isinstance(elem_type, (ir.IdentifiedStructType, ir.LiteralStructType)): return ElemPtr - return Gen._load(ElemPtr, name="subscript_val") + return self._load_arr_elem_with_bswap(Gen, ElemPtr, arr_byte_order) else: if isinstance(pointee, ir.IntType) and pointee.width == 8: - elem_class = self._infer_element_struct_class(Node.value, Gen) + elem_class: str | None = self._infer_element_struct_class(Node.value, Gen) if elem_class and elem_class in Gen.structs: - CastedPtr = Gen.builder.bitcast(ValueVal, ir.PointerType(Gen.structs[elem_class]), name=f"cast_{elem_class}_arr") + CastedPtr: Any = Gen.builder.bitcast(ValueVal, ir.PointerType(Gen.structs[elem_class]), name=f"cast_{elem_class}_arr") if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width < 64: IndexVal = Gen.builder.zext(IndexVal, ir.IntType(64), name="zext_arr_index") ElemPtr = Gen.builder.gep(CastedPtr, [IndexVal], name="subscript") if isinstance(pointee, ir.IntType): - return Gen._load(ElemPtr, name="subscript_val") + return self._load_arr_elem_with_bswap(Gen, ElemPtr, arr_byte_order) return ElemPtr - arr_type = self._infer_array_member_type(Node.value, Gen) + # 指针到 str/bytes 的变量 (BinOp 注解如 str | t.CPtr) + # elem_ptr 是 i8* 但实际指向 i8* (字符串指针), elem_ptr[0] 应加载 8 字节 + if isinstance(Node.value, ast.Name): + _ptr_elem_flag: bool = getattr(Gen, 'var_ptr_element', {}).get(Node.value.id, False) + if _ptr_elem_flag: + CastedPtrPtr: Any = Gen.builder.bitcast(ValueVal, ir.PointerType(ir.PointerType(ir.IntType(8))), name="cast_pp_str") + if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width < 64: + IndexVal = Gen.builder.zext(IndexVal, ir.IntType(64), name="zext_pp_str_index") + ElemPtr = Gen.builder.gep(CastedPtrPtr, [IndexVal], name="subscript") + return Gen._load(ElemPtr, name="str_ptr_load") + arr_type: Any = self._infer_array_member_type(Node.value, Gen) if arr_type and isinstance(arr_type, ir.ArrayType): - arr_ptr = Gen.builder.bitcast(ValueVal, ir.PointerType(arr_type), name=f"cast_arr_subscript") + arr_ptr: Any = Gen.builder.bitcast(ValueVal, ir.PointerType(arr_type), name=f"cast_arr_subscript") zero = ir.Constant(ir.IntType(32), 0) if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width != 32: if IndexVal.type.width < 32: @@ -651,20 +693,20 @@ class ExprAttrHandle(BaseHandle): else: IndexVal = Gen.builder.trunc(IndexVal, ir.IntType(32), name="trunc_arr_index") ElemPtr = Gen.builder.gep(arr_ptr, [zero, IndexVal], name="subscript") - arr_elem_type = arr_type.element + arr_elem_type: Any = arr_type.element if isinstance(arr_elem_type, (ir.IdentifiedStructType, ir.LiteralStructType)): return ElemPtr - return Gen._load(ElemPtr, name="subscript_val") + return self._load_arr_elem_with_bswap(Gen, ElemPtr, arr_byte_order) ElemPtr = Gen.builder.gep(ValueVal, [IndexVal], name="subscript") if isinstance(pointee, (ir.IdentifiedStructType, ir.LiteralStructType)): return ElemPtr - return Gen._load(ElemPtr, name="subscript_val") + return self._load_arr_elem_with_bswap(Gen, ElemPtr, arr_byte_order) elif isinstance(ValueVal.type, ir.ArrayType): zero = ir.Constant(ir.IntType(32), 0) if isinstance(Node.value, ast.Name): - VarName = Node.value.id + VarName: str = Node.value.id if VarName in Gen.variables and Gen.variables[VarName] is not None: - VarPtr = Gen.variables[VarName] + VarPtr: Any = Gen.variables[VarName] if isinstance(VarPtr.type, ir.PointerType) and isinstance(VarPtr.type.pointee, ir.ArrayType): if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width != 32: if IndexVal.type.width < 32: @@ -672,12 +714,12 @@ class ExprAttrHandle(BaseHandle): else: IndexVal = Gen.builder.trunc(IndexVal, ir.IntType(32), name="trunc_arr_index") ElemPtr = Gen.builder.gep(VarPtr, [zero, IndexVal], name="subscript") - var_arr_elem_type = VarPtr.type.pointee.element + var_arr_elem_type: Any = VarPtr.type.pointee.element if isinstance(var_arr_elem_type, (ir.IdentifiedStructType, ir.LiteralStructType)): return ElemPtr - return Gen._load(ElemPtr, name="subscript_val") + return self._load_arr_elem_with_bswap(Gen, ElemPtr, arr_byte_order) if isinstance(Node.value, ast.Attribute): - AttrPtr = self._get_attr_ptr(Node.value) + AttrPtr: Any = self._get_attr_ptr(Node.value) if AttrPtr and isinstance(AttrPtr.type, ir.PointerType) and isinstance(AttrPtr.type.pointee, ir.ArrayType): if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width != 32: if IndexVal.type.width < 32: @@ -685,14 +727,14 @@ class ExprAttrHandle(BaseHandle): else: IndexVal = Gen.builder.trunc(IndexVal, ir.IntType(32), name="trunc_arr_index") ElemPtr = Gen.builder.gep(AttrPtr, [zero, IndexVal], name="subscript") - attr_arr_elem_type = AttrPtr.type.pointee.element + attr_arr_elem_type: Any = AttrPtr.type.pointee.element if isinstance(attr_arr_elem_type, (ir.IdentifiedStructType, ir.LiteralStructType)): return ElemPtr - return Gen._load(ElemPtr, name="subscript_val") + return self._load_arr_elem_with_bswap(Gen, ElemPtr, arr_byte_order) if isinstance(Node.value, ast.Subscript): - InnerPtr = self.HandleSubscriptPtrLlvm(Node.value) + InnerPtr: Any = self.HandleSubscriptPtrLlvm(Node.value) if InnerPtr and isinstance(InnerPtr.type, ir.PointerType): - inner_pointee = InnerPtr.type.pointee + inner_pointee: Any = InnerPtr.type.pointee if isinstance(inner_pointee, ir.ArrayType): if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width != 32: if IndexVal.type.width < 32: @@ -700,40 +742,40 @@ class ExprAttrHandle(BaseHandle): else: IndexVal = Gen.builder.trunc(IndexVal, ir.IntType(32), name="trunc_arr_index") ElemPtr = Gen.builder.gep(InnerPtr, [zero, IndexVal], name="subscript") - inner_elem_type = inner_pointee.element + inner_elem_type: Any = inner_pointee.element if isinstance(inner_elem_type, (ir.IdentifiedStructType, ir.LiteralStructType)): return ElemPtr - return Gen._load(ElemPtr, name="subscript_val") - arr_alloc = Gen._allocaEntry(ValueVal.type, name="arr_subscript_tmp") + return self._load_arr_elem_with_bswap(Gen, ElemPtr, arr_byte_order) + arr_alloc: Any = Gen._allocaEntry(ValueVal.type, name="arr_subscript_tmp") Gen._store(ValueVal, arr_alloc) ElemPtr = Gen.builder.gep(arr_alloc, [zero, IndexVal], name="subscript") - alloc_arr_elem_type = ValueVal.type.element + alloc_arr_elem_type: Any = ValueVal.type.element if isinstance(alloc_arr_elem_type, (ir.IdentifiedStructType, ir.LiteralStructType)): return ElemPtr - return Gen._load(ElemPtr, name="subscript_val") + return self._load_arr_elem_with_bswap(Gen, ElemPtr, arr_byte_order) return None - def HandleSubscriptPtrLlvm(self, Node): - Gen = self.Trans.LlvmGen - ValueVal = self.HandleExprLlvm(Node.value) + def HandleSubscriptPtrLlvm(self, Node: ast.Subscript) -> ir.Value | None: + Gen: LlvmCodeGenerator = self.Trans.LlvmGen + ValueVal: Any = self.HandleExprLlvm(Node.value) if not ValueVal: return None - IndexVal = self.HandleExprLlvm(Node.slice) + IndexVal: Any = self.HandleExprLlvm(Node.slice) if not IndexVal: return None if isinstance(IndexVal.type, ir.PointerType) and isinstance(IndexVal.type.pointee, ir.IntType) and IndexVal.type.pointee.width == 8: - Loaded_byte = Gen._load(IndexVal, name="Load_char_idx_ptr") + Loaded_byte: Any = Gen._load(IndexVal, name="Load_char_idx_ptr") IndexVal = Gen.builder.zext(Loaded_byte, ir.IntType(32), name="char_to_int_idx_ptr") if isinstance(ValueVal.type, ir.PointerType): - pointee = ValueVal.type.pointee + pointee: Any = ValueVal.type.pointee if isinstance(pointee, ir.ArrayType): - zero = ir.Constant(ir.IntType(32), 0) + zero: ir.Constant = ir.Constant(ir.IntType(32), 0) if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width != 32: if IndexVal.type.width < 32: IndexVal = Gen.builder.zext(IndexVal, ir.IntType(32), name="zext_arr_index") else: IndexVal = Gen.builder.trunc(IndexVal, ir.IntType(32), name="trunc_arr_index") - ElemPtr = Gen.builder.gep(ValueVal, [zero, IndexVal], name="subscript_ptr") + ElemPtr: Any = Gen.builder.gep(ValueVal, [zero, IndexVal], name="subscript_ptr") return ElemPtr elif isinstance(pointee, ir.PointerType): if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width < 64: @@ -746,9 +788,9 @@ class ExprAttrHandle(BaseHandle): ElemPtr = Gen.builder.gep(ValueVal, [IndexVal], name="subscript_ptr") return ElemPtr elif isinstance(ValueVal.type, ir.IntType): - var_ptr = self._get_int_ptr(Node.value) + var_ptr: Any = self._get_int_ptr(Node.value) if var_ptr: - i8_ptr = Gen.builder.bitcast(var_ptr, ir.PointerType(ir.IntType(8)), name="int_to_i8ptr") + i8_ptr: Any = Gen.builder.bitcast(var_ptr, ir.PointerType(ir.IntType(8)), name="int_to_i8ptr") if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width < 64: IndexVal = Gen.builder.zext(IndexVal, ir.IntType(64), name="zext_int_index") ElemPtr = Gen.builder.gep(i8_ptr, [IndexVal], name="int_subscript_ptr") @@ -756,9 +798,9 @@ class ExprAttrHandle(BaseHandle): elif isinstance(ValueVal.type, ir.ArrayType): zero = ir.Constant(ir.IntType(32), 0) if isinstance(Node.value, ast.Name): - VarName = Node.value.id + VarName: str = Node.value.id if VarName in Gen.variables and Gen.variables[VarName] is not None: - VarPtr = Gen.variables[VarName] + VarPtr: Any = Gen.variables[VarName] if isinstance(VarPtr.type, ir.PointerType) and isinstance(VarPtr.type.pointee, ir.ArrayType): if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width != 32: if IndexVal.type.width < 32: @@ -768,7 +810,7 @@ class ExprAttrHandle(BaseHandle): ElemPtr = Gen.builder.gep(VarPtr, [zero, IndexVal], name="subscript_ptr") return ElemPtr if isinstance(Node.value, ast.Subscript): - InnerPtr = self.HandleSubscriptPtrLlvm(Node.value) + InnerPtr: Any = self.HandleSubscriptPtrLlvm(Node.value) if InnerPtr: if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width != 32: if IndexVal.type.width < 32: @@ -778,7 +820,7 @@ class ExprAttrHandle(BaseHandle): ElemPtr = Gen.builder.gep(InnerPtr, [zero, IndexVal], name="subscript_ptr") return ElemPtr if isinstance(Node.value, ast.Attribute): - AttrPtr = self._get_attr_ptr(Node.value) + AttrPtr: Any = self._get_attr_ptr(Node.value) if AttrPtr and isinstance(AttrPtr.type, ir.PointerType) and isinstance(AttrPtr.type.pointee, ir.ArrayType): if isinstance(IndexVal.type, ir.IntType) and IndexVal.type.width != 32: if IndexVal.type.width < 32: @@ -787,7 +829,7 @@ class ExprAttrHandle(BaseHandle): IndexVal = Gen.builder.trunc(IndexVal, ir.IntType(32), name="trunc_arr_index") ElemPtr = Gen.builder.gep(AttrPtr, [zero, IndexVal], name="subscript_ptr") return ElemPtr - arr_alloc = Gen._allocaEntry(ValueVal.type, name="arr_subscript_tmp") + arr_alloc: Any = Gen._allocaEntry(ValueVal.type, name="arr_subscript_tmp") Gen._store(ValueVal, arr_alloc) ElemPtr = Gen.builder.gep(arr_alloc, [zero, IndexVal], name="subscript_ptr") return ElemPtr @@ -795,54 +837,54 @@ class ExprAttrHandle(BaseHandle): # ========== _get_attr_ptr / _get_int_ptr / _get_attr_class ========== - def _get_attr_ptr(self, Node): - Gen = self.Trans.LlvmGen + def _get_attr_ptr(self, Node: ast.Attribute) -> ir.Value | None: + Gen: LlvmCodeGenerator = self.Trans.LlvmGen if not isinstance(Node, ast.Attribute): return None if isinstance(Node.value, ast.Name): - VarName = Node.value.id + VarName: str = Node.value.id if VarName == 'self': - ClassName = self.Trans._CurrentCpythonObjectClass + ClassName: str | None = self.Trans._CurrentCpythonObjectClass if ClassName: - offset = Gen._get_member_offset(Node.attr, ClassName) - SelfVar = Gen._get_var_ptr('self') + offset: int | None = Gen._get_member_offset(Node.attr, ClassName) + SelfVar: Any = Gen._get_var_ptr('self') if SelfVar: - SelfPtr = Gen._load(SelfVar, name="self") + SelfPtr: Any = Gen._load(SelfVar, name="self") if isinstance(SelfPtr.type, ir.PointerType): - MemberPtr = Gen.builder.gep(SelfPtr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=Node.attr) + MemberPtr: Any = Gen.builder.gep(SelfPtr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=Node.attr) return MemberPtr ClassName = Gen.var_struct_class.get(VarName) if not ClassName and getattr(Gen, 'global_struct_class', None): ClassName = Gen.global_struct_class.get(VarName) if not ClassName: - imported_modules = getattr(self.Trans, '_ImportedModules', None) - resolved_mod = self.Trans.SymbolTable.resolve_alias(VarName) + imported_modules: Any = getattr(self.Trans, '_ImportedModules', None) + resolved_mod: str = self.Trans.SymbolTable.resolve_alias(VarName) if imported_modules and (VarName in imported_modules or resolved_mod in imported_modules): - AttrName = Node.attr - ModuleSha1Map = getattr(Gen, 'ModuleSha1Map', {}) - candidates = [VarName, resolved_mod] + AttrName: str = Node.attr + ModuleSha1Map: Any = getattr(Gen, 'ModuleSha1Map', {}) + candidates: list[str] = [VarName, resolved_mod] for mod_name in imported_modules: if mod_name.endswith(f".{VarName}") or mod_name == VarName: if mod_name not in candidates: candidates.append(mod_name) for cand in candidates: - sha1 = ModuleSha1Map.get(cand) + sha1: str | None = ModuleSha1Map.get(cand) if sha1: - prefixed = f"{sha1}.{AttrName}" + prefixed: str = f"{sha1}.{AttrName}" if prefixed in Gen.module.globals: return Gen.module.globals[prefixed] if AttrName in Gen.module.globals: - gv = Gen.module.globals[AttrName] + gv: Any = Gen.module.globals[AttrName] if isinstance(gv, ir.GlobalVariable): return gv if ClassName and ClassName in Gen.structs: - VarPtr = Gen.variables.get(VarName) + VarPtr: Any = Gen.variables.get(VarName) if VarPtr: - ObjVal = VarPtr + ObjVal: Any = VarPtr if isinstance(ObjVal.type, ir.PointerType) and isinstance(ObjVal.type.pointee, ir.PointerType): ObjVal = Gen._load(ObjVal, name=f"Load_{VarName}") if isinstance(ObjVal.type, ir.PointerType) and ObjVal.type.pointee == Gen.structs[ClassName]: - ST = Gen.structs[ClassName] + ST: Any = Gen.structs[ClassName] if isinstance(ST, ir.IdentifiedStructType) and (ST.elements is None or len(ST.elements) == 0): self.Trans.ImportHandler._TryLoadStructFromStub(ClassName, Gen) ST = Gen.structs.get(ClassName, ST) @@ -853,12 +895,14 @@ class ExprAttrHandle(BaseHandle): MemberPtr = Gen.builder.gep(ObjVal, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=Node.attr) return MemberPtr elif isinstance(Node.value, ast.Attribute): - InnerPtr = self._get_attr_ptr(Node.value) + InnerPtr: Any = self._get_attr_ptr(Node.value) if InnerPtr and isinstance(InnerPtr.type, ir.PointerType): - pointee = InnerPtr.type.pointee + pointee: Any = InnerPtr.type.pointee if isinstance(pointee, (ir.IdentifiedStructType, ir.LiteralStructType)): - found = Gen.find_struct_by_pointee(pointee) + found: Any = Gen.find_struct_by_pointee(pointee) if found: + CN: str + ST: Any CN, ST = found if isinstance(ST, ir.IdentifiedStructType) and (ST.elements is None or len(ST.elements) == 0): self.Trans.ImportHandler._TryLoadStructFromStub(CN, Gen) @@ -870,15 +914,15 @@ class ExprAttrHandle(BaseHandle): MemberPtr = Gen.builder.gep(InnerPtr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=Node.attr) return MemberPtr elif isinstance(pointee, ir.IntType) and pointee.width == 8: - AttrClassName = self._get_attr_class(Node.value, Gen) + AttrClassName: str | None = self._get_attr_class(Node.value, Gen) if AttrClassName and AttrClassName in Gen.structs: - CastedObj = Gen.builder.bitcast(InnerPtr, ir.PointerType(Gen.structs[AttrClassName]), name=f"cast_{AttrClassName}") + CastedObj: Any = Gen.builder.bitcast(InnerPtr, ir.PointerType(Gen.structs[AttrClassName]), name=f"cast_{AttrClassName}") offset = Gen._get_member_offset(Node.attr, AttrClassName) if offset is not None: MemberPtr = Gen.builder.gep(CastedObj, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=Node.attr) return MemberPtr elif isinstance(Node.value, ast.Subscript): - SubPtr = self.HandleSubscriptPtrLlvm(Node.value) + SubPtr: Any = self.HandleSubscriptPtrLlvm(Node.value) if SubPtr and isinstance(SubPtr.type, ir.PointerType): pointee = SubPtr.type.pointee if isinstance(pointee, (ir.IdentifiedStructType, ir.LiteralStructType)): @@ -891,11 +935,11 @@ class ExprAttrHandle(BaseHandle): return MemberPtr return None - def _HandleSliceLlvm(self, base_val, slice_node, base_ast): - Gen = self.Trans.LlvmGen - lower_val = None - upper_val = None - step_val = None + def _HandleSliceLlvm(self, base_val: ir.Value, slice_node: ast.Slice | ast.Index, base_ast: ast.AST) -> ir.Value | None: + Gen: LlvmCodeGenerator = self.Trans.LlvmGen + lower_val: Any = None + upper_val: Any = None + step_val: Any = None if isinstance(slice_node, ast.Slice): if slice_node.lower: lower_val = self.HandleExprLlvm(slice_node.lower) @@ -907,68 +951,68 @@ class ExprAttrHandle(BaseHandle): return self.HandleExprLlvm(slice_node.value) return None - def _infer_element_struct_class(self, node, Gen): + def _infer_element_struct_class(self, node: ast.AST, Gen: LlvmCodeGenerator) -> str | None: if isinstance(node, ast.Attribute): - attr_name = node.attr + attr_name: str = node.attr if isinstance(node.value, ast.Name) and node.value.id == 'self': - current_class = self.Trans._CurrentCpythonObjectClass + current_class: str | None = self.Trans._CurrentCpythonObjectClass if current_class: if current_class in Gen.class_member_element_class: - elem_class = Gen.class_member_element_class[current_class].get(attr_name) + elem_class: str | None = Gen.class_member_element_class[current_class].get(attr_name) if elem_class and elem_class in Gen.structs: return elem_class if current_class in Gen.class_members: for member_name, member_type in Gen.class_members[current_class]: if member_name == attr_name: if isinstance(member_type, ir.IdentifiedStructType): - found = Gen.find_struct_by_pointee(member_type) + found: Any = Gen.find_struct_by_pointee(member_type) if found: return found[0] break - class_name = Gen.var_struct_class.get(attr_name) + class_name: str | None = Gen.var_struct_class.get(attr_name) if class_name: return class_name elif isinstance(node, ast.Name): - var_name = node.id + var_name: str = node.id class_name = Gen.var_struct_class.get(var_name) if class_name: return class_name return None - def _get_int_ptr(self, target): - Gen = self.Trans.LlvmGen + def _get_int_ptr(self, target: ast.AST) -> ir.Value | None: + Gen: LlvmCodeGenerator = self.Trans.LlvmGen if isinstance(target, ast.Name): - VarName = target.id + VarName: str = target.id if VarName in Gen.variables and Gen.variables[VarName] is not None: - VarPtr = Gen.variables[VarName] + VarPtr: Any = Gen.variables[VarName] if isinstance(VarPtr.type, ir.PointerType): - pointee = VarPtr.type.pointee + pointee: Any = VarPtr.type.pointee if isinstance(pointee, ir.ArrayType): return Gen.builder.gep(VarPtr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), 0)], name=f"arr_start_{VarName}") return VarPtr elif isinstance(target, ast.Attribute): if isinstance(target.value, ast.Name): - obj_name = target.value.id + obj_name: str = target.value.id if obj_name in Gen.variables and Gen.variables[obj_name] is not None: - obj_ptr = Gen.variables[obj_name] + obj_ptr: Any = Gen.variables[obj_name] if isinstance(obj_ptr.type, ir.PointerType): pointee = obj_ptr.type.pointee if isinstance(pointee, ir.PointerType): obj_ptr = Gen._load(obj_ptr, name=f"Load_{obj_name}") pointee = obj_ptr.type.pointee if isinstance(pointee, (ir.IdentifiedStructType, ir.LiteralStructType)): - StructName = None + StructName: str | None = None if isinstance(pointee, ir.IdentifiedStructType): StructName = pointee.name if not StructName: - found = Gen.find_struct_by_pointee(pointee) + found: Any = Gen.find_struct_by_pointee(pointee) if found: StructName = found[0] if StructName and StructName in Gen.structs: - offset = Gen._get_member_offset(target.attr, StructName) + offset: int | None = Gen._get_member_offset(target.attr, StructName) if offset is not None: return Gen.builder.gep(obj_ptr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=f"{target.attr}_ptr") - obj_val = self.HandleExprLlvm(target.value) + obj_val: Any = self.HandleExprLlvm(target.value) if obj_val and isinstance(obj_val.type, ir.PointerType): if isinstance(obj_val.type.pointee, ir.PointerType): obj_val = Gen._load(obj_val, name="Load_attr_ptr") @@ -987,39 +1031,39 @@ class ExprAttrHandle(BaseHandle): return Gen.builder.gep(obj_val, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=f"{target.attr}_ptr") return None - def _resolve_struct_class_for_attr(self, Node, Gen): + def _resolve_struct_class_for_attr(self, Node: ast.AST, Gen: LlvmCodeGenerator) -> str | None: if isinstance(Node, ast.Name): - VarName = Node.id + VarName: str = Node.id if VarName in Gen.var_struct_class: return Gen.var_struct_class[VarName] elif isinstance(Node, ast.Attribute): - ClassName = self._resolve_struct_class_for_attr(Node.value, Gen) + ClassName: str | None = self._resolve_struct_class_for_attr(Node.value, Gen) if ClassName and ClassName in Gen.class_members: for member_name, _ in Gen.class_members[ClassName]: if member_name == Node.attr: return ClassName return None - def _infer_array_member_type(self, Node, Gen): + def _infer_array_member_type(self, Node: ast.AST, Gen: LlvmCodeGenerator) -> ir.ArrayType | None: if isinstance(Node, ast.Attribute): - parent_class = self._get_attr_class(Node, Gen) + parent_class: str | None = self._get_attr_class(Node, Gen) if parent_class and parent_class in Gen.class_members: for m_name, m_type in Gen.class_members[parent_class]: if m_name == Node.attr and isinstance(m_type, ir.ArrayType): return m_type if parent_class and parent_class in Gen.structs: - st = Gen.structs[parent_class] + st: Any = Gen.structs[parent_class] if isinstance(st, ir.IdentifiedStructType) and st.elements is not None: - offset = Gen._get_member_offset(Node.attr, parent_class) + offset: int | None = Gen._get_member_offset(Node.attr, parent_class) if offset is not None and offset < len(st.elements): - elem = st.elements[offset] + elem: Any = st.elements[offset] if isinstance(elem, ir.ArrayType): return elem return None - def _build_attr_path(self, node): - parts = [] - current = node + def _build_attr_path(self, node: ast.AST) -> list[str]: + parts: list[str] = [] + current: ast.AST = node while isinstance(current, ast.Attribute): parts.append(current.attr) current = current.value @@ -1028,29 +1072,29 @@ class ExprAttrHandle(BaseHandle): parts.reverse() return parts - def _try_resolve_nested_cdefine(self, Node): - Gen = self.Trans.LlvmGen - imported_modules = getattr(self.Trans, '_ImportedModules', None) + def _try_resolve_nested_cdefine(self, Node: ast.Attribute) -> ir.Value | None: + Gen: LlvmCodeGenerator = self.Trans.LlvmGen + imported_modules: Any = getattr(self.Trans, '_ImportedModules', None) if not imported_modules: return None - parts = self._build_attr_path(Node) + parts: list[str] = self._build_attr_path(Node) if len(parts) < 2: return None - attr_name = parts[-1] - module_parts = parts[:-1] - possible_keys = [attr_name] - full_path = '.'.join(parts) + attr_name: str = parts[-1] + module_parts: list[str] = parts[:-1] + possible_keys: list[str] = [attr_name] + full_path: str = '.'.join(parts) possible_keys.append(full_path) if module_parts: - ModulePath = '.'.join(module_parts) - resolved_first = self.Trans.SymbolTable.resolve_alias(module_parts[0]) + ModulePath: str = '.'.join(module_parts) + resolved_first: str = self.Trans.SymbolTable.resolve_alias(module_parts[0]) if resolved_first != module_parts[0]: - resolved_parts = [resolved_first] + module_parts[1:] - resolved_path = '.'.join(resolved_parts) + resolved_parts: list[str] = [resolved_first] + module_parts[1:] + resolved_path: str = '.'.join(resolved_parts) possible_keys.append(f"{resolved_path}.{attr_name}") for mod_name in imported_modules: if mod_name.endswith('.' + ModulePath) or mod_name == ModulePath: - key = f"{mod_name}.{attr_name}" + key: str = f"{mod_name}.{attr_name}" if key not in possible_keys: possible_keys.append(key) if module_parts and (mod_name.endswith('.' + module_parts[-1]) or mod_name == module_parts[-1]): @@ -1058,9 +1102,9 @@ class ExprAttrHandle(BaseHandle): if key not in possible_keys: possible_keys.append(key) for lookup_key in possible_keys: - SymInfo = self.Trans.SymbolTable.lookup(lookup_key) + SymInfo: Any = self.Trans.SymbolTable.lookup(lookup_key) if SymInfo and SymInfo.IsDefine and SymInfo.DefineValue is not None: - val = SymInfo.DefineValue + val: Any = SymInfo.DefineValue if isinstance(val, int): if val > 0x7FFFFFFF or val < -0x80000000: return ir.Constant(ir.IntType(64), val & 0xFFFFFFFFFFFFFFFF) @@ -1069,24 +1113,23 @@ class ExprAttrHandle(BaseHandle): return ir.Constant(ir.FloatType(), val) return None - def _try_resolve_cross_module_enum(self, module_alias, enum_class_name, member_name): - Gen = self.Trans.LlvmGen - imported_modules = getattr(self.Trans, '_ImportedModules', None) + def _try_resolve_cross_module_enum(self, module_alias: str, enum_class_name: str, member_name: str) -> ir.Value | None: + Gen: LlvmCodeGenerator = self.Trans.LlvmGen + imported_modules: Any = getattr(self.Trans, '_ImportedModules', None) if not imported_modules: return None - resolved_module = self.Trans.SymbolTable.resolve_alias(module_alias) + resolved_module: str = self.Trans.SymbolTable.resolve_alias(module_alias) if resolved_module not in imported_modules and module_alias not in imported_modules: return None - enum_keys = [enum_class_name, f"{resolved_module}.{enum_class_name}"] + enum_keys: list[str] = [enum_class_name, f"{resolved_module}.{enum_class_name}"] for enum_key in enum_keys: - if self.Trans.SymbolTable.has(enum_key): - SymInfo = self.Trans.SymbolTable[enum_key] + SymInfo: Any = self.Trans.SymbolTable.lookup(enum_key) + if SymInfo: if SymInfo.IsEnum: for qname in (f"{enum_key}.{member_name}", f"{enum_key}_{member_name}"): - if self.Trans.SymbolTable.has(qname): - info = self.Trans.SymbolTable[qname] - if info.IsEnumMember and isinstance(info.value, int): - return ir.Constant(ir.IntType(32), info.value) + info: Any = self.Trans.SymbolTable.lookup(qname) + if info and info.IsEnumMember and isinstance(info.value, int): + return ir.Constant(ir.IntType(32), info.value) for key, info in self.Trans.SymbolTable.items(): if info.IsEnumMember and info.EnumName == enum_key and key == member_name: if isinstance(info.value, int): @@ -1099,17 +1142,17 @@ class ExprAttrHandle(BaseHandle): return ir.Constant(ir.IntType(32), info.value) return None - def _get_attr_class(self, Node, Gen): + def _get_attr_class(self, Node: ast.AST, Gen: LlvmCodeGenerator) -> str | None: if isinstance(Node, ast.Attribute): # 注: 不再硬编码 ZLIB_VERSION / C_OK,它们应从符号表查找 if isinstance(Node.value, ast.Name) and Node.value.id == 'self': - ClassName = self.Trans._CurrentCpythonObjectClass + ClassName: str | None = self.Trans._CurrentCpythonObjectClass if ClassName and ClassName in Gen.class_member_element_class: return Gen.class_member_element_class[ClassName].get(Node.attr) if isinstance(Node.value, ast.Name): - VarName = Node.value.id + VarName: str = Node.value.id if VarName in Gen.var_struct_class: - ParentClass = Gen.var_struct_class[VarName] + ParentClass: str = Gen.var_struct_class[VarName] if ParentClass in Gen.class_member_element_class: return Gen.class_member_element_class[ParentClass].get(Node.attr) if isinstance(Node.value, ast.Attribute): @@ -1118,38 +1161,38 @@ class ExprAttrHandle(BaseHandle): return Gen.class_member_element_class[ParentClass].get(Node.attr) return None - def _get_llvm_member_offset(self, field_name, ClassName, Gen): + def _get_llvm_member_offset(self, field_name: str, ClassName: str, Gen: LlvmCodeGenerator) -> int | None: return Gen._get_member_offset(field_name, ClassName) - def _Load_bitfield_member(self, struct_ptr, ClassName, field_name): - Gen = self.Trans.LlvmGen - bitfield_offsets = Gen.class_member_bitoffsets.get(ClassName, {}) - bitfield_widths = Gen.class_member_bitfields.get(ClassName, {}) + def _Load_bitfield_member(self, struct_ptr: ir.Value, ClassName: str, field_name: str) -> ir.Value | None: + Gen: LlvmCodeGenerator = self.Trans.LlvmGen + bitfield_offsets: Any = Gen.class_member_bitoffsets.get(ClassName, {}) + bitfield_widths: Any = Gen.class_member_bitfields.get(ClassName, {}) if field_name not in bitfield_offsets: return None - bit_offset = bitfield_offsets[field_name] - bit_width = bitfield_widths.get(field_name, 0) + bit_offset: int = bitfield_offsets[field_name] + bit_width: int = bitfield_widths.get(field_name, 0) if bit_width == 0: return None - struct_type = Gen.structs.get(ClassName) + struct_type: Any = Gen.structs.get(ClassName) if struct_type is None or struct_type.elements is None or len(struct_type.elements) == 0: return None - storage_type = struct_type.elements[0] - member_ptr = Gen.builder.gep(struct_ptr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), 0)], name=f"{field_name}_storage_ptr") - storage_val = Gen._load(member_ptr, name=f"{field_name}_storage") - shift_amount = bit_offset + storage_type: Any = struct_type.elements[0] + member_ptr: Any = Gen.builder.gep(struct_ptr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), 0)], name=f"{field_name}_storage_ptr") + storage_val: Any = Gen._load(member_ptr, name=f"{field_name}_storage") + shift_amount: int = bit_offset if shift_amount > 0: - shifted = Gen.builder.lshr(storage_val, ir.Constant(storage_type, shift_amount), name=f"{field_name}_shift") + shifted: Any = Gen.builder.lshr(storage_val, ir.Constant(storage_type, shift_amount), name=f"{field_name}_shift") else: shifted = storage_val - mask = (1 << bit_width) - 1 - masked = Gen.builder.and_(shifted, ir.Constant(storage_type, mask), name=f"{field_name}_mask") - is_signed = Gen.class_member_signeds.get(ClassName, {}).get(field_name, False) + mask: int = (1 << bit_width) - 1 + masked: Any = Gen.builder.and_(shifted, ir.Constant(storage_type, mask), name=f"{field_name}_mask") + is_signed: bool = Gen.class_member_signeds.get(ClassName, {}).get(field_name, False) if is_signed and bit_width > 0: - sign_bit = 1 << (bit_width - 1) - sign_masked = Gen.builder.and_(shifted, ir.Constant(storage_type, sign_bit), name=f"{field_name}_sign") - sign_extend = Gen.builder.icmp_signed('!=', sign_masked, ir.Constant(storage_type, 0), name=f"{field_name}_sign_check") - extended = Gen.builder.select(sign_extend, + sign_bit: int = 1 << (bit_width - 1) + sign_masked: Any = Gen.builder.and_(shifted, ir.Constant(storage_type, sign_bit), name=f"{field_name}_sign") + sign_extend: Any = Gen.builder.icmp_signed('!=', sign_masked, ir.Constant(storage_type, 0), name=f"{field_name}_sign_check") + extended: Any = Gen.builder.select(sign_extend, Gen.builder.sext(masked, ir.IntType(32), name=f"{field_name}_sext"), Gen.builder.zext(masked, ir.IntType(32), name=f"{field_name}_zext"), name=f"{field_name}_extend") diff --git a/lib/core/Handles/HandlesExprBuiltin.py b/lib/core/Handles/HandlesExprBuiltin.py index 1388d13..0969a26 100644 --- a/lib/core/Handles/HandlesExprBuiltin.py +++ b/lib/core/Handles/HandlesExprBuiltin.py @@ -2,13 +2,18 @@ from __future__ import annotations from typing import TYPE_CHECKING if TYPE_CHECKING: from lib.core.translator import Translator -from lib.core.Handles.HandlesBase import BaseHandle + from lib.core.Translator.LlvmGenerator import LlvmGeneratorMixin import ast import llvmlite.ir as ir +from lib.core.Handles.HandlesBase import BaseHandle +from lib.core.VLogger import get_logger as _vlog +from lib.constants.config import mode as _config_mode +from lib.includes.t import CTypeRegistry +from lib.core.SymbolUtils import IsTModule, ExtractTypeNameFromBinOp class ExprBuiltinHandle(BaseHandle): - _C_LIB_FUNCS = { + _C_LIB_FUNCS: dict[str, object] = { 'strlen': lambda: (ir.IntType(64), [ir.PointerType(ir.IntType(8))]), 'strlength': lambda: (ir.IntType(64), [ir.PointerType(ir.IntType(8))]), 'memset': lambda: (ir.PointerType(ir.IntType(8)), [ir.PointerType(ir.IntType(8)), ir.IntType(32), ir.IntType(64)]), @@ -27,11 +32,11 @@ class ExprBuiltinHandle(BaseHandle): 'labs': lambda: (ir.IntType(64), [ir.IntType(64)]), } - def _HandleBuiltinCallLlvm(self, Node): - Gen = self.Trans.LlvmGen + def _HandleBuiltinCallLlvm(self, Node: ast.Call) -> ir.Value | None: + Gen: LlvmGeneratorMixin = self.Trans.LlvmGen if not isinstance(Node.func, ast.Name): return None - FuncName = Node.func.id + FuncName: str = Node.func.id if FuncName == 'print': return self._HandlePrintLlvm(Node) @@ -145,6 +150,19 @@ class ExprBuiltinHandle(BaseHandle): return arg_val return self._EmitStringFromValue(arg_val) return ir.Constant(ir.IntType(8).as_pointer(), None) + elif FuncName == 'bytes': + # bytes() — 类型转换为 i8* 指针 (等同于 t.CPtr / str) + # bytes(int_addr) → inttoptr; bytes(ptr) → bitcast + if Node.args: + arg_val = self.HandleExprLlvm(Node.args[0]) + if arg_val: + if isinstance(arg_val.type, ir.PointerType): + if isinstance(arg_val.type.pointee, ir.IntType) and arg_val.type.pointee.width == 8: + return arg_val + return Gen.builder.bitcast(arg_val, ir.IntType(8).as_pointer(), name="bytes_cast") + if isinstance(arg_val.type, ir.IntType): + return Gen.builder.inttoptr(arg_val, ir.IntType(8).as_pointer(), name="bytes_int2ptr") + return ir.Constant(ir.IntType(8).as_pointer(), None) elif FuncName == 'input': return self._HandleInputLlvm(Node) elif FuncName == 'ord': @@ -177,22 +195,22 @@ class ExprBuiltinHandle(BaseHandle): return self._HandleTypeLlvm(Node) return None - def _HandlePrintLlvm(self, Node): - Gen = self.Trans.LlvmGen - printf_func = Gen.get_or_declare_c_func('printf', ir.FunctionType(ir.IntType(32), [ir.PointerType(ir.IntType(8))], var_arg=True)) - args = Node.args - end_arg = None - sep_arg = None + def _HandlePrintLlvm(self, Node: ast.Call) -> ir.Value | None: + Gen: LlvmGeneratorMixin = self.Trans.LlvmGen + printf_func: ir.Function = Gen.get_or_declare_c_func('printf', ir.FunctionType(ir.IntType(32), [ir.PointerType(ir.IntType(8))], var_arg=True)) + args: list[ast.expr] = Node.args + end_arg: ast.expr | None = None + sep_arg: ast.expr | None = None if Node.keywords: for kw in Node.keywords: if kw.arg == 'end': end_arg = kw.value elif kw.arg == 'sep': sep_arg = kw.value - sep_str = ' ' + sep_str: str = ' ' if sep_arg and isinstance(sep_arg, ast.Constant) and isinstance(sep_arg.value, str): sep_str = sep_arg.value - end_str = '\n' + end_str: str = '\n' if end_arg: if isinstance(end_arg, ast.Constant) and isinstance(end_arg.value, str): end_str = end_arg.value @@ -202,11 +220,10 @@ class ExprBuiltinHandle(BaseHandle): if end_str: nl_fmt = Gen.emit_constant(end_str, 'string') Gen.builder.call(printf_func, [nl_fmt], name="print_nl") - return + return ir.Constant(ir.IntType(32), 0) has_fstring = any(isinstance(arg, ast.JoinedStr) for arg in args) if has_fstring: - self._HandlePrintWithFString(Node, printf_func, args, sep_str, end_str) - return + return self._HandlePrintWithFString(Node, printf_func, args, sep_str, end_str) fmt_parts = [] fmt_args = [] for i, arg in enumerate(args): @@ -288,25 +305,20 @@ class ExprBuiltinHandle(BaseHandle): fmt_parts.append('(unknown)') fmt_parts.append(end_str) fmt_str = ''.join(fmt_parts) - fmt_bytes = fmt_str.encode('utf-8') + b'\x00' - fmt_type = ir.ArrayType(ir.IntType(8), len(fmt_bytes)) - fmt_const = ir.Constant(fmt_type, bytearray(fmt_bytes)) - fmt_gvar = ir.GlobalVariable(Gen.module, fmt_type, name=f"str_const_{Gen.string_const_counter}") - Gen.string_const_counter += 1 - fmt_gvar.initializer = fmt_const - fmt_gvar.linkage = 'internal' - fmt_ptr = Gen.builder.bitcast(fmt_gvar, ir.PointerType(ir.IntType(8)), name="print_fmt") + fmt_ptr = Gen._create_string_global(fmt_str) call_args = [fmt_ptr] + fmt_args return Gen.builder.call(printf_func, call_args, name="print_call") - def _HandlePrintWithFString(self, Node, printf_func, args, sep_str, end_str): - Gen = self.Trans.LlvmGen + def _HandlePrintWithFString(self, Node: ast.Call, printf_func: ir.Function, args: list[ast.expr], sep_str: str, end_str: str) -> ir.Value | None: + Gen: LlvmGeneratorMixin = self.Trans.LlvmGen for i, arg in enumerate(args): if i > 0: sep_const = Gen.emit_constant(sep_str, 'string') Gen.builder.call(printf_func, [sep_const], name="print_sep") if isinstance(arg, ast.JoinedStr): - self.HandleExprLlvm(arg) + str_val = self.HandleExprLlvm(arg) + if str_val: + Gen._emit_printf([str_val], unsigned_flags=[False], sep=None, end=None) else: ClassName = self.Trans.ExprHandler._get_var_class(arg, Gen) if ClassName and Gen._has_function(f'{ClassName}.__str__'): @@ -327,7 +339,7 @@ class ExprBuiltinHandle(BaseHandle): try: val = Gen._load(val, name="print_Load") except Exception as _e: - if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": + if _config_mode == "strict": self.Trans.LogWarning(f"异常被忽略: {_e}") is_u = Gen._check_node_unsigned(arg) if not is_u and id(val) in Gen._unsigned_results: @@ -338,7 +350,7 @@ class ExprBuiltinHandle(BaseHandle): Gen.builder.call(printf_func, [end_const], name="print_end") return ir.Constant(ir.IntType(32), 0) - def _is_char_type(self, arg_node): + def _is_char_type(self, arg_node: ast.AST) -> bool: if isinstance(arg_node, ast.Call): if isinstance(arg_node.func, ast.Name): return arg_node.func.id in ('CChar', 'CUInt8T', 'CInt8T') @@ -346,11 +358,11 @@ class ExprBuiltinHandle(BaseHandle): return arg_node.func.attr in ('CChar', 'CUInt8T', 'CInt8T') return False - def _is_val_unsigned(self, arg_node, val): - Gen = self.Trans.LlvmGen + def _is_val_unsigned(self, arg_node: ast.AST, val: ir.Value) -> bool: + Gen: LlvmGeneratorMixin = self.Trans.LlvmGen if isinstance(arg_node, ast.Name): - var_name = arg_node.id - signedness = Gen.var_signedness.get(var_name) + var_name: str = arg_node.id + signedness: object = Gen.var_signedness.get(var_name) if signedness: if isinstance(signedness, bool): return signedness @@ -359,17 +371,19 @@ class ExprBuiltinHandle(BaseHandle): return False return False - def _try_declare_c_lib_func(self, func_name, Gen): + def _try_declare_c_lib_func(self, func_name: str, Gen: LlvmGeneratorMixin) -> ir.Function | None: if func_name not in self._C_LIB_FUNCS: return None + ret_type: ir.Type + param_types: list[ir.Type] ret_type, param_types = self._C_LIB_FUNCS[func_name]() - func_type = ir.FunctionType(ret_type, param_types) - func = ir.Function(Gen.module, func_type, name=func_name) + func_type: ir.FunctionType = ir.FunctionType(ret_type, param_types) + func: ir.Function = ir.Function(Gen.module, func_type, name=func_name) Gen.functions[func_name] = func return func - def _HandleLenLlvm(self, arg_node): - Gen = self.Trans.LlvmGen + def _HandleLenLlvm(self, arg_node: ast.AST) -> ir.Value | None: + Gen: LlvmGeneratorMixin = self.Trans.LlvmGen if isinstance(arg_node, ast.Attribute) and isinstance(arg_node.value, ast.Name) and arg_node.value.id == 'self': attr_name = arg_node.attr len_member = f'{attr_name}__len' @@ -415,7 +429,7 @@ class ExprBuiltinHandle(BaseHandle): strlen_func = ir.Function(Gen.module, correct_strlen_type, name='strlen') Gen.functions['strlen'] = strlen_func except Exception as _e: - if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": + if _config_mode == "strict": self.Trans.LogWarning(f"异常被忽略: {_e}") if strlen_func: result = Gen.builder.call(strlen_func, [val], name="strlen_call") @@ -424,8 +438,39 @@ class ExprBuiltinHandle(BaseHandle): return ir.Constant(ir.IntType(64), val.type.count) return ir.Constant(ir.IntType(64), 0) - def _HandleSizeofLlvm(self, Node): - Gen = self.Trans.LlvmGen + def _resolve_nested_opaque_structs(self, struct_type: ir.Type, Gen: LlvmGeneratorMixin, visited: set | None = None) -> None: + """递归解析嵌套的 opaque struct,从 stub 文件中加载其定义""" + if visited is None: + visited = set() + if isinstance(struct_type, ir.PointerType): + self._resolve_nested_opaque_structs(struct_type.pointee, Gen, visited) + return + if not isinstance(struct_type, ir.IdentifiedStructType): + return + if struct_type in visited: + return + visited.add(struct_type) + if struct_type.elements is None or len(struct_type.elements) == 0: + # 尝试从 stub 加载 opaque struct + try: + st_name = struct_type.name + except Exception: + st_name = None + if st_name: + # 提取短名称(去掉模块前缀) + if '.' in st_name: + short_name = st_name.split('.', 1)[1] + else: + short_name = st_name + self.Trans.ImportHandler._TryLoadStructFromStub(short_name, Gen) + return + # 递归解析嵌套的 struct 成员 + for elem in struct_type.elements: + self._resolve_nested_opaque_structs(elem, Gen, visited) + + def _HandleSizeofLlvm(self, Node: ast.AST) -> ir.Value: + Gen: LlvmGeneratorMixin = self.Trans.LlvmGen + type_name: str | None if isinstance(Node, ast.Name): type_name = Node.id elif isinstance(Node, ast.Attribute): @@ -434,7 +479,9 @@ class ExprBuiltinHandle(BaseHandle): return ir.Constant(ir.IntType(64), 0) if type_name not in Gen.structs: - from lib.includes.t import CTypeRegistry + # str/bytes 是指针类型 (char*/void*),sizeof = 指针大小 + if type_name in ('str', 'bytes'): + return ir.Constant(ir.IntType(64), 8) ctype_cls = CTypeRegistry.GetClassByName(type_name) if ctype_cls is not None: try: @@ -443,8 +490,6 @@ class ExprBuiltinHandle(BaseHandle): size_bytes = size_bits // 8 return ir.Constant(ir.IntType(64), size_bytes) except Exception as _e: - from lib.core.VLogger import get_logger as _vlog - from lib.constants.config import mode as _config_mode if _config_mode == "strict": raise _vlog().warning(f"解析类型失败: {_e}", "Exception") @@ -459,8 +504,6 @@ class ExprBuiltinHandle(BaseHandle): size_bytes = 8 return ir.Constant(ir.IntType(64), size_bytes) except Exception as _e: - from lib.core.VLogger import get_logger as _vlog - from lib.constants.config import mode as _config_mode if _config_mode == "strict": raise _vlog().warning(f"解析类型失败: {_e}", "Exception") @@ -472,14 +515,16 @@ class ExprBuiltinHandle(BaseHandle): if isinstance(struct_type, ir.IdentifiedStructType) and (struct_type.elements is None or len(struct_type.elements) == 0): self.Trans.ImportHandler._TryLoadStructFromStub(type_name, Gen) struct_type = Gen.structs.get(type_name, struct_type) + # 递归解析所有嵌套的 opaque struct,确保 sizeof 计算正确 + self._resolve_nested_opaque_structs(struct_type, Gen) size = Gen._get_struct_size(struct_type) if size > 0: return ir.Constant(ir.IntType(64), size) return ir.Constant(ir.IntType(64), 0) - def _HandleAbsLlvm(self, arg_node): - Gen = self.Trans.LlvmGen - val = self.HandleExprLlvm(arg_node) + def _HandleAbsLlvm(self, arg_node: ast.AST) -> ir.Value | None: + Gen: LlvmGeneratorMixin = self.Trans.LlvmGen + val: ir.Value | None = self.HandleExprLlvm(arg_node) if not val: return None if isinstance(val.type, ir.PointerType): @@ -502,19 +547,20 @@ class ExprBuiltinHandle(BaseHandle): return Gen.builder.select(is_neg, neg_val, val, name="fabs_result") return None - def _HandleDirLlvm(self, Node): - Gen = self.Trans.LlvmGen + def _HandleDirLlvm(self, Node: ast.Call) -> ir.Value: + Gen: LlvmGeneratorMixin = self.Trans.LlvmGen return ir.Constant(ir.IntType(8).as_pointer(), None) - def _HandleTypeLlvm(self, Node): - Gen = self.Trans.LlvmGen + def _HandleTypeLlvm(self, Node: ast.Call) -> ir.Value: + Gen: LlvmGeneratorMixin = self.Trans.LlvmGen + type_str: str if not Node.args: type_str = "" else: arg = Node.args[0] enum_type_name = None - def _get_attr_path(node): + def _get_attr_path(node: ast.AST) -> str | None: if isinstance(node, ast.Name): return node.id elif isinstance(node, ast.Attribute): @@ -578,8 +624,8 @@ class ExprBuiltinHandle(BaseHandle): type_str = f"" return Gen.emit_constant(type_str, 'string') - def _HandleInputLlvm(self, Node): - Gen = self.Trans.LlvmGen + def _HandleInputLlvm(self, Node: ast.Call) -> ir.Value: + Gen: LlvmGeneratorMixin = self.Trans.LlvmGen if Node.args and isinstance(Node.args[0], ast.Constant) and isinstance(Node.args[0].value, str): prompt = Node.args[0].value prompt_ptr = Gen.emit_constant(prompt, 'string') @@ -590,29 +636,29 @@ class ExprBuiltinHandle(BaseHandle): result = Gen.builder.call(scanf_func, [Gen.emit_constant("%255s", 'string'), input_buffer]) return Gen.builder.gep(input_buffer, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), 0)], name="input_result") - def _HandleAtoiLlvm(self, str_ptr): - Gen = self.Trans.LlvmGen - atoi_func = Gen.get_or_declare_c_func('atoi', ir.FunctionType(ir.IntType(32), [ir.PointerType(ir.IntType(8))])) + def _HandleAtoiLlvm(self, str_ptr: ir.Value) -> ir.Value: + Gen: LlvmGeneratorMixin = self.Trans.LlvmGen + atoi_func: ir.Function = Gen.get_or_declare_c_func('atoi', ir.FunctionType(ir.IntType(32), [ir.PointerType(ir.IntType(8))])) return Gen.builder.call(atoi_func, [str_ptr], name="atoi_result") - def _HandleOrdLlvm(self, expr_node): - Gen = self.Trans.LlvmGen - val = self.HandleExprLlvm(expr_node) + def _HandleOrdLlvm(self, expr_node: ast.AST) -> ir.Value: + Gen: LlvmGeneratorMixin = self.Trans.LlvmGen + val: ir.Value | None = self.HandleExprLlvm(expr_node) if val and isinstance(val.type, ir.PointerType) and isinstance(val.type.pointee, ir.IntType) and val.type.pointee.width == 8: return Gen._load(val, name="ord_result") return ir.Constant(ir.IntType(32), 0) - def _HandleChrLlvm(self, expr_node): - Gen = self.Trans.LlvmGen - val = self.HandleExprLlvm(expr_node) + def _HandleChrLlvm(self, expr_node: ast.AST) -> ir.Value: + Gen: LlvmGeneratorMixin = self.Trans.LlvmGen + val: ir.Value | None = self.HandleExprLlvm(expr_node) if val: char_ptr = Gen._alloca(ir.IntType(8), name="chr_char") Gen.builder.store(Gen.builder.trunc(val, ir.IntType(8), name="trunc_chr"), char_ptr) return Gen.builder.gep(char_ptr, [ir.Constant(ir.IntType(32), 0)], name="chr_result") return ir.Constant(ir.IntType(8).as_pointer(), None) - def _EmitStringFromValue(self, val): - Gen = self.Trans.LlvmGen + def _EmitStringFromValue(self, val: ir.Value) -> ir.Value: + Gen: LlvmGeneratorMixin = self.Trans.LlvmGen if isinstance(val.type, ir.IntType): if val.type.width == 8: buf = Gen._alloca(ir.IntType(8), name="str_buf", size=ir.Constant(ir.IntType(32), 2)) @@ -631,12 +677,12 @@ class ExprBuiltinHandle(BaseHandle): return Gen.builder.gep(buf, [ir.Constant(ir.IntType(32), 0)], name="str_result") return ir.Constant(ir.IntType(8).as_pointer(), None) - def _HandleMallocLlvm(self, args): - Gen = self.Trans.LlvmGen - malloc_type = ir.FunctionType(ir.PointerType(ir.IntType(8)), [ir.IntType(64)]) - malloc_func = Gen._get_or_declare_func('malloc', malloc_type) - param_type = malloc_func.type.pointee.args[0] - size_val = None + def _HandleMallocLlvm(self, args: list[ast.expr]) -> ir.Value: + Gen: LlvmGeneratorMixin = self.Trans.LlvmGen + malloc_type: ir.FunctionType = ir.FunctionType(ir.PointerType(ir.IntType(8)), [ir.IntType(64)]) + malloc_func: ir.Function = Gen._get_or_declare_func('malloc', malloc_type) + param_type: ir.Type = malloc_func.type.pointee.args[0] + size_val: ir.Value | None = None if args: size_val = self.HandleExprLlvm(args[0]) if size_val and isinstance(size_val.type, ir.IntType): @@ -647,16 +693,16 @@ class ExprBuiltinHandle(BaseHandle): size_val = Gen.builder.trunc(size_val, param_type, name="trunc_malloc_size") if not size_val: size_val = ir.Constant(param_type, 1) - result = Gen.builder.call(malloc_func, [size_val], name="malloc_result") + result: ir.Value = Gen.builder.call(malloc_func, [size_val], name="malloc_result") return Gen.builder.bitcast(result, ir.IntType(8).as_pointer(), name="malloc_cast") - def _HandleReallocLlvm(self, args): - Gen = self.Trans.LlvmGen - realloc_type = ir.FunctionType(ir.PointerType(ir.IntType(8)), [ir.PointerType(ir.IntType(8)), ir.IntType(64)]) - realloc_func = Gen._get_or_declare_func('realloc', realloc_type) - size_param_type = realloc_func.type.pointee.args[1] - ptr_val = None - size_val = None + def _HandleReallocLlvm(self, args: list[ast.expr]) -> ir.Value: + Gen: LlvmGeneratorMixin = self.Trans.LlvmGen + realloc_type: ir.FunctionType = ir.FunctionType(ir.PointerType(ir.IntType(8)), [ir.PointerType(ir.IntType(8)), ir.IntType(64)]) + realloc_func: ir.Function = Gen._get_or_declare_func('realloc', realloc_type) + size_param_type: ir.Type = realloc_func.type.pointee.args[1] + ptr_val: ir.Value | None = None + size_val: ir.Value | None = None if len(args) >= 2: ptr_val = self.HandleExprLlvm(args[0]) size_val = self.HandleExprLlvm(args[1]) @@ -674,18 +720,18 @@ class ExprBuiltinHandle(BaseHandle): size_val = Gen.builder.trunc(size_val, size_param_type, name="trunc_realloc_size") if not size_val: size_val = ir.Constant(size_param_type, 0) - result = Gen.builder.call(realloc_func, [ptr_val, size_val], name="realloc_result") + result: ir.Value = Gen.builder.call(realloc_func, [ptr_val, size_val], name="realloc_result") return Gen.builder.bitcast(result, ir.IntType(8).as_pointer(), name="realloc_cast") - def _HandleFreeLlvm(self, args): - Gen = self.Trans.LlvmGen - free_type = ir.FunctionType(ir.VoidType(), [ir.PointerType(ir.IntType(8))]) - free_func = Gen._get_or_declare_func('free', free_type) + def _HandleFreeLlvm(self, args: list[ast.expr]) -> ir.Value: + Gen: LlvmGeneratorMixin = self.Trans.LlvmGen + free_type: ir.FunctionType = ir.FunctionType(ir.VoidType(), [ir.PointerType(ir.IntType(8))]) + free_func: ir.Function = Gen._get_or_declare_func('free', free_type) if args: - var_name = None + var_name: str | None = None if isinstance(args[0], ast.Name): var_name = args[0].id - ptr_val = self.HandleExprLlvm(args[0]) + ptr_val: ir.Value | None = self.HandleExprLlvm(args[0]) if ptr_val is not None: if var_name and hasattr(Gen, '_var_to_heap_ptr') and var_name in Gen._var_to_heap_ptr: registered_val = Gen._var_to_heap_ptr[var_name] @@ -701,17 +747,17 @@ class ExprBuiltinHandle(BaseHandle): Gen.builder.call(free_func, [ptr_val], name="free_call") return ir.Constant(ir.IntType(32), 0) - def _HandleMemcpyLlvm(self, args): - Gen = self.Trans.LlvmGen + def _HandleMemcpyLlvm(self, args: list[ast.expr]) -> ir.Value: + Gen: LlvmGeneratorMixin = self.Trans.LlvmGen if 'llvm.memcpy' not in Gen.functions: - memcpy_type = ir.FunctionType(ir.VoidType(), [ir.PointerType(ir.IntType(8)), ir.PointerType(ir.IntType(8)), ir.IntType(64), ir.IntType(1)]) + memcpy_type: ir.FunctionType = ir.FunctionType(ir.VoidType(), [ir.PointerType(ir.IntType(8)), ir.PointerType(ir.IntType(8)), ir.IntType(64), ir.IntType(1)]) Gen.functions['llvm.memcpy'] = ir.Function(Gen.module, memcpy_type, name='llvm.memcpy') if len(args) >= 3: - dst = self.HandleExprLlvm(args[0]) - src = self.HandleExprLlvm(args[1]) - size = self.HandleExprLlvm(args[2]) + dst: ir.Value | None = self.HandleExprLlvm(args[0]) + src: ir.Value | None = self.HandleExprLlvm(args[1]) + size: ir.Value | None = self.HandleExprLlvm(args[2]) if dst and src and size: - i8ptr = ir.PointerType(ir.IntType(8)) + i8ptr: ir.PointerType = ir.PointerType(ir.IntType(8)) if isinstance(dst.type, ir.PointerType) and dst.type != i8ptr: dst = Gen.builder.bitcast(dst, i8ptr, name="memcpy_dst_cast") elif isinstance(dst.type, ir.IntType): @@ -726,17 +772,17 @@ class ExprBuiltinHandle(BaseHandle): src = Gen.builder.inttoptr(src, i8ptr, name="src_int2ptr") if isinstance(size.type, ir.IntType) and size.type.width < 64: size = Gen.builder.zext(size, ir.IntType(64), name="zext_memcpy_size") - isvolatile = ir.Constant(ir.IntType(1), 0) + isvolatile: ir.Constant = ir.Constant(ir.IntType(1), 0) Gen.builder.call(Gen.functions['llvm.memcpy'], [dst, src, size, isvolatile], name="memcpy_call") return ir.Constant(ir.IntType(32), 0) - def _HandleMemsetLlvm(self, args): - Gen = self.Trans.LlvmGen - memset_func = Gen.get_or_declare_c_func('memset', ir.FunctionType(ir.PointerType(ir.IntType(8)), [ir.PointerType(ir.IntType(8)), ir.IntType(32), ir.IntType(64)])) + def _HandleMemsetLlvm(self, args: list[ast.expr]) -> ir.Value: + Gen: LlvmGeneratorMixin = self.Trans.LlvmGen + memset_func: ir.Function = Gen.get_or_declare_c_func('memset', ir.FunctionType(ir.PointerType(ir.IntType(8)), [ir.PointerType(ir.IntType(8)), ir.IntType(32), ir.IntType(64)])) if len(args) >= 3: - dst = self.HandleExprLlvm(args[0]) - val = self.HandleExprLlvm(args[1]) - size = self.HandleExprLlvm(args[2]) + dst: ir.Value | None = self.HandleExprLlvm(args[0]) + val: ir.Value | None = self.HandleExprLlvm(args[1]) + size: ir.Value | None = self.HandleExprLlvm(args[2]) if dst and val is not None and size: if isinstance(dst.type, ir.PointerType) and not (isinstance(dst.type.pointee, ir.IntType) and dst.type.pointee.width == 8): dst = Gen.builder.bitcast(dst, ir.PointerType(ir.IntType(8)), name="memset_dst_cast") @@ -758,34 +804,33 @@ class ExprBuiltinHandle(BaseHandle): Gen.builder.call(memset_func, [dst, val, size], name="memset_call") return ir.Constant(ir.IntType(32), 0) - def _HandleVaStartLlvm(self, args): - Gen = self.Trans.LlvmGen + def _HandleVaStartLlvm(self, args: list[ast.expr]) -> ir.Value: + Gen: LlvmGeneratorMixin = self.Trans.LlvmGen return ir.Constant(ir.IntType(32), 0) - def _HandleVaEndLlvm(self, args): - Gen = self.Trans.LlvmGen + def _HandleVaEndLlvm(self, args: list[ast.expr]) -> ir.Value: + Gen: LlvmGeneratorMixin = self.Trans.LlvmGen return ir.Constant(ir.IntType(32), 0) - def _HandleArgLlvm(self, args, CallNode=None): - Gen = self.Trans.LlvmGen - va_list_ptr = None - variadic_info = getattr(Gen, '_va_arg_info', None) + def _HandleArgLlvm(self, args: list[ast.expr], CallNode: ast.Call | None = None) -> ir.Value | None: + Gen: LlvmGeneratorMixin = self.Trans.LlvmGen + va_list_ptr: ir.Value | None = None + variadic_info: dict | None = getattr(Gen, '_va_arg_info', None) if not variadic_info: variadic_info = getattr(Gen, '_variadic_info', None) if variadic_info: va_list_ptr = variadic_info.get('va_list_ptr') if not va_list_ptr: - vararg_name = variadic_info.get('vararg_name', 'args') if variadic_info else 'args' + vararg_name: str = variadic_info.get('vararg_name', 'args') if variadic_info else 'args' if vararg_name in Gen.variables: va_list_ptr = Gen.variables[vararg_name] if not va_list_ptr: return ir.Constant(ir.IntType(32), 0) - target_type = ir.IntType(32) + target_type: ir.Type = ir.IntType(32) if args: - type_arg = args[0] + type_arg: ast.expr = args[0] if isinstance(type_arg, ast.Name): - type_name = type_arg.id - from lib.includes.t import CTypeRegistry + type_name: str = type_arg.id if type_name in ('str', 'bytes'): target_type = ir.PointerType(ir.IntType(8)) elif type_name == 'CPtr': @@ -793,19 +838,19 @@ class ExprBuiltinHandle(BaseHandle): elif type_name in Gen.structs: target_type = ir.PointerType(Gen.structs[type_name]) else: - ctype_cls = CTypeRegistry.GetClassByName(type_name) + ctype_cls: type | None = CTypeRegistry.GetClassByName(type_name) if ctype_cls is not None: - llvm_str = CTypeRegistry.CTypeToLLVM(ctype_cls) - resolved = Gen._type_str_to_llvm(llvm_str) + llvm_str: str | None = CTypeRegistry.CTypeToLLVM(ctype_cls) + resolved: ir.Type | None = Gen._type_str_to_llvm(llvm_str) if resolved: target_type = resolved else: - resolved = CTypeRegistry.ResolveName(type_name) + resolved: tuple | None = CTypeRegistry.ResolveName(type_name) if resolved is not None: ctype_cls, ptr_level = resolved llvm_str = CTypeRegistry.CTypeToLLVM(ctype_cls) if llvm_str: - base = Gen._type_str_to_llvm(llvm_str) + base: ir.Type | None = Gen._type_str_to_llvm(llvm_str) if base is not None: for _ in range(ptr_level): if isinstance(base, ir.VoidType): @@ -814,37 +859,31 @@ class ExprBuiltinHandle(BaseHandle): base = ir.PointerType(base) target_type = base elif isinstance(type_arg, ast.Attribute): - if isinstance(type_arg.value, ast.Name) and type_arg.value.id == 't': - attr_name = type_arg.attr - from lib.includes.t import CTypeRegistry - ctype_cls = CTypeRegistry.GetClassByName(attr_name) + if isinstance(type_arg.value, ast.Name) and IsTModule(type_arg.value.id, self.Trans.SymbolTable): + attr_name: str = type_arg.attr + ctype_cls: type | None = CTypeRegistry.GetClassByName(attr_name) if ctype_cls is not None: - llvm_str = CTypeRegistry.CTypeToLLVM(ctype_cls) - resolved = Gen._type_str_to_llvm(llvm_str) + llvm_str: str | None = CTypeRegistry.CTypeToLLVM(ctype_cls) + resolved: ir.Type | None = Gen._type_str_to_llvm(llvm_str) if resolved: target_type = resolved else: - assign_node = getattr(self.Trans, '_current_assign_node', None) + assign_node: ast.AST | None = getattr(self.Trans, '_current_assign_node', None) if assign_node: - ann = getattr(assign_node, 'annotation', None) + ann: ast.AST | None = getattr(assign_node, 'annotation', None) if ann: - ann_name = None + ann_name: str | None = None if isinstance(ann, ast.Name): ann_name = ann.id elif isinstance(ann, ast.Attribute): ann_name = ann.attr elif isinstance(ann, ast.BinOp) and isinstance(ann.op, ast.BitOr): - left = ann.left - if isinstance(left, ast.Name): - ann_name = left.id - elif isinstance(left, ast.Attribute): - ann_name = left.attr + ann_name = ExtractTypeNameFromBinOp(ann) if ann_name: - from lib.includes.t import CTypeRegistry - ctype_cls = CTypeRegistry.GetClassByName(ann_name) + ctype_cls: type | None = CTypeRegistry.GetClassByName(ann_name) if ctype_cls is not None: - llvm_str = CTypeRegistry.CTypeToLLVM(ctype_cls) - resolved = Gen._type_str_to_llvm(llvm_str) + llvm_str: str | None = CTypeRegistry.CTypeToLLVM(ctype_cls) + resolved: ir.Type | None = Gen._type_str_to_llvm(llvm_str) if resolved: target_type = resolved elif ann_name in Gen.structs: @@ -852,11 +891,11 @@ class ExprBuiltinHandle(BaseHandle): if not getattr(Gen, '_va_arg_counter', None): Gen._va_arg_counter = 0 Gen._va_arg_counter += 1 - result = Gen.emit_va_arg(va_list_ptr, target_type) + result: ir.Value | None = Gen.emit_va_arg(va_list_ptr, target_type) if result is not None and getattr(result, 'name', None): result.name = f"va_arg_result_{Gen._va_arg_counter}" return result - def _HandleVaArgLlvm(self, args): - Gen = self.Trans.LlvmGen + def _HandleVaArgLlvm(self, args: list[ast.expr]) -> ir.Value: + Gen: LlvmGeneratorMixin = self.Trans.LlvmGen return ir.Constant(ir.IntType(32), 0) diff --git a/lib/core/Handles/HandlesExprCall.py b/lib/core/Handles/HandlesExprCall.py index 4ad6da1..88f17af 100644 --- a/lib/core/Handles/HandlesExprCall.py +++ b/lib/core/Handles/HandlesExprCall.py @@ -2,30 +2,35 @@ from __future__ import annotations from typing import TYPE_CHECKING if TYPE_CHECKING: from lib.core.translator import Translator -from lib.core.Handles.HandlesBase import BaseHandle, CTypeInfo, FuncMeta -from lib.core.Handles.HandlesAssign import AssignHandle -from lib.includes import t + from lib.core.Translator.LlvmGenerator import LlvmGeneratorMixin import ast +import re import llvmlite.ir as ir +from lib.core.Handles.HandlesBase import BaseHandle, CTypeInfo, FuncMeta +from lib.core.VLogger import get_logger as _vlog +from lib.constants.config import mode as _config_mode +from lib.includes import t +from lib.includes.t import CTypeRegistry +from lib.core.SymbolUtils import IsTModule, ExtractTypeNameFromBinOp class ExprCallHandle(BaseHandle): - def _append_eh_msg_out_arg(self, CallArgs, func, Gen): + def _append_eh_msg_out_arg(self, CallArgs: list[ir.Value], func: ir.Function | None, Gen: LlvmGeneratorMixin) -> None: if not func: return - func_args = func.function_type.args - n_user_args = len(CallArgs) - has_eh_msg = False - has_eh_code = False + func_args: list[ir.Type] = func.function_type.args + n_user_args: int = len(CallArgs) + has_eh_msg: bool = False + has_eh_code: bool = False if len(func_args) > n_user_args: - last_type = func_args[-1] + last_type: ir.Type = func_args[-1] if (isinstance(last_type, ir.PointerType) and isinstance(last_type.pointee, ir.IntType) and last_type.pointee.width == 32): has_eh_code = True if len(func_args) > n_user_args + (1 if has_eh_code else 0): - check_idx = len(func_args) - 1 - (1 if has_eh_code else 0) - check_type = func_args[check_idx] + check_idx: int = len(func_args) - 1 - (1 if has_eh_code else 0) + check_type: ir.Type = func_args[check_idx] if (isinstance(check_type, ir.PointerType) and isinstance(check_type.pointee, ir.PointerType) and isinstance(check_type.pointee.pointee, ir.IntType) @@ -33,8 +38,8 @@ class ExprCallHandle(BaseHandle): has_eh_msg = True if not has_eh_msg: return - eh_msg_ptr = None - eh_code_ptr = None + eh_msg_ptr: ir.Value | None = None + eh_code_ptr: ir.Value | None = None if Gen.eh_except_block_stack: _, _, exception_code, eh_message = Gen.eh_except_block_stack[-1] if eh_message is not None: @@ -57,9 +62,9 @@ class ExprCallHandle(BaseHandle): if has_eh_code: CallArgs.append(eh_code_ptr) - def _check_eh_return(self, result, func_name, Gen, called_func=None): - has_eh_msg_out = False - has_eh_code_out = False + def _check_eh_return(self, result: ir.Value, func_name: str, Gen: LlvmGeneratorMixin, called_func: ir.Function | None = None) -> ir.Value: + has_eh_msg_out: bool = False + has_eh_code_out: bool = False if called_func and hasattr(called_func, 'args') and len(called_func.args) > 0: for arg in called_func.args: if arg.name == '__eh_msg_out__': @@ -67,9 +72,9 @@ class ExprCallHandle(BaseHandle): elif arg.name == '__eh_code_out__': has_eh_code_out = True if not has_eh_msg_out: - return - eh_msg_ptr = None - eh_code_ptr = None + return result + eh_msg_ptr: ir.Value | None = None + eh_code_ptr: ir.Value | None = None if Gen.eh_except_block_stack: _, _, exception_code, eh_message = Gen.eh_except_block_stack[-1] if eh_message is not None: @@ -83,15 +88,15 @@ class ExprCallHandle(BaseHandle): elif arg.name == '__eh_code_out__' and eh_code_ptr is None: eh_code_ptr = arg if eh_msg_ptr is not None: - eh_msg_val = Gen._load(eh_msg_ptr, name=f"Load_eh_msg_{func_name}") - null_ptr = ir.Constant(ir.PointerType(ir.IntType(8)), None) - is_error = Gen.builder.icmp_signed('!=', eh_msg_val, null_ptr, name=f"check_eh_msg_{func_name}") - OkBB = Gen.func.append_basic_block(name=f"ok_after_{func_name}") - ErrorBB = Gen.func.append_basic_block(name=f"error_after_{func_name}") + eh_msg_val: ir.Value = Gen._load(eh_msg_ptr, name=f"Load_eh_msg_{func_name}") + null_ptr: ir.Constant = ir.Constant(ir.PointerType(ir.IntType(8)), None) + is_error: ir.Value = Gen.builder.icmp_signed('!=', eh_msg_val, null_ptr, name=f"check_eh_msg_{func_name}") + OkBB: ir.Block = Gen.func.append_basic_block(name=f"ok_after_{func_name}") + ErrorBB: ir.Block = Gen.func.append_basic_block(name=f"error_after_{func_name}") Gen.builder.cbranch(is_error, ErrorBB, OkBB) Gen.builder.position_at_start(ErrorBB) - ret_type = getattr(Gen.func, 'ftype', None) and Gen.func.ftype.return_type if getattr(Gen, 'func', None) else None - error_ret_val = None + ret_type: ir.Type | None = getattr(Gen.func, 'ftype', None) and Gen.func.ftype.return_type if getattr(Gen, 'func', None) else None + error_ret_val: ir.Constant | None = None if isinstance(ret_type, ir.IdentifiedStructType): if ret_type.elements: error_ret_val = ir.Constant(ret_type, [ @@ -131,10 +136,10 @@ class ExprCallHandle(BaseHandle): Gen.builder.ret(error_ret_val) Gen.builder.position_at_start(OkBB) - def _fill_default_args(self, CallArgs, func, func_name=None): + def _fill_default_args(self, CallArgs: list[ir.Value], func: ir.Function | None, func_name: str | None = None) -> None: - global_defaults = getattr(self.Trans, '_global_function_default_args', {}) - func_defaults = None + global_defaults: dict = getattr(self.Trans, '_global_function_default_args', {}) + func_defaults: list | None = None if func_name: func_defaults = global_defaults.get(func_name) if not func_defaults and func: @@ -145,23 +150,23 @@ class ExprCallHandle(BaseHandle): func_defaults = gv break if func and len(CallArgs) < len(func.args): - total_params = len(func.args) + total_params: int = len(func.args) if func_defaults: - num_defaults = len(func_defaults) - default_start = total_params - num_defaults + num_defaults: int = len(func_defaults) + default_start: int = total_params - num_defaults else: num_defaults = 0 default_start = total_params while len(CallArgs) < total_params: - arg_idx = len(CallArgs) + arg_idx: int = len(CallArgs) arg = func.args[arg_idx] - param_type = arg.type if hasattr(arg, 'type') else arg + param_type: ir.Type = arg.type if hasattr(arg, 'type') else arg if func_defaults and arg_idx >= default_start: - def_idx = arg_idx - default_start + def_idx: int = arg_idx - default_start if def_idx < num_defaults and func_defaults[def_idx] is not None: default_val = func_defaults[def_idx] if isinstance(param_type, ir.IntType): - max_val = (1 << param_type.width) - 1 + max_val: int = (1 << param_type.width) - 1 if isinstance(default_val, bool): default_val = 1 if default_val else 0 if isinstance(default_val, int) and default_val > max_val: @@ -173,7 +178,8 @@ class ExprCallHandle(BaseHandle): CallArgs.append(ir.Constant(param_type, None)) else: try: - CallArgs.append(AssignHandle._zero_value(param_type)) + _zv = Gen._zero_value_for_type(param_type) + CallArgs.append(_zv if _zv is not None else ir.Constant(ir.IntType(32), 0)) except (AssertionError, TypeError): CallArgs.append(ir.Constant(ir.IntType(32), 0)) else: @@ -183,7 +189,8 @@ class ExprCallHandle(BaseHandle): CallArgs.append(ir.Constant(param_type, 0)) else: try: - CallArgs.append(AssignHandle._zero_value(param_type)) + _zv = Gen._zero_value_for_type(param_type) + CallArgs.append(_zv if _zv is not None else ir.Constant(ir.IntType(32), 0)) except (AssertionError, TypeError): CallArgs.append(ir.Constant(ir.IntType(32), 0)) else: @@ -193,14 +200,15 @@ class ExprCallHandle(BaseHandle): CallArgs.append(ir.Constant(param_type, 0)) else: try: - CallArgs.append(AssignHandle._zero_value(param_type)) + _zv = Gen._zero_value_for_type(param_type) + CallArgs.append(_zv if _zv is not None else ir.Constant(ir.IntType(32), 0)) except (AssertionError, TypeError): CallArgs.append(ir.Constant(ir.IntType(32), 0)) - def _HandleCallLlvm(self, Node): - Gen = self.Trans.LlvmGen - FuncAttr = None - ModulePath = None + def _HandleCallLlvm(self, Node: ast.Call) -> ir.Value: + Gen: LlvmGeneratorMixin = self.Trans.LlvmGen + FuncAttr: str | None = None + ModulePath: str | None = None if isinstance(Node.func, ast.Name): FuncName = Node.func.id if hasattr(self.Trans.FunctionHandler, '_generic_templates') and FuncName in self.Trans.FunctionHandler._generic_templates: @@ -208,116 +216,10 @@ class ExprCallHandle(BaseHandle): result = self.Trans.ExprBuiltinHandle._HandleBuiltinCallLlvm(Node) if result is not None: return result - if FuncName == 'print': - return self._HandlePrintLlvm(Node) - elif FuncName == 'len': - if Node.args: - return self._HandleLenLlvm(Node.args[0]) - return ir.Constant(ir.IntType(32), 0) - elif FuncName == 'sizeof': - if Node.args: - return self._HandleSizeofLlvm(Node.args[0]) - return ir.Constant(ir.IntType(32), 0) - elif FuncName == 'abs': - if Node.args: - return self._HandleAbsLlvm(Node.args[0]) - return ir.Constant(ir.IntType(32), 0) - elif FuncName == 'arg': - return self._HandleArgLlvm(Node.args, CallNode=Node) - elif FuncName == 'bool': - if Node.args: - Val = self.HandleExprLlvm(Node.args[0]) - if Val: - if isinstance(Val.type, ir.IntType): - if Val.type.width == 1: - return Val - return Gen.builder.icmp_signed('!=', Val, Gen._ZeroConst(Val.type), name="bool_result") - elif isinstance(Val.type, ir.PointerType): - return Gen.builder.icmp_signed('!=', Val, Gen._ZeroConst(Val.type), name="bool_result") - return Val - return ir.Constant(ir.IntType(1), 0) - elif FuncName == 'int': - if Node.args: - Val = self.HandleExprLlvm(Node.args[0]) - if Val: - if isinstance(Val.type, ir.IntType): - if Val.type.width < 32: - return Gen.builder.zext(Val, ir.IntType(32), name="cast_int") - elif Val.type.width > 32: - return Gen.builder.trunc(Val, ir.IntType(32), name="trunc_int") - return Val - elif isinstance(Val.type, (ir.FloatType, ir.DoubleType)): - return Gen.builder.fptosi(Val, ir.IntType(32), name="fptosi_int") - elif isinstance(Val.type, ir.PointerType): - if self._is_char_pointer(Val): - result = self._HandleAtoiLlvm(Val) - if result: - return result - return ir.Constant(ir.IntType(32), 0) - elif FuncName == 'float' or FuncName == 'double': - if Node.args: - Val = self.HandleExprLlvm(Node.args[0]) - if Val: - target_type = ir.DoubleType() - if isinstance(Val.type, (ir.FloatType, ir.DoubleType)): - if Val.type != target_type: - return Gen.builder.fpext(Val, target_type, name="fpext_double") - return Val - elif isinstance(Val.type, ir.IntType): - if Val.type.width == 1: - return Gen.builder.uitofp(Val, target_type, name="uitofp_double") - return Gen.builder.sitofp(Val, target_type, name="sitofp_double") - return ir.Constant(ir.DoubleType(), 0.0) - elif FuncName == 'str': - if Node.args: - arg_node = Node.args[0] - arg_val = self.HandleExprLlvm(arg_node) - if arg_val: - if isinstance(arg_val.type, ir.PointerType): - ClassName = self.Trans.ExprHandler._get_var_class(arg_node, Gen) - if ClassName and Gen._has_function(f'{ClassName}.__str__'): - if self._is_char_pointer(arg_val): - if ClassName in Gen.structs: - arg_val = Gen.builder.bitcast(arg_val, ir.PointerType(Gen.structs[ClassName]), name=f"cast_{ClassName}_str") - str_val = Gen.builder.call(Gen._get_function(f'{ClassName}.__str__'), [arg_val], name=f"call_{ClassName}.__str__") - return str_val - return arg_val - return self._EmitStringFromValue(arg_val) - return ir.Constant(ir.IntType(8).as_pointer(), None) - elif FuncName == 'input': - return self._HandleInputLlvm(Node) - elif FuncName == 'ord': - if Node.args: - return self._HandleOrdLlvm(Node.args[0]) - return ir.Constant(ir.IntType(32), 0) - elif FuncName == 'chr': - if Node.args: - return self._HandleChrLlvm(Node.args[0]) - return ir.Constant(ir.IntType(8), 0) - elif FuncName == 'malloc': - return self._HandleMallocLlvm(Node.args) - elif FuncName == 'realloc': - return self._HandleReallocLlvm(Node.args) - elif FuncName == 'free': - return self._HandleFreeLlvm(Node.args) - elif FuncName == 'memcpy': - return self._HandleMemcpyLlvm(Node.args) - elif FuncName == 'memset': - return self._HandleMemsetLlvm(Node.args) - elif FuncName == 'va_start': - return self._HandleVaStartLlvm(Node.args) - elif FuncName == 'va_end': - return self._HandleVaEndLlvm(Node.args) - elif FuncName == 'va_arg': - return self._HandleVaArgLlvm(Node.args) - elif FuncName == 'dir': - return self._HandleDirLlvm(Node) - elif FuncName == 'type': - return self._HandleTypeLlvm(Node) if Gen._has_function(FuncName): return self._HandleClosureCallLlvm(Node, FuncName) - if self.Trans.SymbolTable.has(FuncName): - SymInfo = self.Trans.SymbolTable[FuncName] + SymInfo = self.Trans.SymbolTable.lookup(FuncName) + if SymInfo: if SymInfo.IsEnum: if Node.args: arg_val = self.HandleExprLlvm(Node.args[0]) @@ -379,6 +281,13 @@ class ExprCallHandle(BaseHandle): call_args[0] = Gen.builder.bitcast(call_args[0], expected_fn_type.args[0], name=f"cast_env_{FuncName}") return Gen.builder.call(fn_val, call_args, name=f"call_{FuncName}") raise Exception(f"Undefined function: '{FuncName}'") + if isinstance(Node.func, ast.Subscript): + # Handle list[int](mb) syntax — generic class constructor with explicit type args + sub: ast.Subscript = Node.func + if isinstance(sub.value, ast.Name): + ClassName: str = sub.value.id + if hasattr(self.Trans.ClassHandler, '_generic_class_templates') and ClassName in self.Trans.ClassHandler._generic_class_templates: + return self._HandleGenericClassNewLlvm(Node, ClassName, explicit_slice=sub.slice) if isinstance(Node.func, ast.Attribute): if Node.func.attr in ('update', 'final', 'transform'): pass @@ -436,7 +345,18 @@ class ExprCallHandle(BaseHandle): ModulePath = resolved_first + ModulePath[len(first_part):] is_instance_var = isinstance(Node.func.value, ast.Name) and Node.func.value.id in Gen.var_struct_class and Node.func.value.id not in Gen.ModuleSha1Map is_class_name = isinstance(Node.func.value, ast.Name) and (Node.func.value.id in Gen.structs or self.Trans.SymbolTable.is_struct(Node.func.value.id)) - if is_instance_var and not is_class_name: + # 链式方法调用:如 self.__mbuddy__.alloc() + # Node.func.value 是 ast.Attribute,基础是实例变量(如 self) + _is_chained_instance: bool = False + if isinstance(Node.func.value, ast.Attribute): + _base_node: ast.AST = Node.func.value + while isinstance(_base_node, ast.Attribute): + _base_node = _base_node.value + if isinstance(_base_node, ast.Name): + _base_name: str = _base_node.id + if _base_name == 'self' or (_base_name in Gen.var_struct_class and _base_name not in Gen.ModuleSha1Map): + _is_chained_instance = True + if (is_instance_var or _is_chained_instance) and not is_class_name: return self._HandleMethodCallLlvm(Node) FuncAttr = Node.func.attr if FuncAttr in Gen.structs: @@ -516,8 +436,6 @@ class ExprCallHandle(BaseHandle): arg = Node.args[0] if isinstance(arg, ast.Constant) and isinstance(arg.value, str): msg = arg.value - elif isinstance(arg, ast.Str): - msg = arg.s lineno = getattr(Node, 'lineno', 0) raise Exception(f"#error: {msg} (line {lineno})") elif FuncAttr in ('AsmInp', 'AsmOut'): @@ -618,13 +536,7 @@ class ExprCallHandle(BaseHandle): stub_func_type = None if stub_func_type: decl_name = stub_mangled if stub_mangled in getattr(self.Trans.ImportHandler, '_stub_func_cache', {}) else FuncAttr - if decl_name not in Gen.functions: - func_decl = ir.Function(Gen.module, stub_func_type, name=decl_name) - Gen.functions[decl_name] = func_decl - if decl_name != FuncAttr and FuncAttr not in Gen.functions: - Gen.functions[FuncAttr] = func_decl - else: - func_decl = Gen.functions[decl_name] + func_decl = self.GetOrCreateStubFuncDecl(decl_name, stub_func_type, Gen, alias=FuncAttr) CallArgs = [] for arg in Node.args: ArgVal = self.HandleExprLlvm(arg) @@ -644,8 +556,8 @@ class ExprCallHandle(BaseHandle): return self._HandleTypeUnionCastLlvm(Node) raise Exception(f"Unsupported call expression") - def _ensure_struct_declared(self, class_name): - Gen = self.Trans.LlvmGen + def _ensure_struct_declared(self, class_name: str) -> None: + Gen: LlvmGeneratorMixin = self.Trans.LlvmGen # 如果名称是函数或变量,不应创建 struct SymInfo = self.Trans.SymbolTable.lookup(class_name) if SymInfo and (SymInfo.IsFunction or SymInfo.IsVariable): @@ -692,8 +604,8 @@ class ExprCallHandle(BaseHandle): self.Trans.ImportHandler._TryLoadStructFromStub(class_name, Gen) Gen._get_or_create_struct(class_name) - def _HandleStaticMethodCallLlvm(self, Node, ClassName, MethodName): - Gen = self.Trans.LlvmGen + def _HandleStaticMethodCallLlvm(self, Node: ast.Call, ClassName: str, MethodName: str) -> ir.Value | None: + Gen: LlvmGeneratorMixin = self.Trans.LlvmGen struct_sha1_map = getattr(Gen, '_struct_sha1_map', {}) class_sha1 = struct_sha1_map.get(ClassName) if class_sha1: @@ -706,43 +618,26 @@ class ExprCallHandle(BaseHandle): if not func: stub_func_type = self.Trans.ImportHandler._LookupStubFuncType(MangledName, Gen) if stub_func_type: - func = ir.Function(Gen.module, stub_func_type, name=MangledName) - Gen.functions[MangledName] = func + func = self.GetOrCreateStubFuncDecl(MangledName, stub_func_type, Gen) if not func and class_sha1: plain_name = f'{ClassName}.{MethodName}' stub_func_type = self.Trans.ImportHandler._LookupStubFuncType(plain_name, Gen) if stub_func_type: - func = ir.Function(Gen.module, stub_func_type, name=MangledName) - Gen.functions[MangledName] = func + func = self.GetOrCreateStubFuncDecl(MangledName, stub_func_type, Gen) if not func: if ClassName not in Gen.structs: self._ensure_struct_declared(ClassName) - SymKey = f'{ClassName}.{MethodName}' - SymInfo = self.Trans.SymbolTable.lookup(SymKey) or self.Trans.SymbolTable.lookup(MethodName) + SymInfo = self.LookupFunctionSymbol(MethodName, module_path=ClassName) if SymInfo and SymInfo.IsFunction: - ret_type_info = SymInfo.FuncPtrReturn - if isinstance(ret_type_info, CTypeInfo) and ret_type_info.BaseType: - ret_type = ret_type_info.ToLLVM(Gen) - else: - ret_type = Gen._CType2LLVM('i32', False) - param_type_infos = [pt for _, pt in (SymInfo.FuncPtrParams or [])] - if isinstance(ret_type, ir.VoidType): - ret_type = ir.IntType(32) - llvm_param_types = [] - is_static = FuncMeta.STATIC_METHOD in SymInfo.MetaList - if ClassName in Gen.structs and not is_static: - llvm_param_types.append(ir.PointerType(Gen.structs[ClassName])) - for pt in param_type_infos: - if isinstance(pt, CTypeInfo) and pt.BaseType: - lp = pt.ToLLVM(Gen) - else: - lp = Gen._CType2LLVM(pt if isinstance(pt, str) else 'i32', '*' in pt if isinstance(pt, str) else False) - if isinstance(lp, ir.VoidType): - lp = ir.IntType(8).as_pointer() - llvm_param_types.append(lp) - func_type = ir.FunctionType(ret_type, llvm_param_types) - func = ir.Function(Gen.module, func_type, name=MangledName) - Gen.functions[MangledName] = func + sig = self.BuildLLVMFuncTypeFromSig(SymInfo, Gen) + if sig is not None: + ret_type, llvm_param_types, _ = sig + is_static = FuncMeta.STATIC_METHOD in SymInfo.MetaList + if ClassName in Gen.structs and not is_static: + llvm_param_types.insert(0, ir.PointerType(Gen.structs[ClassName])) + func_type = ir.FunctionType(ret_type, llvm_param_types) + func = ir.Function(Gen.module, func_type, name=MangledName) + Gen.functions[MangledName] = func if not func: p = Gen.class_parent.get(ClassName) while p: @@ -759,8 +654,7 @@ class ExprCallHandle(BaseHandle): if not func: return None CallArgs = [] - SymKey = f'{ClassName}.{MethodName}' - SymInfo = self.Trans.SymbolTable.lookup(SymKey) or self.Trans.SymbolTable.lookup(MethodName) + SymInfo = self.LookupFunctionSymbol(MethodName, module_path=ClassName) is_static_call = SymInfo is not None and FuncMeta.STATIC_METHOD in SymInfo.MetaList is_classmethod_call = SymInfo is not None and FuncMeta.CLASS_METHOD in SymInfo.MetaList # @classmethod: 在参数列表前插入 cls(栈上分配的类实例指针) @@ -803,13 +697,14 @@ class ExprCallHandle(BaseHandle): self._check_eh_return(result, FullMethodName, Gen, called_func=func) return result self._append_eh_msg_out_arg(CallArgs, func, Gen) + CallArgs = Gen._apply_auto_addr(MangledName, CallArgs) adjusted = Gen._adjust_args(CallArgs, func) result = Gen.builder.call(func, adjusted, name=f"call_{MangledName}") self._check_eh_return(result, MangledName, Gen, called_func=func) return result - def _HandleInstanceCallLlvm(self, Node, VarName, ClassName): - Gen = self.Trans.LlvmGen + def _HandleInstanceCallLlvm(self, Node: ast.Call, VarName: str, ClassName: str) -> ir.Value: + Gen: LlvmGeneratorMixin = self.Trans.LlvmGen ObjVal = self.HandleExprLlvm(ast.Name(id=VarName, ctx=ast.Load())) if not ObjVal: raise Exception(f"Cannot evaluate object '{VarName}' for __call__") @@ -835,7 +730,7 @@ class ExprCallHandle(BaseHandle): self._check_eh_return(result, CallFuncName, Gen, called_func=func) return result - def _make_virtual_attr_call(self, Node, module_name, attr_name): + def _make_virtual_attr_call(self, Node: ast.Call, module_name: str, attr_name: str) -> ast.Call: virtual_func = ast.Attribute( value=ast.Name(id=module_name, ctx=ast.Load()), attr=attr_name, @@ -849,7 +744,7 @@ class ExprCallHandle(BaseHandle): ast.copy_location(new_node, Node) return new_node - def _get_ModulePath(self, node): + def _get_ModulePath(self, node: ast.AST) -> str | None: parts = [] while isinstance(node, ast.Attribute): parts.append(node.attr) @@ -859,8 +754,8 @@ class ExprCallHandle(BaseHandle): parts.reverse() return '.'.join(parts) if parts else None - def _HandleLLVMIRLlvm(self, Node): - Gen = self.Trans.LlvmGen + def _HandleLLVMIRLlvm(self, Node: ast.Call) -> ir.Value: + Gen: LlvmGeneratorMixin = self.Trans.LlvmGen if not Node.args: return ir.Constant(ir.IntType(32), 0) @@ -928,8 +823,7 @@ class ExprCallHandle(BaseHandle): return self._EmitLLVMIRInstruction(Gen, ir_template, input_ops, output_targets, all_ops, ret_type) - def _EmitLLVMIRInstruction(self, Gen, ir_template, input_ops, output_targets, all_ops, ret_type): - import re + def _EmitLLVMIRInstruction(self, Gen: LlvmGeneratorMixin, ir_template: str, input_ops: list[ir.Value], output_targets: list[ir.Value], all_ops: list[tuple], ret_type: ir.Type) -> ir.Value: template = ir_template.strip() def resolve_op(idx): @@ -1123,7 +1017,7 @@ class ExprCallHandle(BaseHandle): return ir.Constant(ret_type, 0) - def _StoreLLVMIROutputs(self, Gen, result, output_targets): + def _StoreLLVMIROutputs(self, Gen: LlvmGeneratorMixin, result: ir.Value, output_targets: list[ir.Value]) -> ir.Value: for target in output_targets: if isinstance(target, ir.AllocaInstr): if target.type.pointee == result.type: @@ -1154,7 +1048,7 @@ class ExprCallHandle(BaseHandle): Gen.builder.store(result, target) return result - def _ParseLLVMType(self, Gen, type_str): + def _ParseLLVMType(self, Gen: LlvmGeneratorMixin, type_str: str) -> ir.Type | None: type_map = { 'i1': ir.IntType(1), 'i8': ir.IntType(8), 'i16': ir.IntType(16), 'i32': ir.IntType(32), 'i64': ir.IntType(64), 'i128': ir.IntType(128), @@ -1169,7 +1063,7 @@ class ExprCallHandle(BaseHandle): return ir.PointerType(pointee) return None - def _ConvertLLVMIRType(self, Gen, val, expected_type_str): + def _ConvertLLVMIRType(self, Gen: LlvmGeneratorMixin, val: ir.Value, expected_type_str: str) -> ir.Value | None: expected_type = self._ParseLLVMType(Gen, expected_type_str.rstrip('*')) if not expected_type: return val @@ -1202,7 +1096,7 @@ class ExprCallHandle(BaseHandle): return Gen.builder.inttoptr(val, expected_type) return val - def _HandleExternalCallLlvm(self, Node, func_name, ModulePath): + def _HandleExternalCallLlvm(self, Node: ast.Call, func_name: str, ModulePath: str | None) -> ir.Value | None: Gen = self.Trans.LlvmGen # 解析 import 别名: 如 window -> vpsdk.window @@ -1225,13 +1119,12 @@ class ExprCallHandle(BaseHandle): if is_user_module: mangled_name = Gen._mangle_func_name(func_name, ModulePath) - sym_key = f'{ModulePath}.{func_name}' - sym_info = self.Trans.SymbolTable.lookup(sym_key) or self.Trans.SymbolTable.lookup(func_name) + sym_info = self.LookupFunctionSymbol(func_name, module_path=ModulePath) is_inline = sym_info and (sym_info.IsInline or isinstance(sym_info.Storage, t.CInline)) if is_inline and sym_info.InlineBody: self._HandleInlineExpandLlvm(Node, sym_info) return ir.Constant(ir.IntType(32), 1) - sym_info_exact = self.Trans.SymbolTable.lookup(sym_key) + sym_info_exact = self.Trans.SymbolTable.lookup(f'{ModulePath}.{func_name}') if sym_info_exact: exact_params = sym_info_exact.FuncPtrParams exact_param_names = [pn for pn, _ in exact_params] @@ -1264,52 +1157,15 @@ class ExprCallHandle(BaseHandle): decl_name = mangled_name else: decl_name = mangled_name if mangled_name in self.Trans.ImportHandler._stub_func_cache else func_name - if decl_name in Gen.functions: - func_decl = Gen.functions[decl_name] - else: - func_decl = ir.Function(Gen.module, stub_func_type, name=decl_name) - Gen.functions[decl_name] = func_decl - if decl_name != func_name and func_name not in Gen.functions: - Gen.functions[func_name] = func_decl + self.GetOrCreateStubFuncDecl(decl_name, stub_func_type, Gen, alias=func_name) return self._HandleClosureCallLlvm(Node, decl_name) - sym_key = f'{ModulePath}.{func_name}' - sym_info = self.Trans.SymbolTable.lookup(sym_key) - if not sym_info: - sym_info = self.Trans.SymbolTable.lookup(func_name) + sym_info = self.LookupFunctionSymbol(func_name, module_path=ModulePath) if sym_info: - is_func = sym_info.IsFunction - sym_is_variadic = sym_info.IsVariadic - if is_func: - ret_type_info = sym_info.FuncPtrReturn - if isinstance(ret_type_info, CTypeInfo) and ret_type_info.BaseType: - ret_type = ret_type_info.ToLLVM(Gen) - else: - ret_type = Gen._CType2LLVM('i32', False) - sym_params = sym_info.FuncPtrParams - param_type_infos = [pt for _, pt in sym_params] - if isinstance(ret_type, ir.VoidType): - ret_type = ir.IntType(32) - llvm_param_types = [] - for pi, pt in enumerate(param_type_infos): - if isinstance(pt, CTypeInfo) and pt.BaseType: - lp = pt.ToLLVM(Gen) - else: - lp = Gen._CType2LLVM(pt if isinstance(pt, str) else 'i32', '*' in pt if isinstance(pt, str) else False) - if isinstance(lp, ir.VoidType): - lp = ir.IntType(8).as_pointer() - llvm_param_types.append(lp) - if mangled_name not in Gen.functions: - func_type = ir.FunctionType(ret_type, llvm_param_types, var_arg=sym_is_variadic) - func_decl = ir.Function(Gen.module, func_type, name=mangled_name) - Gen.functions[mangled_name] = func_decl - else: - existing = Gen.functions[mangled_name] - existing_type = getattr(existing, 'ftype', None) - new_type = ir.FunctionType(ret_type, llvm_param_types, var_arg=sym_is_variadic) - if existing_type and existing_type != new_type: - replaced = self.Trans.FunctionHandler._replace_function_decl(Gen, func_name, new_type) - if replaced and replaced != existing: - Gen.functions[mangled_name] = replaced + sig = self.BuildLLVMFuncTypeFromSig(sym_info, Gen, mangled_name=mangled_name, use_infer_fallback=True) + if sig is not None: + ret_type, llvm_param_types, sym_is_variadic = sig + self.GetOrCreateFuncDecl(mangled_name, ret_type, llvm_param_types, Gen, + is_variadic=sym_is_variadic, replace_name=func_name) return self._HandleClosureCallLlvm(Node, mangled_name) # 回退: 直接用 func_name 查找(_find_function 会遍历 SHA1 前缀) fallback_func = Gen._find_function(func_name) @@ -1340,8 +1196,6 @@ class ExprCallHandle(BaseHandle): arg = Node.args[0] if isinstance(arg, ast.Constant) and isinstance(arg.value, str): msg = arg.value - elif isinstance(arg, ast.Str): - msg = arg.s lineno = getattr(Node, 'lineno', 0) raise Exception(f"#error: {msg} (line {lineno})") elif func_name in ('AsmInp', 'AsmOut'): @@ -1397,65 +1251,29 @@ class ExprCallHandle(BaseHandle): stub_func_type = None if stub_func_type: decl_name = mangled_name if mangled_name in self.Trans.ImportHandler._stub_func_cache else func_name - func_decl = ir.Function(Gen.module, stub_func_type, name=decl_name) - Gen.functions[decl_name] = func_decl - if decl_name != func_name: - Gen.functions[func_name] = func_decl + self.GetOrCreateStubFuncDecl(decl_name, stub_func_type, Gen, alias=func_name, check_existing=False) return self._HandleClosureCallLlvm(Node, decl_name) - sym_key = f'{ModulePath}.{func_name}' if ModulePath else func_name - sym_info = self.Trans.SymbolTable.lookup(sym_key) - if not sym_info: - sym_info = self.Trans.SymbolTable.lookup(func_name) + sym_info = self.LookupFunctionSymbol(func_name, module_path=ModulePath or None) if sym_info: - is_func = sym_info.IsFunction - sym_is_variadic = sym_info.IsVariadic - if is_func: - ret_type_info = sym_info.FuncPtrReturn - if isinstance(ret_type_info, CTypeInfo) and ret_type_info.BaseType: - ret_type = ret_type_info.ToLLVM(Gen) - else: - ret_type = Gen._CType2LLVM('i32', False) - param_type_infos = [pt for _, pt in sym_info.FuncPtrParams] - if isinstance(ret_type, ir.VoidType): - ret_type = ir.IntType(32) - llvm_param_types = [] - for pt in param_type_infos: - if isinstance(pt, CTypeInfo) and pt.BaseType: - lp = pt.ToLLVM(Gen) - else: - lp = Gen._CType2LLVM(pt if isinstance(pt, str) else 'i32', '*' in pt if isinstance(pt, str) else False) - if isinstance(lp, ir.VoidType): - lp = ir.IntType(8).as_pointer() - llvm_param_types.append(lp) + sig = self.BuildLLVMFuncTypeFromSig(sym_info, Gen) + if sig is not None: + ret_type, llvm_param_types, sym_is_variadic = sig mangled_name = Gen._mangle_func_name(func_name, ModulePath) - if mangled_name not in Gen.functions: - func_type = ir.FunctionType(ret_type, llvm_param_types, var_arg=sym_is_variadic) - func_decl = ir.Function(Gen.module, func_type, name=mangled_name) - Gen.functions[mangled_name] = func_decl - else: - existing = Gen.functions[mangled_name] - existing_type = getattr(existing, 'ftype', None) - new_type = ir.FunctionType(ret_type, llvm_param_types, var_arg=sym_is_variadic) - if existing_type and existing_type != new_type: - replaced = self.Trans.FunctionHandler._replace_function_decl(Gen, func_name, new_type) - if replaced and replaced != existing: - Gen.functions[mangled_name] = replaced + self.GetOrCreateFuncDecl(mangled_name, ret_type, llvm_param_types, Gen, + is_variadic=sym_is_variadic, replace_name=func_name) return self._HandleClosureCallLlvm(Node, mangled_name) return None - def _HandleTypeUnionCastLlvm(self, Node): + def _HandleTypeUnionCastLlvm(self, Node: ast.Call) -> ir.Value | None: Gen = self.Trans.LlvmGen if not Node.args: return None - from lib.core.Handles.HandlesBase import CTypeInfo type_info = None try: type_info = getattr(self.Trans, 'TypeMergeHandler', None) and self.Trans.TypeMergeHandler.MergeTypes(Node.func) except Exception as _e: - from lib.core.VLogger import get_logger as _vlog - from lib.constants.config import mode as _config_mode if _config_mode == "strict": raise _vlog().warning(f"解析类型失败: {_e}", "Exception") @@ -1477,7 +1295,7 @@ class ExprCallHandle(BaseHandle): Gen._export_funcs.add('_type_union_cast') return self._HandleTypeCastLlvm(Node.args[0], target_type_str) - def _HandleTypeCastLlvm(self, expr_node, target_type_str): + def _HandleTypeCastLlvm(self, expr_node: ast.AST, target_type_str: str) -> ir.Value | None: Gen = self.Trans.LlvmGen val = self.HandleExprLlvm(expr_node) if val is None: @@ -1544,7 +1362,7 @@ class ExprCallHandle(BaseHandle): except Exception: # 回退:bitcast 失败时返回原值 return val - def _HandleREnumConstructLlvm(self, Node, RenumName, VariantName, TagValue): + def _HandleREnumConstructLlvm(self, Node: ast.Call, RenumName: str, VariantName: str, TagValue: int) -> ir.Value | None: Gen = self.Trans.LlvmGen if RenumName not in Gen.structs: return None @@ -1571,11 +1389,14 @@ class ExprCallHandle(BaseHandle): Gen._store(ArgVal, elem_ptr) return result - def _HandleTypedefCastLlvm(self, Node, TypedefName): + def _HandleTypedefCastLlvm(self, Node: ast.Call, TypedefName: str) -> ir.Value: Gen = self.Trans.LlvmGen SymInfo = self.Trans.SymbolTable.lookup(TypedefName) if not SymInfo or not SymInfo.IsTypedef: return ir.Constant(ir.IntType(32), 0) + # 确保 Name 已设置,以便 _resolve_typedef_ctype 能正确解析 + if not SymInfo.Name: + SymInfo.Name = TypedefName TargetType = Gen._ctype_to_llvm(SymInfo) if not Node.args: if isinstance(TargetType, ir.IntType): @@ -1614,7 +1435,7 @@ class ExprCallHandle(BaseHandle): return Gen.builder.fptosi(ArgVal, TargetType, name=f"fptosi_{TypedefName}_cast") return ArgVal - def _HandleInlineExpandLlvm(self, Node, sym_info): + def _HandleInlineExpandLlvm(self, Node: ast.Call, sym_info: CTypeInfo) -> None: Gen = self.Trans.LlvmGen inline_body = sym_info.InlineBody inline_params = sym_info.InlineParams or [] @@ -1638,7 +1459,7 @@ class ExprCallHandle(BaseHandle): self.Trans.VarScopes = old_var_scopes return None - def _HandleClosureCallLlvm(self, Node, FuncName): + def _HandleClosureCallLlvm(self, Node: ast.Call, FuncName: str) -> ir.Value: Gen = self.Trans.LlvmGen func = Gen.functions.get(FuncName) if not func: @@ -1812,12 +1633,13 @@ class ExprCallHandle(BaseHandle): adjusted.append(arg) result = Gen.builder.call(func, adjusted, name=f"call_{FuncName}") else: + CallArgs = Gen._apply_auto_addr(FuncName, CallArgs) adjusted = Gen._adjust_args(CallArgs, func) result = Gen.builder.call(func, adjusted, name=f"call_{FuncName}") self._check_eh_return(result, FuncName, Gen, called_func=func) return result - def _HandleMethodCallLlvm(self, Node): + def _HandleMethodCallLlvm(self, Node: ast.Call) -> ir.Value: Gen = self.Trans.LlvmGen MethodName = Node.func.attr # 检查是否为 @staticmethod 或 @classmethod,如果是则走特殊路径 @@ -1832,11 +1654,10 @@ class ExprCallHandle(BaseHandle): return self._HandleStaticMethodCallLlvm(Node, ClassName, MethodName) if FuncMeta.CLASS_METHOD in SymInfo.MetaList: return self._HandleStaticMethodCallLlvm(Node, ClassName, MethodName) - if isinstance(Node.func.value, ast.Name) and Node.func.value.id == 't': + if isinstance(Node.func.value, ast.Name) and IsTModule(Node.func.value.id, self.Trans.SymbolTable): result = self.Trans.TSpecialCallHandle._HandleTSpecialCallLlvm(Node) if result is not None: return result - from lib.includes.t import CTypeRegistry ctype_cls = CTypeRegistry.GetClassByName(MethodName) if ctype_cls is not None: try: @@ -1848,7 +1669,7 @@ class ExprCallHandle(BaseHandle): target_bits = 0 is_float = getattr(ctype_inst, 'IsSigned', False) is None and target_bits > 0 if ctype_inst else False IsPtr_cast = len(Node.args) >= 2 and ( - (isinstance(Node.args[1], ast.Attribute) and Node.args[1].attr == 'CPtr' and isinstance(Node.args[1].value, ast.Name) and Node.args[1].value.id == 't') or + (isinstance(Node.args[1], ast.Attribute) and Node.args[1].attr == 'CPtr' and isinstance(Node.args[1].value, ast.Name) and IsTModule(Node.args[1].value.id, self.Trans.SymbolTable)) or (isinstance(Node.args[1], ast.Name) and Node.args[1].id == 'CPtr') ) if Node.args: @@ -1936,16 +1757,12 @@ class ExprCallHandle(BaseHandle): arg = Node.args[0] if isinstance(arg, ast.Constant) and isinstance(arg.value, str): msg = arg.value - elif isinstance(arg, ast.Str): - msg = arg.s else: try: val = self.HandleExprLlvm(arg) if isinstance(val, str): msg = val except Exception as _e: - from lib.core.VLogger import get_logger as _vlog - from lib.constants.config import mode as _config_mode if _config_mode == "strict": raise _vlog().warning(f"处理函数调用失败: {_e}", "Exception") @@ -2030,6 +1847,7 @@ class ExprCallHandle(BaseHandle): adjusted.append(arg) result = Gen.builder.call(func, adjusted, name=f"call_{MethodName}") else: + CallArgs = Gen._apply_auto_addr(MethodName, CallArgs) adjusted = Gen._adjust_args(CallArgs, func) result = Gen.builder.call(func, adjusted, name=f"call_{MethodName}") return result @@ -2082,6 +1900,7 @@ class ExprCallHandle(BaseHandle): adjusted.append(arg) result = Gen.builder.call(func, adjusted, name=f"call_{MethodName}") else: + CallArgs = Gen._apply_auto_addr(MethodName, CallArgs) adjusted = Gen._adjust_args(CallArgs, func) result = Gen.builder.call(func, adjusted, name=f"call_{MethodName}") return result @@ -2096,8 +1915,7 @@ class ExprCallHandle(BaseHandle): mangled_name = alt_name break if stub_func_type: - func = ir.Function(Gen.module, stub_func_type, name=mangled_name) - Gen.functions[mangled_name] = func + func = self.GetOrCreateStubFuncDecl(mangled_name, stub_func_type, Gen) CallArgs = [] for arg in Node.args: ArgVal = self.HandleExprLlvm(arg) @@ -2105,6 +1923,7 @@ class ExprCallHandle(BaseHandle): CallArgs.append(ArgVal) self._fill_default_args(CallArgs, func, mangled_name) self._append_eh_msg_out_arg(CallArgs, func, Gen) + CallArgs = Gen._apply_auto_addr(mangled_name, CallArgs) adjusted = Gen._adjust_args(CallArgs, func) result = Gen.builder.call(func, adjusted, name=f"call_{MethodName}") self._check_eh_return(result, mangled_name, Gen, called_func=func) @@ -2125,16 +1944,41 @@ class ExprCallHandle(BaseHandle): break if not ClassName and self._is_char_pointer(ObjVal): MethodName = Node.func.attr + # FakeDuck: 检查是否有影子结构体 a__meta__ (per-instance 字段存储) + meta_ptr: ir.Value | None = None + if isinstance(Node.func.value, ast.Name): + meta_name = f"{Node.func.value.id}__meta__" + if meta_name in Gen.variables: + meta_ptr = Gen.variables[meta_name] for CN, ST in Gen.structs.items(): - if isinstance(ST, ir.IdentifiedStructType) and (ST.elements is None or len(ST.elements) == 0): - continue method_key = f'{CN}.{MethodName}' if not Gen._has_function(method_key): continue + # FakeDuck: 不跳过空结构体 (扩展类可能没有数据成员只有方法) try: - casted = Gen.builder.bitcast(ObjVal, ir.PointerType(ST), name=f"cast_{CN}") + # 如果有影子结构体且该类有字段, 使用影子结构体作为 self (而非 bitcast char*) + if meta_ptr is not None and hasattr(ST, 'elements') and len(ST.elements) > 0: + ObjVal = meta_ptr + elif CN == '_str' and hasattr(ST, 'elements') and len(ST.elements) > 0: + # FakeDuck: 字符串字面量/匿名 str 表达式调用 _str 方法时, + # 创建临时影子结构体 (栈上), 设置 __data__ 和 __mbuddy__ 字段。 + # bitcast i8* → _str* 会导致读取垃圾指针 → ACCESS_VIOLATION + tmp_meta: ir.AllocaInstr = Gen._allocaEntry(ST, name="tmp_str_meta") + _data_off = Gen._get_member_offset('__data__', '_str') + if _data_off is not None: + _data_ptr = Gen.builder.gep(tmp_meta, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), _data_off)], name="tmp_str_data") + Gen._store(ObjVal, _data_ptr) + _mpool_off = Gen._get_member_offset('__mbuddy__', '_str') + if _mpool_off is not None: + _mpool_ptr = Gen.builder.gep(tmp_meta, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), _mpool_off)], name="tmp_str_mbuddy") + Gen._store(ir.Constant(ir.PointerType(ir.IntType(8)), None), _mpool_ptr) + # 从 with 上下文自动注入 requires 字段 (如 __mbuddy__) + self._InjectRequiresFields(tmp_meta, '_str', Gen) + ObjVal = tmp_meta + else: + casted = Gen.builder.bitcast(ObjVal, ir.PointerType(ST), name=f"cast_{CN}") + ObjVal = casted ClassName = CN - ObjVal = casted break except Exception: # 回退:bitcast 失败时尝试下一个类 continue @@ -2211,18 +2055,17 @@ class ExprCallHandle(BaseHandle): if not func and class_sha1: stub_func_type = self.Trans.ImportHandler._LookupStubFuncType(FullMethodName, Gen) if stub_func_type: - func = ir.Function(Gen.module, stub_func_type, name=FullMethodName) - Gen.functions[FullMethodName] = func + func = self.GetOrCreateStubFuncDecl(FullMethodName, stub_func_type, Gen) if not func and class_sha1: plain_name = f'{ClassName}.{MethodName}' stub_func_type = self.Trans.ImportHandler._LookupStubFuncType(plain_name, Gen) if stub_func_type: - func = ir.Function(Gen.module, stub_func_type, name=FullMethodName) - Gen.functions[FullMethodName] = func + func = self.GetOrCreateStubFuncDecl(FullMethodName, stub_func_type, Gen) if func: call_args = [ObjVal] + CallArgs self._fill_default_args(call_args, func, FullMethodName) self._append_eh_msg_out_arg(call_args, func, Gen) + call_args = Gen._apply_auto_addr(FullMethodName, call_args) adjusted = Gen._adjust_args(call_args, func) result = Gen.builder.call(func, adjusted, name=f"call_{FullMethodName}") self._check_eh_return(result, FullMethodName, Gen, called_func=func) @@ -2261,206 +2104,6 @@ class ExprCallHandle(BaseHandle): return result raise Exception(f"Undefined method '{MethodName}' in class '{ClassName}' (no function declaration found for '{FullMethodName}')") - def _HandlePrintLlvm(self, Node): - Gen = self.Trans.LlvmGen - printf_func = Gen.get_or_declare_c_func('printf', ir.FunctionType(ir.IntType(32), [ir.PointerType(ir.IntType(8))], var_arg=True)) - args = Node.args - end_arg = None - sep_arg = None - if Node.keywords: - for kw in Node.keywords: - if kw.arg == 'end': - end_arg = kw.value - elif kw.arg == 'sep': - sep_arg = kw.value - sep_str = ' ' - if sep_arg and isinstance(sep_arg, ast.Constant) and isinstance(sep_arg.value, str): - sep_str = sep_arg.value - end_str = '\n' - if end_arg: - if isinstance(end_arg, ast.Constant) and isinstance(end_arg.value, str): - end_str = end_arg.value - elif isinstance(end_arg, ast.Constant) and end_arg.value is None: - end_str = '' - if not args: - if end_str: - nl_fmt = Gen.emit_constant(end_str, 'string') - Gen.builder.call(printf_func, [nl_fmt], name="print_nl") - return - has_fstring = any(isinstance(arg, ast.JoinedStr) for arg in args) - if has_fstring: - self._HandlePrintWithFString(Node, printf_func, args, sep_str, end_str) - return - fmt_parts = [] - fmt_args = [] - for i, arg in enumerate(args): - if i > 0: - fmt_parts.append(sep_str) - val = self.HandleExprLlvm(arg) - if not val: - fmt_parts.append('(null)') - continue - if isinstance(val, ir.Constant) and isinstance(val.type, ir.PointerType) and val.constant is None: - fmt_parts.append('nil') - continue - if isinstance(val.type, ir.PointerType): - pointee = val.type.pointee - if self._is_char_pointer(val): - fmt_parts.append('%s') - fmt_args.append(val) - elif isinstance(pointee, ir.ArrayType) and isinstance(pointee.element, ir.IntType) and pointee.element.width == 8: - elem_ptr = Gen.builder.gep(val, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), 0)], name="print_arr_to_ptr") - fmt_parts.append('%s') - fmt_args.append(elem_ptr) - elif isinstance(pointee, (ir.IdentifiedStructType, ir.LiteralStructType)): - ClassName = self.Trans.ExprHandler._get_var_class(arg, Gen) - if not ClassName and isinstance(arg, ast.Name): - ClassName = Gen.var_struct_class.get(arg.id) - if ClassName and Gen._has_function(f'{ClassName}.__str__'): - if self._is_char_pointer(val): - if ClassName in Gen.structs: - val = Gen.builder.bitcast(val, ir.PointerType(Gen.structs[ClassName]), name=f"cast_{ClassName}") - str_val = Gen.builder.call(Gen._get_function(f'{ClassName}.__str__'), [val], name=f"call_{ClassName}.__str__") - fmt_parts.append('%s') - fmt_args.append(str_val) - else: - int_val = Gen.builder.ptrtoint(val, ir.IntType(64), name="print_ptr_to_int") - fmt_parts.append('0x%llx') - fmt_args.append(int_val) - else: - int_val = Gen.builder.ptrtoint(val, ir.IntType(64), name="print_ptr_to_int") - fmt_parts.append('%lld') - fmt_args.append(int_val) - elif isinstance(val.type, ir.IntType): - is_unsigned = self._is_val_unsigned(arg, val) - if val.type.width == 1: - fmt_parts.append('%d') - val = Gen.builder.zext(val, ir.IntType(32), name="zext_bool_print") - elif val.type.width == 8: - if self._is_char_type(arg): - char_var = Gen._allocaEntry(ir.IntType(8), name="print_char_buf") - Gen.builder.store(val, char_var) - fmt_parts.append('%c') - fmt_args.append(char_var) - continue - fmt_parts.append('%d') - if is_unsigned: - val = Gen.builder.zext(val, ir.IntType(32), name="zext_i8_print") - else: - val = Gen.builder.sext(val, ir.IntType(32), name="sext_i8_print") - elif val.type.width == 16: - fmt_parts.append('%u' if is_unsigned else '%d') - if is_unsigned: - val = Gen.builder.zext(val, ir.IntType(32), name="zext_i16_print") - else: - val = Gen.builder.sext(val, ir.IntType(32), name="sext_i16_print") - elif val.type.width == 32: - fmt_parts.append('%u' if is_unsigned else '%d') - elif val.type.width == 64: - fmt_parts.append('%llu' if is_unsigned else '%lld') - else: - fmt_parts.append('%d') - val = Gen.builder.zext(val, ir.IntType(32), name="zext_int_print") - fmt_args.append(val) - elif isinstance(val.type, ir.FloatType): - fmt_parts.append('%f') - fmt_args.append(Gen.builder.fpext(val, ir.DoubleType(), name="fpext_printf_float")) - elif isinstance(val.type, ir.DoubleType): - fmt_parts.append('%f') - fmt_args.append(val) - else: - fmt_parts.append('(unknown)') - fmt_parts.append(end_str) - fmt_str = ''.join(fmt_parts) - fmt_bytes = fmt_str.encode('utf-8') + b'\x00' - fmt_type = ir.ArrayType(ir.IntType(8), len(fmt_bytes)) - fmt_const = ir.Constant(fmt_type, bytearray(fmt_bytes)) - fmt_gvar = ir.GlobalVariable(Gen.module, fmt_type, name=f"str_const_{Gen.string_const_counter}") - Gen.string_const_counter += 1 - fmt_gvar.initializer = fmt_const - fmt_gvar.linkage = 'internal' - fmt_ptr = Gen.builder.bitcast(fmt_gvar, ir.PointerType(ir.IntType(8)), name="print_fmt") - call_args = [fmt_ptr] + fmt_args - Gen.builder.call(printf_func, call_args, name="print_call") - - def _HandlePrintWithFString(self, Node, printf_func, args, sep_str, end_str): - Gen = self.Trans.LlvmGen - for i, arg in enumerate(args): - if i > 0: - sep_const = Gen.emit_constant(sep_str, 'string') - Gen.builder.call(printf_func, [sep_const], name="print_sep") - if isinstance(arg, ast.JoinedStr): - self.HandleExprLlvm(arg) - else: - ClassName = self.Trans.ExprHandler._get_var_class(arg, Gen) - if not ClassName and isinstance(arg, ast.Name): - ClassName = Gen.var_struct_class.get(arg.id) - if ClassName and Gen._has_function(f'{ClassName}.__str__'): - obj_val = self.HandleExprLlvm(arg) - if obj_val: - if self._is_char_pointer(obj_val): - if ClassName in Gen.structs: - obj_val = Gen.builder.bitcast(obj_val, ir.PointerType(Gen.structs[ClassName]), name=f"cast_{ClassName}") - str_val = Gen.builder.call(Gen._get_function(f'{ClassName}.__str__'), [obj_val], name=f"call_{ClassName}.__str__") - Gen._RegisterTempPtr(str_val) - Gen._emit_printf([str_val], unsigned_flags=[False], sep=None, end=None) - elif isinstance(arg, ast.Name) and arg.id in Gen.var_struct_class: - ClassName = Gen.var_struct_class[arg.id] - obj_val = self.HandleExprLlvm(arg) - if obj_val and ClassName in Gen.structs: - str_func = Gen._find_function(f'{ClassName}.__str__') - if str_func: - if isinstance(obj_val.type, ir.PointerType) and not isinstance(obj_val.type.pointee, type(Gen.structs[ClassName])): - obj_val = Gen.builder.bitcast(obj_val, ir.PointerType(Gen.structs[ClassName]), name=f"cast_{ClassName}") - str_val = Gen.builder.call(str_func, [obj_val], name=f"call_{ClassName}.__str__") - Gen._RegisterTempPtr(str_val) - Gen._emit_printf([str_val], unsigned_flags=[False], sep=None, end=None) - else: - val = self.HandleExprLlvm(arg) - self._print_value(val=val, arg=arg, Gen=Gen, fmt_parts=fmt_parts, fmt_args=fmt_args) - else: - val = self.HandleExprLlvm(arg) - self._print_value(val=val, arg=arg, Gen=Gen, fmt_parts=fmt_parts, fmt_args=fmt_args) - else: - val = self.HandleExprLlvm(arg) - if val: - if isinstance(val.type, ir.PointerType): - pointee = val.type.pointee - if not self._is_char_pointer(val): - try: - val = Gen._load(val, name="print_Load") - except Exception as _e: - if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": - self.Trans.LogWarning(f"异常被忽略: {_e}") - is_u = Gen._check_node_unsigned(arg) - if not is_u and id(val) in Gen._unsigned_results: - is_u = True - Gen._emit_printf([val], unsigned_flags=[is_u], sep=None, end=None) - if end_str: - end_const = Gen.emit_constant(end_str, 'string') - Gen.builder.call(printf_func, [end_const], name="print_end") - - def _is_char_type(self, arg_node): - if isinstance(arg_node, ast.Call): - if isinstance(arg_node.func, ast.Name): - return arg_node.func.id in ('CChar', 'CUInt8T', 'CInt8T') - if isinstance(arg_node.func, ast.Attribute): - return arg_node.func.attr in ('CChar', 'CUInt8T', 'CInt8T') - return False - - def _is_val_unsigned(self, arg_node, val): - Gen = self.Trans.LlvmGen - if isinstance(arg_node, ast.Name): - var_name = arg_node.id - signedness = Gen.var_signedness.get(var_name) - if signedness: - if isinstance(signedness, bool): - return signedness - return 'unsigned' in signedness - if isinstance(val.type, ir.IntType): - return False - return False - _C_LIB_FUNCS = { 'malloc': lambda: (ir.PointerType(ir.IntType(8)), [ir.IntType(64)]), 'calloc': lambda: (ir.PointerType(ir.IntType(8)), [ir.IntType(64), ir.IntType(64)]), @@ -2484,7 +2127,7 @@ class ExprCallHandle(BaseHandle): 'labs': lambda: (ir.IntType(64), [ir.IntType(64)]), } - def _try_declare_c_lib_func(self, func_name, Gen): + def _try_declare_c_lib_func(self, func_name: str, Gen: LlvmGeneratorMixin) -> ir.Function | None: if func_name not in self._C_LIB_FUNCS: return None ret_type, param_types = self._C_LIB_FUNCS[func_name]() @@ -2493,7 +2136,7 @@ class ExprCallHandle(BaseHandle): Gen.functions[func_name] = func return func - def _HandleLenLlvm(self, arg_node): + def _HandleLenLlvm(self, arg_node: ast.AST) -> ir.Value | None: Gen = self.Trans.LlvmGen if isinstance(arg_node, ast.Attribute) and isinstance(arg_node.value, ast.Name) and arg_node.value.id == 'self': attr_name = arg_node.attr @@ -2540,7 +2183,7 @@ class ExprCallHandle(BaseHandle): strlen_func = ir.Function(Gen.module, correct_strlen_type, name='strlen') Gen.functions['strlen'] = strlen_func except Exception as _e: - if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": + if _config_mode == "strict": self.Trans.LogWarning(f"异常被忽略: {_e}") if strlen_func: result = Gen.builder.call(strlen_func, [val], name="strlen_call") @@ -2549,7 +2192,40 @@ class ExprCallHandle(BaseHandle): return ir.Constant(ir.IntType(64), val.type.count) return ir.Constant(ir.IntType(64), 0) - def _HandleSizeofLlvm(self, Node): + def _resolve_opaque_struct_members(self, struct_type: ir.Type, Gen: LlvmGeneratorMixin, _visited: set | None = None) -> None: + """Recursively resolve opaque struct members by loading from stub files.""" + if _visited is None: + _visited = set() + if not isinstance(struct_type, ir.IdentifiedStructType): + return + # 防止循环引用导致无限递归 + try: + st_id = id(struct_type) + except Exception: + st_id = struct_type + if st_id in _visited: + return + _visited.add(st_id) + if struct_type.elements is None or len(struct_type.elements) == 0: + # Find the class name for this opaque struct and try to resolve + for cn, st in Gen.structs.items(): + try: + if st == struct_type or (hasattr(st, 'name') and hasattr(struct_type, 'name') and st.name == struct_type.name): + self.Trans.ImportHandler._TryLoadStructFromStub(cn, Gen) + break + except (AssertionError, RuntimeError): + pass + # Re-get the struct in case it was resolved + if struct_type.elements: + for elem in struct_type.elements: + if isinstance(elem, ir.IdentifiedStructType): + self._resolve_opaque_struct_members(elem, Gen, _visited) + elif isinstance(elem, ir.PointerType): + pointee = elem.pointee + if isinstance(pointee, ir.IdentifiedStructType): + self._resolve_opaque_struct_members(pointee, Gen, _visited) + + def _HandleSizeofLlvm(self, Node: ast.AST) -> ir.Constant: Gen = self.Trans.LlvmGen if isinstance(Node, ast.Name): type_name = Node.id @@ -2559,7 +2235,9 @@ class ExprCallHandle(BaseHandle): return ir.Constant(ir.IntType(64), 0) if type_name not in Gen.structs: - from lib.includes.t import CTypeRegistry + # str/bytes 是指针类型 (char*/void*),sizeof = 指针大小 + if type_name in ('str', 'bytes'): + return ir.Constant(ir.IntType(64), 8) ctype_cls = CTypeRegistry.GetClassByName(type_name) if ctype_cls is not None: try: @@ -2568,8 +2246,6 @@ class ExprCallHandle(BaseHandle): size_bytes = size_bits // 8 return ir.Constant(ir.IntType(64), size_bytes) except Exception as _e: - from lib.core.VLogger import get_logger as _vlog - from lib.constants.config import mode as _config_mode if _config_mode == "strict": raise _vlog().warning(f"解析类型失败: {_e}", "Exception") @@ -2584,8 +2260,6 @@ class ExprCallHandle(BaseHandle): size_bytes = 8 return ir.Constant(ir.IntType(64), size_bytes) except Exception as _e: - from lib.core.VLogger import get_logger as _vlog - from lib.constants.config import mode as _config_mode if _config_mode == "strict": raise _vlog().warning(f"解析类型失败: {_e}", "Exception") @@ -2597,12 +2271,14 @@ class ExprCallHandle(BaseHandle): if isinstance(struct_type, ir.IdentifiedStructType) and (struct_type.elements is None or len(struct_type.elements) == 0): self.Trans.ImportHandler._TryLoadStructFromStub(type_name, Gen) struct_type = Gen.structs.get(type_name, struct_type) + # Recursively resolve opaque struct members + self._resolve_opaque_struct_members(struct_type, Gen) size = Gen._get_struct_size(struct_type) if size > 0: return ir.Constant(ir.IntType(64), size) return ir.Constant(ir.IntType(64), 0) - def _HandleAbsLlvm(self, arg_node): + def _HandleAbsLlvm(self, arg_node: ast.AST) -> ir.Value | None: Gen = self.Trans.LlvmGen val = self.HandleExprLlvm(arg_node) if not val: @@ -2627,11 +2303,11 @@ class ExprCallHandle(BaseHandle): return Gen.builder.select(is_neg, neg_val, val, name="fabs_result") return None - def _HandleDirLlvm(self, Node): + def _HandleDirLlvm(self, Node: ast.Call) -> ir.Constant: Gen = self.Trans.LlvmGen return ir.Constant(ir.IntType(8).as_pointer(), None) - def _HandleTypeLlvm(self, Node): + def _HandleTypeLlvm(self, Node: ast.Call) -> ir.Value: Gen = self.Trans.LlvmGen if not Node.args: type_str = "" @@ -2653,19 +2329,18 @@ class ExprCallHandle(BaseHandle): type_info = Gen.var_type_info[arg_name] if isinstance(type_info, dict) and type_info.get('type') == 'enum': enum_type_name = type_info.get('name') - if not enum_type_name and self.Trans.SymbolTable.has(arg_name): - TypeInfo = self.Trans.SymbolTable[arg_name] - if TypeInfo.IsEnum: + if not enum_type_name: + TypeInfo = self.Trans.SymbolTable.lookup(arg_name) + if TypeInfo and TypeInfo.IsEnum: enum_type_name = arg_name elif isinstance(arg, ast.Attribute): LastPart = None enum_class_name = None if isinstance(arg.value, ast.Name): LastPart = arg.attr - if self.Trans.SymbolTable.has(LastPart): - AttrInfo = self.Trans.SymbolTable[LastPart] - if AttrInfo.IsEnumMember and AttrInfo.EnumName: - enum_type_name = AttrInfo.EnumName + AttrInfo = self.Trans.SymbolTable.lookup(LastPart) + if AttrInfo and AttrInfo.IsEnumMember and AttrInfo.EnumName: + enum_type_name = AttrInfo.EnumName elif isinstance(arg.value, ast.Attribute): attr_path = _get_attr_path(arg) if attr_path: @@ -2677,11 +2352,10 @@ class ExprCallHandle(BaseHandle): qualified_name_under = f"{enum_class_name}_{LastPart}" enum_member_found = None for qname in (qualified_name_dot, qualified_name_under): - if self.Trans.SymbolTable.has(qname): - info = self.Trans.SymbolTable[qname] - if info.IsEnumMember and info.EnumName == enum_class_name: - enum_member_found = info - break + info = self.Trans.SymbolTable.lookup(qname) + if info and info.IsEnumMember and info.EnumName == enum_class_name: + enum_member_found = info + break if not enum_member_found: for key in self.Trans.SymbolTable: if key == LastPart: @@ -2703,7 +2377,7 @@ class ExprCallHandle(BaseHandle): type_str = f"" return Gen.emit_constant(type_str, 'string') - def _HandleInputLlvm(self, Node): + def _HandleInputLlvm(self, Node: ast.Call) -> ir.Value: Gen = self.Trans.LlvmGen if Node.args and isinstance(Node.args[0], ast.Constant) and isinstance(Node.args[0].value, str): prompt = Node.args[0].value @@ -2715,19 +2389,19 @@ class ExprCallHandle(BaseHandle): result = Gen.builder.call(scanf_func, [Gen.emit_constant("%255s", 'string'), input_buffer]) return Gen.builder.gep(input_buffer, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), 0)], name="input_result") - def _HandleAtoiLlvm(self, str_ptr): + def _HandleAtoiLlvm(self, str_ptr: ir.Value) -> ir.Value: Gen = self.Trans.LlvmGen atoi_func = Gen.get_or_declare_c_func('atoi', ir.FunctionType(ir.IntType(32), [ir.PointerType(ir.IntType(8))])) return Gen.builder.call(atoi_func, [str_ptr], name="atoi_result") - def _HandleOrdLlvm(self, expr_node): + def _HandleOrdLlvm(self, expr_node: ast.AST) -> ir.Value: Gen = self.Trans.LlvmGen val = self.HandleExprLlvm(expr_node) if val and self._is_char_pointer(val): return Gen._load(val, name="ord_result") return ir.Constant(ir.IntType(32), 0) - def _HandleChrLlvm(self, expr_node): + def _HandleChrLlvm(self, expr_node: ast.AST) -> ir.Value: Gen = self.Trans.LlvmGen val = self.HandleExprLlvm(expr_node) if val: @@ -2736,7 +2410,7 @@ class ExprCallHandle(BaseHandle): return Gen.builder.gep(char_ptr, [ir.Constant(ir.IntType(32), 0)], name="chr_result") return ir.Constant(ir.IntType(8).as_pointer(), None) - def _EmitStringFromValue(self, val): + def _EmitStringFromValue(self, val: ir.Value) -> ir.Value: Gen = self.Trans.LlvmGen if isinstance(val.type, ir.IntType): buf = Gen._alloca(ir.IntType(8), name="str_buf", size=ir.Constant(ir.IntType(32), 32)) @@ -2750,7 +2424,7 @@ class ExprCallHandle(BaseHandle): return Gen.builder.gep(buf, [ir.Constant(ir.IntType(32), 0)], name="str_result") return ir.Constant(ir.IntType(8).as_pointer(), None) - def _HandleMallocLlvm(self, args): + def _HandleMallocLlvm(self, args: list[ast.AST]) -> ir.Value: Gen = self.Trans.LlvmGen malloc_type = ir.FunctionType(ir.PointerType(ir.IntType(8)), [ir.IntType(64)]) malloc_func = Gen._get_or_declare_func('malloc', malloc_type) @@ -2769,7 +2443,7 @@ class ExprCallHandle(BaseHandle): result = Gen.builder.call(malloc_func, [size_val], name="malloc_result") return Gen.builder.bitcast(result, ir.IntType(8).as_pointer(), name="malloc_cast") - def _HandleReallocLlvm(self, args): + def _HandleReallocLlvm(self, args: list[ast.AST]) -> ir.Value: Gen = self.Trans.LlvmGen realloc_type = ir.FunctionType(ir.PointerType(ir.IntType(8)), [ir.PointerType(ir.IntType(8)), ir.IntType(64)]) realloc_func = Gen._get_or_declare_func('realloc', realloc_type) @@ -2796,7 +2470,7 @@ class ExprCallHandle(BaseHandle): result = Gen.builder.call(realloc_func, [ptr_val, size_val], name="realloc_result") return Gen.builder.bitcast(result, ir.IntType(8).as_pointer(), name="realloc_cast") - def _HandleFreeLlvm(self, args): + def _HandleFreeLlvm(self, args: list[ast.AST]) -> ir.Constant: Gen = self.Trans.LlvmGen free_type = ir.FunctionType(ir.VoidType(), [ir.PointerType(ir.IntType(8))]) free_func = Gen._get_or_declare_func('free', free_type) @@ -2815,7 +2489,7 @@ class ExprCallHandle(BaseHandle): Gen.builder.call(free_func, [ptr_val], name="free_call") return ir.Constant(ir.IntType(32), 0) - def _HandleMemcpyLlvm(self, args): + def _HandleMemcpyLlvm(self, args: list[ast.AST]) -> None: Gen = self.Trans.LlvmGen if 'llvm.memcpy' not in Gen.functions: memcpy_type = ir.FunctionType(ir.VoidType(), [ir.PointerType(ir.IntType(8)), ir.PointerType(ir.IntType(8)), ir.IntType(64), ir.IntType(1)]) @@ -2844,7 +2518,7 @@ class ExprCallHandle(BaseHandle): Gen.builder.call(Gen.functions['llvm.memcpy'], [dst, src, size, isvolatile], name="memcpy_call") return None - def _HandleMemsetLlvm(self, args): + def _HandleMemsetLlvm(self, args: list[ast.AST]) -> None: Gen = self.Trans.LlvmGen memset_func = Gen.get_or_declare_c_func('memset', ir.FunctionType(ir.PointerType(ir.IntType(8)), [ir.PointerType(ir.IntType(8)), ir.IntType(32), ir.IntType(64)])) if len(args) >= 3: @@ -2866,15 +2540,15 @@ class ExprCallHandle(BaseHandle): Gen.builder.call(memset_func, [dst, val, size], name="memset_call") return None - def _HandleVaStartLlvm(self, args): + def _HandleVaStartLlvm(self, args: list[ast.AST]) -> None: Gen = self.Trans.LlvmGen return None - def _HandleVaEndLlvm(self, args): + def _HandleVaEndLlvm(self, args: list[ast.AST]) -> None: Gen = self.Trans.LlvmGen return None - def _HandleArgLlvm(self, args, CallNode=None): + def _HandleArgLlvm(self, args: list[ast.AST], CallNode: ast.Call | None = None) -> ir.Value | None: Gen = self.Trans.LlvmGen va_list_ptr = None variadic_info = getattr(Gen, '_va_arg_info', None) @@ -2893,7 +2567,6 @@ class ExprCallHandle(BaseHandle): type_arg = args[0] if isinstance(type_arg, ast.Name): type_name = type_arg.id - from lib.includes.t import CTypeRegistry if type_name in ('str', 'bytes'): target_type = ir.PointerType(ir.IntType(8)) elif type_name == 'CPtr': @@ -2922,9 +2595,8 @@ class ExprCallHandle(BaseHandle): base = ir.PointerType(base) target_type = base elif isinstance(type_arg, ast.Attribute): - if isinstance(type_arg.value, ast.Name) and type_arg.value.id == 't': + if isinstance(type_arg.value, ast.Name) and IsTModule(type_arg.value.id, self.Trans.SymbolTable): attr_name = type_arg.attr - from lib.includes.t import CTypeRegistry ctype_cls = CTypeRegistry.GetClassByName(attr_name) if ctype_cls is not None: llvm_str = CTypeRegistry.CTypeToLLVM(ctype_cls) @@ -2942,13 +2614,8 @@ class ExprCallHandle(BaseHandle): elif isinstance(ann, ast.Attribute): ann_name = ann.attr elif isinstance(ann, ast.BinOp) and isinstance(ann.op, ast.BitOr): - left = ann.left - if isinstance(left, ast.Name): - ann_name = left.id - elif isinstance(left, ast.Attribute): - ann_name = left.attr + ann_name = ExtractTypeNameFromBinOp(ann) if ann_name: - from lib.includes.t import CTypeRegistry ctype_cls = CTypeRegistry.GetClassByName(ann_name) if ctype_cls is not None: llvm_str = CTypeRegistry.CTypeToLLVM(ctype_cls) @@ -2964,22 +2631,22 @@ class ExprCallHandle(BaseHandle): result.name = f"va_arg_result_{Gen._va_arg_counter}" return result - def _HandleVaArgLlvm(self, args): - Gen = self.Trans.LlvmGen + def _HandleVaArgLlvm(self, args: list[ast.AST]) -> ir.Constant: + Gen: LlvmGeneratorMixin = self.Trans.LlvmGen return ir.Constant(ir.IntType(32), 0) - def _HandleCDerefAsLlvm(self, Node): - Gen = self.Trans.LlvmGen + def _HandleCDerefAsLlvm(self, Node: ast.Call) -> ir.Constant: + Gen: LlvmGeneratorMixin = self.Trans.LlvmGen if len(Node.args) < 2: return ir.Constant(ir.IntType(32), 0) - ptr_val = self.HandleExprLlvm(Node.args[0]) - val_val = self.HandleExprLlvm(Node.args[1]) + ptr_val: ir.Value | None = self.HandleExprLlvm(Node.args[0]) + val_val: ir.Value | None = self.HandleExprLlvm(Node.args[1]) if ptr_val is None or val_val is None: return ir.Constant(ir.IntType(32), 0) if isinstance(ptr_val.type, ir.PointerType): - store_val = val_val + store_val: ir.Value = val_val if isinstance(val_val.type, ir.PointerType): - void_pp = ir.PointerType(ir.PointerType(ir.IntType(8))) + void_pp: ir.PointerType = ir.PointerType(ir.PointerType(ir.IntType(8))) if ptr_val.type != void_pp: ptr_val = Gen.builder.bitcast(ptr_val, void_pp, name="deref_as_pp") if val_val.type.pointee != ir.IntType(8): @@ -3005,8 +2672,68 @@ class ExprCallHandle(BaseHandle): Gen.builder.store(store_val, ptr_val) return ir.Constant(ir.IntType(32), 0) - def _HandleClassNewLlvm(self, Node, ClassName): - Gen = self.Trans.LlvmGen + def _InjectRequiresFields(self, result: ir.Value, ClassName: str, Gen: LlvmGeneratorMixin) -> None: + """在 __new__ 后、__init__ 前自动注入 __requires__/__require_must__ 字段。 + + - 编译期:对 __require_must__ 做纯静态可达性检查(遍历 _with_provides_stack) + - 运行时:对每个 requires 字段调用 _find_provider,非 NULL 则 bitcast 写入 + """ + requires_all: list[str] = [] + requires_all.extend(Gen.class_requires.get(ClassName, [])) + requires_all.extend(Gen.class_require_must.get(ClassName, [])) + if not requires_all: + return + # 编译期 __require_must__ 静态检查 + must_fields: list[str] = Gen.class_require_must.get(ClassName, []) + if must_fields: + # 跳过类自身方法内的检查(类的实现内部不需要 with 上下文) + current_class = getattr(Gen, '_current_class_name', None) + if current_class != ClassName: + available: set[str] = set() + for provides_list in Gen._with_provides_stack: + available.update(provides_list) + for field in must_fields: + if field not in available: + raise SyntaxError( + f"[TransPyC] Class '{ClassName}' __require_must__ field '{field}' " + f"not provided by any enclosing 'with' context" + ) + # 运行时注入 + find_func = Gen.functions.get('_find_provider') + if not find_func: + return + members = Gen.class_members.get(ClassName, []) + has_vtable = ClassName in Gen.class_vtable + base = 1 if has_vtable else 0 + field_map: dict[str, tuple[int, ir.Type]] = {} + for i, (mname, mtype) in enumerate(members): + if mname in requires_all: + field_map[mname] = (base + i, mtype) + for field_name in requires_all: + if field_name not in field_map: + continue + field_idx, field_type = field_map[field_name] + field_str = Gen._create_string_global(field_name) + ptr_val = Gen.builder.call(find_func, [field_str], name=f"find_{field_name}") + null_ptr = ir.Constant(ptr_val.type, None) + is_null = Gen.builder.icmp_unsigned('==', ptr_val, null_ptr, name=f"is_null_{field_name}") + skip_bb = Gen.func.append_basic_block(f"skip_inject_{field_name}") + inject_bb = Gen.func.append_basic_block(f"inject_{field_name}") + Gen.builder.cbranch(is_null, skip_bb, inject_bb) + Gen.builder.position_at_end(inject_bb) + if isinstance(field_type, ir.PointerType): + casted = Gen.builder.bitcast(ptr_val, field_type, name=f"cast_{field_name}") + elif isinstance(field_type, ir.IntType): + casted = Gen.builder.ptrtoint(ptr_val, field_type, name=f"cast_{field_name}") + else: + casted = Gen.builder.bitcast(ptr_val, ir.PointerType(ir.IntType(8)), name=f"cast_{field_name}") + elem_ptr = Gen.builder.gep(result, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), field_idx)], name=f"field_{field_name}_ptr") + Gen._store(casted, elem_ptr) + Gen.builder.branch(skip_bb) + Gen.builder.position_at_end(skip_bb) + + def _HandleClassNewLlvm(self, Node: ast.Call, ClassName: str) -> ir.Value: + Gen: LlvmGeneratorMixin = self.Trans.LlvmGen if hasattr(self.Trans.ClassHandler, '_generic_class_templates') and ClassName in self.Trans.ClassHandler._generic_class_templates: return self._HandleGenericClassNewLlvm(Node, ClassName) NewFuncName = f'{ClassName}.__before_init__' @@ -3034,6 +2761,7 @@ class ExprCallHandle(BaseHandle): if ArgVal: NewMethodArgs.append(ArgVal) self._fill_default_args(NewMethodArgs, NewMethodFunc, NewMethodFuncName) + NewMethodArgs = Gen._apply_auto_addr(NewMethodFuncName, NewMethodArgs) adjusted_new = Gen._adjust_args(NewMethodArgs, NewMethodFunc) heap_ptr = Gen.builder.call(NewMethodFunc, adjusted_new, name=f"new_{ClassName}") if heap_ptr: @@ -3051,6 +2779,8 @@ class ExprCallHandle(BaseHandle): result = Gen.builder.inttoptr(i64_val, target_ptr_type, name=f"new_{ClassName}_ptr") else: result = Gen.builder.inttoptr(heap_ptr, target_ptr_type, name=f"new_{ClassName}_ptr") + # __new__ 后、__init__ 前:自动注入 requires 字段 + self._InjectRequiresFields(result, ClassName, Gen) if Gen._has_function(InitFuncName): InitFunc = Gen._get_function(InitFuncName) InitArgs = [result] @@ -3064,6 +2794,7 @@ class ExprCallHandle(BaseHandle): InitArgs.append(ArgVal) self._fill_default_args(InitArgs, InitFunc, InitFuncName) self._append_eh_msg_out_arg(InitArgs, InitFunc, Gen) + InitArgs = Gen._apply_auto_addr(InitFuncName, InitArgs) adjusted_init = Gen._adjust_args(InitArgs, InitFunc) Gen.builder.call(InitFunc, adjusted_init, name=f"init_{ClassName}") return result @@ -3079,29 +2810,7 @@ class ExprCallHandle(BaseHandle): StructType = StructType.pointee is_opaque = isinstance(StructType, ir.IdentifiedStructType) and (StructType.elements is None or len(StructType.elements) == 0) if is_opaque: - result = Gen._allocaEntry(StructType, name=f"{ClassName}_alloca") - Gen.builder.store(ir.Constant(StructType, None), result) - InitFunc = Gen.functions.get(InitFuncName) - if not InitFunc: - g = Gen.module.globals.get(InitFuncName) - if g and isinstance(g, ir.Function): - Gen.functions[InitFuncName] = g - InitFunc = g - if InitFunc: - InitArgs = [result] - for arg in Node.args: - ArgVal = self.HandleExprLlvm(arg) - if ArgVal: - InitArgs.append(ArgVal) - for kw in Node.keywords: - ArgVal = self.HandleExprLlvm(kw.value) - if ArgVal: - InitArgs.append(ArgVal) - self._fill_default_args(InitArgs, InitFunc, InitFuncName) - self._append_eh_msg_out_arg(InitArgs, InitFunc, Gen) - adjusted_init = Gen._adjust_args(InitArgs, InitFunc) - Gen.builder.call(InitFunc, adjusted_init, name=f"init_{ClassName}") - return result + return None result = Gen._allocaEntry(StructType, name=f"{ClassName}_alloca") # Call __new__ method if it exists (may replace self with heap pointer) if has_new_method: @@ -3117,6 +2826,7 @@ class ExprCallHandle(BaseHandle): if ArgVal: NewMethodArgs.append(ArgVal) self._fill_default_args(NewMethodArgs, NewMethodFunc, NewMethodFuncName) + NewMethodArgs = Gen._apply_auto_addr(NewMethodFuncName, NewMethodArgs) adjusted_new = Gen._adjust_args(NewMethodArgs, NewMethodFunc) heap_ptr = Gen.builder.call(NewMethodFunc, adjusted_new, name=f"new_{ClassName}") if heap_ptr: @@ -3134,6 +2844,8 @@ class ExprCallHandle(BaseHandle): result = Gen.builder.inttoptr(i64_val, target_ptr_type, name=f"new_{ClassName}_ptr") else: result = Gen.builder.inttoptr(heap_ptr, target_ptr_type, name=f"new_{ClassName}_ptr") + # __new__ 后、__init__ 前:自动注入 requires 字段 + self._InjectRequiresFields(result, ClassName, Gen) InitFunc = Gen.functions.get(InitFuncName) if not InitFunc: g = Gen.module.globals.get(InitFuncName) @@ -3161,6 +2873,7 @@ class ExprCallHandle(BaseHandle): InitArgs.append(ArgVal) self._fill_default_args(InitArgs, InitFunc, InitFuncName) self._append_eh_msg_out_arg(InitArgs, InitFunc, Gen) + InitArgs = Gen._apply_auto_addr(InitFuncName, InitArgs) adjusted_init = Gen._adjust_args(InitArgs, InitFunc) Gen.builder.call(InitFunc, adjusted_init, name=f"init_{ClassName}") elif Node.args or Node.keywords: @@ -3171,8 +2884,8 @@ class ExprCallHandle(BaseHandle): return result return ir.Constant(ir.IntType(32), 0) - def _ZeroInitStruct(self, struct_ptr, StructType): - Gen = self.Trans.LlvmGen + def _ZeroInitStruct(self, struct_ptr: ir.Value, StructType: ir.Type) -> None: + Gen: LlvmGeneratorMixin = self.Trans.LlvmGen if isinstance(StructType, ir.IdentifiedStructType) and StructType.elements: for i, elem_type in enumerate(StructType.elements): elem_ptr = Gen.builder.gep(struct_ptr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), i)], name=f"zero_elem_{i}") @@ -3185,7 +2898,7 @@ class ExprCallHandle(BaseHandle): zero_arr = ir.Constant(StructType, None) Gen._store(zero_arr, struct_ptr) - def _GetZeroValue(self, typ): + def _GetZeroValue(self, typ: ir.Type) -> ir.Constant | None: if isinstance(typ, ir.IntType): return ir.Constant(typ, 0) elif isinstance(typ, ir.PointerType): @@ -3196,10 +2909,10 @@ class ExprCallHandle(BaseHandle): return ir.Constant(typ, None) return None - def _InitStructDefaults(self, struct_ptr, ClassName, StructType): - Gen = self.Trans.LlvmGen - defaults = Gen.class_member_defaults.get(ClassName, {}) - members = Gen.class_members.get(ClassName, []) + def _InitStructDefaults(self, struct_ptr: ir.Value, ClassName: str, StructType: ir.Type) -> None: + Gen: LlvmGeneratorMixin = self.Trans.LlvmGen + defaults: dict = Gen.class_member_defaults.get(ClassName, {}) + members: list[tuple] = Gen.class_members.get(ClassName, []) if not defaults or not members: return if not isinstance(StructType, ir.IdentifiedStructType): @@ -3213,8 +2926,8 @@ class ExprCallHandle(BaseHandle): elem_ptr = Gen.builder.gep(struct_ptr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), base + i)], name=f"default_{ClassName}_{member_name}") Gen._store(default_val, elem_ptr) - def _InitStructFromArgs(self, struct_ptr, Node, ClassName, StructType): - Gen = self.Trans.LlvmGen + def _InitStructFromArgs(self, struct_ptr: ir.Value, Node: ast.Call, ClassName: str, StructType: ir.Type) -> None: + Gen: LlvmGeneratorMixin = self.Trans.LlvmGen if not isinstance(StructType, ir.IdentifiedStructType): return members = Gen.class_members.get(ClassName, []) @@ -3263,9 +2976,9 @@ class ExprCallHandle(BaseHandle): elem_ptr = Gen.builder.gep(struct_ptr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), elem_idx)], name=f"init_elem_{ClassName}_{kw.arg}") Gen._store(val, elem_ptr) - def _HandleSubscriptPtrLlvm(self, Node): - Gen = self.Trans.LlvmGen - ClassName = self.Trans.ExprHandler._get_var_class(Node.value, Gen) + def _HandleSubscriptPtrLlvm(self, Node: ast.Subscript) -> ir.Value | None: + Gen: LlvmGeneratorMixin = self.Trans.LlvmGen + ClassName: str | None = self.Trans.ExprHandler._get_var_class(Node.value, Gen) if ClassName and ClassName in Gen.structs and Gen._has_function(f'{ClassName}.__getitem__'): obj_val = self.HandleExprLlvm(Node.value) idx_val = self.HandleExprLlvm(Node.slice) @@ -3334,12 +3047,12 @@ class ExprCallHandle(BaseHandle): return ElemPtr return None - def _HandleGenericCallLlvm(self, Node, FuncName): - Gen = self.Trans.LlvmGen - template = self.Trans.FunctionHandler._generic_templates[FuncName] - type_param_names = template['type_params'] - type_args = [] - CallArgs = [] + def _HandleGenericCallLlvm(self, Node: ast.Call, FuncName: str) -> ir.Value | None: + Gen: LlvmGeneratorMixin = self.Trans.LlvmGen + template: dict = self.Trans.FunctionHandler._generic_templates[FuncName] + type_param_names: list[str] = template['type_params'] + type_args: list[str] = [] + CallArgs: list[ir.Value] = [] for i, arg_node in enumerate(Node.args): arg_val = self.HandleExprLlvm(arg_node) if arg_val: @@ -3369,16 +3082,56 @@ class ExprCallHandle(BaseHandle): return None if not CallArgs: CallArgs = [ir.Constant(ir.IntType(32), 0) for _ in func.args] + CallArgs = Gen._apply_auto_addr(spec_name, CallArgs) adjusted = Gen._adjust_args(CallArgs, func) return Gen.builder.call(func, adjusted, name=f"call_{spec_name}") - def _HandleGenericClassNewLlvm(self, Node, ClassName): - Gen = self.Trans.LlvmGen - template = self.Trans.ClassHandler._generic_class_templates[ClassName] - type_param_names = template['type_params'] - type_args = [] - type_names = [] - all_inferred = [] + def _HandleGenericClassNewLlvm(self, Node: ast.Call, ClassName: str, explicit_slice: ast.AST | None = None) -> ir.Value: + Gen: LlvmGeneratorMixin = self.Trans.LlvmGen + template: dict = self.Trans.ClassHandler._generic_class_templates[ClassName] + type_param_names: list[str] = template['type_params'] + type_args: list[str] = [] + type_names: list[str] = [] + # 如果有显式类型参数 (如 list[int](mb)),直接从 slice 提取 + if explicit_slice is not None: + slice_nodes: list[ast.AST] = [] + if isinstance(explicit_slice, ast.Tuple): + slice_nodes = list(explicit_slice.elts) + else: + slice_nodes = [explicit_slice] + for sn in slice_nodes: + if isinstance(sn, ast.Name): + tn: str = sn.id + ts: str = 'int' + # 映射 Viper 内建类型到 (type_str, type_name) + if tn == 'int': + ts, tn = 'int', 'CInt' + elif tn == 'double': + ts, tn = 'double', 'CDouble' + elif tn == 'float': + ts, tn = 'float', 'CFloat' + elif tn == 'char': + ts, tn = 'i8', 'CChar' + elif tn == 'bool': + ts, tn = 'i8', 'CBool' + elif tn in ('CInt', 'CUInt', 'CInt32T', 'CUInt32T', 'CInt64T', 'CUInt64T', 'CInt16T', 'CUInt16T', 'CInt8T', 'CUInt8T', 'CChar', 'CShort', 'CLong'): + ts = 'int' + elif tn in ('CDouble', 'CFloat', 'CFloat64T', 'CFloat32T'): + ts = 'double' + else: + # 自定义结构体类型,直接用名称 + ts = tn + type_args.append(ts) + type_names.append(tn) + # 补齐缺少的类型参数 + while len(type_args) < len(type_param_names): + type_args.append('int') + type_names.append('CInt') + spec_name = self.Trans.ClassHandler._specialize_generic_class(ClassName, type_args, Gen, type_names=type_names) + if spec_name is None: + return ir.Constant(ir.IntType(32), 0) + return self._HandleClassNewLlvm(Node, spec_name) + all_inferred: list[tuple[str, str]] = [] for i, arg_node in enumerate(Node.args): type_str = 'int' type_name = 'CInt' diff --git a/lib/core/Handles/HandlesExprFormat.py b/lib/core/Handles/HandlesExprFormat.py index a0ab30b..02693cf 100644 --- a/lib/core/Handles/HandlesExprFormat.py +++ b/lib/core/Handles/HandlesExprFormat.py @@ -1,110 +1,271 @@ -from __future__ import annotations -from typing import TYPE_CHECKING -if TYPE_CHECKING: - from lib.core.translator import Translator -from lib.core.Handles.HandlesBase import BaseHandle -import ast -import llvmlite.ir as ir - - -class ExprFormatHandle(BaseHandle): - def _HandleJoinedStrLlvm(self, Node, return_str=False): - Gen = self.Trans.LlvmGen - if not Gen or not Gen.builder: - return ir.Constant(ir.IntType(8).as_pointer(), None) - format_str = "" - cast_args = [] - for part in Node.values: - if isinstance(part, ast.Constant) and isinstance(part.value, str): - format_str += part.value.replace('\\', '\\\\').replace('%', '%%').replace('\n', '\\n').replace('\t', '\\t').replace('\0', '\\0') - elif isinstance(part, ast.FormattedValue): - fmt_class = self.Trans.ExprHandler._get_var_class(part.value, Gen) - if fmt_class and Gen._has_function(f'{fmt_class}.__str__'): - obj_val = self.HandleExprLlvm(part.value) - if obj_val: - if isinstance(obj_val.type, ir.PointerType) and isinstance(obj_val.type.pointee, ir.IntType) and obj_val.type.pointee.width == 8: - if fmt_class in Gen.structs: - obj_val = Gen.builder.bitcast(obj_val, ir.PointerType(Gen.structs[fmt_class]), name=f"cast_{fmt_class}") - val = Gen.builder.call(Gen._get_function(f'{fmt_class}.__str__'), [obj_val], name=f"call_{fmt_class}.__str__") - Gen.RegisterTempPtr(val) - format_str += "%s" - cast_args.append(val) - else: - format_str += "%s" - cast_args.append(ir.Constant(ir.PointerType(ir.IntType(8)), None)) - continue - val = self.HandleExprLlvm(part.value) - if not val: - format_str += "%d" - cast_args.append(ir.Constant(ir.IntType(32), 0)) - continue - if isinstance(val.type, ir.PointerType): - pointee = val.type.pointee - if isinstance(pointee, ir.IntType) and pointee.width == 8: - format_str += "%s" - cast_args.append(val) - elif isinstance(pointee, (ir.LiteralStructType, ir.IdentifiedStructType)): - int_val = Gen.builder.ptrtoint(val, ir.IntType(64), name="fstr_ptr2int") - trunc_val = Gen.builder.trunc(int_val, ir.IntType(32), name="fstr_trunc") - format_str += "%d" - cast_args.append(trunc_val) - else: - Loaded = Gen._load(val, name="fstr_deref") - if isinstance(Loaded.type, ir.IntType): - if Loaded.type.width == 8: - format_str += "%c" - ext = Gen.builder.zext(Loaded, ir.IntType(32), name="fstr_char2int") - cast_args.append(ext) - else: - format_str += "%d" - cast_args.append(Loaded) - elif isinstance(Loaded.type, (ir.FloatType, ir.DoubleType)): - format_str += "%f" - cast_args.append(Loaded) - elif isinstance(Loaded.type, ir.PointerType): - format_str += "%s" - cast_args.append(Loaded) - else: - format_str += "%d" - cast_args.append(Loaded) - elif isinstance(val.type, ir.IntType): - if val.type.width == 8: - format_str += "%c" - ext = Gen.builder.zext(val, ir.IntType(32), name="fstr_char2int") - cast_args.append(ext) - elif val.type.width == 1: - zext = Gen.builder.zext(val, ir.IntType(32), name="fstr_bool2int") - format_str += "%d" - cast_args.append(zext) - else: - is_u = Gen._check_node_unsigned(part.value) - format_str += "%u" if is_u else "%d" - cast_args.append(val) - elif isinstance(val.type, (ir.FloatType, ir.DoubleType)): - format_str += "%f" - cast_args.append(val) - else: - format_str += "%d" - cast_args.append(val) - if not format_str and not cast_args: - return Gen.emit_constant("", 'string') - encoded = format_str.encode('utf-8') + b'\x00' - string_type = ir.ArrayType(ir.IntType(8), len(encoded)) - string_const = ir.Constant(string_type, bytearray(encoded)) - global_var = ir.GlobalVariable(Gen.module, string_type, name=f"str_const_{Gen.string_const_counter}") - Gen.string_const_counter += 1 - global_var.initializer = string_const - global_var.linkage = 'internal' - format_ptr = Gen.builder.bitcast(global_var, ir.PointerType(ir.IntType(8))) - if return_str: - buf_size = ir.Constant(ir.IntType(64), 1024) - calloc_type = ir.FunctionType(ir.PointerType(ir.IntType(8)), [ir.IntType(64), ir.IntType(64)]) - calloc_func = Gen._get_or_declare_func('calloc', calloc_type) - buf_ptr = Gen.builder.call(calloc_func, [ir.Constant(ir.IntType(64), 1), buf_size], name="call_calloc_buf") - sprintf_func = Gen.get_or_declare_c_func('sprintf', ir.FunctionType(ir.IntType(32), [ir.PointerType(ir.IntType(8)), ir.PointerType(ir.IntType(8))], var_arg=True)) - sprintf_args = [buf_ptr, format_ptr] + cast_args - Gen.builder.call(sprintf_func, sprintf_args, name="call_sprintf") - return buf_ptr - printf_func = Gen.get_or_declare_c_func('printf', ir.FunctionType(ir.IntType(32), [ir.PointerType(ir.IntType(8))], var_arg=True)) - call_args = [format_ptr] + cast_args - return Gen.builder.call(printf_func, call_args, name="call_fstring") +from __future__ import annotations +from typing import TYPE_CHECKING, Any +if TYPE_CHECKING: + from lib.core.translator import Translator + from lib.core.LlvmCodeGenerator import LlvmCodeGenerator +from lib.core.Handles.HandlesBase import BaseHandle +import ast +import re +import llvmlite.ir as ir + + +class ExprFormatHandle(BaseHandle): + def _HandleJoinedStrLlvm(self, Node: ast.JoinedStr) -> ir.Value: + Gen: LlvmCodeGenerator = self.Trans.LlvmGen + if not Gen or not Gen.builder: + return ir.Constant(ir.IntType(8).as_pointer(), None) + format_str: str = "" + cast_args: list[Any] = [] + for part in Node.values: + if isinstance(part, ast.Constant) and isinstance(part.value, str): + format_str += part.value.replace('\\', '\\\\').replace('%', '%%').replace('\n', '\\n').replace('\t', '\\t').replace('\0', '\\0') + elif isinstance(part, ast.FormattedValue): + fmt_class: str | None = self.Trans.ExprHandler._get_var_class(part.value, Gen) + if fmt_class and Gen._has_function(f'{fmt_class}.__str__'): + obj_val: Any = self.HandleExprLlvm(part.value) + if obj_val: + if isinstance(obj_val.type, ir.PointerType) and isinstance(obj_val.type.pointee, ir.IntType) and obj_val.type.pointee.width == 8: + if fmt_class in Gen.structs: + obj_val = Gen.builder.bitcast(obj_val, ir.PointerType(Gen.structs[fmt_class]), name=f"cast_{fmt_class}") + val: Any = Gen.builder.call(Gen._get_function(f'{fmt_class}.__str__'), [obj_val], name=f"call_{fmt_class}.__str__") + Gen._RegisterTempPtr(val) + format_str += "%s" + cast_args.append(val) + else: + format_str += "%s" + cast_args.append(ir.Constant(ir.PointerType(ir.IntType(8)), None)) + continue + val = self.HandleExprLlvm(part.value) + if not val: + format_str += "%d" + cast_args.append(ir.Constant(ir.IntType(32), 0)) + continue + # 检查 format_spec(Python f-string 格式说明符) + if part.format_spec is not None: + c_fmt: str | None = self._parse_format_spec(part.format_spec, val) + if c_fmt is not None: + cast_val: Any = self._cast_value_for_format(val, c_fmt, Gen, part.value) + format_str += c_fmt + cast_args.append(cast_val) + continue + if isinstance(val.type, ir.PointerType): + pointee: ir.Type = val.type.pointee + if isinstance(pointee, ir.IntType) and pointee.width == 8: + format_str += "%s" + cast_args.append(val) + elif isinstance(pointee, (ir.LiteralStructType, ir.IdentifiedStructType)): + int_val: Any = Gen.builder.ptrtoint(val, ir.IntType(64), name="fstr_ptr2int") + trunc_val: Any = Gen.builder.trunc(int_val, ir.IntType(32), name="fstr_trunc") + format_str += "%d" + cast_args.append(trunc_val) + else: + Loaded: Any = Gen._load(val, name="fstr_deref") + if isinstance(Loaded.type, ir.IntType): + if Loaded.type.width == 8: + format_str += "%c" + ext: Any = Gen.builder.zext(Loaded, ir.IntType(32), name="fstr_char2int") + cast_args.append(ext) + else: + format_str += "%d" + cast_args.append(Loaded) + elif isinstance(Loaded.type, (ir.FloatType, ir.DoubleType)): + format_str += "%f" + cast_args.append(Loaded) + elif isinstance(Loaded.type, ir.PointerType): + format_str += "%s" + cast_args.append(Loaded) + else: + format_str += "%d" + cast_args.append(Loaded) + elif isinstance(val.type, ir.IntType): + if val.type.width == 8: + format_str += "%c" + ext = Gen.builder.zext(val, ir.IntType(32), name="fstr_char2int") + cast_args.append(ext) + elif val.type.width == 1: + zext: Any = Gen.builder.zext(val, ir.IntType(32), name="fstr_bool2int") + format_str += "%d" + cast_args.append(zext) + else: + is_u: bool = Gen._check_node_unsigned(part.value) + format_str += "%u" if is_u else "%d" + cast_args.append(val) + elif isinstance(val.type, (ir.FloatType, ir.DoubleType)): + format_str += "%f" + cast_args.append(val) + else: + format_str += "%d" + cast_args.append(val) + if not format_str: + return Gen.emit_constant("", 'string') + format_ptr: Any = Gen._create_string_global(format_str) + # 统一使用 snprintf 生成字符串,返回 i8* + # __str__ 方法内使用堆分配(返回值需持久化),其他场景使用栈分配(自动释放) + in_str_method: bool = bool(getattr(Gen, 'func', None) and getattr(Gen.func, 'name', '').endswith('.__str__')) + snprintf_type: ir.FunctionType = ir.FunctionType(ir.IntType(32), [ + ir.PointerType(ir.IntType(8)), + ir.IntType(64), + ir.PointerType(ir.IntType(8)) + ], var_arg=True) + snprintf_func: Any = Gen.get_or_declare_c_func('snprintf', snprintf_type) + null_ptr: ir.Constant = ir.Constant(ir.PointerType(ir.IntType(8)), None) + # 第一遍:获取所需长度(NULL 缓冲,size=0) + len_val: ir.Value = Gen.builder.call(snprintf_func, [null_ptr, ir.Constant(ir.IntType(64), 0), format_ptr] + cast_args, name="fstr_len") + # 加 1 用于 null 终止符 + size_val: ir.Value = Gen.builder.add(len_val, ir.Constant(ir.IntType(32), 1), name="fstr_size") + size_ext: ir.Value = Gen.builder.zext(size_val, ir.IntType(64), name="fstr_size_ext") + if in_str_method: + # 堆分配(__str__ 返回值需跨函数生命周期) + malloc_type: ir.FunctionType = ir.FunctionType(ir.PointerType(ir.IntType(8)), [ir.IntType(64)]) + malloc_func: Any = Gen._get_or_declare_func('malloc', malloc_type) + buf_ptr: ir.Value = Gen.builder.call(malloc_func, [size_ext], name="fstr_heap_buf") + Gen.builder.call(snprintf_func, [buf_ptr, size_ext, format_ptr] + cast_args, name="fstr_snprintf") + Gen._RegisterTempPtr(buf_ptr) + return buf_ptr + # 栈分配(局部使用,自动释放) + buf_ptr: ir.Value = Gen._alloca(ir.IntType(8), name="fstr_stack_buf", size=size_val) + Gen.builder.call(snprintf_func, [buf_ptr, size_ext, format_ptr] + cast_args, name="fstr_snprintf") + return buf_ptr + + def _parse_format_spec(self, format_spec_node: ast.AST, val: ir.Value) -> str | None: + """将 Python f-string format_spec 转换为 C printf 格式说明符。 + + 支持: d/x/X/o/c/f/s 及 [[fill]align][sign][#][0][width][.precision][type] 语法。 + 返回 None 表示无法解析,调用方应回退到类型推断。 + """ + if isinstance(format_spec_node, ast.JoinedStr): + parts: list[str] = [] + for v in format_spec_node.values: + if isinstance(v, ast.Constant) and isinstance(v.value, str): + parts.append(v.value) + else: + return None + spec_str: str = ''.join(parts) + elif isinstance(format_spec_node, ast.Constant) and isinstance(format_spec_node.value, str): + spec_str = format_spec_node.value + else: + return None + + if not spec_str: + return None + + m: Any = re.match(r'^(.?[<>=^])?([+\- ])?(#)?(0)?(\d+)?(,)?(\.\d+)?([bcdeEfFgGnosxX%])?$', spec_str) + if not m: + return None + + fill_align, sign, alt, zero, width, comma, precision, fmt_type = m.groups() + + c_flags: str = '' + if sign == '+': + c_flags += '+' + elif sign == ' ': + c_flags += ' ' + if alt: + c_flags += '#' + + if fill_align: + align_char: str = fill_align[-1] if len(fill_align) > 1 else fill_align[0] + if align_char in ('<', '^'): + c_flags += '-' + if zero: + c_flags += '0' + + c_width: str = width or '' + c_precision: str = precision or '' + + length_mod: str = '' + if isinstance(val.type, ir.IntType): + if val.type.width == 64: + length_mod = 'll' + elif val.type.width == 32: + length_mod = 'l' + elif val.type.width == 16: + length_mod = 'h' + elif val.type.width == 8: + length_mod = 'hh' + + c_specifier: str = '' + if fmt_type in ('d', 'n'): + c_specifier = f'{length_mod}d' + elif fmt_type == 'x': + c_specifier = f'{length_mod}x' + elif fmt_type == 'X': + c_specifier = f'{length_mod}X' + elif fmt_type == 'o': + c_specifier = f'{length_mod}o' + elif fmt_type == 'b': + return None + elif fmt_type == 'c': + c_specifier = 'c' + elif fmt_type in ('f', 'F'): + c_specifier = 'f' + elif fmt_type in ('e', 'E', 'g', 'G'): + c_specifier = fmt_type + elif fmt_type == 's': + c_specifier = 's' + elif fmt_type == '%': + c_specifier = 'f%%' + else: + if isinstance(val.type, ir.IntType): + if val.type.width == 8: + c_specifier = 'c' + elif val.type.width == 1: + c_specifier = 'd' + else: + c_specifier = f'{length_mod}d' + elif isinstance(val.type, (ir.FloatType, ir.DoubleType)): + c_specifier = 'f' + elif isinstance(val.type, ir.PointerType): + c_specifier = 's' + else: + c_specifier = 'd' + + return f'%{c_flags}{c_width}{c_precision}{c_specifier}' + + def _cast_value_for_format(self, val: ir.Value, c_fmt: str, Gen: Any, arg_node: ast.AST) -> ir.Value: + """根据 C printf 格式说明符转换值类型。""" + fmt_type_char: str = '' + for ch in reversed(c_fmt): + if ch.isalpha() and ch not in ('l', 'h'): + fmt_type_char = ch + break + elif ch == '%': + break + + if fmt_type_char == 's': + if isinstance(val.type, ir.PointerType): + pointee: ir.Type = val.type.pointee + if isinstance(pointee, ir.IntType) and pointee.width == 8: + return val + if isinstance(pointee, ir.ArrayType) and isinstance(pointee.element, ir.IntType) and pointee.element.width == 8: + return Gen.builder.gep(val, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), 0)], name="fstr_arr2ptr") + return val + elif fmt_type_char == 'c': + if isinstance(val.type, ir.IntType) and val.type.width < 32: + return Gen.builder.zext(val, ir.IntType(32), name="fstr_zext_c") + return val + elif fmt_type_char in ('d', 'x', 'X', 'o', 'i'): + if isinstance(val.type, ir.IntType): + if val.type.width == 8: + is_u: bool = Gen._check_node_unsigned(arg_node) + if is_u: + return Gen.builder.zext(val, ir.IntType(32), name="fstr_zext_i8") + return Gen.builder.sext(val, ir.IntType(32), name="fstr_sext_i8") + elif val.type.width == 16: + is_u = Gen._check_node_unsigned(arg_node) + if is_u: + return Gen.builder.zext(val, ir.IntType(32), name="fstr_zext_i16") + return Gen.builder.sext(val, ir.IntType(32), name="fstr_sext_i16") + elif val.type.width == 1: + return Gen.builder.zext(val, ir.IntType(32), name="fstr_zext_bool") + return val + elif isinstance(val.type, (ir.FloatType, ir.DoubleType)): + return Gen.builder.fptosi(val, ir.IntType(32), name="fstr_f2i") + return val + elif fmt_type_char in ('f', 'e', 'E', 'g', 'G'): + if isinstance(val.type, ir.FloatType): + return Gen.builder.fpext(val, ir.DoubleType(), name="fstr_fpext") + elif isinstance(val.type, ir.IntType): + return Gen.builder.sitofp(val, ir.DoubleType(), name="fstr_i2f") + return val + return val \ No newline at end of file diff --git a/lib/core/Handles/HandlesExprLambda.py b/lib/core/Handles/HandlesExprLambda.py index a8d8410..e07e353 100644 --- a/lib/core/Handles/HandlesExprLambda.py +++ b/lib/core/Handles/HandlesExprLambda.py @@ -1,232 +1,233 @@ -from __future__ import annotations -from typing import TYPE_CHECKING -if TYPE_CHECKING: - from lib.core.translator import Translator -from lib.core.Handles.HandlesBase import BaseHandle -import ast -import llvmlite.ir as ir - - -class ExprLambdaHandle(BaseHandle): - def _HandleLambdaLlvm(self, Node): - Gen = self.Trans.LlvmGen - if not getattr(Gen, '_lambda_counter', None): - Gen._lambda_counter = 0 - lambda_id = Gen._lambda_counter - Gen._lambda_counter += 1 - fn_name = f"lambda_fn_{lambda_id}" - captured_vars = self._get_lambda_captured_vars(Node) - env_types = [] - env_var_names = [] - for var_name, var_val in captured_vars: - env_types.append(var_val.type) - env_var_names.append(var_name) - env_struct_type = ir.LiteralStructType(env_types) if env_types else ir.LiteralStructType([]) - ret_type = self.Trans.ExprUtils._infer_expr_llvm_type_full(Node.body) - param_types = [ir.PointerType(env_struct_type)] - if Node.args: - for arg in Node.args.args: - param_types.append(ir.IntType(32)) - fn_type = ir.FunctionType(ret_type, param_types) - fn = ir.Function(Gen.module, fn_type, name=fn_name) - Gen.functions[fn_name] = fn - entry_block = fn.append_basic_block(name=f"{fn_name}_entry") - prev_builder = Gen.builder - prev_func = Gen.func - prev_vars = dict(Gen.variables) - Gen.builder = ir.IRBuilder(entry_block) - Gen.func = fn - Gen.variables = {} - for i, arg in enumerate(fn.args): - arg.name = f"arg_{i}" if i > 0 else "env" - if env_types: - for idx, var_name in enumerate(env_var_names): - env_ptr = fn.args[0] - zero = ir.Constant(ir.IntType(32), 0) - member_ptr = Gen.builder.gep(env_ptr, [zero, ir.Constant(ir.IntType(32), idx)], name=f"env_{var_name}") - Loaded = Gen._load(member_ptr, name=f"Load_env_{var_name}") - temp_alloca = Gen._alloca(Loaded.type, name=f"temp_{var_name}") - Gen._store(Loaded, temp_alloca) - Gen.variables[var_name] = temp_alloca - if Node.args: - for i, arg in enumerate(Node.args.args): - Gen.variables[arg.arg] = Gen._alloca(ir.IntType(32), name=arg.arg) - Gen._store(fn.args[i + 1], Gen.variables[arg.arg]) - body_val = self.HandleExprLlvm(Node.body) - if body_val: - if isinstance(body_val.type, ir.PointerType) and not isinstance(ret_type, ir.PointerType): - body_val = Gen._load(body_val, name="Load_lambda_ret") - if body_val.type != ret_type: - if isinstance(body_val.type, ir.IntType) and isinstance(ret_type, ir.IntType): - if body_val.type.width < ret_type.width: - body_val = Gen.builder.zext(body_val, ret_type, name="zext_lambda_ret") - elif body_val.type.width > ret_type.width: - body_val = Gen.builder.trunc(body_val, ret_type, name="trunc_lambda_ret") - elif isinstance(body_val.type, ir.PointerType) and isinstance(ret_type, ir.PointerType): - body_val = Gen.builder.bitcast(body_val, ret_type, name="bitcast_lambda_ret") - Gen.builder.ret(body_val) - else: - Gen.builder.ret(ir.Constant(ret_type, 0)) - Gen.builder = prev_builder - Gen.func = prev_func - Gen.variables = prev_vars - closure_struct_type = ir.LiteralStructType([ - ir.PointerType(ir.IntType(8)), - ir.PointerType(fn_type) - ]) - closure_ptr = Gen._alloca(closure_struct_type, name=f"closure_{lambda_id}") - env_ptr = Gen._alloca(env_struct_type, name=f"env_{lambda_id}") - if env_types: - for idx, (var_name, var_val) in enumerate(captured_vars): - zero = ir.Constant(ir.IntType(32), 0) - member_ptr = Gen.builder.gep(env_ptr, [zero, ir.Constant(ir.IntType(32), idx)], name=f"store_env_{var_name}") - Gen._store(var_val, member_ptr) - zero = ir.Constant(ir.IntType(32), 0) - env_field_ptr = Gen.builder.gep(closure_ptr, [zero, zero], name="closure_env_ptr") - env_i8_ptr = Gen.builder.bitcast(env_ptr, ir.PointerType(ir.IntType(8)), name="env_i8_ptr") - Gen._store(env_i8_ptr, env_field_ptr) - fn_field_ptr = Gen.builder.gep(closure_ptr, [zero, ir.Constant(ir.IntType(32), 1)], name="closure_fn_ptr") - Gen._store(fn, fn_field_ptr) - return closure_ptr - - def _get_lambda_captured_vars(self, Node): - Gen = self.Trans.LlvmGen - captured = [] - free_vars = self._get_lambda_free_vars(Node) - for var_name in free_vars: - if var_name in Gen.variables: - var_ptr = Gen.variables[var_name] - if isinstance(var_ptr, ir.AllocaInstr) or isinstance(var_ptr, ir.GlobalVariable): - Loaded = Gen._load(var_ptr, name=f"capture_{var_name}") - captured.append((var_name, Loaded)) - return captured - - def _get_lambda_free_vars(self, Node): - bound_vars = set() - free_vars = set() - # 收集 lambda body 中的 bound 和 free 变量 - self.Trans.ExprUtils._collect_names(Node.body, bound_vars, free_vars) - # lambda 参数也是 bound 的 - if Node.args: - for arg in Node.args.args: - bound_vars.add(arg.arg) - # free 变量 = 在 body 中引用(Load)但不是参数也不是 body 内赋值的变量 - result = free_vars - bound_vars - return list(result) - - def _HandleIfExpLlvm(self, Node): - Gen = self.Trans.LlvmGen - TestVal = self.HandleExprLlvm(Node.test) - if not TestVal: - return None - if not isinstance(TestVal.type, ir.IntType) or TestVal.type.width != 1: - TestVal = Gen.builder.icmp_signed('!=', TestVal, Gen._ZeroConst(TestVal.type), name="ifexp_cond") - ThenBB = Gen.func.append_basic_block(name="ifexp.then") - ElseBB = Gen.func.append_basic_block(name="ifexp.else") - MergeBB = Gen.func.append_basic_block(name="ifexp.end") - Gen.builder.cbranch(TestVal, ThenBB, ElseBB) - # 先在 ThenBB 中生成 BodyVal - Gen.builder.position_at_start(ThenBB) - BodyVal = self.HandleExprLlvm(Node.body) - if not BodyVal: - BodyVal = ir.Constant(ir.IntType(32), 0) - ThenEndBB = Gen.builder.block - # 在 ElseBB 中生成 OrelseVal - Gen.builder.position_at_start(ElseBB) - OrelseVal = self.HandleExprLlvm(Node.orelse) - if not OrelseVal: - OrelseVal = ir.Constant(ir.IntType(32), 0) - ElseEndBB = Gen.builder.block - # 确定 phi 节点的目标类型 - result_type = BodyVal.type - if BodyVal.type != OrelseVal.type: - if isinstance(BodyVal.type, ir.IntType) and isinstance(OrelseVal.type, ir.IntType): - result_type = BodyVal.type if BodyVal.type.width >= OrelseVal.type.width else OrelseVal.type - elif isinstance(BodyVal.type, ir.PointerType) and isinstance(OrelseVal.type, ir.PointerType): - # 指针类型,使用 BodyVal 的类型 - result_type = BodyVal.type - elif isinstance(BodyVal.type, ir.IntType) and isinstance(OrelseVal.type, ir.PointerType): - # BodyVal 是整数,OrelseVal 是指针(字符串字面量) - # 如果指针指向 i8,将指针转换为 i8(加载字符) - if isinstance(OrelseVal.type.pointee, ir.IntType) and OrelseVal.type.pointee.width == 8: - result_type = ir.IntType(8) - else: - result_type = OrelseVal.type - elif isinstance(BodyVal.type, ir.PointerType) and isinstance(OrelseVal.type, ir.IntType): - # BodyVal 是指针(字符串字面量),OrelseVal 是整数 - # 如果指针指向 i8,将指针转换为 i8(加载字符) - if isinstance(BodyVal.type.pointee, ir.IntType) and BodyVal.type.pointee.width == 8: - result_type = ir.IntType(8) - else: - result_type = BodyVal.type - else: - result_type = OrelseVal.type - # 在 ThenBB 末尾添加类型转换(如果需要)和分支 - if not ThenEndBB.is_terminated: - Gen.builder.position_at_end(ThenEndBB) - if BodyVal.type != result_type: - if isinstance(BodyVal.type, ir.IntType) and isinstance(result_type, ir.IntType): - if BodyVal.type.width < result_type.width: - BodyVal = Gen.builder.zext(BodyVal, result_type, name="ifexp_body_zext") - else: - BodyVal = Gen.builder.trunc(BodyVal, result_type, name="ifexp_body_trunc") - elif isinstance(BodyVal.type, ir.IntType) and isinstance(result_type, ir.PointerType): - # 如果 result_type 是 i8*,说明 Else 分支是字符串字面量 - # 不应该将整数转换为指针,而应该保持整数类型 - # 这里将 result_type 改为 i8 - result_type = ir.IntType(8) - # 重新处理 Else 分支的类型转换 - elif isinstance(BodyVal.type, ir.PointerType) and isinstance(result_type, ir.IntType): - # 指针转整数 - BodyVal = Gen.builder.ptrtoint(BodyVal, result_type, name="ifexp_body_ptr2int") - Gen.builder.branch(MergeBB) - # 在 ElseBB 末尾添加类型转换(如果需要)和分支 - if not ElseEndBB.is_terminated: - Gen.builder.position_at_end(ElseEndBB) - if OrelseVal.type != result_type: - if isinstance(OrelseVal.type, ir.IntType) and isinstance(result_type, ir.IntType): - if OrelseVal.type.width < result_type.width: - OrelseVal = Gen.builder.zext(OrelseVal, result_type, name="ifexp_orelse_zext") - else: - OrelseVal = Gen.builder.trunc(OrelseVal, result_type, name="ifexp_orelse_trunc") - elif isinstance(OrelseVal.type, ir.IntType) and isinstance(result_type, ir.PointerType): - # 如果 result_type 是 i8*,说明 BodyVal 分支是字符串字面量 - # 不应该将整数转换为指针,而应该保持整数类型 - # 这里将 result_type 改为 i8 - result_type = ir.IntType(8) - # 重新处理 BodyVal 分支的类型转换(已经在上面处理过了) - elif isinstance(OrelseVal.type, ir.PointerType) and isinstance(result_type, ir.IntType): - # 如果指针指向 i8,加载字符值 - if isinstance(OrelseVal.type.pointee, ir.IntType) and OrelseVal.type.pointee.width == 8: - OrelseVal = Gen._load(OrelseVal, name="ifexp_orelse_Load_char") - else: - OrelseVal = Gen.builder.ptrtoint(OrelseVal, result_type, name="ifexp_orelse_ptr2int") - Gen.builder.branch(MergeBB) - Gen.builder.position_at_start(MergeBB) - result_phi = Gen.builder.phi(result_type, name="ifexp.result") - result_phi.add_incoming(BodyVal, ThenEndBB) - result_phi.add_incoming(OrelseVal, ElseEndBB) - return result_phi - - def _HandleNamedExprLlvm(self, Node): - Gen = self.Trans.LlvmGen - ValueVal = self.HandleExprLlvm(Node.value) - if not ValueVal: - return None - TargetName = Node.target.id - if TargetName in Gen._reg_values: - del Gen._reg_values[TargetName] - if TargetName in Gen.variables and Gen.variables[TargetName] is not None: - VarPtr = Gen.variables[TargetName] - if VarPtr.type.pointee == ValueVal.type: - Gen._store(ValueVal, VarPtr) - else: - NewVar = Gen._alloca(ValueVal.type, name=TargetName) - Gen._store(ValueVal, NewVar) - Gen.variables[TargetName] = NewVar - else: - NewVar = Gen._alloca(ValueVal.type, name=TargetName) - Gen._store(ValueVal, NewVar) - Gen.variables[TargetName] = NewVar - Gen._reg_values[TargetName] = ValueVal - return ValueVal +from __future__ import annotations +from typing import TYPE_CHECKING, Any +if TYPE_CHECKING: + from lib.core.translator import Translator + from lib.core.LlvmCodeGenerator import LlvmCodeGenerator +from lib.core.Handles.HandlesBase import BaseHandle +import ast +import llvmlite.ir as ir + + +class ExprLambdaHandle(BaseHandle): + def _HandleLambdaLlvm(self, Node: ast.Lambda) -> ir.Value: + Gen: LlvmCodeGenerator = self.Trans.LlvmGen + if not getattr(Gen, '_lambda_counter', None): + Gen._lambda_counter = 0 + lambda_id: int = Gen._lambda_counter + Gen._lambda_counter += 1 + fn_name: str = f"lambda_fn_{lambda_id}" + captured_vars: list[tuple[str, Any]] = self._get_lambda_captured_vars(Node) + env_types: list[ir.Type] = [] + env_var_names: list[str] = [] + for var_name, var_val in captured_vars: + env_types.append(var_val.type) + env_var_names.append(var_name) + env_struct_type: ir.LiteralStructType = ir.LiteralStructType(env_types) if env_types else ir.LiteralStructType([]) + ret_type: ir.Type = self.Trans.ExprUtils._infer_expr_llvm_type_full(Node.body) + param_types: list[ir.Type] = [ir.PointerType(env_struct_type)] + if Node.args: + for arg in Node.args.args: + param_types.append(ir.IntType(32)) + fn_type: ir.FunctionType = ir.FunctionType(ret_type, param_types) + fn: ir.Function = ir.Function(Gen.module, fn_type, name=fn_name) + Gen.functions[fn_name] = fn + entry_block: ir.Block = fn.append_basic_block(name=f"{fn_name}_entry") + prev_builder: Any = Gen.builder + prev_func: Any = Gen.func + prev_vars: dict[str, Any] = dict(Gen.variables) + Gen.builder = ir.IRBuilder(entry_block) + Gen.func = fn + Gen.variables = {} + for i, arg in enumerate(fn.args): + arg.name = f"arg_{i}" if i > 0 else "env" + if env_types: + for idx, var_name in enumerate(env_var_names): + env_ptr: Any = fn.args[0] + zero: ir.Constant = ir.Constant(ir.IntType(32), 0) + member_ptr: Any = Gen.builder.gep(env_ptr, [zero, ir.Constant(ir.IntType(32), idx)], name=f"env_{var_name}") + Loaded: Any = Gen._load(member_ptr, name=f"Load_env_{var_name}") + temp_alloca: Any = Gen._alloca(Loaded.type, name=f"temp_{var_name}") + Gen._store(Loaded, temp_alloca) + Gen.variables[var_name] = temp_alloca + if Node.args: + for i, arg in enumerate(Node.args.args): + Gen.variables[arg.arg] = Gen._alloca(ir.IntType(32), name=arg.arg) + Gen._store(fn.args[i + 1], Gen.variables[arg.arg]) + body_val: Any = self.HandleExprLlvm(Node.body) + if body_val: + if isinstance(body_val.type, ir.PointerType) and not isinstance(ret_type, ir.PointerType): + body_val = Gen._load(body_val, name="Load_lambda_ret") + if body_val.type != ret_type: + if isinstance(body_val.type, ir.IntType) and isinstance(ret_type, ir.IntType): + if body_val.type.width < ret_type.width: + body_val = Gen.builder.zext(body_val, ret_type, name="zext_lambda_ret") + elif body_val.type.width > ret_type.width: + body_val = Gen.builder.trunc(body_val, ret_type, name="trunc_lambda_ret") + elif isinstance(body_val.type, ir.PointerType) and isinstance(ret_type, ir.PointerType): + body_val = Gen.builder.bitcast(body_val, ret_type, name="bitcast_lambda_ret") + Gen.builder.ret(body_val) + else: + Gen.builder.ret(ir.Constant(ret_type, 0)) + Gen.builder = prev_builder + Gen.func = prev_func + Gen.variables = prev_vars + closure_struct_type: ir.LiteralStructType = ir.LiteralStructType([ + ir.PointerType(ir.IntType(8)), + ir.PointerType(fn_type) + ]) + closure_ptr: Any = Gen._alloca(closure_struct_type, name=f"closure_{lambda_id}") + env_ptr: Any = Gen._alloca(env_struct_type, name=f"env_{lambda_id}") + if env_types: + for idx, (var_name, var_val) in enumerate(captured_vars): + zero = ir.Constant(ir.IntType(32), 0) + member_ptr = Gen.builder.gep(env_ptr, [zero, ir.Constant(ir.IntType(32), idx)], name=f"store_env_{var_name}") + Gen._store(var_val, member_ptr) + zero = ir.Constant(ir.IntType(32), 0) + env_field_ptr: Any = Gen.builder.gep(closure_ptr, [zero, zero], name="closure_env_ptr") + env_i8_ptr: Any = Gen.builder.bitcast(env_ptr, ir.PointerType(ir.IntType(8)), name="env_i8_ptr") + Gen._store(env_i8_ptr, env_field_ptr) + fn_field_ptr: Any = Gen.builder.gep(closure_ptr, [zero, ir.Constant(ir.IntType(32), 1)], name="closure_fn_ptr") + Gen._store(fn, fn_field_ptr) + return closure_ptr + + def _get_lambda_captured_vars(self, Node: ast.Lambda) -> list[tuple[str, ir.Value]]: + Gen: LlvmCodeGenerator = self.Trans.LlvmGen + captured: list[tuple[str, Any]] = [] + free_vars: list[str] = self._get_lambda_free_vars(Node) + for var_name in free_vars: + if var_name in Gen.variables: + var_ptr: Any = Gen.variables[var_name] + if isinstance(var_ptr, ir.AllocaInstr) or isinstance(var_ptr, ir.GlobalVariable): + Loaded: Any = Gen._load(var_ptr, name=f"capture_{var_name}") + captured.append((var_name, Loaded)) + return captured + + def _get_lambda_free_vars(self, Node: ast.Lambda) -> list[str]: + bound_vars: set[str] = set() + free_vars: set[str] = set() + # 收集 lambda body 中的 bound 和 free 变量 + self.Trans.ExprUtils._collect_names(Node.body, bound_vars, free_vars) + # lambda 参数也是 bound 的 + if Node.args: + for arg in Node.args.args: + bound_vars.add(arg.arg) + # free 变量 = 在 body 中引用(Load)但不是参数也不是 body 内赋值的变量 + result: list[str] = list(free_vars - bound_vars) + return result + + def _HandleIfExpLlvm(self, Node: ast.IfExp) -> ir.Value | None: + Gen: LlvmCodeGenerator = self.Trans.LlvmGen + TestVal: Any = self.HandleExprLlvm(Node.test) + if not TestVal: + return None + if not isinstance(TestVal.type, ir.IntType) or TestVal.type.width != 1: + TestVal = Gen.builder.icmp_signed('!=', TestVal, Gen._ZeroConst(TestVal.type), name="ifexp_cond") + ThenBB: ir.Block = Gen.func.append_basic_block(name="ifexp.then") + ElseBB: ir.Block = Gen.func.append_basic_block(name="ifexp.else") + MergeBB: ir.Block = Gen.func.append_basic_block(name="ifexp.end") + Gen.builder.cbranch(TestVal, ThenBB, ElseBB) + # 先在 ThenBB 中生成 BodyVal + Gen.builder.position_at_start(ThenBB) + BodyVal: Any = self.HandleExprLlvm(Node.body) + if not BodyVal: + BodyVal = ir.Constant(ir.IntType(32), 0) + ThenEndBB: ir.Block = Gen.builder.block + # 在 ElseBB 中生成 OrelseVal + Gen.builder.position_at_start(ElseBB) + OrelseVal: Any = self.HandleExprLlvm(Node.orelse) + if not OrelseVal: + OrelseVal = ir.Constant(ir.IntType(32), 0) + ElseEndBB: ir.Block = Gen.builder.block + # 确定 phi 节点的目标类型 + result_type: ir.Type = BodyVal.type + if BodyVal.type != OrelseVal.type: + if isinstance(BodyVal.type, ir.IntType) and isinstance(OrelseVal.type, ir.IntType): + result_type = BodyVal.type if BodyVal.type.width >= OrelseVal.type.width else OrelseVal.type + elif isinstance(BodyVal.type, ir.PointerType) and isinstance(OrelseVal.type, ir.PointerType): + # 指针类型,使用 BodyVal 的类型 + result_type = BodyVal.type + elif isinstance(BodyVal.type, ir.IntType) and isinstance(OrelseVal.type, ir.PointerType): + # BodyVal 是整数,OrelseVal 是指针(字符串字面量) + # 如果指针指向 i8,将指针转换为 i8(加载字符) + if isinstance(OrelseVal.type.pointee, ir.IntType) and OrelseVal.type.pointee.width == 8: + result_type = ir.IntType(8) + else: + result_type = OrelseVal.type + elif isinstance(BodyVal.type, ir.PointerType) and isinstance(OrelseVal.type, ir.IntType): + # BodyVal 是指针(字符串字面量),OrelseVal 是整数 + # 如果指针指向 i8,将指针转换为 i8(加载字符) + if isinstance(BodyVal.type.pointee, ir.IntType) and BodyVal.type.pointee.width == 8: + result_type = ir.IntType(8) + else: + result_type = BodyVal.type + else: + result_type = OrelseVal.type + # 在 ThenBB 末尾添加类型转换(如果需要)和分支 + if not ThenEndBB.is_terminated: + Gen.builder.position_at_end(ThenEndBB) + if BodyVal.type != result_type: + if isinstance(BodyVal.type, ir.IntType) and isinstance(result_type, ir.IntType): + if BodyVal.type.width < result_type.width: + BodyVal = Gen.builder.zext(BodyVal, result_type, name="ifexp_body_zext") + else: + BodyVal = Gen.builder.trunc(BodyVal, result_type, name="ifexp_body_trunc") + elif isinstance(BodyVal.type, ir.IntType) and isinstance(result_type, ir.PointerType): + # 如果 result_type 是 i8*,说明 Else 分支是字符串字面量 + # 不应该将整数转换为指针,而应该保持整数类型 + # 这里将 result_type 改为 i8 + result_type = ir.IntType(8) + # 重新处理 Else 分支的类型转换 + elif isinstance(BodyVal.type, ir.PointerType) and isinstance(result_type, ir.IntType): + # 指针转整数 + BodyVal = Gen.builder.ptrtoint(BodyVal, result_type, name="ifexp_body_ptr2int") + Gen.builder.branch(MergeBB) + # 在 ElseBB 末尾添加类型转换(如果需要)和分支 + if not ElseEndBB.is_terminated: + Gen.builder.position_at_end(ElseEndBB) + if OrelseVal.type != result_type: + if isinstance(OrelseVal.type, ir.IntType) and isinstance(result_type, ir.IntType): + if OrelseVal.type.width < result_type.width: + OrelseVal = Gen.builder.zext(OrelseVal, result_type, name="ifexp_orelse_zext") + else: + OrelseVal = Gen.builder.trunc(OrelseVal, result_type, name="ifexp_orelse_trunc") + elif isinstance(OrelseVal.type, ir.IntType) and isinstance(result_type, ir.PointerType): + # 如果 result_type 是 i8*,说明 BodyVal 分支是字符串字面量 + # 不应该将整数转换为指针,而应该保持整数类型 + # 这里将 result_type 改为 i8 + result_type = ir.IntType(8) + # 重新处理 BodyVal 分支的类型转换(已经在上面处理过了) + elif isinstance(OrelseVal.type, ir.PointerType) and isinstance(result_type, ir.IntType): + # 如果指针指向 i8,加载字符值 + if isinstance(OrelseVal.type.pointee, ir.IntType) and OrelseVal.type.pointee.width == 8: + OrelseVal = Gen._load(OrelseVal, name="ifexp_orelse_Load_char") + else: + OrelseVal = Gen.builder.ptrtoint(OrelseVal, result_type, name="ifexp_orelse_ptr2int") + Gen.builder.branch(MergeBB) + Gen.builder.position_at_start(MergeBB) + result_phi: Any = Gen.builder.phi(result_type, name="ifexp.result") + result_phi.add_incoming(BodyVal, ThenEndBB) + result_phi.add_incoming(OrelseVal, ElseEndBB) + return result_phi + + def _HandleNamedExprLlvm(self, Node: ast.NamedExpr) -> ir.Value: + Gen: LlvmCodeGenerator = self.Trans.LlvmGen + ValueVal: Any = self.HandleExprLlvm(Node.value) + if not ValueVal: + return None + TargetName: str = Node.target.id + if TargetName in Gen._reg_values: + del Gen._reg_values[TargetName] + if TargetName in Gen.variables and Gen.variables[TargetName] is not None: + VarPtr: Any = Gen.variables[TargetName] + if VarPtr.type.pointee == ValueVal.type: + Gen._store(ValueVal, VarPtr) + else: + NewVar: Any = Gen._alloca(ValueVal.type, name=TargetName) + Gen._store(ValueVal, NewVar) + Gen.variables[TargetName] = NewVar + else: + NewVar = Gen._alloca(ValueVal.type, name=TargetName) + Gen._store(ValueVal, NewVar) + Gen.variables[TargetName] = NewVar + Gen._reg_values[TargetName] = ValueVal + return ValueVal \ No newline at end of file diff --git a/lib/core/Handles/HandlesExprOps.py b/lib/core/Handles/HandlesExprOps.py index a44c677..6257cbc 100644 --- a/lib/core/Handles/HandlesExprOps.py +++ b/lib/core/Handles/HandlesExprOps.py @@ -1,402 +1,431 @@ -from __future__ import annotations -from typing import TYPE_CHECKING -if TYPE_CHECKING: - from lib.core.translator import Translator -from lib.core.Handles.HandlesBase import BaseHandle -import ast -import llvmlite.ir as ir - - -class ExprOpsHandle(BaseHandle): - def _HandleBinOpLlvm(self, Node, VarType=None): - Gen = self.Trans.LlvmGen - Gen._set_node_info(Node, "BinOp") - LeftVal = self.HandleExprLlvm(Node.left, VarType) - if not LeftVal: - return None - RightVal = self.HandleExprLlvm(Node.right, VarType) - if not RightVal: - return None - Op = self.Trans.ExprHandler.GetOpSymbol(Node.op) - if not Op: - return None - OP_OVERLOAD_MAP = { - '+': '__add__', '-': '__sub__', '*': '__mul__', - '/': '__truediv__', '//': '__floordiv__', '%': '__mod__', - '**': '__pow__', - } - if Op in OP_OVERLOAD_MAP: - LeftClassName = None - if isinstance(LeftVal.type, ir.PointerType): - pointee = LeftVal.type.pointee - if isinstance(pointee, (ir.IdentifiedStructType, ir.LiteralStructType)): - for CN, ST in Gen.structs.items(): - if pointee == ST: - LeftClassName = CN - break - elif isinstance(pointee, ir.IntType) and pointee.width == 8: - LeftClassName = self.Trans.ExprUtils._get_var_class(Node.left, Gen) - if LeftClassName and LeftClassName in Gen.structs: - TargetStructPtr = ir.PointerType(Gen.structs[LeftClassName]) - LeftVal = Gen.builder.bitcast(LeftVal, TargetStructPtr, name=f"bitcast_to_{LeftClassName}") - if LeftClassName is None and isinstance(Node.left, ast.Name): - LeftClassName = Gen.var_struct_class.get(Node.left.id) - if LeftClassName and LeftClassName in Gen.structs: - if isinstance(LeftVal.type, ir.PointerType) and isinstance(LeftVal.type.pointee, ir.IntType) and LeftVal.type.pointee.width == 8: - TargetStructPtr = ir.PointerType(Gen.structs[LeftClassName]) - LeftVal = Gen.builder.bitcast(LeftVal, TargetStructPtr, name=f"bitcast_to_{LeftClassName}") - if LeftClassName: - op_name = OP_OVERLOAD_MAP[Op] - result = self.Trans.ExprUtils._try_operator_overLoad(LeftClassName, op_name, LeftVal, Gen, RightVal) - if result is not None: - return result - if Op in ('+', 'Add') and isinstance(LeftVal.type, ir.PointerType) and isinstance(RightVal.type, ir.IntType): - if isinstance(LeftVal.type.pointee, ir.IntType) and LeftVal.type.pointee.width == 8: - if isinstance(Node.left, ast.Constant) and isinstance(Node.left.value, str) and len(Node.left.value) == 1: - CharVal = Gen._load(LeftVal, name="Load_char_const") - CharAsInt = Gen.builder.zext(CharVal, RightVal.type, name="char_to_int") - result = Gen.builder.add(CharAsInt, RightVal, name="char_add") - TruncResult = Gen.builder.trunc(result, ir.IntType(8), name="add_to_char") - return TruncResult - is_unsigned = Gen._check_node_unsigned(Node.left) or Gen._check_node_unsigned(Node.right) - if isinstance(LeftVal.type, ir.IntType) and isinstance(RightVal.type, ir.IntType): - if LeftVal.type.width < RightVal.type.width: - need_zext = is_unsigned or Gen._check_node_unsigned(Node.left) or LeftVal.type.width == 8 - if not need_zext and isinstance(RightVal, ir.Constant): - signed_max = (1 << (LeftVal.type.width - 1)) - 1 - try: - if RightVal.constant > signed_max: - need_zext = True - except (TypeError, ValueError): - pass - if need_zext: - LeftVal = Gen.builder.zext(LeftVal, RightVal.type, name="zext_left") - else: - LeftVal = Gen.builder.sext(LeftVal, RightVal.type, name="sext_left") - elif LeftVal.type.width > RightVal.type.width: - need_zext = is_unsigned or Gen._check_node_unsigned(Node.right) or RightVal.type.width == 8 - if not need_zext and isinstance(LeftVal, ir.Constant): - signed_max = (1 << (RightVal.type.width - 1)) - 1 - try: - if LeftVal.constant > signed_max: - need_zext = True - except (TypeError, ValueError): - pass - if need_zext: - RightVal = Gen.builder.zext(RightVal, LeftVal.type, name="zext_right") - else: - RightVal = Gen.builder.sext(RightVal, LeftVal.type, name="zext_right") - elif isinstance(LeftVal.type, ir.PointerType) and isinstance(RightVal.type, ir.IntType): - if Op not in ('+', '-', 'Add', 'Sub') and isinstance(LeftVal.type.pointee, ir.IntType): - LeftVal = Gen._load(LeftVal, name="deref_ptr_binop") - if LeftVal.type.width < RightVal.type.width: - LeftVal = Gen.builder.zext(LeftVal, RightVal.type, name="zext_deref_left") - elif LeftVal.type.width > RightVal.type.width: - RightVal = Gen.builder.zext(RightVal, LeftVal.type, name="zext_right_deref") - elif isinstance(RightVal.type, ir.PointerType) and isinstance(LeftVal.type, ir.IntType): - if Op not in ('+', '-', 'Add', 'Sub') and isinstance(RightVal.type.pointee, ir.IntType): - RightVal = Gen._load(RightVal, name="deref_ptr_binop_r") - if RightVal.type.width < LeftVal.type.width: - RightVal = Gen.builder.zext(RightVal, LeftVal.type, name="zext_deref_right") - elif RightVal.type.width > LeftVal.type.width: - LeftVal = Gen.builder.zext(LeftVal, RightVal.type, name="zext_left_deref") - if Op in ('>>', 'RShift') and isinstance(Node.left, ast.Name): - vname = Node.left.id - if vname in Gen.var_signedness and Gen.var_signedness[vname]: - is_unsigned = True - result = Gen.emit_binary_op(Op, LeftVal, RightVal, is_unsigned=is_unsigned) - return result - - def _HandleBoolOpLlvm(self, Node): - Gen = self.Trans.LlvmGen - - def _to_bool(val, name): - if isinstance(val.type, (ir.FloatType, ir.DoubleType)): - return Gen.builder.fcmp_ordered('!=', val, ir.Constant(val.type, 0.0), name=name) - if not isinstance(val.type, ir.IntType) or val.type.width != 1: - return Gen.builder.icmp_signed('!=', val, Gen._ZeroConst(val.type), name=name) - return val - - values = Node.values - if len(values) < 2: - return self.HandleExprLlvm(values[0]) if values else None - if isinstance(Node.op, ast.And): - phi_incomings = [] - end_bb = Gen.func.append_basic_block(name="and.end") - for idx in range(len(values) - 1): - val = self.HandleExprLlvm(values[idx]) - if not val: - if not end_bb.is_terminated: - saved_block = Gen.builder.block - Gen.builder.position_at_start(end_bb) - Gen.builder.unreachable() - Gen.builder.position_at_end(saved_block) - return None - if not isinstance(val.type, ir.IntType) or val.type.width != 1: - val = _to_bool(val, f"andcond{idx}") - cur_bb = Gen.builder.block - next_bb = Gen.func.append_basic_block(name=f"and.rhs{idx}") - Gen.builder.cbranch(val, next_bb, end_bb) - phi_incomings.append((ir.Constant(ir.IntType(1), 0), cur_bb)) - Gen.builder.position_at_start(next_bb) - last_val = self.HandleExprLlvm(values[-1]) - if not last_val: - last_val = ir.Constant(ir.IntType(1), 0) - if not isinstance(last_val.type, ir.IntType) or last_val.type.width != 1: - last_val = _to_bool(last_val, "andcond_last") - last_bb = Gen.builder.block - Gen.builder.branch(end_bb) - Gen.builder.position_at_start(end_bb) - result_phi = Gen.builder.phi(ir.IntType(1), name="and.result") - for const_val, bb in phi_incomings: - result_phi.add_incoming(const_val, bb) - result_phi.add_incoming(last_val, last_bb) - return result_phi - elif isinstance(Node.op, ast.Or): - phi_incomings = [] - end_bb = Gen.func.append_basic_block(name="or.end") - for idx in range(len(values) - 1): - val = self.HandleExprLlvm(values[idx]) - if not val: - if not end_bb.is_terminated: - saved_block = Gen.builder.block - Gen.builder.position_at_start(end_bb) - Gen.builder.unreachable() - Gen.builder.position_at_end(saved_block) - return None - if not isinstance(val.type, ir.IntType) or val.type.width != 1: - val = _to_bool(val, f"orcond{idx}") - cur_bb = Gen.builder.block - next_bb = Gen.func.append_basic_block(name=f"or.rhs{idx}") - Gen.builder.cbranch(val, end_bb, next_bb) - phi_incomings.append((ir.Constant(ir.IntType(1), 1), cur_bb)) - Gen.builder.position_at_start(next_bb) - last_val = self.HandleExprLlvm(values[-1]) - if not last_val: - last_val = ir.Constant(ir.IntType(1), 1) - if not isinstance(last_val.type, ir.IntType) or last_val.type.width != 1: - last_val = _to_bool(last_val, "orcond_last") - last_bb = Gen.builder.block - Gen.builder.branch(end_bb) - Gen.builder.position_at_start(end_bb) - result_phi = Gen.builder.phi(ir.IntType(1), name="or.result") - for const_val, bb in phi_incomings: - result_phi.add_incoming(const_val, bb) - result_phi.add_incoming(last_val, last_bb) - return result_phi - return None - - def _HandleUnaryOpLlvm(self, Node): - Gen = self.Trans.LlvmGen - OperandVal = self.HandleExprLlvm(Node.operand) - if not OperandVal: - return None - OpSymbol = self.Trans.ExprHandler.GetUnaryOpSymbol(Node.op) - if not OpSymbol: - return None - UNARY_OVERLOAD_MAP = { - '-': '__neg__', - '+': '__pos__', - '~': '__invert__', - } - if OpSymbol in UNARY_OVERLOAD_MAP: - ClassName = None - if isinstance(OperandVal.type, ir.PointerType): - pointee = OperandVal.type.pointee - if isinstance(pointee, (ir.IdentifiedStructType, ir.LiteralStructType)): - for CN, ST in Gen.structs.items(): - if pointee == ST: - ClassName = CN - break - elif isinstance(pointee, ir.IntType) and pointee.width == 8: - ClassName = self.Trans.ExprUtils._get_var_class(Node.operand, Gen) - if ClassName and ClassName in Gen.structs: - TargetStructPtr = ir.PointerType(Gen.structs[ClassName]) - OperandVal = Gen.builder.bitcast(OperandVal, TargetStructPtr, name=f"bitcast_to_{ClassName}") - if ClassName is None and isinstance(Node.operand, ast.Name): - ClassName = Gen.var_struct_class.get(Node.operand.id) - if ClassName and ClassName in Gen.structs: - if isinstance(OperandVal.type, ir.PointerType) and isinstance(OperandVal.type.pointee, ir.IntType) and OperandVal.type.pointee.width == 8: - TargetStructPtr = ir.PointerType(Gen.structs[ClassName]) - OperandVal = Gen.builder.bitcast(OperandVal, TargetStructPtr, name=f"bitcast_to_{ClassName}") - if ClassName: - op_name = UNARY_OVERLOAD_MAP[OpSymbol] - result = self.Trans.ExprUtils._try_operator_overLoad(ClassName, op_name, OperandVal, Gen) - if result is not None: - return result - if OpSymbol == 'not': - if isinstance(OperandVal.type, ir.IntType) and OperandVal.type.width == 1: - return Gen.builder.not_(OperandVal, name="not_result") - if isinstance(OperandVal.type, ir.PointerType): - null_val = ir.Constant(OperandVal.type, None) - return Gen.builder.icmp_signed('==', OperandVal, null_val, name="not_result") - zero = ir.Constant(OperandVal.type, 0) - return Gen.builder.icmp_signed('==', OperandVal, zero, name="not_result") - elif OpSymbol == '~': - if isinstance(OperandVal.type, ir.IntType): - mask = (1 << OperandVal.type.width) - 1 - return Gen.builder.xor(OperandVal, ir.Constant(OperandVal.type, mask), name="bnot_result") - return Gen.builder.xor(OperandVal, ir.Constant(OperandVal.type, -1), name="bnot_result") - elif OpSymbol == '+': - return OperandVal - elif OpSymbol == '-': - if isinstance(OperandVal.type, ir.IntType): - return Gen.builder.neg(OperandVal, name="neg_result") - elif isinstance(OperandVal.type, (ir.FloatType, ir.DoubleType)): - return Gen.builder.fneg(OperandVal, name="fneg_result") - return None - - def _HandleCompareLlvm(self, Node): - Gen = self.Trans.LlvmGen - LeftVal = self.HandleExprLlvm(Node.left) - if not LeftVal: - return None - is_unsigned = Gen._check_node_unsigned(Node.left) or (Gen._check_node_unsigned(Node.comparators[0]) if Node.comparators else False) - if len(Node.ops) == 1: - Op = Node.ops[0] - ComparatorSymbol = self.Trans.ExprHandler.GetComparatorSymbol(Op) - if not ComparatorSymbol: - return None - RightVal = self.HandleExprLlvm(Node.comparators[0]) - if not RightVal: - return None - if isinstance(LeftVal, ir.Constant) and isinstance(RightVal, ir.Constant): - if isinstance(LeftVal.type, ir.IntType) and isinstance(RightVal.type, ir.IntType): - lv, rv = LeftVal.constant, RightVal.constant - lw, rw = LeftVal.type.width, RightVal.type.width - if lw < rw: - lv = lv if lv >= 0 else lv + (1 << lw) - elif rw < lw: - rv = rv if rv >= 0 else rv + (1 << rw) - if is_unsigned: - mask_l = (1 << max(lw, rw)) - 1 - lv = lv & mask_l - rv = rv & mask_l - cmp_map = { - '==': lv == rv, '!=': lv != rv, - '<': lv < rv, '>': lv > rv, - '<=': lv <= rv, '>=': lv >= rv, - } - result = cmp_map.get(ComparatorSymbol, False) - return ir.Constant(ir.IntType(1), 1 if result else 0) - if isinstance(LeftVal.type, ir.IntType) and isinstance(RightVal.type, ir.IntType): - if LeftVal.type.width < RightVal.type.width: - # 如果宽类型常量值超出窄类型有符号范围,则必须用zext - # i8 类型默认使用 zext(系统编程中 i8 几乎总是无符号字节) - need_zext = is_unsigned or Gen._check_node_unsigned(Node.left) or LeftVal.type.width == 8 - if not need_zext and isinstance(RightVal, ir.Constant): - signed_max = (1 << (LeftVal.type.width - 1)) - 1 - try: - if RightVal.constant > signed_max or RightVal.constant < 0: - need_zext = True - except (TypeError, ValueError): - pass - if need_zext: - LeftVal = Gen.builder.zext(LeftVal, RightVal.type, name="zext_left_cmp") - else: - LeftVal = Gen.builder.sext(LeftVal, RightVal.type, name="sext_left_cmp") - elif LeftVal.type.width > RightVal.type.width: - need_zext = is_unsigned or Gen._check_node_unsigned(Node.comparators[0]) or RightVal.type.width == 8 - if not need_zext and isinstance(LeftVal, ir.Constant): - signed_max = (1 << (RightVal.type.width - 1)) - 1 - try: - if LeftVal.constant > signed_max or LeftVal.constant < 0: - need_zext = True - except (TypeError, ValueError): - pass - if need_zext: - RightVal = Gen.builder.zext(RightVal, LeftVal.type, name="zext_right_cmp") - else: - RightVal = Gen.builder.sext(RightVal, LeftVal.type, name="sext_right_cmp") - elif isinstance(LeftVal.type, ir.PointerType) and isinstance(RightVal.type, ir.IntType): - if isinstance(LeftVal.type.pointee, ir.IntType) and LeftVal.type.pointee.width == 8 and isinstance(RightVal.type, ir.IntType) and RightVal.type.width == 8: - LeftVal = Gen._load(LeftVal, name="Load_char_ptr_cmp") - else: - if isinstance(RightVal, ir.Constant) and RightVal.constant == 0: - RightVal = ir.Constant(LeftVal.type, None) - else: - RightVal = Gen.builder.inttoptr(RightVal, LeftVal.type, name="int2ptr_cmp") - elif isinstance(RightVal.type, ir.PointerType) and isinstance(LeftVal.type, ir.IntType): - if isinstance(RightVal.type.pointee, ir.IntType) and RightVal.type.pointee.width == 8 and isinstance(LeftVal.type, ir.IntType) and LeftVal.type.width == 8: - RightVal = Gen._load(RightVal, name="Load_char_ptr_cmp") - else: - if isinstance(LeftVal, ir.Constant) and LeftVal.constant == 0: - LeftVal = ir.Constant(RightVal.type, None) - else: - LeftVal = Gen.builder.inttoptr(LeftVal, RightVal.type, name="int2ptr_cmp") - if isinstance(LeftVal.type, ir.PointerType) and isinstance(RightVal.type, ir.PointerType): - result = Gen.builder.icmp_unsigned(ComparatorSymbol, LeftVal, RightVal, name="cmpresult") - elif isinstance(LeftVal.type, (ir.FloatType, ir.DoubleType)) or isinstance(RightVal.type, (ir.FloatType, ir.DoubleType)): - if isinstance(LeftVal.type, (ir.FloatType, ir.DoubleType)) and isinstance(RightVal.type, ir.IntType): - RightVal = Gen.builder.sitofp(RightVal, LeftVal.type, name="int_to_float_cmp") - elif isinstance(RightVal.type, (ir.FloatType, ir.DoubleType)) and isinstance(LeftVal.type, ir.IntType): - LeftVal = Gen.builder.sitofp(LeftVal, RightVal.type, name="int_to_float_cmp") - result = Gen.builder.fcmp_unordered(ComparatorSymbol, LeftVal, RightVal, name="cmpresult") - elif is_unsigned: - result = Gen.builder.icmp_unsigned(ComparatorSymbol, LeftVal, RightVal, name="cmpresult") - else: - result = Gen.builder.icmp_signed(ComparatorSymbol, LeftVal, RightVal, name="cmpresult") - return result - EndBB = Gen.func.append_basic_block(name="cmp.end") - result_val = None - PrevBB = Gen.builder.block - for i, (Op, Comparator) in enumerate(zip(Node.ops, Node.comparators)): - ComparatorSymbol = self.Trans.ExprHandler.GetComparatorSymbol(Op) - if not ComparatorSymbol: - continue - RightVal = self.HandleExprLlvm(Comparator) - if not RightVal: - continue - NextBB = Gen.func.append_basic_block(name="cmp.next") - if isinstance(LeftVal.type, ir.IntType) and isinstance(RightVal.type, ir.IntType): - if LeftVal.type.width < RightVal.type.width: - need_zext = is_unsigned or Gen._check_node_unsigned(Node.left) or LeftVal.type.width == 8 - if not need_zext and isinstance(RightVal, ir.Constant): - signed_max = (1 << (LeftVal.type.width - 1)) - 1 - try: - if RightVal.constant > signed_max or RightVal.constant < 0: - need_zext = True - except (TypeError, ValueError): - pass - if need_zext: - LeftVal = Gen.builder.zext(LeftVal, RightVal.type, name=f"zext_left_{i}") - else: - LeftVal = Gen.builder.sext(LeftVal, RightVal.type, name=f"sext_left_{i}") - elif LeftVal.type.width > RightVal.type.width: - need_zext = is_unsigned or Gen._check_node_unsigned(Comparator) or RightVal.type.width == 8 - if not need_zext and isinstance(LeftVal, ir.Constant): - signed_max = (1 << (RightVal.type.width - 1)) - 1 - try: - if LeftVal.constant > signed_max or LeftVal.constant < 0: - need_zext = True - except (TypeError, ValueError): - pass - if need_zext: - RightVal = Gen.builder.zext(RightVal, LeftVal.type, name=f"zext_right_{i}") - else: - RightVal = Gen.builder.sext(RightVal, LeftVal.type, name=f"sext_right_{i}") - if is_unsigned: - cmp_result = Gen.builder.icmp_unsigned(ComparatorSymbol, LeftVal, RightVal, name=f"cmp_{i}") - elif isinstance(LeftVal.type, (ir.FloatType, ir.DoubleType)) or isinstance(RightVal.type, (ir.FloatType, ir.DoubleType)): - if isinstance(LeftVal.type, (ir.FloatType, ir.DoubleType)) and isinstance(RightVal.type, ir.IntType): - RightVal = Gen.builder.sitofp(RightVal, LeftVal.type, name=f"int_to_float_cmp_{i}") - elif isinstance(RightVal.type, (ir.FloatType, ir.DoubleType)) and isinstance(LeftVal.type, ir.IntType): - LeftVal = Gen.builder.sitofp(LeftVal, RightVal.type, name=f"int_to_float_cmp_{i}") - cmp_result = Gen.builder.fcmp_unordered(ComparatorSymbol, LeftVal, RightVal, name=f"cmp_{i}") - else: - cmp_result = Gen.builder.icmp_signed(ComparatorSymbol, LeftVal, RightVal, name=f"cmp_{i}") - if result_val is None: - result_val = cmp_result - else: - result_val = Gen.builder.and_(result_val, cmp_result, name=f"and_cmp_{i}") - Gen.builder.cbranch(cmp_result, NextBB, EndBB) - Gen.builder.position_at_start(NextBB) - LeftVal = RightVal - Gen.builder.branch(EndBB) - Gen.builder.position_at_start(EndBB) - final_result = Gen.builder.phi(ir.IntType(1), name="final_cmp") - final_result.add_incoming(ir.Constant(ir.IntType(1), 0), PrevBB) - for i in range(len(Node.ops)): - bb = Gen.func.append_basic_block(name=f"cmp.end.{i}") - final_result.add_incoming(ir.Constant(ir.IntType(1), 1), bb) - return final_result +from __future__ import annotations +from typing import TYPE_CHECKING, Any +if TYPE_CHECKING: + from lib.core.translator import Translator + from lib.core.LlvmCodeGenerator import LlvmCodeGenerator +from lib.core.Handles.HandlesBase import BaseHandle +import ast +import llvmlite.ir as ir + + +class ExprOpsHandle(BaseHandle): + def _HandleBinOpLlvm(self, Node: ast.BinOp, VarType: ir.Type | str | None = None) -> ir.Value | None: + Gen: LlvmCodeGenerator = self.Trans.LlvmGen + Gen._set_node_info(Node, "BinOp") + LeftVal: Any = self.HandleExprLlvm(Node.left, VarType) + if not LeftVal: + return None + RightVal: Any = self.HandleExprLlvm(Node.right, VarType) + if not RightVal: + return None + Op: str | None = self.Trans.ExprHandler.GetOpSymbol(Node.op) + if not Op: + return None + OP_OVERLOAD_MAP: dict[str, str] = { + '+': '__add__', '-': '__sub__', '*': '__mul__', + '/': '__truediv__', '//': '__floordiv__', '%': '__mod__', + '**': '__pow__', + } + if Op in OP_OVERLOAD_MAP: + LeftClassName: str | None = None + if isinstance(LeftVal.type, ir.PointerType): + pointee: ir.Type = LeftVal.type.pointee + if isinstance(pointee, (ir.IdentifiedStructType, ir.LiteralStructType)): + for CN, ST in Gen.structs.items(): + if pointee == ST: + LeftClassName = CN + break + elif isinstance(pointee, ir.IntType) and pointee.width == 8: + LeftClassName = self.Trans.ExprUtils._get_var_class(Node.left, Gen) + if LeftClassName and LeftClassName in Gen.structs: + TargetStructPtr: ir.PointerType = ir.PointerType(Gen.structs[LeftClassName]) + LeftVal = Gen.builder.bitcast(LeftVal, TargetStructPtr, name=f"bitcast_to_{LeftClassName}") + if LeftClassName is None and isinstance(Node.left, ast.Name): + LeftClassName = Gen.var_struct_class.get(Node.left.id) + if LeftClassName and LeftClassName in Gen.structs: + if isinstance(LeftVal.type, ir.PointerType) and isinstance(LeftVal.type.pointee, ir.IntType) and LeftVal.type.pointee.width == 8: + TargetStructPtr = ir.PointerType(Gen.structs[LeftClassName]) + LeftVal = Gen.builder.bitcast(LeftVal, TargetStructPtr, name=f"bitcast_to_{LeftClassName}") + if LeftClassName: + op_name: str = OP_OVERLOAD_MAP[Op] + result: Any = self.Trans.ExprUtils._try_operator_overLoad(LeftClassName, op_name, LeftVal, Gen, RightVal) + if result is not None: + return result + if Op in ('+', 'Add') and isinstance(LeftVal.type, ir.PointerType) and isinstance(RightVal.type, ir.IntType): + if isinstance(LeftVal.type.pointee, ir.IntType) and LeftVal.type.pointee.width == 8: + if isinstance(Node.left, ast.Constant) and isinstance(Node.left.value, str) and len(Node.left.value) == 1: + CharVal: Any = Gen._load(LeftVal, name="Load_char_const") + CharAsInt: Any = Gen.builder.zext(CharVal, RightVal.type, name="char_to_int") + result = Gen.builder.add(CharAsInt, RightVal, name="char_add") + TruncResult: Any = Gen.builder.trunc(result, ir.IntType(8), name="add_to_char") + return TruncResult + is_unsigned: bool = Gen._check_node_unsigned(Node.left) or Gen._check_node_unsigned(Node.right) + if isinstance(LeftVal.type, ir.IntType) and isinstance(RightVal.type, ir.IntType): + if LeftVal.type.width < RightVal.type.width: + need_zext: bool = is_unsigned or Gen._check_node_unsigned(Node.left) or LeftVal.type.width == 8 + if not need_zext and isinstance(RightVal, ir.Constant): + signed_max: int = (1 << (LeftVal.type.width - 1)) - 1 + try: + if RightVal.constant > signed_max: + need_zext = True + except (TypeError, ValueError): + pass + if need_zext: + LeftVal = Gen.builder.zext(LeftVal, RightVal.type, name="zext_left") + else: + LeftVal = Gen.builder.sext(LeftVal, RightVal.type, name="sext_left") + elif LeftVal.type.width > RightVal.type.width: + need_zext = is_unsigned or Gen._check_node_unsigned(Node.right) or RightVal.type.width == 8 + if not need_zext and isinstance(LeftVal, ir.Constant): + signed_max = (1 << (RightVal.type.width - 1)) - 1 + try: + if LeftVal.constant > signed_max: + need_zext = True + except (TypeError, ValueError): + pass + if need_zext: + RightVal = Gen.builder.zext(RightVal, LeftVal.type, name="zext_right") + else: + RightVal = Gen.builder.sext(RightVal, LeftVal.type, name="sext_right") + elif isinstance(LeftVal.type, ir.PointerType) and isinstance(RightVal.type, ir.IntType): + if Op not in ('+', '-', 'Add', 'Sub') and isinstance(LeftVal.type.pointee, ir.IntType): + LeftVal = Gen._load(LeftVal, name="deref_ptr_binop") + if LeftVal.type.width < RightVal.type.width: + LeftVal = Gen.builder.zext(LeftVal, RightVal.type, name="zext_deref_left") + elif LeftVal.type.width > RightVal.type.width: + RightVal = Gen.builder.zext(RightVal, LeftVal.type, name="zext_right_deref") + elif isinstance(RightVal.type, ir.PointerType) and isinstance(LeftVal.type, ir.IntType): + if Op not in ('+', '-', 'Add', 'Sub') and isinstance(RightVal.type.pointee, ir.IntType): + RightVal = Gen._load(RightVal, name="deref_ptr_binop_r") + if RightVal.type.width < LeftVal.type.width: + RightVal = Gen.builder.zext(RightVal, LeftVal.type, name="zext_deref_right") + elif RightVal.type.width > LeftVal.type.width: + LeftVal = Gen.builder.zext(LeftVal, RightVal.type, name="zext_left_deref") + if Op in ('>>', 'RShift') and isinstance(Node.left, ast.Name): + vname: str = Node.left.id + if vname in Gen.var_signedness and Gen.var_signedness[vname]: + is_unsigned = True + result = Gen.emit_binary_op(Op, LeftVal, RightVal, is_unsigned=is_unsigned) + return result + + def _HandleBoolOpLlvm(self, Node: ast.BoolOp) -> ir.Value | None: + Gen: LlvmCodeGenerator = self.Trans.LlvmGen + + def _to_bool(val: Any, name: str) -> Any: + if isinstance(val.type, (ir.FloatType, ir.DoubleType)): + return Gen.builder.fcmp_ordered('!=', val, ir.Constant(val.type, 0.0), name=name) + if not isinstance(val.type, ir.IntType) or val.type.width != 1: + return Gen.builder.icmp_signed('!=', val, Gen._ZeroConst(val.type), name=name) + return val + + values: list[ast.expr] = Node.values + if len(values) < 2: + return self.HandleExprLlvm(values[0]) if values else None + if isinstance(Node.op, ast.And): + phi_incomings: list[tuple[ir.Constant, ir.Block]] = [] + end_bb: ir.Block = Gen.func.append_basic_block(name="and.end") + for idx in range(len(values) - 1): + val: Any = self.HandleExprLlvm(values[idx]) + if not val: + if not end_bb.is_terminated: + saved_block: ir.Block = Gen.builder.block + Gen.builder.position_at_start(end_bb) + Gen.builder.unreachable() + Gen.builder.position_at_end(saved_block) + return None + if not isinstance(val.type, ir.IntType) or val.type.width != 1: + val = _to_bool(val, f"andcond{idx}") + cur_bb: ir.Block = Gen.builder.block + next_bb: ir.Block = Gen.func.append_basic_block(name=f"and.rhs{idx}") + Gen.builder.cbranch(val, next_bb, end_bb) + phi_incomings.append((ir.Constant(ir.IntType(1), 0), cur_bb)) + Gen.builder.position_at_start(next_bb) + last_val: Any = self.HandleExprLlvm(values[-1]) + if not last_val: + last_val = ir.Constant(ir.IntType(1), 0) + if not isinstance(last_val.type, ir.IntType) or last_val.type.width != 1: + last_val = _to_bool(last_val, "andcond_last") + last_bb: ir.Block = Gen.builder.block + Gen.builder.branch(end_bb) + Gen.builder.position_at_start(end_bb) + result_phi: Any = Gen.builder.phi(ir.IntType(1), name="and.result") + for const_val, bb in phi_incomings: + result_phi.add_incoming(const_val, bb) + result_phi.add_incoming(last_val, last_bb) + return result_phi + elif isinstance(Node.op, ast.Or): + phi_incomings = [] + end_bb = Gen.func.append_basic_block(name="or.end") + for idx in range(len(values) - 1): + val = self.HandleExprLlvm(values[idx]) + if not val: + if not end_bb.is_terminated: + saved_block = Gen.builder.block + Gen.builder.position_at_start(end_bb) + Gen.builder.unreachable() + Gen.builder.position_at_end(saved_block) + return None + if not isinstance(val.type, ir.IntType) or val.type.width != 1: + val = _to_bool(val, f"orcond{idx}") + cur_bb = Gen.builder.block + next_bb = Gen.func.append_basic_block(name=f"or.rhs{idx}") + Gen.builder.cbranch(val, end_bb, next_bb) + phi_incomings.append((ir.Constant(ir.IntType(1), 1), cur_bb)) + Gen.builder.position_at_start(next_bb) + last_val = self.HandleExprLlvm(values[-1]) + if not last_val: + last_val = ir.Constant(ir.IntType(1), 1) + if not isinstance(last_val.type, ir.IntType) or last_val.type.width != 1: + last_val = _to_bool(last_val, "orcond_last") + last_bb = Gen.builder.block + Gen.builder.branch(end_bb) + Gen.builder.position_at_start(end_bb) + result_phi = Gen.builder.phi(ir.IntType(1), name="or.result") + for const_val, bb in phi_incomings: + result_phi.add_incoming(const_val, bb) + result_phi.add_incoming(last_val, last_bb) + return result_phi + return None + + def _HandleUnaryOpLlvm(self, Node: ast.UnaryOp) -> ir.Value | None: + Gen: LlvmCodeGenerator = self.Trans.LlvmGen + OperandVal: Any = self.HandleExprLlvm(Node.operand) + if not OperandVal: + return None + OpSymbol: str | None = self.Trans.ExprHandler.GetUnaryOpSymbol(Node.op) + if not OpSymbol: + return None + UNARY_OVERLOAD_MAP: dict[str, str] = { + '-': '__neg__', + '+': '__pos__', + '~': '__invert__', + } + if OpSymbol in UNARY_OVERLOAD_MAP: + ClassName: str | None = None + if isinstance(OperandVal.type, ir.PointerType): + pointee: ir.Type = OperandVal.type.pointee + if isinstance(pointee, (ir.IdentifiedStructType, ir.LiteralStructType)): + for CN, ST in Gen.structs.items(): + if pointee == ST: + ClassName = CN + break + elif isinstance(pointee, ir.IntType) and pointee.width == 8: + ClassName = self.Trans.ExprUtils._get_var_class(Node.operand, Gen) + if ClassName and ClassName in Gen.structs: + TargetStructPtr: ir.PointerType = ir.PointerType(Gen.structs[ClassName]) + OperandVal = Gen.builder.bitcast(OperandVal, TargetStructPtr, name=f"bitcast_to_{ClassName}") + if ClassName is None and isinstance(Node.operand, ast.Name): + ClassName = Gen.var_struct_class.get(Node.operand.id) + if ClassName and ClassName in Gen.structs: + if isinstance(OperandVal.type, ir.PointerType) and isinstance(OperandVal.type.pointee, ir.IntType) and OperandVal.type.pointee.width == 8: + TargetStructPtr = ir.PointerType(Gen.structs[ClassName]) + OperandVal = Gen.builder.bitcast(OperandVal, TargetStructPtr, name=f"bitcast_to_{ClassName}") + if ClassName: + op_name: str = UNARY_OVERLOAD_MAP[OpSymbol] + result: Any = self.Trans.ExprUtils._try_operator_overLoad(ClassName, op_name, OperandVal, Gen) + if result is not None: + return result + if OpSymbol == 'not': + if isinstance(OperandVal.type, ir.IntType) and OperandVal.type.width == 1: + return Gen.builder.not_(OperandVal, name="not_result") + if isinstance(OperandVal.type, ir.PointerType): + null_val: ir.Constant = ir.Constant(OperandVal.type, None) + return Gen.builder.icmp_signed('==', OperandVal, null_val, name="not_result") + zero: ir.Constant = ir.Constant(OperandVal.type, 0) + return Gen.builder.icmp_signed('==', OperandVal, zero, name="not_result") + elif OpSymbol == '~': + if isinstance(OperandVal.type, ir.IntType): + mask: int = (1 << OperandVal.type.width) - 1 + return Gen.builder.xor(OperandVal, ir.Constant(OperandVal.type, mask), name="bnot_result") + return Gen.builder.xor(OperandVal, ir.Constant(OperandVal.type, -1), name="bnot_result") + elif OpSymbol == '+': + return OperandVal + elif OpSymbol == '-': + if isinstance(OperandVal.type, ir.IntType): + return Gen.builder.neg(OperandVal, name="neg_result") + elif isinstance(OperandVal.type, (ir.FloatType, ir.DoubleType)): + return Gen.builder.fneg(OperandVal, name="fneg_result") + return None + + def _HandleCompareLlvm(self, Node: ast.Compare) -> ir.Value | None: + Gen: LlvmCodeGenerator = self.Trans.LlvmGen + LeftVal: Any = self.HandleExprLlvm(Node.left) + if not LeftVal: + return None + is_unsigned: bool = Gen._check_node_unsigned(Node.left) or (Gen._check_node_unsigned(Node.comparators[0]) if Node.comparators else False) + if len(Node.ops) == 1: + Op: ast.cmpop = Node.ops[0] + ComparatorSymbol: str | None = self.Trans.ExprHandler.GetComparatorSymbol(Op) + if not ComparatorSymbol: + return None + RightVal: Any = self.HandleExprLlvm(Node.comparators[0]) + if not RightVal: + return None + if isinstance(LeftVal, ir.Constant) and isinstance(RightVal, ir.Constant): + if isinstance(LeftVal.type, ir.IntType) and isinstance(RightVal.type, ir.IntType): + lv: int = LeftVal.constant + rv: int = RightVal.constant + lw: int = LeftVal.type.width + rw: int = RightVal.type.width + if lw < rw: + lv = lv if lv >= 0 else lv + (1 << lw) + elif rw < lw: + rv = rv if rv >= 0 else rv + (1 << rw) + if is_unsigned: + mask_l: int = (1 << max(lw, rw)) - 1 + lv = lv & mask_l + rv = rv & mask_l + cmp_map: dict[str, bool] = { + '==': lv == rv, '!=': lv != rv, + '<': lv < rv, '>': lv > rv, + '<=': lv <= rv, '>=': lv >= rv, + } + result: bool = cmp_map.get(ComparatorSymbol, False) + return ir.Constant(ir.IntType(1), 1 if result else 0) + if isinstance(LeftVal.type, ir.IntType) and isinstance(RightVal.type, ir.IntType): + if LeftVal.type.width < RightVal.type.width: + # 如果宽类型常量值超出窄类型有符号范围,则必须用zext + # i8 类型默认使用 zext(系统编程中 i8 几乎总是无符号字节) + need_zext: bool = is_unsigned or Gen._check_node_unsigned(Node.left) or LeftVal.type.width == 8 + if not need_zext and isinstance(RightVal, ir.Constant): + signed_max: int = (1 << (LeftVal.type.width - 1)) - 1 + try: + if RightVal.constant > signed_max or RightVal.constant < 0: + need_zext = True + except (TypeError, ValueError): + pass + if need_zext: + LeftVal = Gen.builder.zext(LeftVal, RightVal.type, name="zext_left_cmp") + else: + LeftVal = Gen.builder.sext(LeftVal, RightVal.type, name="sext_left_cmp") + elif LeftVal.type.width > RightVal.type.width: + need_zext = is_unsigned or Gen._check_node_unsigned(Node.comparators[0]) or RightVal.type.width == 8 + if not need_zext and isinstance(LeftVal, ir.Constant): + signed_max = (1 << (RightVal.type.width - 1)) - 1 + try: + if LeftVal.constant > signed_max or LeftVal.constant < 0: + need_zext = True + except (TypeError, ValueError): + pass + if need_zext: + RightVal = Gen.builder.zext(RightVal, LeftVal.type, name="zext_right_cmp") + else: + RightVal = Gen.builder.sext(RightVal, LeftVal.type, name="sext_right_cmp") + elif isinstance(LeftVal.type, ir.PointerType) and isinstance(RightVal.type, ir.IntType): + if isinstance(LeftVal.type.pointee, ir.IntType) and LeftVal.type.pointee.width == 8 and isinstance(RightVal.type, ir.IntType) and RightVal.type.width == 8: + LeftVal = Gen._load(LeftVal, name="Load_char_ptr_cmp") + else: + if isinstance(RightVal, ir.Constant) and RightVal.constant == 0: + RightVal = ir.Constant(LeftVal.type, None) + else: + RightVal = Gen.builder.inttoptr(RightVal, LeftVal.type, name="int2ptr_cmp") + elif isinstance(RightVal.type, ir.PointerType) and isinstance(LeftVal.type, ir.IntType): + if isinstance(RightVal.type.pointee, ir.IntType) and RightVal.type.pointee.width == 8 and isinstance(LeftVal.type, ir.IntType) and LeftVal.type.width == 8: + RightVal = Gen._load(RightVal, name="Load_char_ptr_cmp") + else: + if isinstance(LeftVal, ir.Constant) and LeftVal.constant == 0: + LeftVal = ir.Constant(RightVal.type, None) + else: + LeftVal = Gen.builder.inttoptr(LeftVal, RightVal.type, name="int2ptr_cmp") + # is / is not: 地址比较(指针)或值比较(int) + if ComparatorSymbol in ('is', 'is not'): + if isinstance(LeftVal.type, ir.PointerType) and isinstance(RightVal.type, ir.PointerType): + addr_cmp = Gen.builder.icmp_unsigned('==', LeftVal, RightVal, name="is_cmp") + if ComparatorSymbol == 'is not': + addr_cmp = Gen.builder.not_(addr_cmp, name="is_not_result") + return addr_cmp + if isinstance(LeftVal.type, ir.IntType) and isinstance(RightVal.type, ir.IntType): + val_cmp = Gen.builder.icmp_signed('==', LeftVal, RightVal, name="is_cmp") + if ComparatorSymbol == 'is not': + val_cmp = Gen.builder.not_(val_cmp, name="is_not_result") + return val_cmp + # str/bytes == str/bytes: 值比较(调用 strcmp),None 比较用地址 + if ComparatorSymbol in ('==', '!='): + if (isinstance(LeftVal.type, ir.PointerType) and isinstance(LeftVal.type.pointee, ir.IntType) and LeftVal.type.pointee.width == 8 + and isinstance(RightVal.type, ir.PointerType) and isinstance(RightVal.type.pointee, ir.IntType) and RightVal.type.pointee.width == 8): + left_is_null: bool = isinstance(LeftVal, ir.Constant) and LeftVal.constant is None + right_is_null: bool = isinstance(RightVal, ir.Constant) and RightVal.constant is None + if not (left_is_null or right_is_null): + strcmp_func = Gen.get_or_declare_c_func('strcmp', ir.FunctionType(ir.IntType(32), [ir.IntType(8).as_pointer(), ir.IntType(8).as_pointer()])) + cmp_result = Gen.builder.call(strcmp_func, [LeftVal, RightVal], name="str_eq_cmp") + zero = ir.Constant(ir.IntType(32), 0) + eq_result = Gen.builder.icmp_signed('==', cmp_result, zero, name="str_eq") + if ComparatorSymbol == '!=': + eq_result = Gen.builder.not_(eq_result, name="str_neq") + return eq_result + if isinstance(LeftVal.type, ir.PointerType) and isinstance(RightVal.type, ir.PointerType): + result = Gen.builder.icmp_unsigned(ComparatorSymbol, LeftVal, RightVal, name="cmpresult") + elif isinstance(LeftVal.type, (ir.FloatType, ir.DoubleType)) or isinstance(RightVal.type, (ir.FloatType, ir.DoubleType)): + if isinstance(LeftVal.type, (ir.FloatType, ir.DoubleType)) and isinstance(RightVal.type, ir.IntType): + RightVal = Gen.builder.sitofp(RightVal, LeftVal.type, name="int_to_float_cmp") + elif isinstance(RightVal.type, (ir.FloatType, ir.DoubleType)) and isinstance(LeftVal.type, ir.IntType): + LeftVal = Gen.builder.sitofp(LeftVal, RightVal.type, name="int_to_float_cmp") + result = Gen.builder.fcmp_unordered(ComparatorSymbol, LeftVal, RightVal, name="cmpresult") + elif is_unsigned: + result = Gen.builder.icmp_unsigned(ComparatorSymbol, LeftVal, RightVal, name="cmpresult") + else: + result = Gen.builder.icmp_signed(ComparatorSymbol, LeftVal, RightVal, name="cmpresult") + return result + EndBB: ir.Block = Gen.func.append_basic_block(name="cmp.end") + result_val: Any = None + PrevBB: ir.Block = Gen.builder.block + for i, (Op, Comparator) in enumerate(zip(Node.ops, Node.comparators)): + ComparatorSymbol = self.Trans.ExprHandler.GetComparatorSymbol(Op) + if not ComparatorSymbol: + continue + RightVal = self.HandleExprLlvm(Comparator) + if not RightVal: + continue + NextBB: ir.Block = Gen.func.append_basic_block(name="cmp.next") + if isinstance(LeftVal.type, ir.IntType) and isinstance(RightVal.type, ir.IntType): + if LeftVal.type.width < RightVal.type.width: + need_zext = is_unsigned or Gen._check_node_unsigned(Node.left) or LeftVal.type.width == 8 + if not need_zext and isinstance(RightVal, ir.Constant): + signed_max = (1 << (LeftVal.type.width - 1)) - 1 + try: + if RightVal.constant > signed_max or RightVal.constant < 0: + need_zext = True + except (TypeError, ValueError): + pass + if need_zext: + LeftVal = Gen.builder.zext(LeftVal, RightVal.type, name=f"zext_left_{i}") + else: + LeftVal = Gen.builder.sext(LeftVal, RightVal.type, name=f"sext_left_{i}") + elif LeftVal.type.width > RightVal.type.width: + need_zext = is_unsigned or Gen._check_node_unsigned(Comparator) or RightVal.type.width == 8 + if not need_zext and isinstance(LeftVal, ir.Constant): + signed_max = (1 << (RightVal.type.width - 1)) - 1 + try: + if LeftVal.constant > signed_max or LeftVal.constant < 0: + need_zext = True + except (TypeError, ValueError): + pass + if need_zext: + RightVal = Gen.builder.zext(RightVal, LeftVal.type, name=f"zext_right_{i}") + else: + RightVal = Gen.builder.sext(RightVal, LeftVal.type, name=f"sext_right_{i}") + if is_unsigned: + cmp_result: Any = Gen.builder.icmp_unsigned(ComparatorSymbol, LeftVal, RightVal, name=f"cmp_{i}") + elif isinstance(LeftVal.type, (ir.FloatType, ir.DoubleType)) or isinstance(RightVal.type, (ir.FloatType, ir.DoubleType)): + if isinstance(LeftVal.type, (ir.FloatType, ir.DoubleType)) and isinstance(RightVal.type, ir.IntType): + RightVal = Gen.builder.sitofp(RightVal, LeftVal.type, name=f"int_to_float_cmp_{i}") + elif isinstance(RightVal.type, (ir.FloatType, ir.DoubleType)) and isinstance(LeftVal.type, ir.IntType): + LeftVal = Gen.builder.sitofp(LeftVal, RightVal.type, name=f"int_to_float_cmp_{i}") + cmp_result = Gen.builder.fcmp_unordered(ComparatorSymbol, LeftVal, RightVal, name=f"cmp_{i}") + else: + cmp_result = Gen.builder.icmp_signed(ComparatorSymbol, LeftVal, RightVal, name=f"cmp_{i}") + if result_val is None: + result_val = cmp_result + else: + result_val = Gen.builder.and_(result_val, cmp_result, name=f"and_cmp_{i}") + Gen.builder.cbranch(cmp_result, NextBB, EndBB) + Gen.builder.position_at_start(NextBB) + LeftVal = RightVal + Gen.builder.branch(EndBB) + Gen.builder.position_at_start(EndBB) + final_result: Any = Gen.builder.phi(ir.IntType(1), name="final_cmp") + final_result.add_incoming(ir.Constant(ir.IntType(1), 0), PrevBB) + for i in range(len(Node.ops)): + bb: ir.Block = Gen.func.append_basic_block(name=f"cmp.end.{i}") + final_result.add_incoming(ir.Constant(ir.IntType(1), 1), bb) + return final_result \ No newline at end of file diff --git a/lib/core/Handles/HandlesExprUtils.py b/lib/core/Handles/HandlesExprUtils.py index a545308..0fd865d 100644 --- a/lib/core/Handles/HandlesExprUtils.py +++ b/lib/core/Handles/HandlesExprUtils.py @@ -1,240 +1,241 @@ -from __future__ import annotations -from typing import TYPE_CHECKING -if TYPE_CHECKING: - from lib.core.translator import Translator -import ast -import llvmlite.ir as ir - - -class ExprUtils: - def __init__(self, translator: "Translator"): - self.Trans = translator - - def GetOpSymbol(self, Op): - OpMap = { - ast.Add: '+', ast.Sub: '-', ast.Mult: '*', ast.Div: '/', - ast.FloorDiv: '//', ast.Mod: '%', ast.Pow: '**', ast.BitAnd: '&', - ast.BitOr: '|', ast.BitXor: '^', ast.LShift: '<<', ast.RShift: '>>', - ast.MatMult: '@', - } - return OpMap.get(type(Op), None) - - def GetUnaryOpSymbol(self, Op): - OpMap = {ast.Invert: '~', ast.Not: 'not', ast.UAdd: '+', ast.USub: '-'} - return OpMap.get(type(Op), None) - - def GetComparatorSymbol(self, Op): - OpMap = { - ast.Eq: '==', ast.NotEq: '!=', ast.Lt: '<', ast.LtE: '<=', - ast.Gt: '>', ast.GtE: '>=', ast.Is: 'is', ast.IsNot: 'is not', - ast.In: 'in', ast.NotIn: 'not in', - } - return OpMap.get(type(Op), None) - - def _get_var_class(self, node, Gen): - if isinstance(node, ast.Name): - VarName = node.id - return Gen.var_struct_class.get(VarName) - if isinstance(node, ast.Attribute): - AttrName = node.attr - return Gen.var_struct_class.get(AttrName) - return None - - def _try_operator_overLoad(self, ClassName, op_name, obj_val, Gen, other_val=None): - FullMethodName = f'{ClassName}.{op_name}' - if not Gen._has_function(FullMethodName): - FullMethodName = f'{ClassName}.{op_name}__' - if Gen._has_function(FullMethodName): - func = Gen._get_function(FullMethodName) - call_args = [obj_val] - if other_val is not None: - call_args.append(other_val) - if len(func.ftype.args) == len(call_args): - for i, (expected_type, actual_val) in enumerate(zip(func.ftype.args, call_args)): - if isinstance(expected_type, ir.PointerType) and isinstance(actual_val.type, ir.PointerType): - if expected_type != actual_val.type: - if isinstance(expected_type.pointee, (ir.IdentifiedStructType, ir.LiteralStructType)): - call_args[i] = Gen.builder.bitcast(actual_val, expected_type, name=f"bitcast_arg_{i}") - result = Gen.builder.call(func, call_args, name=f"call_{FullMethodName}") - return result - return None - - def _llvm_type_to_detailed_string(self, llvm_type, var_name=""): - info = { - 'name': "unknown", - 'size': 0, - 'signed': False, - 'ptr': False - } - if isinstance(llvm_type, ir.IntType): - info['size'] = llvm_type.width // 8 - info['signed'] = True - if llvm_type.width == 8: - info['name'] = "char" - elif llvm_type.width == 16: - info['name'] = "short" - elif llvm_type.width == 32: - info['name'] = "int" - elif llvm_type.width == 64: - info['name'] = "long long" - else: - info['name'] = f"int{llvm_type.width}" - elif isinstance(llvm_type, ir.DoubleType): - info['size'] = 8 - info['signed'] = True - info['name'] = "double" - elif isinstance(llvm_type, ir.FloatType): - info['size'] = 4 - info['signed'] = True - info['name'] = "float" - elif isinstance(llvm_type, ir.PointerType): - info['size'] = 8 - info['signed'] = False - info['ptr'] = True - pointee_info = self._llvm_type_to_detailed_string(llvm_type.pointee) - info['name'] = f"{pointee_info['name']}*" - elif isinstance(llvm_type, (ir.LiteralStructType, ir.IdentifiedStructType)): - size = 0 - for elem in llvm_type.elements: - elem_info = self._llvm_type_to_detailed_string(elem) - size += elem_info['size'] - info['size'] = size - info['signed'] = False - if isinstance(llvm_type, ir.IdentifiedStructType): - info['name'] = llvm_type.name - else: - info['name'] = "struct" - elif isinstance(llvm_type, ir.ArrayType): - elem_info = self._llvm_type_to_detailed_string(llvm_type.element) - info['size'] = elem_info['size'] * llvm_type.count - info['signed'] = elem_info['signed'] - info['name'] = f"{elem_info['name']}[]" - elif isinstance(llvm_type, ir.VoidType): - info['size'] = 0 - info['signed'] = False - info['name'] = "void" - else: - info['size'] = 0 - info['signed'] = False - info['name'] = str(llvm_type) - return info - - def _infer_expr_llvm_type_full(self, node): - Gen = self.Trans.LlvmGen - if isinstance(node, ast.Constant): - if isinstance(node.value, bool): - return ir.IntType(32) - elif isinstance(node.value, int): - return ir.IntType(32) - elif isinstance(node.value, float): - return ir.DoubleType() - elif isinstance(node.value, str): - if getattr(node, 'kind', None) == 'u': - return ir.PointerType(ir.IntType(16)) - return ir.PointerType(ir.IntType(8)) - return ir.IntType(32) - elif isinstance(node, ast.Name): - if node.id in Gen.variables: - var_ptr = Gen.variables[node.id] - if isinstance(var_ptr.type, ir.PointerType): - return var_ptr.type.pointee - return var_ptr.type - if node.id in Gen._reg_values: - return Gen._reg_values[node.id].type - return ir.IntType(32) - elif isinstance(node, ast.Attribute): - attr_name = node.attr - if self.Trans.SymbolTable.has(attr_name): - AttrInfo = self.Trans.SymbolTable[attr_name] - if getattr(AttrInfo, 'IsEnumMember', None): - return ir.IntType(32) - return ir.IntType(32) - elif isinstance(node, ast.BinOp): - left_type = self._infer_expr_llvm_type_full(node.left) - right_type = self._infer_expr_llvm_type_full(node.right) - if isinstance(left_type, (ir.FloatType, ir.DoubleType)) or isinstance(right_type, (ir.FloatType, ir.DoubleType)): - return ir.DoubleType() - if isinstance(left_type, ir.PointerType) or isinstance(right_type, ir.PointerType): - return ir.PointerType(ir.IntType(8)) - return ir.IntType(32) - elif isinstance(node, ast.UnaryOp): - return self._infer_expr_llvm_type_full(node.operand) - elif isinstance(node, ast.Subscript): - val_type = self._infer_expr_llvm_type_full(node.value) - if isinstance(val_type, ir.PointerType): - if isinstance(val_type.pointee, ir.IntType) and val_type.pointee.width == 8: - return ir.IntType(8) - if isinstance(val_type.pointee, ir.ArrayType): - return ir.PointerType(val_type.pointee.element) - return val_type.pointee - if isinstance(val_type, ir.ArrayType): - return val_type.element - if isinstance(val_type, ir.IntType): - return ir.IntType(8) - return ir.IntType(32) - elif isinstance(node, ast.Call): - if isinstance(node.func, ast.Name): - func_name = node.func.id - if Gen._has_function(func_name): - fn = Gen._get_function(func_name) - return fn.function_type.return_type - if func_name == 'len': - return ir.IntType(32) - if func_name == 'sizeof': - return ir.IntType(32) - if func_name == 'ord': - return ir.IntType(32) - if func_name == 'chr': - return ir.IntType(8) - if func_name == 'int': - return ir.IntType(32) - if func_name == 'float' or func_name == 'double': - return ir.DoubleType() - elif isinstance(node.func, ast.Attribute): - if isinstance(node.func.value, ast.Name) and node.func.value.id == 'c': - if node.func.attr == 'Deref': - return ir.IntType(64) - if isinstance(node.func.value, ast.Name) and node.func.value.id == 't': - if node.func.attr == 'CChar': - return ir.PointerType(ir.IntType(8)) - return ir.IntType(32) - elif isinstance(node, ast.Compare): - return ir.IntType(1) - elif isinstance(node, ast.BoolOp): - return ir.IntType(1) - elif isinstance(node, ast.IfExp): - return self._infer_expr_llvm_type_full(node.body) - elif isinstance(node, ast.Attribute): - return ir.PointerType(ir.IntType(8)) - return ir.IntType(32) - - def _collect_names(self, node, bound, free=None): - """收集 AST 节点中的绑定变量和自由变量 - - Args: - node: AST 节点 - bound: 集合,收集绑定变量(ast.Store 上下文) - free: 集合,收集自由变量(ast.Load 上下文),可为 None - """ - if free is None: - free = set() - if isinstance(node, ast.Name): - if isinstance(node.ctx, ast.Store): - bound.add(node.id) - elif isinstance(node.ctx, ast.Load): - free.add(node.id) - elif isinstance(node, (ast.Lambda, ast.FunctionDef, ast.AsyncFunctionDef)): - # 这些节点有自己的作用域,不递归进入 - # 但需要收集参数名作为 bound - if hasattr(node, 'args') and node.args: - for arg in node.args.args: - bound.add(arg.arg) - elif getattr(node, '_fields', None): - for field in node._fields: - value = getattr(node, field, None) - if isinstance(value, list): - for item in value: - if isinstance(item, (ast.stmt, ast.expr)): - self._collect_names(item, bound, free) - elif isinstance(value, (ast.stmt, ast.expr)): - self._collect_names(value, bound, free) +from __future__ import annotations +from typing import TYPE_CHECKING, Any +if TYPE_CHECKING: + from lib.core.translator import Translator + from lib.core.LlvmCodeGenerator import LlvmCodeGenerator +import ast +import llvmlite.ir as ir +from lib.core.SymbolUtils import IsTModule + + +class ExprUtils: + def __init__(self, translator: "Translator") -> None: + self.Trans: Translator = translator + + def GetOpSymbol(self, Op: ast.cmpop | ast.operator | ast.unaryoperator) -> str | None: + OpMap: dict[type, str] = { + ast.Add: '+', ast.Sub: '-', ast.Mult: '*', ast.Div: '/', + ast.FloorDiv: '//', ast.Mod: '%', ast.Pow: '**', ast.BitAnd: '&', + ast.BitOr: '|', ast.BitXor: '^', ast.LShift: '<<', ast.RShift: '>>', + ast.MatMult: '@', + } + return OpMap.get(type(Op), None) + + def GetUnaryOpSymbol(self, Op: ast.unaryoperator) -> str | None: + OpMap: dict[type, str] = {ast.Invert: '~', ast.Not: 'not', ast.UAdd: '+', ast.USub: '-'} + return OpMap.get(type(Op), None) + + def GetComparatorSymbol(self, Op: ast.cmpop) -> str | None: + OpMap: dict[type, str] = { + ast.Eq: '==', ast.NotEq: '!=', ast.Lt: '<', ast.LtE: '<=', + ast.Gt: '>', ast.GtE: '>=', ast.Is: 'is', ast.IsNot: 'is not', + ast.In: 'in', ast.NotIn: 'not in', + } + return OpMap.get(type(Op), None) + + def _get_var_class(self, node: ast.AST, Gen: LlvmCodeGenerator) -> str | None: + if isinstance(node, ast.Name): + VarName: str = node.id + return Gen.var_struct_class.get(VarName) + if isinstance(node, ast.Attribute): + AttrName: str = node.attr + return Gen.var_struct_class.get(AttrName) + return None + + def _try_operator_overLoad(self, ClassName: str, op_name: str, obj_val: ir.Value, Gen: LlvmCodeGenerator, other_val: ir.Value | None = None) -> ir.Value | None: + FullMethodName: str = f'{ClassName}.{op_name}' + if not Gen._has_function(FullMethodName): + FullMethodName = f'{ClassName}.{op_name}__' + if Gen._has_function(FullMethodName): + func: Any = Gen._get_function(FullMethodName) + call_args: list[Any] = [obj_val] + if other_val is not None: + call_args.append(other_val) + if len(func.ftype.args) == len(call_args): + for i, (expected_type, actual_val) in enumerate(zip(func.ftype.args, call_args)): + if isinstance(expected_type, ir.PointerType) and isinstance(actual_val.type, ir.PointerType): + if expected_type != actual_val.type: + if isinstance(expected_type.pointee, (ir.IdentifiedStructType, ir.LiteralStructType)): + call_args[i] = Gen.builder.bitcast(actual_val, expected_type, name=f"bitcast_arg_{i}") + result: Any = Gen.builder.call(func, call_args, name=f"call_{FullMethodName}") + return result + return None + + def _llvm_type_to_detailed_string(self, llvm_type: ir.Type, var_name: str = "") -> dict[str, Any]: + info: dict[str, Any] = { + 'name': "unknown", + 'size': 0, + 'signed': False, + 'ptr': False + } + if isinstance(llvm_type, ir.IntType): + info['size'] = llvm_type.width // 8 + info['signed'] = True + if llvm_type.width == 8: + info['name'] = "char" + elif llvm_type.width == 16: + info['name'] = "short" + elif llvm_type.width == 32: + info['name'] = "int" + elif llvm_type.width == 64: + info['name'] = "long long" + else: + info['name'] = f"int{llvm_type.width}" + elif isinstance(llvm_type, ir.DoubleType): + info['size'] = 8 + info['signed'] = True + info['name'] = "double" + elif isinstance(llvm_type, ir.FloatType): + info['size'] = 4 + info['signed'] = True + info['name'] = "float" + elif isinstance(llvm_type, ir.PointerType): + info['size'] = 8 + info['signed'] = False + info['ptr'] = True + pointee_info: dict[str, Any] = self._llvm_type_to_detailed_string(llvm_type.pointee) + info['name'] = f"{pointee_info['name']}*" + elif isinstance(llvm_type, (ir.LiteralStructType, ir.IdentifiedStructType)): + size: int = 0 + for elem in llvm_type.elements: + elem_info: dict[str, Any] = self._llvm_type_to_detailed_string(elem) + size += elem_info['size'] + info['size'] = size + info['signed'] = False + if isinstance(llvm_type, ir.IdentifiedStructType): + info['name'] = llvm_type.name + else: + info['name'] = "struct" + elif isinstance(llvm_type, ir.ArrayType): + elem_info = self._llvm_type_to_detailed_string(llvm_type.element) + info['size'] = elem_info['size'] * llvm_type.count + info['signed'] = elem_info['signed'] + info['name'] = f"{elem_info['name']}[]" + elif isinstance(llvm_type, ir.VoidType): + info['size'] = 0 + info['signed'] = False + info['name'] = "void" + else: + info['size'] = 0 + info['signed'] = False + info['name'] = str(llvm_type) + return info + + def _infer_expr_llvm_type_full(self, node: ast.AST) -> ir.Type: + Gen: LlvmCodeGenerator = self.Trans.LlvmGen + if isinstance(node, ast.Constant): + if isinstance(node.value, bool): + return ir.IntType(32) + elif isinstance(node.value, int): + return ir.IntType(32) + elif isinstance(node.value, float): + return ir.DoubleType() + elif isinstance(node.value, str): + if getattr(node, 'kind', None) == 'u': + return ir.PointerType(ir.IntType(16)) + return ir.PointerType(ir.IntType(8)) + return ir.IntType(32) + elif isinstance(node, ast.Name): + if node.id in Gen.variables: + var_ptr: Any = Gen.variables[node.id] + if isinstance(var_ptr.type, ir.PointerType): + return var_ptr.type.pointee + return var_ptr.type + if node.id in Gen._reg_values: + return Gen._reg_values[node.id].type + return ir.IntType(32) + elif isinstance(node, ast.Attribute): + attr_name: str = node.attr + AttrInfo: Any = self.Trans.SymbolTable.lookup(attr_name) + if AttrInfo and getattr(AttrInfo, 'IsEnumMember', None): + return ir.IntType(32) + return ir.IntType(32) + elif isinstance(node, ast.BinOp): + left_type: ir.Type = self._infer_expr_llvm_type_full(node.left) + right_type: ir.Type = self._infer_expr_llvm_type_full(node.right) + if isinstance(left_type, (ir.FloatType, ir.DoubleType)) or isinstance(right_type, (ir.FloatType, ir.DoubleType)): + return ir.DoubleType() + if isinstance(left_type, ir.PointerType) or isinstance(right_type, ir.PointerType): + return ir.PointerType(ir.IntType(8)) + return ir.IntType(32) + elif isinstance(node, ast.UnaryOp): + return self._infer_expr_llvm_type_full(node.operand) + elif isinstance(node, ast.Subscript): + val_type: ir.Type = self._infer_expr_llvm_type_full(node.value) + if isinstance(val_type, ir.PointerType): + if isinstance(val_type.pointee, ir.IntType) and val_type.pointee.width == 8: + return ir.IntType(8) + if isinstance(val_type.pointee, ir.ArrayType): + return ir.PointerType(val_type.pointee.element) + return val_type.pointee + if isinstance(val_type, ir.ArrayType): + return val_type.element + if isinstance(val_type, ir.IntType): + return ir.IntType(8) + return ir.IntType(32) + elif isinstance(node, ast.Call): + if isinstance(node.func, ast.Name): + func_name: str = node.func.id + if Gen._has_function(func_name): + fn: Any = Gen._get_function(func_name) + return fn.function_type.return_type + if func_name == 'len': + return ir.IntType(32) + if func_name == 'sizeof': + return ir.IntType(32) + if func_name == 'ord': + return ir.IntType(32) + if func_name == 'chr': + return ir.IntType(8) + if func_name == 'int': + return ir.IntType(32) + if func_name == 'float' or func_name == 'double': + return ir.DoubleType() + elif isinstance(node.func, ast.Attribute): + if isinstance(node.func.value, ast.Name) and node.func.value.id == 'c': + if node.func.attr == 'Deref': + return ir.IntType(64) + if isinstance(node.func.value, ast.Name) and IsTModule(node.func.value.id, self.Trans.SymbolTable): + if node.func.attr == 'CChar': + return ir.PointerType(ir.IntType(8)) + return ir.IntType(32) + elif isinstance(node, ast.Compare): + return ir.IntType(1) + elif isinstance(node, ast.BoolOp): + return ir.IntType(1) + elif isinstance(node, ast.IfExp): + return self._infer_expr_llvm_type_full(node.body) + elif isinstance(node, ast.Attribute): + return ir.PointerType(ir.IntType(8)) + return ir.IntType(32) + + def _collect_names(self, node: ast.AST, bound: set[str], free: set[str] | None = None) -> None: + """收集 AST 节点中的绑定变量和自由变量 + + Args: + node: AST 节点 + bound: 集合,收集绑定变量(ast.Store 上下文) + free: 集合,收集自由变量(ast.Load 上下文),可为 None + """ + if free is None: + free = set() + if isinstance(node, ast.Name): + if isinstance(node.ctx, ast.Store): + bound.add(node.id) + elif isinstance(node.ctx, ast.Load): + free.add(node.id) + elif isinstance(node, (ast.Lambda, ast.FunctionDef, ast.AsyncFunctionDef)): + # 这些节点有自己的作用域,不递归进入 + # 但需要收集参数名作为 bound + if hasattr(node, 'args') and node.args: + for arg in node.args.args: + bound.add(arg.arg) + elif getattr(node, '_fields', None): + for field in node._fields: + value: Any = getattr(node, field, None) + if isinstance(value, list): + for item in value: + if isinstance(item, (ast.stmt, ast.expr)): + self._collect_names(item, bound, free) + elif isinstance(value, (ast.stmt, ast.expr)): + self._collect_names(value, bound, free) \ No newline at end of file diff --git a/lib/core/Handles/HandlesFor.py b/lib/core/Handles/HandlesFor.py index 19752db..9806d68 100644 --- a/lib/core/Handles/HandlesFor.py +++ b/lib/core/Handles/HandlesFor.py @@ -1,495 +1,1046 @@ -from __future__ import annotations -from typing import TYPE_CHECKING -if TYPE_CHECKING: - from lib.core.translator import Translator -from lib.core.Handles.HandlesBase import BaseHandle -import ast -import llvmlite.ir as ir - - -class ForHandle(BaseHandle): - def _HandleForLlvm(self, Node): - Gen = self.Trans.LlvmGen - Gen._set_node_info(Node, "For") - if not isinstance(Node.target, ast.Name): - return - TargetName = Node.target.id - StartVal = None - EndVal = None - StepVal = None - IsRange = False - CondOp = '<' - if isinstance(Node.iter, ast.Call): - CallFunc = Node.iter.func - if isinstance(CallFunc, ast.Name) and CallFunc.id == 'range': - IsRange = True - RangeArgs = Node.iter.args - RangeEndArg = RangeArgs[1] if len(RangeArgs) >= 2 else RangeArgs[0] if len(RangeArgs) >= 1 else None - OptimizedEnd = False - if len(RangeArgs) >= 2 and isinstance(RangeEndArg, ast.BinOp): - if isinstance(RangeEndArg.op, ast.Add): - if (isinstance(RangeEndArg.right, ast.Constant) and RangeEndArg.right.value == 1): - EndVal = self.HandleExprLlvm(RangeEndArg.left) - CondOp = '<=' - OptimizedEnd = True - elif (isinstance(RangeEndArg.left, ast.Constant) and RangeEndArg.left.value == 1): - EndVal = self.HandleExprLlvm(RangeEndArg.right) - CondOp = '<=' - OptimizedEnd = True - elif isinstance(RangeEndArg.op, ast.Sub): - if isinstance(RangeEndArg.right, ast.Constant) and RangeEndArg.right.value == 1: - EndVal = self.HandleExprLlvm(RangeEndArg.left) - CondOp = '<' - OptimizedEnd = True - if not OptimizedEnd: - if len(RangeArgs) == 1: - EndVal = self.HandleExprLlvm(RangeArgs[0]) - else: - EndVal = self.HandleExprLlvm(RangeEndArg) - if len(RangeArgs) == 1: - StartVal = ir.Constant(ir.IntType(32), 0) - elif len(RangeArgs) >= 2: - StartVal = self.HandleExprLlvm(RangeArgs[0]) - if len(RangeArgs) >= 3: - StepVal = self.HandleExprLlvm(RangeArgs[2]) - # Check if step is a negative constant — need to flip condition - step_arg = RangeArgs[2] - if isinstance(step_arg, ast.UnaryOp) and isinstance(step_arg.op, ast.USub): - if isinstance(step_arg.operand, ast.Constant) and isinstance(step_arg.operand.value, (int, float)): - if step_arg.operand.value > 0: - CondOp = '>' - elif isinstance(step_arg, ast.Constant) and isinstance(step_arg.value, (int, float)): - if step_arg.value < 0: - CondOp = '>' - if not EndVal: - return - if not isinstance(EndVal.type, ir.IntType): - if isinstance(EndVal.type, ir.PointerType) and isinstance(EndVal.type.pointee, ir.IntType): - EndVal = Gen._load(EndVal, name="Load_end") - else: - EndVal = Gen.builder.ptrtoint(EndVal, ir.IntType(64), name="end") - if StartVal and not isinstance(StartVal.type, ir.IntType): - if isinstance(StartVal.type, ir.PointerType) and isinstance(StartVal.type.pointee, ir.IntType): - StartVal = Gen._load(StartVal, name="Load_start") - else: - StartVal = Gen.builder.ptrtoint(StartVal, ir.IntType(64), name="start") - else: - StartVal = ir.Constant(ir.IntType(64), 0) - if not StartVal: - StartVal = ir.Constant(EndVal.type, 0) - if StepVal is None: - StepVal = ir.Constant(EndVal.type, 1) - if not IsRange: - IterClassName = self.Trans.ExprHandler._get_var_class(Node.iter, Gen) - if not IterClassName and isinstance(Node.iter, ast.Call) and isinstance(Node.iter.func, ast.Name): - IterClassName = Node.iter.func.id - if IterClassName not in Gen.structs: - IterClassName = None - if IterClassName and Gen._has_function(f'{IterClassName}.__iter__') and Gen._has_function(f'{IterClassName}.__next__'): - self._HandleForIterLlvm(Node, IterClassName) - return - IterVal = self.HandleExprLlvm(Node.iter) - if not IterVal: - return - if isinstance(IterVal.type, ir.PointerType) and isinstance(IterVal.type.pointee, ir.IntType) and IterVal.type.pointee.width == 8: - self._HandleForStrLlvm(Node, IterVal) - return - if isinstance(IterVal.type, ir.PointerType) and isinstance(IterVal.type.pointee, ir.ArrayType): - self._HandleForListLlvm(Node, IterVal) - return - StartVal = ir.Constant(ir.IntType(32), 0) - EndVal = IterVal - if not isinstance(EndVal.type, ir.IntType): - EndVal = Gen.builder.ptrtoint(EndVal, ir.IntType(64), name="end") - StartVal = ir.Constant(ir.IntType(64), 0) - StepVal = ir.Constant(EndVal.type, 1) - CondOp = '<' - if TargetName in Gen._reg_values: - del Gen._reg_values[TargetName] - if TargetName in Gen.variables and Gen.variables[TargetName] is not None: - LoopVar = Gen.variables[TargetName] - if isinstance(LoopVar.type, ir.PointerType) and isinstance(LoopVar.type.pointee, ir.IntType) and LoopVar.type.pointee == EndVal.type and isinstance(EndVal.type, ir.IntType) and StartVal.type == LoopVar.type.pointee and EndVal.type == StartVal.type: - Gen._store(StartVal, LoopVar) - else: - NewVar = Gen._allocaEntry(EndVal.type, name=TargetName) - if StartVal.type != EndVal.type: - if isinstance(EndVal.type, ir.IntType) and isinstance(StartVal.type, ir.IntType): - if StartVal.type.width < EndVal.type.width: - StartVal = Gen.builder.zext(StartVal, EndVal.type, name="zext_loop_start") - elif StartVal.type.width > EndVal.type.width: - StartVal = Gen.builder.trunc(StartVal, EndVal.type, name="trunc_loop_start") - Gen._store(StartVal, NewVar) - Gen.variables[TargetName] = NewVar - LoopVar = NewVar - else: - LoopVar = Gen._allocaEntry(EndVal.type, name=TargetName) - Gen.variables[TargetName] = LoopVar - Gen._store(StartVal, LoopVar) - if StepVal and isinstance(StepVal.type, ir.IntType) and isinstance(EndVal.type, ir.IntType): - if StepVal.type.width < EndVal.type.width: - StepVal = Gen.builder.zext(StepVal, EndVal.type, name="zext_loop_step") - elif StepVal.type.width > EndVal.type.width: - StepVal = Gen.builder.trunc(StepVal, EndVal.type, name="trunc_loop_step") - Gen._record_var_signedness(TargetName, 'int') - CondBB = Gen.func.append_basic_block(name="for.cond") - BodyBB = Gen.func.append_basic_block(name="for.body") - StepBB = Gen.func.append_basic_block(name="for.step") - ElseBB = Gen.func.append_basic_block(name="for.else") if Node.orelse else None - AfterBB = Gen.func.append_basic_block(name="for.end") - Gen.loop_break_targets.append(AfterBB) - Gen.loop_continue_targets.append(StepBB) - Gen.builder.branch(CondBB) - Gen.builder.position_at_start(CondBB) - LoopVal = Gen._load(LoopVar, name=TargetName) - is_unsigned = Gen._is_var_unsigned(TargetName) - if is_unsigned: - Cond = Gen.builder.icmp_unsigned(CondOp, LoopVal, EndVal, name="forcond") - else: - Cond = Gen.builder.icmp_signed(CondOp, LoopVal, EndVal, name="forcond") - Gen.builder.cbranch(Cond, BodyBB, ElseBB if ElseBB else AfterBB) - Gen.builder.position_at_start(BodyBB) - CachedLoopVal = Gen._load(LoopVar, name=TargetName) - Gen._reg_values[TargetName] = CachedLoopVal - self.HandleBodyLlvm(Node.body) - StepLoopVal = CachedLoopVal - if TargetName in Gen._reg_values and Gen._reg_values[TargetName] is CachedLoopVal: - del Gen._reg_values[TargetName] - else: - StepLoopVal = Gen._load(LoopVar, name=TargetName) - if not Gen.builder.block.is_terminated: - Gen.builder.branch(StepBB) - Gen.builder.position_at_start(StepBB) - StepLoopVal2 = Gen._load(LoopVar, name=TargetName) - NextVal = Gen.builder.add(StepLoopVal2, StepVal, name="next") - Gen._store(NextVal, LoopVar) - Gen.builder.branch(CondBB) - Gen.loop_break_targets.pop() - Gen.loop_continue_targets.pop() - if ElseBB: - Gen.builder.position_at_start(ElseBB) - self.HandleBodyLlvm(Node.orelse) - if not Gen.builder.block.is_terminated: - Gen.builder.branch(AfterBB) - Gen.builder.position_at_start(AfterBB) - - def _HandleGlobalLlvm(self, Node): - Gen = self.Trans.LlvmGen - for name in Node.names: - Gen.global_vars.add(name) - if name in Gen.module.globals: - Gen.variables[name] = Gen.module.globals[name] - if name in Gen._reg_values: - del Gen._reg_values[name] - - def _HandleNonlocalLlvm(self, Node): - Gen = self.Trans.LlvmGen - for name in Node.names: - if name in Gen._reg_values and name not in Gen.variables: - OldVal = Gen._reg_values[name] - var = Gen._allocaEntry(OldVal.type, name=name) - Gen._store(OldVal, var) - Gen.variables[name] = var - del Gen._reg_values[name] - - def _collect_implicit_nonlocal(self, Node, Gen): - param_names = set() - for arg in Node.args.args: - param_names.add(arg.arg) - local_names = set() - for child in ast.walk(Node): - if isinstance(child, ast.Assign): - for target in child.targets: - if isinstance(target, ast.Name): - local_names.add(target.id) - elif isinstance(target, ast.Tuple): - for elt in target.elts: - if isinstance(elt, ast.Name): - local_names.add(elt.id) - elif isinstance(child, ast.AugAssign): - if isinstance(child.target, ast.Name): - local_names.add(child.target.id) - elif isinstance(child, ast.AnnAssign): - if isinstance(child.target, ast.Name): - local_names.add(child.target.id) - elif isinstance(child, ast.For): - if isinstance(child.target, ast.Name): - local_names.add(child.target.id) - read_names = set() - for child in ast.walk(Node): - if isinstance(child, ast.Name) and isinstance(child.ctx, ast.Load): - name = child.id - if name not in param_names and name not in local_names: - read_names.add(name) - implicit = [] - for name in read_names: - if name in Gen.variables and Gen.variables[name] is not None: - implicit.append(name) - elif name in Gen._reg_values: - implicit.append(name) - for called_name in read_names: - if called_name in Gen.nonlocal_params: - for nv, _ in Gen.nonlocal_params[called_name]: - if nv not in param_names and nv not in local_names: - if nv not in read_names: - if nv in Gen.variables and Gen.variables[nv] is not None: - implicit.append(nv) - elif nv in Gen._reg_values: - implicit.append(nv) - return implicit - - def _collect_all_nonlocal_names(self, Node): - """Recursively collect all nonlocal variable names from a function and its nested functions.""" - names = set() - for stmt in Node.body: - if isinstance(stmt, ast.Nonlocal): - for name in stmt.names: - names.add(name) - elif isinstance(stmt, ast.FunctionDef): - # Recursively collect from nested functions - sub_names = self._collect_all_nonlocal_names(stmt) - names.update(sub_names) - return names - - def _HandleNestedFunctionLlvm(self, Node): - Gen = self.Trans.LlvmGen - nonlocal_var_names = [] - for stmt in Node.body: - if isinstance(stmt, ast.Nonlocal): - for name in stmt.names: - nonlocal_var_names.append(name) - # Pre-scan ALL nested functions recursively for their nonlocal needs (passthrough) - for stmt in Node.body: - if isinstance(stmt, ast.FunctionDef): - sub_nonlocal_names = self._collect_all_nonlocal_names(stmt) - for name in sub_nonlocal_names: - if name not in nonlocal_var_names: - nonlocal_var_names.append(name) - implicit_names = self._collect_implicit_nonlocal(Node, Gen) - for name in implicit_names: - if name not in nonlocal_var_names: - nonlocal_var_names.append(name) - extra_params = [] - for var_name in nonlocal_var_names: - if var_name in Gen.variables and Gen.variables[var_name] is not None: - var = Gen.variables[var_name] - extra_params.append((var_name, var.type)) - elif var_name in Gen._reg_values: - OldVal = Gen._reg_values[var_name] - var = Gen._allocaEntry(OldVal.type, name=var_name) - Gen._store(OldVal, var) - Gen.variables[var_name] = var - del Gen._reg_values[var_name] - extra_params.append((var_name, var.type)) - else: - # Search outer scope stack for the variable - found_var = None - for scope in reversed(Gen._variable_scope_stack): - if var_name in scope and scope[var_name] is not None: - found_var = scope[var_name] - break - if found_var is not None: - # Add to current scope so it can be passed to nested functions - Gen.variables[var_name] = found_var - extra_params.append((var_name, found_var.type)) - else: - var = Gen._allocaEntry(ir.IntType(32), name=var_name) - Gen.variables[var_name] = var - extra_params.append((var_name, var.type)) - if extra_params: - Gen.nonlocal_params[Node.name] = [(name, ptr_type) for name, ptr_type in extra_params] - # Push current variables to scope stack before compiling nested function - Gen._variable_scope_stack.append(Gen.variables.copy()) - saved_builder = Gen.builder - saved_func = Gen.func - saved_variables = Gen.variables.copy() - saved_reg_values = Gen._reg_values.copy() - saved_global_vars = Gen.global_vars.copy() - saved_var_signedness = Gen.var_signedness.copy() - saved_var_type_info = Gen.var_type_info.copy() - saved_var_type_assignments = Gen.var_type_assignments.copy() - saved_CurrentCReturnTypes = getattr(self.Trans, 'CurrentCReturnTypes', None) - saved_CurrentCpythonObjectClass = getattr(self.Trans, '_CurrentCpythonObjectClass', None) - saved_VarScopes = len(self.Trans.VarScopes) - self.Trans.FunctionHandler._EmitFunctionLlvm(Node, Gen, extra_params=extra_params if extra_params else None) - Gen.builder = saved_builder - Gen.func = saved_func - Gen.variables = saved_variables - Gen._reg_values = saved_reg_values - Gen.global_vars = saved_global_vars - Gen.var_signedness = saved_var_signedness - Gen.var_type_info = saved_var_type_info - Gen.var_type_assignments = saved_var_type_assignments - self.Trans.CurrentCReturnTypes = saved_CurrentCReturnTypes - self.Trans._CurrentCpythonObjectClass = saved_CurrentCpythonObjectClass - while len(self.Trans.VarScopes) > saved_VarScopes: - self.Trans.VarScopes.pop() - # Pop scope stack - if Gen._variable_scope_stack: - Gen._variable_scope_stack.pop() - - def _HandleForListLlvm(self, Node, ArrPtr): - Gen = self.Trans.LlvmGen - if not isinstance(Node.target, ast.Name): - return - TargetName = Node.target.id - ElemType = ArrPtr.type.pointee.element - ArrayCount = ArrPtr.type.pointee.count - IdxVal = Gen._allocaEntry(ir.IntType(32), name=f"arr_idx") - Gen.builder.store(ir.Constant(ir.IntType(32), 0), IdxVal) - if TargetName in Gen._reg_values: - del Gen._reg_values[TargetName] - LoopVar = Gen._allocaEntry(ElemType, name=TargetName) - Gen.variables[TargetName] = LoopVar - Gen._store(ir.Constant(ElemType, None), LoopVar) - CondBB = Gen.func.append_basic_block(name="arrfor.cond") - BodyBB = Gen.func.append_basic_block(name="arrfor.body") - StepBB = Gen.func.append_basic_block(name="arrfor.step") - ElseBB = Gen.func.append_basic_block(name="arrfor.else") if Node.orelse else None - AfterBB = Gen.func.append_basic_block(name="arrfor.end") - Gen.loop_break_targets.append(AfterBB) - Gen.loop_continue_targets.append(StepBB) - Gen.builder.branch(CondBB) - Gen.builder.position_at_start(CondBB) - CurIdx = Gen._load(IdxVal, name="cur_idx") - IsDone = Gen.builder.icmp_signed('<', CurIdx, ir.Constant(ir.IntType(32), ArrayCount), name="arr_in_bounds") - Gen.builder.cbranch(IsDone, BodyBB, ElseBB if ElseBB else AfterBB) - Gen.builder.position_at_start(BodyBB) - ElemPtr = Gen.builder.gep(ArrPtr, [ir.Constant(ir.IntType(32), 0), CurIdx], name="arr_elem_ptr") - ElemVal = Gen._load(ElemPtr, name="arr_elem_val") - Gen._store(ElemVal, LoopVar) - Gen._record_var_signedness(TargetName, 'ptr') - Gen._reg_values[TargetName] = ElemVal - self.HandleBodyLlvm(Node.body) - if TargetName in Gen._reg_values and Gen._reg_values[TargetName] is ElemVal: - del Gen._reg_values[TargetName] - if not Gen.builder.block.is_terminated: - Gen.builder.branch(StepBB) - Gen.builder.position_at_start(StepBB) - CurIdx2 = Gen._load(IdxVal, name="cur_idx2") - NextIdx = Gen.builder.add(CurIdx2, ir.Constant(ir.IntType(32), 1), name="next_idx") - Gen._store(NextIdx, IdxVal) - Gen.builder.branch(CondBB) - Gen.loop_break_targets.pop() - Gen.loop_continue_targets.pop() - if ElseBB: - Gen.builder.position_at_start(ElseBB) - self.HandleBodyLlvm(Node.orelse) - if not Gen.builder.block.is_terminated: - Gen.builder.branch(AfterBB) - Gen.builder.position_at_start(AfterBB) - - def _HandleForStrLlvm(self, Node, StrVal): - Gen = self.Trans.LlvmGen - if not isinstance(Node.target, ast.Name): - return - TargetName = Node.target.id - Gen._UnregisterTempPtr(StrVal) - PtrVal = Gen.builder.alloca(ir.IntType(8).as_pointer(), name=f"str_ptr_copy") - Gen.builder.store(StrVal, PtrVal) - CharType = ir.IntType(8) - if TargetName in Gen._reg_values: - del Gen._reg_values[TargetName] - LoopVar = Gen._allocaEntry(CharType, name=TargetName) - Gen.variables[TargetName] = LoopVar - Gen._store(ir.Constant(CharType, 0), LoopVar) - CondBB = Gen.func.append_basic_block(name="strfor.cond") - BodyBB = Gen.func.append_basic_block(name="strfor.body") - StepBB = Gen.func.append_basic_block(name="strfor.step") - ElseBB = Gen.func.append_basic_block(name="strfor.else") if Node.orelse else None - AfterBB = Gen.func.append_basic_block(name="strfor.end") - Gen.loop_break_targets.append(AfterBB) - Gen.loop_continue_targets.append(StepBB) - Gen.builder.branch(CondBB) - Gen.builder.position_at_start(CondBB) - CurrentPtr = Gen._load(PtrVal, name="current_ptr") - RawChar = Gen._load(CurrentPtr, name="raw_char") - NullCond = Gen.builder.icmp_signed('==', RawChar, ir.Constant(CharType, 0), name="is_null") - Gen.builder.cbranch(NullCond, ElseBB if ElseBB else AfterBB, BodyBB) - Gen.builder.position_at_start(BodyBB) - Gen._store(RawChar, LoopVar) - Gen._record_var_signedness(TargetName, 'char') - Gen._reg_values[TargetName] = RawChar - self.HandleBodyLlvm(Node.body) - if TargetName in Gen._reg_values and Gen._reg_values[TargetName] is RawChar: - del Gen._reg_values[TargetName] - if not Gen.builder.block.is_terminated: - Gen.builder.branch(StepBB) - Gen.builder.position_at_start(StepBB) - CurrentPtr2 = Gen._load(PtrVal, name="current_ptr2") - NextPtr = Gen.builder.gep(CurrentPtr2, [ir.Constant(ir.IntType(32), 1)], name="next_ptr") - Gen._store(NextPtr, PtrVal) - Gen.builder.branch(CondBB) - Gen.loop_break_targets.pop() - Gen.loop_continue_targets.pop() - if ElseBB: - Gen.builder.position_at_start(ElseBB) - self.HandleBodyLlvm(Node.orelse) - if not Gen.builder.block.is_terminated: - Gen.builder.branch(AfterBB) - Gen.builder.position_at_start(AfterBB) - - def _HandleForIterLlvm(self, Node, ClassName): - Gen = self.Trans.LlvmGen - if not isinstance(Node.target, ast.Name): - return - TargetName = Node.target.id - IterVal = self.HandleExprLlvm(Node.iter) - if not IterVal: - return - Gen._UnregisterTempPtr(IterVal) - if isinstance(IterVal.type, ir.PointerType) and isinstance(IterVal.type.pointee, ir.IntType) and IterVal.type.pointee.width == 8: - IterVal = Gen.builder.bitcast(IterVal, ir.PointerType(Gen.structs[ClassName]), name=f"cast_{ClassName}") - IterCall = Gen._get_function(f'{ClassName}.__iter__') - IterResult = Gen.builder.call(IterCall, [IterVal], name=f"call_{ClassName}.__iter__") - Gen._UnregisterTempPtr(IterResult) - if isinstance(IterResult.type, ir.PointerType) and isinstance(IterResult.type.pointee, ir.IntType) and IterResult.type.pointee.width == 8: - IterResult = Gen.builder.bitcast(IterResult, ir.PointerType(Gen.structs[ClassName]), name=f"cast_iter_{ClassName}") - NextCall = Gen._get_function(f'{ClassName}.__next__') - StopFlagPtr = Gen._allocaEntry(ir.IntType(1), name="stop_iter_flag") - Gen.builder.store(ir.Constant(ir.IntType(1), 0), StopFlagPtr) - NextReturnType = NextCall.function_type.return_type - if TargetName in Gen._reg_values: - del Gen._reg_values[TargetName] - LoopVar = Gen._allocaEntry(NextReturnType, name=TargetName) - Gen.variables[TargetName] = LoopVar - CondBB = Gen.func.append_basic_block(name="iter.cond") - BodyBB = Gen.func.append_basic_block(name="iter.body") - StepBB = Gen.func.append_basic_block(name="iter.step") - ElseBB = Gen.func.append_basic_block(name="iter.else") if Node.orelse else None - AfterBB = Gen.func.append_basic_block(name="iter.end") - Gen.loop_break_targets.append(AfterBB) - Gen.loop_continue_targets.append(StepBB) - Gen.builder.branch(CondBB) - Gen.builder.position_at_start(CondBB) - Gen.builder.store(ir.Constant(ir.IntType(1), 0), StopFlagPtr) - NextCallArgs = [IterResult, StopFlagPtr] - if NextCall and len(NextCall.function_type.args) > len(NextCallArgs): - last_param_type = NextCall.function_type.args[-1] - if (isinstance(last_param_type, ir.PointerType) - and isinstance(last_param_type.pointee, ir.PointerType) - and isinstance(last_param_type.pointee.pointee, ir.IntType) - and last_param_type.pointee.pointee.width == 8): - null_msg = Gen._allocaEntry(ir.PointerType(ir.IntType(8)), name="eh_msg_out_null") - NextCallArgs.append(null_msg) - NextVal = Gen.builder.call(NextCall, NextCallArgs, name=f"call_{ClassName}.__next__") - StopFlag = Gen.builder.load(StopFlagPtr, name="stop_flag") - Cond = Gen.builder.icmp_signed('==', StopFlag, ir.Constant(ir.IntType(1), 0), name="iter_cond") - Gen.builder.cbranch(Cond, BodyBB, ElseBB if ElseBB else AfterBB) - Gen.builder.position_at_start(BodyBB) - Gen._store(NextVal, LoopVar) - Gen._reg_values[TargetName] = NextVal - self.HandleBodyLlvm(Node.body) - if TargetName in Gen._reg_values and Gen._reg_values[TargetName] is NextVal: - del Gen._reg_values[TargetName] - if not Gen.builder.block.is_terminated: - Gen.builder.branch(StepBB) - Gen.builder.position_at_start(StepBB) - Gen.builder.branch(CondBB) - Gen.loop_break_targets.pop() - Gen.loop_continue_targets.pop() - if ElseBB: - Gen.builder.position_at_start(ElseBB) - self.HandleBodyLlvm(Node.orelse) - if not Gen.builder.block.is_terminated: - Gen.builder.branch(AfterBB) - Gen.builder.position_at_start(AfterBB) +from __future__ import annotations +from typing import TYPE_CHECKING +if TYPE_CHECKING: + from lib.core.translator import Translator +from lib.core.Handles.HandlesBase import BaseHandle +import ast +import llvmlite.ir as ir + + +class ForHandle(BaseHandle): + def _HandleForLlvm(self, Node: ast.For) -> None: + Gen: "Translator.LlvmGen" = self.Trans.LlvmGen + Gen._set_node_info(Node, "For") + # zip() 内置:for a, b in zip(iter1, iter2): + if (isinstance(Node.iter, ast.Call) + and isinstance(Node.iter.func, ast.Name) + and Node.iter.func.id == 'zip' + and isinstance(Node.target, ast.Tuple)): + self._HandleForZipLlvm(Node) + return + # enumerate() 内置:for idx, val in enumerate(iterable): + if (isinstance(Node.iter, ast.Call) + and isinstance(Node.iter.func, ast.Name) + and Node.iter.func.id == 'enumerate' + and isinstance(Node.target, ast.Tuple) + and Node.iter.args): + self._HandleForEnumerateLlvm(Node) + return + if not isinstance(Node.target, ast.Name): + return + TargetName: str = Node.target.id + StartVal: ir.Value | None = None + EndVal: ir.Value | None = None + StepVal: ir.Value | None = None + IsRange: bool = False + CondOp: str = '<' + if isinstance(Node.iter, ast.Call): + CallFunc: ast.expr = Node.iter.func + if isinstance(CallFunc, ast.Name) and CallFunc.id == 'range': + IsRange = True + RangeArgs: list[ast.expr] = Node.iter.args + RangeEndArg: ast.expr | None = RangeArgs[1] if len(RangeArgs) >= 2 else RangeArgs[0] if len(RangeArgs) >= 1 else None + OptimizedEnd: bool = False + if len(RangeArgs) >= 2 and isinstance(RangeEndArg, ast.BinOp): + if isinstance(RangeEndArg.op, ast.Add): + if (isinstance(RangeEndArg.right, ast.Constant) and RangeEndArg.right.value == 1): + EndVal = self.HandleExprLlvm(RangeEndArg.left) + CondOp = '<=' + OptimizedEnd = True + elif (isinstance(RangeEndArg.left, ast.Constant) and RangeEndArg.left.value == 1): + EndVal = self.HandleExprLlvm(RangeEndArg.right) + CondOp = '<=' + OptimizedEnd = True + elif isinstance(RangeEndArg.op, ast.Sub): + if isinstance(RangeEndArg.right, ast.Constant) and RangeEndArg.right.value == 1: + EndVal = self.HandleExprLlvm(RangeEndArg.left) + CondOp = '<' + OptimizedEnd = True + if not OptimizedEnd: + if len(RangeArgs) == 1: + EndVal = self.HandleExprLlvm(RangeArgs[0]) + else: + EndVal = self.HandleExprLlvm(RangeEndArg) + if len(RangeArgs) == 1: + StartVal = ir.Constant(ir.IntType(32), 0) + elif len(RangeArgs) >= 2: + StartVal = self.HandleExprLlvm(RangeArgs[0]) + if len(RangeArgs) >= 3: + StepVal = self.HandleExprLlvm(RangeArgs[2]) + # Check if step is a negative constant — need to flip condition + step_arg: ast.expr = RangeArgs[2] + if isinstance(step_arg, ast.UnaryOp) and isinstance(step_arg.op, ast.USub): + if isinstance(step_arg.operand, ast.Constant) and isinstance(step_arg.operand.value, (int, float)): + if step_arg.operand.value > 0: + CondOp = '>' + elif isinstance(step_arg, ast.Constant) and isinstance(step_arg.value, (int, float)): + if step_arg.value < 0: + CondOp = '>' + if not EndVal: + return + if not isinstance(EndVal.type, ir.IntType): + if isinstance(EndVal.type, ir.PointerType) and isinstance(EndVal.type.pointee, ir.IntType): + EndVal = Gen._load(EndVal, name="Load_end") + else: + EndVal = Gen.builder.ptrtoint(EndVal, ir.IntType(64), name="end") + if StartVal and not isinstance(StartVal.type, ir.IntType): + if isinstance(StartVal.type, ir.PointerType) and isinstance(StartVal.type.pointee, ir.IntType): + StartVal = Gen._load(StartVal, name="Load_start") + else: + StartVal = Gen.builder.ptrtoint(StartVal, ir.IntType(64), name="start") + else: + StartVal = ir.Constant(ir.IntType(64), 0) + if not StartVal: + StartVal = ir.Constant(EndVal.type, 0) + if StepVal is None: + StepVal = ir.Constant(EndVal.type, 1) + if not IsRange: + # 检测 c.Addr(x) 模式:按原始变量类型迭代(for i64 in i64* 语义) + if (isinstance(Node.iter, ast.Call) + and isinstance(Node.iter.func, ast.Attribute) + and isinstance(Node.iter.func.value, ast.Name) + and Node.iter.func.value.id == 'c' + and Node.iter.func.attr == 'Addr' + and Node.iter.args): + AddrArg: ast.expr = Node.iter.args[0] + if isinstance(AddrArg, ast.Name) and AddrArg.id in Gen.variables: + _var_ptr: ir.Value | None = Gen.variables[AddrArg.id] + if _var_ptr is not None and isinstance(_var_ptr.type, ir.PointerType): + _pointee: ir.Type = _var_ptr.type.pointee + # 标量整数变量 + if isinstance(_pointee, ir.IntType): + if _pointee.width == 8: + self._HandleForStrLlvm(Node, _var_ptr) + return + self._HandleForPtrLlvm(Node, _var_ptr, _pointee) + return + # 数组变量:取元素类型 + if isinstance(_pointee, ir.ArrayType) and isinstance(_pointee.element, ir.IntType): + _elem_type: ir.IntType = _pointee.element + if _elem_type.width == 8: + self._HandleForStrLlvm(Node, _var_ptr) + return + _typed_ptr: ir.Value = Gen.builder.bitcast(_var_ptr, ir.PointerType(_elem_type), name="addr_arr_elem_cast") + self._HandleForPtrLlvm(Node, _typed_ptr, _elem_type) + return + IterClassName: str | None = self.Trans.ExprHandler._get_var_class(Node.iter, Gen) + if not IterClassName and isinstance(Node.iter, ast.Call) and isinstance(Node.iter.func, ast.Name): + IterClassName = Node.iter.func.id + if IterClassName not in Gen.structs: + IterClassName = None + if IterClassName and Gen._has_function(f'{IterClassName}.__iter__') and Gen._has_function(f'{IterClassName}.__next__'): + self._HandleForIterLlvm(Node, IterClassName) + return + IterVal: ir.Value | None = self.HandleExprLlvm(Node.iter) + if not IterVal: + return + # 回退:通过 LLVM 类型查找结构体类名,检测 __iter__/__next__ + if not IterClassName and isinstance(IterVal.type, ir.PointerType): + _pointee: ir.Type = IterVal.type.pointee + if isinstance(_pointee, (ir.IdentifiedStructType, ir.LiteralStructType)): + _found: tuple[str, ir.Type] | None = Gen.find_struct_by_pointee(_pointee) + if _found: + _cn: str = _found[0] + if not (Gen._has_function(f'{_cn}.__iter__') and Gen._has_function(f'{_cn}.__next__')): + # temp stub 可能不包含泛型特化方法,尝试从 output stub 按需加载 + self.Trans.ImportHandler._TryLoadFuncDeclsFromOutputStub(_cn, Gen) + if Gen._has_function(f'{_cn}.__iter__') and Gen._has_function(f'{_cn}.__next__'): + Gen._UnregisterTempPtr(IterVal) + self._HandleForIterLlvm(Node, _cn) + return + if isinstance(IterVal.type, ir.PointerType) and isinstance(IterVal.type.pointee, ir.IntType) and IterVal.type.pointee.width == 8: + self._HandleForStrLlvm(Node, IterVal) + return + if isinstance(IterVal.type, ir.PointerType) and isinstance(IterVal.type.pointee, ir.ArrayType): + self._HandleForListLlvm(Node, IterVal) + return + StartVal = ir.Constant(ir.IntType(32), 0) + EndVal = IterVal + if not isinstance(EndVal.type, ir.IntType): + EndVal = Gen.builder.ptrtoint(EndVal, ir.IntType(64), name="end") + StartVal = ir.Constant(ir.IntType(64), 0) + StepVal = ir.Constant(EndVal.type, 1) + CondOp = '<' + if TargetName in Gen._reg_values: + del Gen._reg_values[TargetName] + LoopVar: ir.AllocaInstr + if TargetName in Gen.variables and Gen.variables[TargetName] is not None: + LoopVar = Gen.variables[TargetName] + if isinstance(LoopVar.type, ir.PointerType) and isinstance(LoopVar.type.pointee, ir.IntType) and LoopVar.type.pointee == EndVal.type and isinstance(EndVal.type, ir.IntType) and StartVal.type == LoopVar.type.pointee and EndVal.type == StartVal.type: + Gen._store(StartVal, LoopVar) + else: + NewVar: ir.AllocaInstr = Gen._allocaEntry(EndVal.type, name=TargetName) + if StartVal.type != EndVal.type: + if isinstance(EndVal.type, ir.IntType) and isinstance(StartVal.type, ir.IntType): + if StartVal.type.width < EndVal.type.width: + StartVal = Gen.builder.zext(StartVal, EndVal.type, name="zext_loop_start") + elif StartVal.type.width > EndVal.type.width: + StartVal = Gen.builder.trunc(StartVal, EndVal.type, name="trunc_loop_start") + Gen._store(StartVal, NewVar) + Gen.variables[TargetName] = NewVar + LoopVar = NewVar + else: + LoopVar = Gen._allocaEntry(EndVal.type, name=TargetName) + Gen.variables[TargetName] = LoopVar + Gen._store(StartVal, LoopVar) + if StepVal and isinstance(StepVal.type, ir.IntType) and isinstance(EndVal.type, ir.IntType): + if StepVal.type.width < EndVal.type.width: + StepVal = Gen.builder.zext(StepVal, EndVal.type, name="zext_loop_step") + elif StepVal.type.width > EndVal.type.width: + StepVal = Gen.builder.trunc(StepVal, EndVal.type, name="trunc_loop_step") + Gen._record_var_signedness(TargetName, 'int') + CondBB: ir.Block = Gen.func.append_basic_block(name="for.cond") + BodyBB: ir.Block = Gen.func.append_basic_block(name="for.body") + StepBB: ir.Block = Gen.func.append_basic_block(name="for.step") + ElseBB: ir.Block | None = Gen.func.append_basic_block(name="for.else") if Node.orelse else None + AfterBB: ir.Block = Gen.func.append_basic_block(name="for.end") + Gen.loop_break_targets.append(AfterBB) + Gen.loop_continue_targets.append(StepBB) + Gen.builder.branch(CondBB) + Gen.builder.position_at_start(CondBB) + LoopVal: ir.Value = Gen._load(LoopVar, name=TargetName) + is_unsigned: bool = Gen._is_var_unsigned(TargetName) + Cond: ir.Value + if is_unsigned: + Cond = Gen.builder.icmp_unsigned(CondOp, LoopVal, EndVal, name="forcond") + else: + Cond = Gen.builder.icmp_signed(CondOp, LoopVal, EndVal, name="forcond") + Gen.builder.cbranch(Cond, BodyBB, ElseBB if ElseBB else AfterBB) + Gen.builder.position_at_start(BodyBB) + CachedLoopVal: ir.Value = Gen._load(LoopVar, name=TargetName) + Gen._reg_values[TargetName] = CachedLoopVal + self.HandleBodyLlvm(Node.body) + StepLoopVal: ir.Value = CachedLoopVal + if TargetName in Gen._reg_values and Gen._reg_values[TargetName] is CachedLoopVal: + del Gen._reg_values[TargetName] + else: + StepLoopVal = Gen._load(LoopVar, name=TargetName) + if not Gen.builder.block.is_terminated: + Gen.builder.branch(StepBB) + Gen.builder.position_at_start(StepBB) + StepLoopVal2: ir.Value = Gen._load(LoopVar, name=TargetName) + NextVal: ir.Value = Gen.builder.add(StepLoopVal2, StepVal, name="next") + Gen._store(NextVal, LoopVar) + Gen.builder.branch(CondBB) + Gen.loop_break_targets.pop() + Gen.loop_continue_targets.pop() + if ElseBB: + Gen.builder.position_at_start(ElseBB) + self.HandleBodyLlvm(Node.orelse) + if not Gen.builder.block.is_terminated: + Gen.builder.branch(AfterBB) + Gen.builder.position_at_start(AfterBB) + + def _HandleGlobalLlvm(self, Node: ast.Global) -> None: + Gen: "Translator.LlvmGen" = self.Trans.LlvmGen + self._RegisterGlobalNames(Node.names, Gen, clear_reg_values=True) + + def _RegisterGlobalNames(self, names: list[str], Gen: "Translator.LlvmGen", clear_reg_values: bool = False) -> None: + for name in names: + Gen.global_vars.add(name) + if name in Gen.module.globals: + Gen.variables[name] = Gen.module.globals[name] + if clear_reg_values and name in Gen._reg_values: + del Gen._reg_values[name] + + def _HandleNonlocalLlvm(self, Node: ast.Nonlocal) -> None: + Gen: "Translator.LlvmGen" = self.Trans.LlvmGen + for name in Node.names: + if name in Gen._reg_values and name not in Gen.variables: + OldVal: ir.Value = Gen._reg_values[name] + var: ir.AllocaInstr = Gen._allocaEntry(OldVal.type, name=name) + Gen._store(OldVal, var) + Gen.variables[name] = var + del Gen._reg_values[name] + + def _collect_implicit_nonlocal(self, Node: ast.FunctionDef, Gen: "Translator.LlvmGen") -> list[str]: + param_names: set[str] = set() + for arg in Node.args.args: + param_names.add(arg.arg) + local_names: set[str] = set() + for child in ast.walk(Node): + if isinstance(child, ast.Assign): + for target in child.targets: + if isinstance(target, ast.Name): + local_names.add(target.id) + elif isinstance(target, ast.Tuple): + for elt in target.elts: + if isinstance(elt, ast.Name): + local_names.add(elt.id) + elif isinstance(child, ast.AugAssign): + if isinstance(child.target, ast.Name): + local_names.add(child.target.id) + elif isinstance(child, ast.AnnAssign): + if isinstance(child.target, ast.Name): + local_names.add(child.target.id) + elif isinstance(child, ast.For): + if isinstance(child.target, ast.Name): + local_names.add(child.target.id) + read_names: set[str] = set() + for child in ast.walk(Node): + if isinstance(child, ast.Name) and isinstance(child.ctx, ast.Load): + name: str = child.id + if name not in param_names and name not in local_names: + read_names.add(name) + implicit: list[str] = [] + for name in read_names: + if name in Gen.variables and Gen.variables[name] is not None: + implicit.append(name) + elif name in Gen._reg_values: + implicit.append(name) + for called_name in read_names: + if called_name in Gen.nonlocal_params: + for nv, _ in Gen.nonlocal_params[called_name]: + if nv not in param_names and nv not in local_names: + if nv not in read_names: + if nv in Gen.variables and Gen.variables[nv] is not None: + implicit.append(nv) + elif nv in Gen._reg_values: + implicit.append(nv) + return implicit + + def _collect_all_nonlocal_names(self, Node: ast.FunctionDef) -> set[str]: + """Recursively collect all nonlocal variable names from a function and its nested functions.""" + names: set[str] = set() + for stmt in Node.body: + if isinstance(stmt, ast.Nonlocal): + for name in stmt.names: + names.add(name) + elif isinstance(stmt, ast.FunctionDef): + # Recursively collect from nested functions + sub_names: set[str] = self._collect_all_nonlocal_names(stmt) + names.update(sub_names) + return names + + def _HandleNestedFunctionLlvm(self, Node: ast.FunctionDef) -> None: + Gen: "Translator.LlvmGen" = self.Trans.LlvmGen + nonlocal_var_names: list[str] = [] + for stmt in Node.body: + if isinstance(stmt, ast.Nonlocal): + for name in stmt.names: + nonlocal_var_names.append(name) + # Pre-scan ALL nested functions recursively for their nonlocal needs (passthrough) + for stmt in Node.body: + if isinstance(stmt, ast.FunctionDef): + sub_nonlocal_names: set[str] = self._collect_all_nonlocal_names(stmt) + for name in sub_nonlocal_names: + if name not in nonlocal_var_names: + nonlocal_var_names.append(name) + implicit_names: list[str] = self._collect_implicit_nonlocal(Node, Gen) + for name in implicit_names: + if name not in nonlocal_var_names: + nonlocal_var_names.append(name) + extra_params: list[tuple[str, ir.Type]] = [] + for var_name in nonlocal_var_names: + if var_name in Gen.variables and Gen.variables[var_name] is not None: + var: ir.Value = Gen.variables[var_name] + extra_params.append((var_name, var.type)) + elif var_name in Gen._reg_values: + OldVal: ir.Value = Gen._reg_values[var_name] + var: ir.AllocaInstr = Gen._allocaEntry(OldVal.type, name=var_name) + Gen._store(OldVal, var) + Gen.variables[var_name] = var + del Gen._reg_values[var_name] + extra_params.append((var_name, var.type)) + else: + # Search outer scope stack for the variable + found_var: ir.Value | None = None + for scope in reversed(Gen._variable_scope_stack): + if var_name in scope and scope[var_name] is not None: + found_var = scope[var_name] + break + if found_var is not None: + # Add to current scope so it can be passed to nested functions + Gen.variables[var_name] = found_var + extra_params.append((var_name, found_var.type)) + else: + var = Gen._allocaEntry(ir.IntType(32), name=var_name) + Gen.variables[var_name] = var + extra_params.append((var_name, var.type)) + if extra_params: + Gen.nonlocal_params[Node.name] = [(name, ptr_type) for name, ptr_type in extra_params] + # Push current variables to scope stack before compiling nested function + Gen._variable_scope_stack.append(Gen.variables.copy()) + saved_builder: ir.IRBuilder = Gen.builder + saved_func: ir.Function = Gen.func + saved_variables: dict[str, ir.Value] = Gen.variables.copy() + saved_reg_values: dict[str, ir.Value] = Gen._reg_values.copy() + saved_global_vars: set[str] = Gen.global_vars.copy() + saved_var_signedness: dict[str, str] = Gen.var_signedness.copy() + saved_var_type_info: dict[str, dict[str, str]] = Gen.var_type_info.copy() + saved_var_type_assignments: dict[str, list[dict[str, str]]] = Gen.var_type_assignments.copy() + saved_CurrentCReturnTypes: object | None = getattr(self.Trans, 'CurrentCReturnTypes', None) + saved_CurrentCpythonObjectClass: str | None = getattr(self.Trans, '_CurrentCpythonObjectClass', None) + saved_VarScopes: int = len(self.Trans.VarScopes) + self.Trans.FunctionHandler._EmitFunctionLlvm(Node, Gen, extra_params=extra_params if extra_params else None) + Gen.builder = saved_builder + Gen.func = saved_func + Gen.variables = saved_variables + Gen._reg_values = saved_reg_values + Gen.global_vars = saved_global_vars + Gen.var_signedness = saved_var_signedness + Gen.var_type_info = saved_var_type_info + Gen.var_type_assignments = saved_var_type_assignments + self.Trans.CurrentCReturnTypes = saved_CurrentCReturnTypes + self.Trans._CurrentCpythonObjectClass = saved_CurrentCpythonObjectClass + while len(self.Trans.VarScopes) > saved_VarScopes: + self.Trans.VarScopes.pop() + # Pop scope stack + if Gen._variable_scope_stack: + Gen._variable_scope_stack.pop() + + def _HandleForListLlvm(self, Node: ast.For, ArrPtr: ir.Value) -> None: + Gen: "Translator.LlvmGen" = self.Trans.LlvmGen + if not isinstance(Node.target, ast.Name): + return + TargetName: str = Node.target.id + ElemType: ir.Type = ArrPtr.type.pointee.element + ArrayCount: int = ArrPtr.type.pointee.count + IdxVal: ir.AllocaInstr = Gen._allocaEntry(ir.IntType(32), name=f"arr_idx") + Gen.builder.store(ir.Constant(ir.IntType(32), 0), IdxVal) + if TargetName in Gen._reg_values: + del Gen._reg_values[TargetName] + LoopVar: ir.AllocaInstr = Gen._allocaEntry(ElemType, name=TargetName) + Gen.variables[TargetName] = LoopVar + Gen._store(ir.Constant(ElemType, None), LoopVar) + CondBB: ir.Block = Gen.func.append_basic_block(name="arrfor.cond") + BodyBB: ir.Block = Gen.func.append_basic_block(name="arrfor.body") + StepBB: ir.Block = Gen.func.append_basic_block(name="arrfor.step") + ElseBB: ir.Block | None = Gen.func.append_basic_block(name="arrfor.else") if Node.orelse else None + AfterBB: ir.Block = Gen.func.append_basic_block(name="arrfor.end") + Gen.loop_break_targets.append(AfterBB) + Gen.loop_continue_targets.append(StepBB) + Gen.builder.branch(CondBB) + Gen.builder.position_at_start(CondBB) + CurIdx: ir.Value = Gen._load(IdxVal, name="cur_idx") + IsDone: ir.Value = Gen.builder.icmp_signed('<', CurIdx, ir.Constant(ir.IntType(32), ArrayCount), name="arr_in_bounds") + Gen.builder.cbranch(IsDone, BodyBB, ElseBB if ElseBB else AfterBB) + Gen.builder.position_at_start(BodyBB) + ElemPtr: ir.Value = Gen.builder.gep(ArrPtr, [ir.Constant(ir.IntType(32), 0), CurIdx], name="arr_elem_ptr") + ElemVal: ir.Value = Gen._load(ElemPtr, name="arr_elem_val") + Gen._store(ElemVal, LoopVar) + Gen._record_var_signedness(TargetName, 'ptr') + Gen._reg_values[TargetName] = ElemVal + self.HandleBodyLlvm(Node.body) + if TargetName in Gen._reg_values and Gen._reg_values[TargetName] is ElemVal: + del Gen._reg_values[TargetName] + if not Gen.builder.block.is_terminated: + Gen.builder.branch(StepBB) + Gen.builder.position_at_start(StepBB) + CurIdx2: ir.Value = Gen._load(IdxVal, name="cur_idx2") + NextIdx: ir.Value = Gen.builder.add(CurIdx2, ir.Constant(ir.IntType(32), 1), name="next_idx") + Gen._store(NextIdx, IdxVal) + Gen.builder.branch(CondBB) + Gen.loop_break_targets.pop() + Gen.loop_continue_targets.pop() + if ElseBB: + Gen.builder.position_at_start(ElseBB) + self.HandleBodyLlvm(Node.orelse) + if not Gen.builder.block.is_terminated: + Gen.builder.branch(AfterBB) + Gen.builder.position_at_start(AfterBB) + + def _HandleForStrLlvm(self, Node: ast.For, StrVal: ir.Value) -> None: + Gen: "Translator.LlvmGen" = self.Trans.LlvmGen + if not isinstance(Node.target, ast.Name): + return + TargetName: str = Node.target.id + Gen._UnregisterTempPtr(StrVal) + PtrVal: ir.AllocaInstr = Gen.builder.alloca(ir.IntType(8).as_pointer(), name=f"str_ptr_copy") + Gen.builder.store(StrVal, PtrVal) + CharType: ir.IntType = ir.IntType(8) + if TargetName in Gen._reg_values: + del Gen._reg_values[TargetName] + LoopVar: ir.AllocaInstr = Gen._allocaEntry(CharType, name=TargetName) + Gen.variables[TargetName] = LoopVar + Gen._store(ir.Constant(CharType, 0), LoopVar) + CondBB: ir.Block = Gen.func.append_basic_block(name="strfor.cond") + BodyBB: ir.Block = Gen.func.append_basic_block(name="strfor.body") + StepBB: ir.Block = Gen.func.append_basic_block(name="strfor.step") + ElseBB: ir.Block | None = Gen.func.append_basic_block(name="strfor.else") if Node.orelse else None + AfterBB: ir.Block = Gen.func.append_basic_block(name="strfor.end") + Gen.loop_break_targets.append(AfterBB) + Gen.loop_continue_targets.append(StepBB) + Gen.builder.branch(CondBB) + Gen.builder.position_at_start(CondBB) + CurrentPtr: ir.Value = Gen._load(PtrVal, name="current_ptr") + RawChar: ir.Value = Gen._load(CurrentPtr, name="raw_char") + NullCond: ir.Value = Gen.builder.icmp_signed('==', RawChar, ir.Constant(CharType, 0), name="is_null") + Gen.builder.cbranch(NullCond, ElseBB if ElseBB else AfterBB, BodyBB) + Gen.builder.position_at_start(BodyBB) + Gen._store(RawChar, LoopVar) + Gen._record_var_signedness(TargetName, 'char') + Gen._reg_values[TargetName] = RawChar + self.HandleBodyLlvm(Node.body) + if TargetName in Gen._reg_values and Gen._reg_values[TargetName] is RawChar: + del Gen._reg_values[TargetName] + if not Gen.builder.block.is_terminated: + Gen.builder.branch(StepBB) + Gen.builder.position_at_start(StepBB) + CurrentPtr2: ir.Value = Gen._load(PtrVal, name="current_ptr2") + NextPtr: ir.Value = Gen.builder.gep(CurrentPtr2, [ir.Constant(ir.IntType(32), 1)], name="next_ptr") + Gen._store(NextPtr, PtrVal) + Gen.builder.branch(CondBB) + Gen.loop_break_targets.pop() + Gen.loop_continue_targets.pop() + if ElseBB: + Gen.builder.position_at_start(ElseBB) + self.HandleBodyLlvm(Node.orelse) + if not Gen.builder.block.is_terminated: + Gen.builder.branch(AfterBB) + Gen.builder.position_at_start(AfterBB) + + def _HandleForPtrLlvm(self, Node: ast.For, PtrVal: ir.Value, ElemType: ir.IntType) -> None: + """通用指针迭代:按 ElemType 大小逐元素迭代,终止条件为元素值 == 0 + + 适用于 for i in c.Addr(u) where u: i32/i64 等非 i8 整数类型。 + """ + Gen: "Translator.LlvmGen" = self.Trans.LlvmGen + if not isinstance(Node.target, ast.Name): + return + TargetName: str = Node.target.id + # 确保 PtrVal 是 ElemType* + TypedPtr: ir.Value = PtrVal + if isinstance(PtrVal.type, ir.PointerType) and PtrVal.type.pointee is not ElemType: + TypedPtr = Gen.builder.bitcast(PtrVal, ir.PointerType(ElemType), name="ptr_elem_cast") + Gen._UnregisterTempPtr(TypedPtr) + # 分配指针副本 + PtrCopy: ir.AllocaInstr = Gen.builder.alloca(ir.PointerType(ElemType), name="ptr_copy") + Gen.builder.store(TypedPtr, PtrCopy) + if TargetName in Gen._reg_values: + del Gen._reg_values[TargetName] + LoopVar: ir.AllocaInstr = Gen._allocaEntry(ElemType, name=TargetName) + Gen.variables[TargetName] = LoopVar + Gen._store(ir.Constant(ElemType, 0), LoopVar) + CondBB: ir.Block = Gen.func.append_basic_block(name="ptrfor.cond") + BodyBB: ir.Block = Gen.func.append_basic_block(name="ptrfor.body") + StepBB: ir.Block = Gen.func.append_basic_block(name="ptrfor.step") + ElseBB: ir.Block | None = Gen.func.append_basic_block(name="ptrfor.else") if Node.orelse else None + AfterBB: ir.Block = Gen.func.append_basic_block(name="ptrfor.end") + Gen.loop_break_targets.append(AfterBB) + Gen.loop_continue_targets.append(StepBB) + Gen.builder.branch(CondBB) + Gen.builder.position_at_start(CondBB) + CurrentPtr: ir.Value = Gen._load(PtrCopy, name="current_ptr") + RawElem: ir.Value = Gen._load(CurrentPtr, name="raw_elem") + NullCond: ir.Value = Gen.builder.icmp_signed('==', RawElem, ir.Constant(ElemType, 0), name="is_null") + Gen.builder.cbranch(NullCond, ElseBB if ElseBB else AfterBB, BodyBB) + Gen.builder.position_at_start(BodyBB) + Gen._store(RawElem, LoopVar) + Gen._record_var_signedness(TargetName, 'int') + Gen._reg_values[TargetName] = RawElem + self.HandleBodyLlvm(Node.body) + if TargetName in Gen._reg_values and Gen._reg_values[TargetName] is RawElem: + del Gen._reg_values[TargetName] + if not Gen.builder.block.is_terminated: + Gen.builder.branch(StepBB) + Gen.builder.position_at_start(StepBB) + CurrentPtr2: ir.Value = Gen._load(PtrCopy, name="current_ptr2") + NextPtr: ir.Value = Gen.builder.gep(CurrentPtr2, [ir.Constant(ir.IntType(32), 1)], name="next_ptr") + Gen._store(NextPtr, PtrCopy) + Gen.builder.branch(CondBB) + Gen.loop_break_targets.pop() + Gen.loop_continue_targets.pop() + if ElseBB: + Gen.builder.position_at_start(ElseBB) + self.HandleBodyLlvm(Node.orelse) + if not Gen.builder.block.is_terminated: + Gen.builder.branch(AfterBB) + Gen.builder.position_at_start(AfterBB) + + def _HandleForIterLlvm(self, Node: ast.For, ClassName: str) -> None: + Gen: "Translator.LlvmGen" = self.Trans.LlvmGen + if not isinstance(Node.target, ast.Name): + return + TargetName: str = Node.target.id + IterVal: ir.Value | None = self.HandleExprLlvm(Node.iter) + if not IterVal: + return + Gen._UnregisterTempPtr(IterVal) + if isinstance(IterVal.type, ir.PointerType) and isinstance(IterVal.type.pointee, ir.IntType) and IterVal.type.pointee.width == 8: + IterVal = Gen.builder.bitcast(IterVal, ir.PointerType(Gen.structs[ClassName]), name=f"cast_{ClassName}") + IterCall: ir.Function = Gen._get_function(f'{ClassName}.__iter__') + IterResult: ir.Value = Gen.builder.call(IterCall, [IterVal], name=f"call_{ClassName}.__iter__") + Gen._UnregisterTempPtr(IterResult) + if isinstance(IterResult.type, ir.PointerType) and isinstance(IterResult.type.pointee, ir.IntType) and IterResult.type.pointee.width == 8: + IterResult = Gen.builder.bitcast(IterResult, ir.PointerType(Gen.structs[ClassName]), name=f"cast_iter_{ClassName}") + NextCall: ir.Function = Gen._get_function(f'{ClassName}.__next__') + StopFlagPtr: ir.AllocaInstr = Gen._allocaEntry(ir.IntType(1), name="stop_iter_flag") + Gen.builder.store(ir.Constant(ir.IntType(1), 0), StopFlagPtr) + NextReturnType: ir.Type = NextCall.function_type.return_type + if TargetName in Gen._reg_values: + del Gen._reg_values[TargetName] + LoopVar: ir.AllocaInstr = Gen._allocaEntry(NextReturnType, name=TargetName) + Gen.variables[TargetName] = LoopVar + CondBB: ir.Block = Gen.func.append_basic_block(name="iter.cond") + BodyBB: ir.Block = Gen.func.append_basic_block(name="iter.body") + StepBB: ir.Block = Gen.func.append_basic_block(name="iter.step") + ElseBB: ir.Block | None = Gen.func.append_basic_block(name="iter.else") if Node.orelse else None + AfterBB: ir.Block = Gen.func.append_basic_block(name="iter.end") + Gen.loop_break_targets.append(AfterBB) + Gen.loop_continue_targets.append(StepBB) + Gen.builder.branch(CondBB) + Gen.builder.position_at_start(CondBB) + Gen.builder.store(ir.Constant(ir.IntType(1), 0), StopFlagPtr) + NextCallArgs: list[ir.Value] = [IterResult, StopFlagPtr] + if NextCall and len(NextCall.function_type.args) > len(NextCallArgs): + last_param_type: ir.Type = NextCall.function_type.args[-1] + if (isinstance(last_param_type, ir.PointerType) + and isinstance(last_param_type.pointee, ir.PointerType) + and isinstance(last_param_type.pointee.pointee, ir.IntType) + and last_param_type.pointee.pointee.width == 8): + null_msg: ir.AllocaInstr = Gen._allocaEntry(ir.PointerType(ir.IntType(8)), name="eh_msg_out_null") + NextCallArgs.append(null_msg) + NextVal: ir.Value = Gen.builder.call(NextCall, NextCallArgs, name=f"call_{ClassName}.__next__") + StopFlag: ir.Value = Gen.builder.load(StopFlagPtr, name="stop_flag") + Cond: ir.Value = Gen.builder.icmp_signed('==', StopFlag, ir.Constant(ir.IntType(1), 0), name="iter_cond") + Gen.builder.cbranch(Cond, BodyBB, ElseBB if ElseBB else AfterBB) + Gen.builder.position_at_start(BodyBB) + Gen._store(NextVal, LoopVar) + Gen._reg_values[TargetName] = NextVal + self.HandleBodyLlvm(Node.body) + if TargetName in Gen._reg_values and Gen._reg_values[TargetName] is NextVal: + del Gen._reg_values[TargetName] + if not Gen.builder.block.is_terminated: + Gen.builder.branch(StepBB) + Gen.builder.position_at_start(StepBB) + Gen.builder.branch(CondBB) + Gen.loop_break_targets.pop() + Gen.loop_continue_targets.pop() + if ElseBB: + Gen.builder.position_at_start(ElseBB) + self.HandleBodyLlvm(Node.orelse) + if not Gen.builder.block.is_terminated: + Gen.builder.branch(AfterBB) + Gen.builder.position_at_start(AfterBB) + + # ===== zip() 内置支持 ===== + + def _HandleForZipLlvm(self, Node: ast.For) -> None: + """for a, b in zip(iter1, iter2): — 多迭代器并行迭代 + + 兼容 range、__iter__/__next__、字符串、数组、指针等所有迭代类型。 + 任一迭代器停止则退出循环。 + """ + Gen: "Translator.LlvmGen" = self.Trans.LlvmGen + if not isinstance(Node.target, ast.Tuple): + return + Targets: list[ast.Name] = [t for t in Node.target.elts if isinstance(t, ast.Name)] + ZipArgs: list[ast.expr] = Node.iter.args + if len(Targets) != len(ZipArgs) or len(Targets) < 2: + return + + # 为每个可迭代对象设置迭代状态 + IterInfos: list[dict] = [] + for i, arg in enumerate(ZipArgs): + target_name: str = Targets[i].id + info: dict | None = self._zip_setup_iter(arg, target_name, Gen) + if info is None: + return + IterInfos.append(info) + + CondBB: ir.Block = Gen.func.append_basic_block(name="zip.cond") + BodyBB: ir.Block = Gen.func.append_basic_block(name="zip.body") + StepBB: ir.Block = Gen.func.append_basic_block(name="zip.step") + ElseBB: ir.Block | None = Gen.func.append_basic_block(name="zip.else") if Node.orelse else None + AfterBB: ir.Block = Gen.func.append_basic_block(name="zip.end") + Gen.loop_break_targets.append(AfterBB) + Gen.loop_continue_targets.append(StepBB) + Gen.builder.branch(CondBB) + + # Cond 块:为每个迭代器获取下一个值和停止条件 + Gen.builder.position_at_start(CondBB) + AnyStopped: ir.Value | None = None + for info in IterInfos: + val: ir.Value + stopped: ir.Value + val, stopped = self._zip_get_next(info, Gen) + info['last_value'] = val + if AnyStopped is None: + AnyStopped = stopped + else: + AnyStopped = Gen.builder.or_(AnyStopped, stopped, name="zip_any_stop") + Gen.builder.cbranch(AnyStopped, ElseBB if ElseBB else AfterBB, BodyBB) + + # Body 块:赋值并执行循环体 + Gen.builder.position_at_start(BodyBB) + for info in IterInfos: + Gen._store(info['last_value'], info['loop_var']) + Gen._reg_values[info['target_name']] = info['last_value'] + self.HandleBodyLlvm(Node.body) + for info in IterInfos: + tn: str = info['target_name'] + if tn in Gen._reg_values and Gen._reg_values[tn] is info['last_value']: + del Gen._reg_values[tn] + if not Gen.builder.block.is_terminated: + Gen.builder.branch(StepBB) + + # Step 块:跳回 Cond(推进已在 Cond 中完成) + Gen.builder.position_at_start(StepBB) + Gen.builder.branch(CondBB) + Gen.loop_break_targets.pop() + Gen.loop_continue_targets.pop() + if ElseBB: + Gen.builder.position_at_start(ElseBB) + self.HandleBodyLlvm(Node.orelse) + if not Gen.builder.block.is_terminated: + Gen.builder.branch(AfterBB) + Gen.builder.position_at_start(AfterBB) + + def _zip_setup_iter(self, arg: ast.expr, target_name: str, Gen: "Translator.LlvmGen") -> dict | None: + """为 zip 参数设置迭代状态,返回包含迭代信息的 dict。""" + if target_name in Gen._reg_values: + del Gen._reg_values[target_name] + + # Case 1: range(n) / range(start, end) / range(start, end, step) + if isinstance(arg, ast.Call) and isinstance(arg.func, ast.Name) and arg.func.id == 'range': + return self._zip_setup_range(arg, target_name, Gen) + + # Case 2: c.Addr(x) — 指针/数组迭代 + if (isinstance(arg, ast.Call) + and isinstance(arg.func, ast.Attribute) + and isinstance(arg.func.value, ast.Name) + and arg.func.value.id == 'c' + and arg.func.attr == 'Addr' + and arg.args): + AddrArg: ast.expr = arg.args[0] + if isinstance(AddrArg, ast.Name) and AddrArg.id in Gen.variables: + _var_ptr: ir.Value | None = Gen.variables[AddrArg.id] + if _var_ptr is not None and isinstance(_var_ptr.type, ir.PointerType): + _pointee: ir.Type = _var_ptr.type.pointee + if isinstance(_pointee, ir.IntType): + if _pointee.width == 8: + return self._zip_setup_str(_var_ptr, target_name, Gen) + return self._zip_setup_ptr(_var_ptr, target_name, _pointee, Gen) + if isinstance(_pointee, ir.ArrayType) and isinstance(_pointee.element, ir.IntType): + _elem_type: ir.IntType = _pointee.element + if _elem_type.width == 8: + return self._zip_setup_str(_var_ptr, target_name, Gen) + _typed_ptr: ir.Value = Gen.builder.bitcast(_var_ptr, ir.PointerType(_elem_type), name="zip_addr_cast") + return self._zip_setup_ptr(_typed_ptr, target_name, _elem_type, Gen) + + # Case 3: __iter__/__next__ 类迭代 + IterClassName: str | None = self.Trans.ExprHandler._get_var_class(arg, Gen) + if not IterClassName and isinstance(arg, ast.Call) and isinstance(arg.func, ast.Name): + IterClassName = arg.func.id + if IterClassName not in Gen.structs: + IterClassName = None + if IterClassName and Gen._has_function(f'{IterClassName}.__iter__') and Gen._has_function(f'{IterClassName}.__next__'): + return self._zip_setup_iter_class(arg, target_name, IterClassName, Gen) + + # Case 4-6: 求值表达式后按类型分发 + IterVal: ir.Value | None = self.HandleExprLlvm(arg) + if not IterVal: + return None + # 回退:通过 LLVM 类型查找结构体类名,检测 __iter__/__next__ + if not IterClassName and isinstance(IterVal.type, ir.PointerType): + _pointee: ir.Type = IterVal.type.pointee + if isinstance(_pointee, (ir.IdentifiedStructType, ir.LiteralStructType)): + _found: tuple[str, ir.Type] | None = Gen.find_struct_by_pointee(_pointee) + if _found: + _cn: str = _found[0] + if not (Gen._has_function(f'{_cn}.__iter__') and Gen._has_function(f'{_cn}.__next__')): + self.Trans.ImportHandler._TryLoadFuncDeclsFromOutputStub(_cn, Gen) + if Gen._has_function(f'{_cn}.__iter__') and Gen._has_function(f'{_cn}.__next__'): + Gen._UnregisterTempPtr(IterVal) + return self._zip_setup_iter_class_from_val(IterVal, target_name, _cn, Gen) + if isinstance(IterVal.type, ir.PointerType) and isinstance(IterVal.type.pointee, ir.IntType) and IterVal.type.pointee.width == 8: + return self._zip_setup_str(IterVal, target_name, Gen) + if isinstance(IterVal.type, ir.PointerType) and isinstance(IterVal.type.pointee, ir.ArrayType): + return self._zip_setup_array(IterVal, target_name, Gen) + # Case 6: 整数计数器 + return self._zip_setup_int(IterVal, target_name, Gen) + + def _zip_setup_range(self, arg: ast.Call, target_name: str, Gen: "Translator.LlvmGen") -> dict | None: + RangeArgs: list[ast.expr] = arg.args + if len(RangeArgs) == 1: + StartVal: ir.Value = ir.Constant(ir.IntType(32), 0) + EndVal: ir.Value = self.HandleExprLlvm(RangeArgs[0]) + StepVal: ir.Value = ir.Constant(ir.IntType(32), 1) + elif len(RangeArgs) == 2: + StartVal = self.HandleExprLlvm(RangeArgs[0]) + EndVal = self.HandleExprLlvm(RangeArgs[1]) + StepVal = ir.Constant(ir.IntType(32), 1) + elif len(RangeArgs) >= 3: + StartVal = self.HandleExprLlvm(RangeArgs[0]) + EndVal = self.HandleExprLlvm(RangeArgs[1]) + StepVal = self.HandleExprLlvm(RangeArgs[2]) + else: + return None + if not EndVal: + return None + if not isinstance(EndVal.type, ir.IntType): + if isinstance(EndVal.type, ir.PointerType) and isinstance(EndVal.type.pointee, ir.IntType): + EndVal = Gen._load(EndVal, name="zip_end") + else: + EndVal = Gen.builder.ptrtoint(EndVal, ir.IntType(64), name="zip_end") + if not isinstance(StartVal.type, ir.IntType): + StartVal = ir.Constant(EndVal.type, 0) + if isinstance(StartVal.type, ir.IntType) and isinstance(EndVal.type, ir.IntType): + if StartVal.type.width < EndVal.type.width: + StartVal = Gen.builder.zext(StartVal, EndVal.type, name="zip_start_zext") + elif StartVal.type.width > EndVal.type.width: + EndVal = Gen.builder.zext(EndVal, StartVal.type, name="zip_end_zext") + if isinstance(StepVal.type, ir.IntType) and isinstance(EndVal.type, ir.IntType): + if StepVal.type.width < EndVal.type.width: + StepVal = Gen.builder.zext(StepVal, EndVal.type, name="zip_step_zext") + IdxVar: ir.AllocaInstr = Gen._allocaEntry(EndVal.type, name=f"zip_{target_name}_idx") + Gen._store(StartVal, IdxVar) + LoopVar: ir.AllocaInstr = Gen._allocaEntry(EndVal.type, name=target_name) + Gen.variables[target_name] = LoopVar + Gen._store(StartVal, LoopVar) + Gen._record_var_signedness(target_name, 'int') + return { + 'iter_type': 'range', + 'target_name': target_name, + 'value_type': EndVal.type, + 'idx_var': IdxVar, + 'end_val': EndVal, + 'step_val': StepVal, + 'loop_var': LoopVar, + } + + def _zip_setup_iter_class(self, arg: ast.expr, target_name: str, ClassName: str, Gen: "Translator.LlvmGen") -> dict | None: + IterVal: ir.Value | None = self.HandleExprLlvm(arg) + if not IterVal: + return None + return self._zip_setup_iter_class_from_val(IterVal, target_name, ClassName, Gen) + + def _zip_setup_iter_class_from_val(self, IterVal: ir.Value, target_name: str, ClassName: str, Gen: "Translator.LlvmGen") -> dict | None: + Gen._UnregisterTempPtr(IterVal) + if isinstance(IterVal.type, ir.PointerType) and isinstance(IterVal.type.pointee, ir.IntType) and IterVal.type.pointee.width == 8: + IterVal = Gen.builder.bitcast(IterVal, ir.PointerType(Gen.structs[ClassName]), name=f"zip_cast_{ClassName}") + IterCall: ir.Function = Gen._get_function(f'{ClassName}.__iter__') + IterResult: ir.Value = Gen.builder.call(IterCall, [IterVal], name=f"zip_call_{ClassName}.__iter__") + Gen._UnregisterTempPtr(IterResult) + if isinstance(IterResult.type, ir.PointerType) and isinstance(IterResult.type.pointee, ir.IntType) and IterResult.type.pointee.width == 8: + IterResult = Gen.builder.bitcast(IterResult, ir.PointerType(Gen.structs[ClassName]), name=f"zip_cast_iter_{ClassName}") + NextCall: ir.Function = Gen._get_function(f'{ClassName}.__next__') + StopFlagPtr: ir.AllocaInstr = Gen._allocaEntry(ir.IntType(1), name=f"zip_stop_{target_name}") + Gen.builder.store(ir.Constant(ir.IntType(1), 0), StopFlagPtr) + NextReturnType: ir.Type = NextCall.function_type.return_type + LoopVar: ir.AllocaInstr = Gen._allocaEntry(NextReturnType, name=target_name) + Gen.variables[target_name] = LoopVar + return { + 'iter_type': 'iter', + 'target_name': target_name, + 'value_type': NextReturnType, + 'iter_obj': IterResult, + 'next_call': NextCall, + 'stop_flag': StopFlagPtr, + 'loop_var': LoopVar, + } + + def _zip_setup_str(self, StrVal: ir.Value, target_name: str, Gen: "Translator.LlvmGen") -> dict: + Gen._UnregisterTempPtr(StrVal) + PtrVal: ir.AllocaInstr = Gen.builder.alloca(ir.IntType(8).as_pointer(), name=f"zip_{target_name}_ptr") + Gen.builder.store(StrVal, PtrVal) + CharType: ir.IntType = ir.IntType(8) + LoopVar: ir.AllocaInstr = Gen._allocaEntry(CharType, name=target_name) + Gen.variables[target_name] = LoopVar + Gen._store(ir.Constant(CharType, 0), LoopVar) + Gen._record_var_signedness(target_name, 'char') + return { + 'iter_type': 'str', + 'target_name': target_name, + 'value_type': CharType, + 'ptr_var': PtrVal, + 'loop_var': LoopVar, + } + + def _zip_setup_array(self, ArrPtr: ir.Value, target_name: str, Gen: "Translator.LlvmGen") -> dict: + ElemType: ir.Type = ArrPtr.type.pointee.element + ArrayCount: int = ArrPtr.type.pointee.count + IdxVar: ir.AllocaInstr = Gen._allocaEntry(ir.IntType(32), name=f"zip_{target_name}_idx") + Gen.builder.store(ir.Constant(ir.IntType(32), 0), IdxVar) + LoopVar: ir.AllocaInstr = Gen._allocaEntry(ElemType, name=target_name) + Gen.variables[target_name] = LoopVar + Gen._store(ir.Constant(ElemType, None), LoopVar) + Gen._record_var_signedness(target_name, 'ptr') + return { + 'iter_type': 'array', + 'target_name': target_name, + 'value_type': ElemType, + 'arr_ptr': ArrPtr, + 'idx_var': IdxVar, + 'count_val': ir.Constant(ir.IntType(32), ArrayCount), + 'loop_var': LoopVar, + } + + def _zip_setup_ptr(self, PtrVal: ir.Value, target_name: str, ElemType: ir.IntType, Gen: "Translator.LlvmGen") -> dict: + TypedPtr: ir.Value = PtrVal + if isinstance(PtrVal.type, ir.PointerType) and PtrVal.type.pointee is not ElemType: + TypedPtr = Gen.builder.bitcast(PtrVal, ir.PointerType(ElemType), name="zip_ptr_cast") + Gen._UnregisterTempPtr(TypedPtr) + PtrCopy: ir.AllocaInstr = Gen.builder.alloca(ir.PointerType(ElemType), name=f"zip_{target_name}_ptr") + Gen.builder.store(TypedPtr, PtrCopy) + LoopVar: ir.AllocaInstr = Gen._allocaEntry(ElemType, name=target_name) + Gen.variables[target_name] = LoopVar + Gen._store(ir.Constant(ElemType, 0), LoopVar) + Gen._record_var_signedness(target_name, 'int') + return { + 'iter_type': 'ptr', + 'target_name': target_name, + 'value_type': ElemType, + 'ptr_var': PtrCopy, + 'loop_var': LoopVar, + } + + def _zip_setup_int(self, IterVal: ir.Value, target_name: str, Gen: "Translator.LlvmGen") -> dict: + EndVal: ir.Value = IterVal + if not isinstance(EndVal.type, ir.IntType): + EndVal = Gen.builder.ptrtoint(EndVal, ir.IntType(64), name="zip_int_end") + StartVal: ir.Value = ir.Constant(EndVal.type, 0) + StepVal: ir.Value = ir.Constant(EndVal.type, 1) + IdxVar: ir.AllocaInstr = Gen._allocaEntry(EndVal.type, name=f"zip_{target_name}_idx") + Gen._store(StartVal, IdxVar) + LoopVar: ir.AllocaInstr = Gen._allocaEntry(EndVal.type, name=target_name) + Gen.variables[target_name] = LoopVar + Gen._store(StartVal, LoopVar) + Gen._record_var_signedness(target_name, 'int') + return { + 'iter_type': 'range', + 'target_name': target_name, + 'value_type': EndVal.type, + 'idx_var': IdxVar, + 'end_val': EndVal, + 'step_val': StepVal, + 'loop_var': LoopVar, + } + + def _zip_get_next(self, info: dict, Gen: "Translator.LlvmGen") -> tuple[ir.Value, ir.Value]: + """生成获取下一个值和停止条件的 IR。返回 (value, stopped_cond)。""" + iter_type: str = info['iter_type'] + + if iter_type == 'range': + idx: ir.Value = Gen._load(info['idx_var'], name="zip_range_idx") + stopped: ir.Value = Gen.builder.icmp_signed('>=', idx, info['end_val'], name="zip_range_stop") + next_idx: ir.Value = Gen.builder.add(idx, info['step_val'], name="zip_range_next") + Gen._store(next_idx, info['idx_var']) + return idx, stopped + + if iter_type == 'iter': + Gen.builder.store(ir.Constant(ir.IntType(1), 0), info['stop_flag']) + args: list[ir.Value] = [info['iter_obj'], info['stop_flag']] + NextCall: ir.Function = info['next_call'] + if NextCall and len(NextCall.function_type.args) > len(args): + last_param_type: ir.Type = NextCall.function_type.args[-1] + if (isinstance(last_param_type, ir.PointerType) + and isinstance(last_param_type.pointee, ir.PointerType) + and isinstance(last_param_type.pointee.pointee, ir.IntType) + and last_param_type.pointee.pointee.width == 8): + null_msg: ir.AllocaInstr = Gen._allocaEntry(ir.PointerType(ir.IntType(8)), name="zip_eh_msg") + args.append(null_msg) + val: ir.Value = Gen.builder.call(NextCall, args, name="zip_iter_next") + stopped = Gen.builder.load(info['stop_flag'], name="zip_iter_stop") + return val, stopped + + if iter_type == 'str': + ptr: ir.Value = Gen._load(info['ptr_var'], name="zip_str_ptr") + val = Gen._load(ptr, name="zip_str_val") + stopped = Gen.builder.icmp_signed('==', val, ir.Constant(ir.IntType(8), 0), name="zip_str_stop") + next_ptr: ir.Value = Gen.builder.gep(ptr, [ir.Constant(ir.IntType(32), 1)], name="zip_str_next") + Gen._store(next_ptr, info['ptr_var']) + return val, stopped + + if iter_type == 'ptr': + ptr = Gen._load(info['ptr_var'], name="zip_ptr_cur") + val = Gen._load(ptr, name="zip_ptr_val") + elem_type: ir.IntType = info['value_type'] + stopped = Gen.builder.icmp_signed('==', val, ir.Constant(elem_type, 0), name="zip_ptr_stop") + next_ptr = Gen.builder.gep(ptr, [ir.Constant(ir.IntType(32), 1)], name="zip_ptr_next") + Gen._store(next_ptr, info['ptr_var']) + return val, stopped + + if iter_type == 'array': + idx = Gen._load(info['idx_var'], name="zip_arr_idx") + stopped = Gen.builder.icmp_signed('>=', idx, info['count_val'], name="zip_arr_stop") + elem_ptr: ir.Value = Gen.builder.gep(info['arr_ptr'], [ir.Constant(ir.IntType(32), 0), idx], name="zip_arr_elem") + val = Gen._load(elem_ptr, name="zip_arr_val") + next_idx = Gen.builder.add(idx, ir.Constant(ir.IntType(32), 1), name="zip_arr_next") + Gen._store(next_idx, info['idx_var']) + return val, stopped + + # 回退:立即停止 + return ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(1), 1) + + # ===== enumerate() 内置支持 ===== + + def _HandleForEnumerateLlvm(self, Node: ast.For) -> None: + """for idx, val in enumerate(iterable): — 带索引迭代 + + 等价于 zip(range(0, ∞), iterable),但无需 len()。 + idx 从 0 开始,每次迭代 +1。 + """ + Gen: "Translator.LlvmGen" = self.Trans.LlvmGen + if not isinstance(Node.target, ast.Tuple): + return + Targets: list[ast.Name] = [t for t in Node.target.elts if isinstance(t, ast.Name)] + if len(Targets) != 2: + return + IdxTargetName: str = Targets[0].id + ValTargetName: str = Targets[1].id + IterArg: ast.expr = Node.iter.args[0] + + # 设置内部可迭代对象(复用 zip 基础设施) + if ValTargetName in Gen._reg_values: + del Gen._reg_values[ValTargetName] + if IdxTargetName in Gen._reg_values: + del Gen._reg_values[IdxTargetName] + IterInfo: dict | None = self._zip_setup_iter(IterArg, ValTargetName, Gen) + if IterInfo is None: + return + + # 索引计数器(i32,从 0 开始) + IdxType: ir.IntType = ir.IntType(32) + IdxVar: ir.AllocaInstr = Gen._allocaEntry(IdxType, name=f"enum_{IdxTargetName}") + Gen._store(ir.Constant(IdxType, 0), IdxVar) + IdxLoopVar: ir.AllocaInstr = Gen._allocaEntry(IdxType, name=IdxTargetName) + Gen.variables[IdxTargetName] = IdxLoopVar + Gen._store(ir.Constant(IdxType, 0), IdxLoopVar) + Gen._record_var_signedness(IdxTargetName, 'int') + + CondBB: ir.Block = Gen.func.append_basic_block(name="enum.cond") + BodyBB: ir.Block = Gen.func.append_basic_block(name="enum.body") + StepBB: ir.Block = Gen.func.append_basic_block(name="enum.step") + ElseBB: ir.Block | None = Gen.func.append_basic_block(name="enum.else") if Node.orelse else None + AfterBB: ir.Block = Gen.func.append_basic_block(name="enum.end") + Gen.loop_break_targets.append(AfterBB) + Gen.loop_continue_targets.append(StepBB) + Gen.builder.branch(CondBB) + + # Cond 块:获取下一个值和停止条件 + Gen.builder.position_at_start(CondBB) + CurIdx: ir.Value = Gen._load(IdxVar, name="enum_idx") + Val, Stopped = self._zip_get_next(IterInfo, Gen) + IterInfo['last_value'] = Val + Gen.builder.cbranch(Stopped, ElseBB if ElseBB else AfterBB, BodyBB) + + # Body 块:赋值并执行循环体 + Gen.builder.position_at_start(BodyBB) + Gen._store(CurIdx, IdxLoopVar) + Gen._store(Val, IterInfo['loop_var']) + Gen._reg_values[IdxTargetName] = CurIdx + Gen._reg_values[ValTargetName] = Val + self.HandleBodyLlvm(Node.body) + if IdxTargetName in Gen._reg_values and Gen._reg_values[IdxTargetName] is CurIdx: + del Gen._reg_values[IdxTargetName] + if ValTargetName in Gen._reg_values and Gen._reg_values[ValTargetName] is Val: + del Gen._reg_values[ValTargetName] + if not Gen.builder.block.is_terminated: + Gen.builder.branch(StepBB) + + # Step 块:索引 +1,跳回 Cond + Gen.builder.position_at_start(StepBB) + CurIdx2: ir.Value = Gen._load(IdxVar, name="enum_idx2") + NextIdx: ir.Value = Gen.builder.add(CurIdx2, ir.Constant(IdxType, 1), name="enum_next") + Gen._store(NextIdx, IdxVar) + Gen.builder.branch(CondBB) + Gen.loop_break_targets.pop() + Gen.loop_continue_targets.pop() + if ElseBB: + Gen.builder.position_at_start(ElseBB) + self.HandleBodyLlvm(Node.orelse) + if not Gen.builder.block.is_terminated: + Gen.builder.branch(AfterBB) + Gen.builder.position_at_start(AfterBB) \ No newline at end of file diff --git a/lib/core/Handles/HandlesFunctions.py b/lib/core/Handles/HandlesFunctions.py index 4c3df47..0eba41f 100644 --- a/lib/core/Handles/HandlesFunctions.py +++ b/lib/core/Handles/HandlesFunctions.py @@ -1,17 +1,28 @@ from __future__ import annotations -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Any if TYPE_CHECKING: from lib.core.translator import Translator -from lib.core.Handles.HandlesBase import BaseHandle, CTypeInfo, FuncMeta -from lib.includes import t + from lib.core.LlvmCodeGenerator import LlvmCodeGenerator import ast +import copy +import traceback import llvmlite.ir as ir +from lib.core.Handles.HandlesBase import BaseHandle, CTypeInfo, FuncMeta +from lib.core.SymbolUtils import IsTModule +from lib.core.VLogger import get_logger as _vlog +from lib.constants.config import mode as _config_mode +from lib.includes import t +from lib.includes.t import CTypeRegistry + + +# t 模块存储类标记装饰器名称集合 +_T_STORAGE_DECORATORS = frozenset({'CExport', 'CExtern', 'CStatic', 'State', 'CInline', 'TLS'}) class FunctionHandle(BaseHandle): @staticmethod - def _ExtractFuncMeta(decorator_list) -> FuncMeta: - meta = FuncMeta.NONE + def _ExtractFuncMeta(decorator_list: list[ast.AST]) -> FuncMeta: + meta: FuncMeta = FuncMeta.NONE if not decorator_list: return meta for d in decorator_list: @@ -35,7 +46,67 @@ class FunctionHandle(BaseHandle): meta |= FuncMeta.PROPERTY_DELETER return meta - def _body_contains_raise(self, body): + def _extract_decorator_storage_flags(self, Node: ast.FunctionDef) -> dict[str, bool]: + """从装饰器列表中提取 t 模块存储类标记 + + 支持 @t.CExport, @t.CExtern, @t.CStatic, @t.State, @t.CInline + 也支持 from t import CExport 等别名形式 + + Returns: + dict with keys: 'is_export', 'is_extern', 'is_static', 'is_state', 'is_inline' + """ + flags: dict[str, bool] = { + 'is_export': False, 'is_extern': False, + 'is_static': False, 'is_state': False, 'is_inline': False, + } + if not Node.decorator_list: + return flags + symtab: object = self.Trans.SymbolTable + for decorator in Node.decorator_list: + attr_name: str | None = None + # @t.CExport 形式 + if isinstance(decorator, ast.Attribute) and isinstance(decorator.value, ast.Name): + if IsTModule(decorator.value.id, symtab): + attr_name = decorator.attr + # @CExport 形式 (from t import CExport) + elif isinstance(decorator, ast.Name): + cls: type | None = getattr(t, decorator.id, None) + if cls is None and hasattr(symtab, '_t_type_symbols'): + cls = symtab._t_type_symbols.get(decorator.id) + if cls is not None and isinstance(cls, type) and issubclass(cls, t.CType): + attr_name = cls.__name__ + if attr_name and attr_name in _T_STORAGE_DECORATORS: + if attr_name == 'CExport': + flags['is_export'] = True + elif attr_name == 'CExtern': + flags['is_extern'] = True + elif attr_name == 'CStatic': + flags['is_static'] = True + elif attr_name == 'State': + flags['is_state'] = True + elif attr_name == 'CInline': + flags['is_inline'] = True + return flags + + @staticmethod + def _is_t_storage_decorator(decorator: ast.AST, symtab: object) -> bool: + """检查装饰器是否是 t 模块存储类标记(用于排除 behavior_decorators)""" + attr_name: str | None = None + if isinstance(decorator, ast.Attribute) and isinstance(decorator.value, ast.Name): + if IsTModule(decorator.value.id, symtab): + attr_name = decorator.attr + elif isinstance(decorator, ast.Name): + cls: type | None = getattr(t, decorator.id, None) + if cls is None and hasattr(symtab, '_t_type_symbols'): + cls = symtab._t_type_symbols.get(decorator.id) + if cls is not None and isinstance(cls, type) and issubclass(cls, t.CType): + attr_name = cls.__name__ + elif decorator.id in _T_STORAGE_DECORATORS and hasattr(t, decorator.id): + # TLS 是普通函数标记,不是 CType 子类 + attr_name = decorator.id + return attr_name in _T_STORAGE_DECORATORS if attr_name else False + + def _body_contains_raise(self, body: list[ast.AST]) -> bool: for node in ast.walk(ast.Module(body=body, type_ignores=[])): if isinstance(node, ast.Raise): if node.exc: @@ -45,18 +116,18 @@ class FunctionHandle(BaseHandle): continue return True if isinstance(node, ast.Call): - called_name = None + called_name: str | None = None if isinstance(node.func, ast.Name): called_name = node.func.id elif isinstance(node.func, ast.Attribute): called_name = node.func.attr if called_name: - Gen = self.Trans.LlvmGen + Gen: LlvmCodeGenerator = self.Trans.LlvmGen for prefix in ['', f'{called_name}.', f'__']: for suffix in ['', f'.{called_name}']: - fname = f'{prefix}{called_name}{suffix}' + fname: str = f'{prefix}{called_name}{suffix}' if fname in Gen.functions: - func = Gen.functions[fname] + func: Any = Gen.functions[fname] if len(func.args) > 0: for arg in func.args: if hasattr(arg, 'name') and arg.name in ('__eh_msg_out__', '__eh_code_out__'): @@ -70,48 +141,48 @@ class FunctionHandle(BaseHandle): 'writeonly', 'inaccessiblememonly', 'inaccessiblemem_or_argmemonly', }) - def _ExtractLLVMAttrs(self, node): - attrs = [] + def _ExtractLLVMAttrs(self, node: ast.AST) -> list[str]: + attrs: list[str] = [] if isinstance(node, ast.BinOp): attrs.extend(self._ExtractLLVMAttrs(node.left)) attrs.extend(self._ExtractLLVMAttrs(node.right)) elif isinstance(node, ast.Attribute): - attr_name = self._GetAttrLLVMName(node) + attr_name: str | None = self._GetAttrLLVMName(node) if attr_name: attrs.append(attr_name) return attrs - def _GetAttrLLVMName(self, node): + def _GetAttrLLVMName(self, node: ast.AST) -> str | None: if not isinstance(node, ast.Attribute): return None if node.attr not in self._LLVM_ATTR_NAMES: return None - value = node.value + value: ast.AST = node.value if not isinstance(value, ast.Attribute) or value.attr != 'llvm': return None - inner = value.value + inner: ast.AST = value.value if not isinstance(inner, ast.Attribute) or inner.attr != 'attr': return None if not isinstance(inner.value, ast.Name) or inner.value.id != 't': return None return node.attr - def _infer_return_type_from_body(self, Node, Gen=None, ClassName=None): - local_var_types = {} + def _infer_return_type_from_body(self, Node: ast.AST, Gen: LlvmCodeGenerator | None = None, ClassName: str | None = None) -> tuple[str, bool] | None: + local_var_types: dict[str, tuple[str, bool]] = {} for child in ast.walk(Node): if isinstance(child, ast.Assign) and len(child.targets) == 1: - target = child.targets[0] + target: ast.AST = child.targets[0] if isinstance(target, ast.Name) and isinstance(child.value, ast.Subscript): - sub = child.value + sub: ast.Subscript = child.value if (isinstance(sub.value, ast.Attribute) and isinstance(sub.value.value, ast.Name) and sub.value.value.id == 'self' and ClassName and ClassName in Gen.class_members): - member_name = sub.value.attr + member_name: str = sub.value.attr for m_name, m_type in Gen.class_members[ClassName]: if m_name == member_name: if isinstance(m_type, ir.ArrayType): - elem_type = m_type.element + elem_type: ir.Type = m_type.element if isinstance(elem_type, ir.FloatType): local_var_types[target.id] = ('float', False) elif isinstance(elem_type, ir.DoubleType): @@ -127,7 +198,7 @@ class FunctionHandle(BaseHandle): else: local_var_types[target.id] = ('void', True) elif isinstance(elem_type, ir.IdentifiedStructType): - struct_name = elem_type.name + struct_name: str = elem_type.name if struct_name: for sn, st in Gen.structs.items(): if st.name == struct_name or sn == struct_name: @@ -136,7 +207,7 @@ class FunctionHandle(BaseHandle): else: local_var_types[target.id] = (elem_type.name, False) elif isinstance(m_type, ir.PointerType): - pointee = m_type.pointee + pointee: ir.Type = m_type.pointee if isinstance(pointee, ir.FloatType): local_var_types[target.id] = ('float', False) elif isinstance(pointee, ir.DoubleType): @@ -156,20 +227,20 @@ class FunctionHandle(BaseHandle): break for child in ast.walk(Node): if isinstance(child, ast.Return) and child.value: - val = child.value + val: ast.AST = child.value if isinstance(val, ast.Name) and val.id == 'self' and ClassName: return (ClassName, True) if isinstance(val, ast.Call): if isinstance(val.func, ast.Name): - callee = val.func.id + callee: str = val.func.id if callee == 'malloc': return ('char', True) if callee == 'chr': return ('char', False) if Gen and callee in Gen.functions: - func = Gen.functions[callee] + func: Any = Gen.functions[callee] if hasattr(func, 'ftype'): - ret_type = func.ftype.return_type + ret_type: ir.Type = func.ftype.return_type if isinstance(ret_type, ir.PointerType): if isinstance(ret_type.pointee, ir.IntType) and ret_type.pointee.width == 8: return ('char', True) @@ -182,17 +253,17 @@ class FunctionHandle(BaseHandle): return ('void', False) elif isinstance(val.func, ast.Attribute): pass - callee_name = None + callee_name: str | None = None if isinstance(val.func, ast.Name): callee_name = val.func.id elif isinstance(val.func, ast.Attribute): callee_name = getattr(val.func, 'attr', None) if callee_name: - sym = self.Trans.SymbolTable.lookup(callee_name) + sym: Any = self.Trans.SymbolTable.lookup(callee_name) if sym and isinstance(sym, dict): - ret_type_str = sym.get('return_type', '') + ret_type_str: str = sym.get('return_type', '') if ret_type_str and ret_type_str != 'int': - IsPtr = sym.get('IsPtr', False) + IsPtr: bool = sym.get('IsPtr', False) return (ret_type_str, IsPtr) elif isinstance(val, ast.Constant): if val.value is None: @@ -200,26 +271,26 @@ class FunctionHandle(BaseHandle): elif isinstance(val.value, str) and len(val.value) <= 1: return ('char', True) elif isinstance(val, ast.Name): - var_name = val.id + var_name: str = val.id if var_name in local_var_types: return local_var_types[var_name] - var_info = self.Trans.SymbolTable.lookup(var_name) + var_info: Any = self.Trans.SymbolTable.lookup(var_name) if var_info and isinstance(var_info, dict): - var_type = var_info.get('type', '') + var_type: str = var_info.get('type', '') if var_type and var_type != 'int': - IsPtr = var_info.get('IsPtr', False) + IsPtr: bool = var_info.get('IsPtr', False) return (var_type, IsPtr) elif isinstance(val, ast.Subscript): if (isinstance(val.value, ast.Attribute) and isinstance(val.value.value, ast.Name) and val.value.value.id == 'self' and ClassName): - member_name = val.value.attr + member_name: str = val.value.attr if ClassName in Gen.class_members: for m_name, m_type in Gen.class_members[ClassName]: if m_name == member_name: if isinstance(m_type, ir.ArrayType): - elem_type = m_type.element + elem_type: ir.Type = m_type.element if isinstance(elem_type, ir.FloatType): return ('float', False) elif isinstance(elem_type, ir.DoubleType): @@ -233,14 +304,14 @@ class FunctionHandle(BaseHandle): return ('char', True) return ('void', True) elif isinstance(elem_type, ir.IdentifiedStructType): - struct_name = elem_type.name + struct_name: str = elem_type.name if struct_name: for sn, st in Gen.structs.items(): if st.name == struct_name or sn == struct_name: return (sn, False) return (elem_type.name, False) elif isinstance(m_type, ir.PointerType): - pointee = m_type.pointee + pointee: ir.Type = m_type.pointee if isinstance(pointee, ir.FloatType): return ('float', False) elif isinstance(pointee, ir.DoubleType): @@ -258,32 +329,32 @@ class FunctionHandle(BaseHandle): return (pointee.name, True) break if isinstance(val.value, ast.Name): - var_name = val.value.id - var_info = self.Trans.SymbolTable.lookup(var_name) + var_name: str = val.value.id + var_info: Any = self.Trans.SymbolTable.lookup(var_name) if var_info and isinstance(var_info, dict): - var_type = var_info.get('type', '') - if var_type.startswith('list[') or var_type.startswith('List['): - inner = var_type[var_type.index('[') + 1:var_type.rindex(']')] - parts = inner.split(',') - elem_type_str = parts[0].strip() + var_type: str = var_info.get('type', '') + if var_type.startswith('list[') or var_type.startswith('List[') or var_type.startswith('t.CArray['): + inner: str = var_type[var_type.index('[') + 1:var_type.rindex(']')] + parts: list[str] = inner.split(',') + elem_type_str: str = parts[0].strip() if elem_type_str and elem_type_str != 'int': - IsPtr = var_info.get('IsPtr', False) + IsPtr: bool = var_info.get('IsPtr', False) return (elem_type_str, IsPtr) return None - def _GetFunctionSignatureLlvm(self, Node, Gen, ClassName=None, extra_params=None): - RawFuncName = Node.name + def _GetFunctionSignatureLlvm(self, Node: ast.FunctionDef, Gen: LlvmCodeGenerator, ClassName: str | None = None, extra_params: list[tuple[str, Any]] | None = None) -> tuple[str, ir.FunctionType, Any, list[Any], list[ast.AST], bool, str | None, bool]: + RawFuncName: str = Node.name if ClassName: - FuncName = f"{ClassName}.{RawFuncName}" + FuncName: str = f"{ClassName}.{RawFuncName}" else: FuncName = RawFuncName # property setter/deleter 使用不同的函数名后缀,避免与 getter 冲突 - func_meta = self._ExtractFuncMeta(Node.decorator_list) + func_meta: FuncMeta = self._ExtractFuncMeta(Node.decorator_list) if FuncMeta.PROPERTY_SETTER in func_meta: FuncName = FuncName + '$set' elif FuncMeta.PROPERTY_DELETER in func_meta: FuncName = FuncName + '$del' - CReturnTypes = [] + CReturnTypes: list[ast.AST] = [] if Node.decorator_list: for decorator in Node.decorator_list: if isinstance(decorator, ast.Call) and isinstance(decorator.func, ast.Attribute): @@ -291,20 +362,20 @@ class FunctionHandle(BaseHandle): for arg in decorator.args: CReturnTypes.append(arg) if Node.returns: - llvm_attrs = self._ExtractLLVMAttrs(Node.returns) + llvm_attrs: list[str] = self._ExtractLLVMAttrs(Node.returns) if llvm_attrs: if not hasattr(self, '_pending_llvm_attrs'): self._pending_llvm_attrs = {} self._pending_llvm_attrs[FuncName] = llvm_attrs if isinstance(Node.returns, ast.Subscript) and isinstance(Node.returns.value, ast.Name) and Node.returns.value.id == 'tuple': - slice_node = Node.returns.slice + slice_node: ast.AST = Node.returns.slice if isinstance(slice_node, ast.Tuple): for elt in slice_node.elts: CReturnTypes.append(elt) else: CReturnTypes.append(slice_node) - IsPtr = False - ReturnTypeInfo = None + IsPtr: bool = False + ReturnTypeInfo: Any = None if Node.returns: if CReturnTypes: ReturnTypeInfo = CTypeInfo() @@ -317,11 +388,11 @@ class FunctionHandle(BaseHandle): ReturnTypeInfo = CTypeInfo() ReturnTypeInfo.BaseType = t.CVoid() if (ReturnTypeInfo.IsVoid and ReturnTypeInfo.PtrCount == 0 and not ReturnTypeInfo.IsState) or ReturnTypeInfo.PtrCount >= 2: - def _FindNonVoidCTypeInfo(node): + def _FindNonVoidCTypeInfo(node: ast.AST) -> Any: if isinstance(node, ast.BinOp) and isinstance(node.op, ast.BitOr): - results = [] + results: list[Any] = [] for child in [node.left, node.right]: - r = _FindNonVoidCTypeInfo(child) + r: Any = _FindNonVoidCTypeInfo(child) if r and not r.IsVoid: results.append(r) for r in results: @@ -329,26 +400,26 @@ class FunctionHandle(BaseHandle): return r return results[0] if results else None try: - SideInfo = CTypeInfo.FromNode(node, self.Trans.SymbolTable) + SideInfo: Any = CTypeInfo.FromNode(node, self.Trans.SymbolTable) if SideInfo: return SideInfo except Exception as _e: - if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": + if _config_mode == "strict": self.Trans.LogWarning(f"异常被忽略: {_e}") return None - found = _FindNonVoidCTypeInfo(Node.returns) + found: Any = _FindNonVoidCTypeInfo(Node.returns) if found and not found.IsVoid: ReturnTypeInfo = found if ReturnTypeInfo.IsVoid and ReturnTypeInfo.PtrCount == 0 and not ReturnTypeInfo.IsState: ReturnTypeInfo = CTypeInfo() ReturnTypeInfo.BaseType = t.CInt() else: - is_str_type = False + is_str_type: bool = False if isinstance(Node.returns, ast.Name) and Node.returns.id in ('str', 'bytes'): is_str_type = True ReturnTypeInfo = CTypeInfo.FromNode(Node.returns, self.Trans.SymbolTable) if ReturnTypeInfo and ReturnTypeInfo.IsDefine: - inferred = self._infer_return_type_from_body(Node, Gen, ClassName) + inferred: Any = self._infer_return_type_from_body(Node, Gen, ClassName) if inferred: ReturnTypeInfo = CTypeInfo.FromTypeName(inferred[0]) ReturnTypeInfo.PtrCount = 1 if inferred[1] else 0 @@ -371,7 +442,41 @@ class FunctionHandle(BaseHandle): ReturnTypeInfo = CTypeInfo() ReturnTypeInfo.BaseType = t.CChar() ReturnTypeInfo.PtrCount = 1 - if ReturnTypeInfo.IsVoid and ReturnTypeInfo.PtrCount == 0 and not ReturnTypeInfo.IsState: + # 检查泛型类返回类型 (如 list[str]) + # 注意:_from_node_subscript 对未识别的泛型下标(如 list[str])返回空 CTypeInfo(BaseType=None), + # 此时 IsVoid 为 False(因为 IsVoid 仅检查 t.CVoid 实例),需额外检测 BaseType is None + if (isinstance(Node.returns, ast.Subscript) + and isinstance(Node.returns.value, ast.Name) + and hasattr(self.Trans.ClassHandler, '_generic_class_templates') + and Node.returns.value.id in self.Trans.ClassHandler._generic_class_templates + and (ReturnTypeInfo.IsVoid or ReturnTypeInfo.BaseType is None) and ReturnTypeInfo.PtrCount == 0): + ret_class: str = Node.returns.value.id + ret_slice: ast.AST = Node.returns.slice + ret_type_args: list[str] = [] + ret_type_names: list[str] = [] + if isinstance(ret_slice, ast.Tuple): + for elt in ret_slice.elts: + if isinstance(elt, ast.Name): + tn2: str = elt.id + ts2: str = tn2 + if tn2 == 'int': + ts2, tn2 = 'int', 'CInt' + ret_type_args.append(ts2) + ret_type_names.append(tn2) + elif isinstance(ret_slice, ast.Name): + tn2: str = ret_slice.id + ts2: str = tn2 + if tn2 == 'int': + ts2, tn2 = 'int', 'CInt' + ret_type_args.append(ts2) + ret_type_names.append(tn2) + spec_name2: str | None = self.Trans.ClassHandler._specialize_generic_class( + ret_class, ret_type_args, Gen, type_names=ret_type_names) + if spec_name2 and spec_name2 in Gen.structs: + ReturnTypeInfo = CTypeInfo() + ReturnTypeInfo.BaseType = t.CStruct(name=spec_name2) + ReturnTypeInfo.PtrCount = 1 + if (ReturnTypeInfo.IsVoid or ReturnTypeInfo.BaseType is None) and ReturnTypeInfo.PtrCount == 0 and not ReturnTypeInfo.IsState: ReturnTypeInfo = CTypeInfo() ReturnTypeInfo.BaseType = t.CInt() except Exception: # 回退:设置默认返回类型为 CInt @@ -380,12 +485,12 @@ class FunctionHandle(BaseHandle): else: ReturnTypeInfo = CTypeInfo() ReturnTypeInfo.BaseType = t.CInt() - inferred = self._infer_return_type_from_body(Node, Gen, ClassName) + inferred: Any = self._infer_return_type_from_body(Node, Gen, ClassName) if inferred: ReturnTypeInfo = CTypeInfo.FromTypeName(inferred[0]) ReturnTypeInfo.PtrCount = 1 if inferred[1] else 0 IsPtr = ReturnTypeInfo.IsPtr if ReturnTypeInfo else False - ReturnType = Gen._ctype_to_llvm(ReturnTypeInfo) + ReturnType: ir.Type = Gen._ctype_to_llvm(ReturnTypeInfo) if isinstance(ReturnType, ir.PointerType) and isinstance(ReturnType.pointee, ir.PointerType): if isinstance(ReturnType.pointee.pointee, (ir.LiteralStructType, ir.IdentifiedStructType)): ReturnType = ir.PointerType(ReturnType.pointee.pointee) @@ -394,9 +499,9 @@ class FunctionHandle(BaseHandle): ReturnType = ir.PointerType(ir.IntType(8)) if isinstance(ReturnType, ir.VoidType) and FuncName == 'main': ReturnType = ir.IntType(32) - IsMethod = False - IsClassMethod = False - ResolvedClassName = ClassName + IsMethod: bool = False + IsClassMethod: bool = False + ResolvedClassName: str | None = ClassName func_meta = self._ExtractFuncMeta(Node.decorator_list) if not ResolvedClassName: for potential_class in Gen.class_methods: @@ -409,10 +514,11 @@ class FunctionHandle(BaseHandle): IsClassMethod = FuncMeta.CLASS_METHOD in func_meta if RawFuncName == '__init__': IsMethod = False - ParamTypes = [] - ParamNames = [] - ParamTypeStrs = [] - CReturnLlvmTypes = [] + ParamTypes: list[ir.Type] = [] + ParamNames: list[str] = [] + ParamTypeStrs: list[Any] = [] + auto_addr_modes: list[str | None] = [] + CReturnLlvmTypes: list[ir.Type] = [] if CReturnTypes: for i, ReturnTypeNode in enumerate(CReturnTypes): ReturnTypeInfo = CTypeInfo.FromNode(ReturnTypeNode, self.Trans.SymbolTable) @@ -423,18 +529,15 @@ class FunctionHandle(BaseHandle): if ReturnTypeInfo is None: ReturnTypeInfo = CTypeInfo() ReturnTypeInfo.BaseType = t.CInt() - RetType = Gen._ctype_to_llvm(ReturnTypeInfo) + RetType: ir.Type = Gen._ctype_to_llvm(ReturnTypeInfo) CReturnLlvmTypes.append(RetType) ReturnType = ir.LiteralStructType(CReturnLlvmTypes) for Arg in Node.args.args: + ParamIsUnsigned: bool = False if Arg.annotation: try: - if isinstance(Arg.annotation, ast.BinOp) and isinstance(Arg.annotation.op, ast.BitOr): - ParamTypeInfo = self.Trans.TypeMergeHandler.MergeTypes(Arg.annotation) - if ParamTypeInfo is None: - ParamTypeInfo = CTypeInfo.FromNode(Arg.annotation, self.Trans.SymbolTable) - else: - ParamTypeInfo = CTypeInfo.FromNode(Arg.annotation, self.Trans.SymbolTable) + ParamTypeInfo: Any + ParamTypeInfo = self.ResolveAnnotationType(Arg.annotation) if ParamTypeInfo is None: ParamTypeInfo = CTypeInfo() ParamTypeInfo.BaseType = t.CInt() @@ -447,15 +550,19 @@ class FunctionHandle(BaseHandle): ParamTypeInfo.BaseType = t.CChar() ParamTypeInfo.PtrCount = 1 IsPtr = True - ParamType = Gen._ctype_to_llvm(ParamTypeInfo) - ParamTypeStr = ParamTypeInfo + # C 语言中数组参数退化为指针:list[type, N] → type* + if ParamTypeInfo.ArrayDims: + ParamTypeInfo.ArrayDims = [] + ParamTypeInfo.PtrCount = max(ParamTypeInfo.PtrCount, 1) + ParamType: ir.Type = Gen._ctype_to_llvm(ParamTypeInfo) + ParamTypeStr: Any = ParamTypeInfo except Exception as e: ParamType = ir.IntType(32) ParamTypeStr = CTypeInfo() ParamTypeStr.BaseType = t.CInt() else: if ClassName and Arg.arg != 'self': - op_method_names = ['__add__', '__sub__', '__mul__', '__truediv__', '__floordiv__', '__mod__', '__pow__', + op_method_names: list[str] = ['__add__', '__sub__', '__mul__', '__truediv__', '__floordiv__', '__mod__', '__pow__', '__radd__', '__rsub__', '__rmul__', '__rtruediv__', '__rfloordiv__', '__rmod__', '__rpow__', '__iadd__', '__isub__', '__imul__', '__itruediv__', '__ifloordiv__', '__imod__', '__ipow__', '__eq__', '__ne__', '__lt__', '__le__', '__gt__', '__ge__', @@ -471,9 +578,17 @@ class FunctionHandle(BaseHandle): ParamTypes.append(ParamType) ParamNames.append(Arg.arg) ParamTypeStrs.append(ParamTypeStr) + # 检测 t.CNeedPtr / t.CAutoPtr 参数注解 + auto_mode: str | None = None + if ParamTypeStr is not None and hasattr(ParamTypeStr, 'BaseType') and ParamTypeStr.BaseType is not None: + if isinstance(ParamTypeStr.BaseType, t.CAutoPtr): + auto_mode = 'always' + elif isinstance(ParamTypeStr.BaseType, t.CNeedPtr): + auto_mode = 'need' + auto_addr_modes.append(auto_mode) if IsMethod and ResolvedClassName and ResolvedClassName in Gen.structs: - StructPtrType = ir.PointerType(Gen.structs[ResolvedClassName]) - SelfIdx = next((i for i, n in enumerate(ParamNames) if n == "self"), -1) + StructPtrType: ir.PointerType = ir.PointerType(Gen.structs[ResolvedClassName]) + SelfIdx: int = next((i for i, n in enumerate(ParamNames) if n == "self"), -1) if SelfIdx >= 0: ParamTypes[SelfIdx] = StructPtrType else: @@ -481,17 +596,17 @@ class FunctionHandle(BaseHandle): ParamNames.insert(0, "self") ParamTypeStrs.insert(0, f"struct {ResolvedClassName}") elif not IsMethod and ResolvedClassName and ResolvedClassName in Gen.structs: - SelfIdx = next((i for i, n in enumerate(ParamNames) if n == "self"), -1) + SelfIdx: int = next((i for i, n in enumerate(ParamNames) if n == "self"), -1) if SelfIdx >= 0: - StructPtrType = ir.PointerType(Gen.structs[ResolvedClassName]) + StructPtrType: ir.PointerType = ir.PointerType(Gen.structs[ResolvedClassName]) ParamTypes[SelfIdx] = StructPtrType # @classmethod: 将 cls 参数设为类指针类型 if IsClassMethod: - ClsIdx = next((i for i, n in enumerate(ParamNames) if n == "cls"), -1) + ClsIdx: int = next((i for i, n in enumerate(ParamNames) if n == "cls"), -1) if ClsIdx >= 0: - StructPtrType = ir.PointerType(Gen.structs[ResolvedClassName]) + StructPtrType: ir.PointerType = ir.PointerType(Gen.structs[ResolvedClassName]) ParamTypes[ClsIdx] = StructPtrType - IsVariadic = Node.args.vararg is not None + IsVariadic: bool = Node.args.vararg is not None if extra_params: for var_name, ptr_type in extra_params: ParamTypes.append(ptr_type) @@ -499,28 +614,32 @@ class FunctionHandle(BaseHandle): if IsMethod and RawFuncName == '__next__': ParamTypes.append(ir.PointerType(ir.IntType(1))) ParamNames.append('__stop_iter_flag__') - HasRaise = self._body_contains_raise(Node.body) + HasRaise: bool = self._body_contains_raise(Node.body) if HasRaise and RawFuncName != 'main': ParamTypes.append(ir.PointerType(ir.PointerType(ir.IntType(8)))) ParamNames.append('__eh_msg_out__') ParamTypes.append(ir.PointerType(ir.IntType(32))) ParamNames.append('__eh_code_out__') - FuncType = ir.FunctionType(ReturnType, ParamTypes, var_arg=IsVariadic) + FuncType: ir.FunctionType = ir.FunctionType(ReturnType, ParamTypes, var_arg=IsVariadic) + # 存储 auto_addr_modes(为额外参数补 None) + total_params: int = len(ParamTypes) + while len(auto_addr_modes) < total_params: + auto_addr_modes.append(None) + Gen._auto_addr_params[FuncName] = auto_addr_modes return FuncName, FuncType, ReturnTypeInfo, ParamTypeStrs, CReturnTypes, IsMethod, ResolvedClassName, IsVariadic - def _is_generic_function(self, Node): + def _is_generic_function(self, Node: ast.FunctionDef) -> bool: if hasattr(Node, 'type_params') and Node.type_params: return True return False - def _mangle_generic_name(self, func_name, type_args, has_cexport=False): - from lib.includes.t import CTypeRegistry - mangled_args = [] + def _mangle_generic_name(self, func_name: str, type_args: list[str], has_cexport: bool = False) -> str: + mangled_args: list[str] = [] for ta in type_args: - llvm_str = CTypeRegistry.NameToLLVM(ta) + llvm_str: str | None = CTypeRegistry.NameToLLVM(ta) if llvm_str: if llvm_str in ('float', 'double', 'half', 'fp128'): - mangled = 'f' + str(CTypeRegistry.GetClassByName(ta)().Size) + mangled: str = 'f' + str(CTypeRegistry.GetClassByName(ta)().Size) else: mangled = llvm_str else: @@ -530,7 +649,7 @@ class FunctionHandle(BaseHandle): return func_name + '_T_' + '_'.join(mangled_args) return func_name + '[' + ']['.join(mangled_args) + ']' - def _apply_type_map_to_node(self, Node, type_map): + def _apply_type_map_to_node(self, Node: ast.FunctionDef, type_map: dict[str, str]) -> None: for arg in Node.args.args: if arg.annotation: arg.annotation = self._replace_type_in_annotation(arg.annotation, type_map) @@ -538,25 +657,25 @@ class FunctionHandle(BaseHandle): Node.returns = self._replace_type_in_annotation(Node.returns, type_map) self._apply_type_map_to_body(Node.body, type_map) - def _replace_type_in_annotation(self, node, type_map): + def _replace_type_in_annotation(self, node: ast.AST, type_map: dict[str, str]) -> ast.AST: if isinstance(node, ast.Name): if node.id in type_map: - replacement = type_map[node.id] + replacement: str = type_map[node.id] return ast.Name(id=replacement, ctx=ast.Load()) elif isinstance(node, ast.BinOp) and isinstance(node.op, ast.BitOr): node.left = self._replace_type_in_annotation(node.left, type_map) node.right = self._replace_type_in_annotation(node.right, type_map) elif isinstance(node, ast.Attribute): if hasattr(node, 'attr') and node.attr in type_map: - replacement = type_map[node.attr] + replacement: str = type_map[node.attr] return ast.Name(id=replacement, ctx=ast.Load()) return node - def _apply_type_map_to_body(self, body, type_map): + def _apply_type_map_to_body(self, body: list[ast.AST], type_map: dict[str, str]) -> None: for stmt in body: self._apply_type_map_to_stmt(stmt, type_map) - def _apply_type_map_to_stmt(self, node, type_map): + def _apply_type_map_to_stmt(self, node: ast.AST, type_map: dict[str, str]) -> None: if isinstance(node, ast.Return) and node.value: self._apply_type_map_to_expr(node.value, type_map) elif isinstance(node, ast.Assign): @@ -588,22 +707,22 @@ class FunctionHandle(BaseHandle): for s in node.body: self._apply_type_map_to_stmt(s, type_map) - def _apply_type_map_to_expr(self, node, type_map): + def _apply_type_map_to_expr(self, node: ast.AST | None, type_map: dict[str, str]) -> None: if node is None: return if isinstance(node, ast.Call): if isinstance(node.func, ast.Name) and node.func.id in type_map: - replacement = type_map[node.func.id] + replacement: str = type_map[node.func.id] node.func = ast.Name(id=replacement, ctx=ast.Load()) elif isinstance(node.func, ast.Attribute): if isinstance(node.func.value, ast.Name) and node.func.value.id in type_map: - replacement = type_map[node.func.value.id] + replacement: str = type_map[node.func.value.id] node.func.value = ast.Name(id=replacement, ctx=ast.Load()) for arg in node.args: self._apply_type_map_to_expr(arg, type_map) elif isinstance(node, ast.Attribute): if isinstance(node.value, ast.Name) and node.value.id in type_map: - replacement = type_map[node.value.id] + replacement: str = type_map[node.value.id] node.value = ast.Name(id=replacement, ctx=ast.Load()) elif isinstance(node, ast.BinOp): self._apply_type_map_to_expr(node.left, type_map) @@ -621,8 +740,11 @@ class FunctionHandle(BaseHandle): self._apply_type_map_to_expr(node.test, type_map) self._apply_type_map_to_expr(node.body, type_map) self._apply_type_map_to_expr(node.orelse, type_map) + elif isinstance(node, ast.Name): + if node.id in type_map: + node.id = type_map[node.id] - def _infer_type_arg_from_value(self, val, Gen): + def _infer_type_arg_from_value(self, val: ir.Value, Gen: LlvmCodeGenerator) -> str: if val is None: return 'int' if isinstance(val.type, ir.IntType): @@ -641,23 +763,24 @@ class FunctionHandle(BaseHandle): return 'void*' return 'int' - def _specialize_generic_function(self, FuncName, type_args, Gen): + def _specialize_generic_function(self, FuncName: str, type_args: list[str], Gen: LlvmCodeGenerator) -> str | None: if not hasattr(self, '_generic_templates') or FuncName not in self._generic_templates: return None - template = self._generic_templates[FuncName] - Node = template['node'] - type_param_names = template['type_params'] - ClassName = template['class_name'] + template: dict[str, Any] = self._generic_templates[FuncName] + Node: ast.FunctionDef = template['node'] + type_param_names: list[str] = template['type_params'] + ClassName: str | None = template['class_name'] if len(type_args) != len(type_param_names): return None - spec_key = FuncName + '<' + ','.join(type_args) + '>' + spec_key: str = FuncName + '<' + ','.join(type_args) + '>' if not hasattr(self, '_generic_specializations'): self._generic_specializations = {} if spec_key in self._generic_specializations: return self._generic_specializations[spec_key] - has_cexport = False + has_cexport: bool = False if Node.returns: try: + RetTypeInfo: Any = None if isinstance(Node.returns, ast.BinOp) and isinstance(Node.returns.op, ast.BitOr): RetTypeInfo = self.Trans.TypeMergeHandler.MergeTypes(Node.returns) else: @@ -665,14 +788,13 @@ class FunctionHandle(BaseHandle): if isinstance(RetTypeInfo, CTypeInfo) and RetTypeInfo.Storage and isinstance(RetTypeInfo.Storage, t.CExport): has_cexport = True except Exception as _e: - if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": + if _config_mode == "strict": self.Trans.LogWarning(f"异常被忽略: {_e}") - spec_name = self._mangle_generic_name(FuncName, type_args, has_cexport) - type_map = {} + spec_name: str = self._mangle_generic_name(FuncName, type_args, has_cexport) + type_map: dict[str, str] = {} for i, tp_name in enumerate(type_param_names): type_map[tp_name] = type_args[i] - import copy - SpecNode = copy.deepcopy(Node) + SpecNode: ast.FunctionDef = copy.deepcopy(Node) SpecNode.type_params = [] SpecNode.name = spec_name self._apply_type_map_to_node(SpecNode, type_map) @@ -680,16 +802,16 @@ class FunctionHandle(BaseHandle): if not hasattr(Gen, '_export_funcs'): Gen._export_funcs = set() Gen._export_funcs.add(spec_name) - saved_builder = Gen.builder - saved_variables = dict(Gen.variables) if Gen.variables else {} - saved_direct_values = dict(Gen._direct_values) if Gen._direct_values else {} - saved_var_type_info = dict(Gen.var_type_info) if Gen.var_type_info else {} - saved_var_signedness = dict(Gen.var_signedness) if Gen.var_signedness else {} - saved_global_vars = set(Gen.global_vars) if Gen.global_vars else set() - saved_var_scopes = [dict(s) for s in self.Trans.VarScopes] if self.Trans.VarScopes else [] - saved_func = Gen.func - saved_current_func_name = getattr(Gen, '_current_func_name', None) - saved_block = None + saved_builder: Any = Gen.builder + saved_variables: dict[str, Any] = dict(Gen.variables) if Gen.variables else {} + saved_direct_values: dict[str, Any] = dict(Gen._direct_values) if Gen._direct_values else {} + saved_var_type_info: dict[str, Any] = dict(Gen.var_type_info) if Gen.var_type_info else {} + saved_var_signedness: dict[str, Any] = dict(Gen.var_signedness) if Gen.var_signedness else {} + saved_global_vars: set[str] = set(Gen.global_vars) if Gen.global_vars else set() + saved_var_scopes: list[dict[str, Any]] = [dict(s) for s in self.Trans.VarScopes] if self.Trans.VarScopes else [] + saved_func: Any = Gen.func + saved_current_func_name: str | None = getattr(Gen, '_current_func_name', None) + saved_block: Any = None if Gen.builder and Gen.builder.block and not Gen.builder.block.is_terminated: saved_block = Gen.builder.block self._EmitFunctionForwardDeclLlvm(SpecNode, Gen, ClassName=ClassName) @@ -712,33 +834,38 @@ class FunctionHandle(BaseHandle): self.Trans._generic_specializations[spec_key] = spec_name return spec_name - def _EmitFunctionForwardDeclLlvm(self, Node, Gen, ClassName=None): + def _EmitFunctionForwardDeclLlvm(self, Node: ast.FunctionDef, Gen: LlvmCodeGenerator, ClassName: str | None = None) -> None: if self._is_generic_function(Node): if not hasattr(self, '_generic_templates'): self._generic_templates = {} - RawFuncName = Node.name + RawFuncName: str = Node.name if ClassName: - FuncName = f"{ClassName}.{RawFuncName}" + FuncName: str = f"{ClassName}.{RawFuncName}" else: FuncName = RawFuncName - type_params = [tp.name for tp in Node.type_params] + type_params: list[str] = [tp.name for tp in Node.type_params] self._generic_templates[FuncName] = { 'node': Node, 'type_params': type_params, 'class_name': ClassName, } return - result = self._GetFunctionSignatureLlvm(Node, Gen, ClassName) + result: Any = self._GetFunctionSignatureLlvm(Node, Gen, ClassName) if result is None: return + FuncName: str + FuncType: ir.FunctionType + ReturnTypeInfo: Any + ParamTypeStrs: list[Any] + CReturnTypes: list[ast.AST] + IsMethod: bool + ResolvedClassName: str | None + IsVariadic: bool FuncName, FuncType, ReturnTypeInfo, ParamTypeStrs, CReturnTypes, IsMethod, ResolvedClassName, IsVariadic = result if Node.returns: try: - RetTypeInfo = None - if isinstance(Node.returns, ast.BinOp) and isinstance(Node.returns.op, ast.BitOr): - RetTypeInfo = getattr(self.Trans, 'TypeMergeHandler', None) and self.Trans.TypeMergeHandler.MergeTypes(Node.returns) - else: - RetTypeInfo = CTypeInfo.FromNode(Node.returns, self.Trans.SymbolTable) + RetTypeInfo: Any = None + RetTypeInfo = self.ResolveAnnotationType(Node.returns) if isinstance(RetTypeInfo, CTypeInfo) and RetTypeInfo.Storage and isinstance(RetTypeInfo.Storage, t.CExport) and not RetTypeInfo.IsState: Gen._export_funcs.add(FuncName) if isinstance(RetTypeInfo, CTypeInfo) and RetTypeInfo.Storage and isinstance(RetTypeInfo.Storage, t.CExtern): @@ -746,17 +873,21 @@ class FunctionHandle(BaseHandle): if isinstance(RetTypeInfo, CTypeInfo) and RetTypeInfo.IsState: Gen._export_funcs.add(FuncName) # t.State 标记的函数必须保持原始名称,以便链接器解析 except Exception as _e: - if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": + if _config_mode == "strict": self.Trans.LogWarning(f"异常被忽略: {_e}") - MangledName = Gen._mangle_func_name(FuncName) - need_new = MangledName not in Gen.functions + # 装饰器形式的存储类标记(@t.CExport / @t.CExtern / @t.State 等) + deco_flags: dict[str, bool] = self._extract_decorator_storage_flags(Node) + if deco_flags['is_export'] or deco_flags['is_extern'] or deco_flags['is_state']: + Gen._export_funcs.add(FuncName) + MangledName: str = Gen._mangle_func_name(FuncName) + need_new: bool = MangledName not in Gen.functions if not need_new: - existing = Gen.functions[MangledName] + existing: Any = Gen.functions[MangledName] if getattr(existing, 'name', MangledName) != MangledName: need_new = True if need_new: try: - func = ir.Function(Gen.module, FuncType, name=MangledName) + func: ir.Function = ir.Function(Gen.module, FuncType, name=MangledName) func.attributes.add('noredzone') if hasattr(self, '_cdefine_funcs') and FuncName in self._cdefine_funcs: func.linkage = 'linkonce_odr' @@ -766,19 +897,17 @@ class FunctionHandle(BaseHandle): try: func.attributes.add(attr_name) except Exception as _e: - from lib.core.VLogger import get_logger as _vlog - from lib.constants.config import mode as _config_mode if _config_mode == "strict": raise _vlog().warning(f"添加函数属性失败: {_e}", "Exception") Gen.functions[MangledName] = func Gen.functions[FuncName] = func except Exception as _e: - if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": + if _config_mode == "strict": self.Trans.LogWarning(f"异常被忽略: {_e}") else: existing = Gen.functions[MangledName] - existing_type = getattr(existing, 'ftype', None) + existing_type: ir.FunctionType | None = getattr(existing, 'ftype', None) if existing_type and existing_type != FuncType: Gen.functions[MangledName] = self._replace_function_decl(Gen, FuncName, FuncType) Gen.functions[FuncName] = Gen.functions[MangledName] @@ -787,39 +916,38 @@ class FunctionHandle(BaseHandle): Gen.functions[MangledName] = self._replace_function_decl(Gen, FuncName, FuncType) Gen.functions[FuncName] = Gen.functions[MangledName] except Exception as _e: - if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": + if _config_mode == "strict": self.Trans.LogWarning(f"异常被忽略: {_e}") self.Trans.FunctionDefCache[FuncName] = Node - def _replace_function_decl(self, Gen, FuncName, NewFuncType): - MangledName = Gen._mangle_func_name(FuncName) - old_func = Gen.functions.get(MangledName) + def _replace_function_decl(self, Gen: LlvmCodeGenerator, FuncName: str, NewFuncType: ir.FunctionType) -> ir.Function: + MangledName: str = Gen._mangle_func_name(FuncName) + old_func: Any = Gen.functions.get(MangledName) if old_func is None: try: return ir.Function(Gen.module, NewFuncType, name=MangledName) except Exception: # 回退:函数已存在时返回旧函数 return old_func try: - old_name = old_func.name + old_name: str = old_func.name if old_name in getattr(Gen.module, 'globals', {}): del Gen.module.globals[old_name] - module_scope = getattr(Gen.module, 'scope', None) + module_scope: Any = getattr(Gen.module, 'scope', None) if getattr(module_scope, '_useset', None): module_scope._useset.discard(old_name) if getattr(Gen.module, '_guessed_names', None): Gen.module._guessed_names.discard(FuncName) - new_func = ir.Function(Gen.module, NewFuncType, name=MangledName) + new_func: ir.Function = ir.Function(Gen.module, NewFuncType, name=MangledName) Gen.functions[MangledName] = new_func Gen.functions[FuncName] = new_func return new_func except Exception as ex: - import traceback traceback.print_exc() Gen.functions[MangledName] = old_func Gen.functions[FuncName] = old_func return old_func - def _EmitFunctionLlvm(self, Node, Gen, ClassName=None, extra_params=None): + def _EmitFunctionLlvm(self, Node: ast.FunctionDef, Gen: LlvmCodeGenerator, ClassName: str | None = None, extra_params: list[tuple[str, ir.Type]] | None = None) -> ir.Function | None: if self._is_generic_function(Node): return RawFuncName = Node.name @@ -841,8 +969,12 @@ class FunctionHandle(BaseHandle): behavior_decorators = [] # 内置装饰器名称,这些由编译器特殊处理,不作为行为装饰器 _BUILTIN_DECORATORS = {'staticmethod', 'property', 'classmethod'} + _symtab: object = self.Trans.SymbolTable if Node.decorator_list: for decorator in Node.decorator_list: + # 跳过 t 模块存储类标记装饰器(@t.CExport / @CExport 等) + if self._is_t_storage_decorator(decorator, _symtab): + continue # 识别自定义行为装饰器:@name(ast.Name 形式) if isinstance(decorator, ast.Name): if decorator.id not in _BUILTIN_DECORATORS: @@ -868,7 +1000,7 @@ class FunctionHandle(BaseHandle): elif decorator.func.attr == 'Attribute' and isinstance(decorator.func.value, ast.Name) and decorator.func.value.id == 'c': for arg in decorator.args: if isinstance(arg, ast.Call) and isinstance(arg.func, ast.Attribute): - if isinstance(arg.func.value, ast.Attribute) and isinstance(arg.func.value.value, ast.Name) and arg.func.value.value.id == 't' and arg.func.value.attr == 'attr': + if isinstance(arg.func.value, ast.Attribute) and isinstance(arg.func.value.value, ast.Name) and IsTModule(arg.func.value.value.id, self.Trans.SymbolTable) and arg.func.value.attr == 'attr': attr_name = arg.func.attr str_args = [a.value for a in arg.args if isinstance(a, ast.Constant) and isinstance(a.value, str)] int_args = [a.value for a in arg.args if isinstance(a, ast.Constant) and isinstance(a.value, int)] @@ -881,19 +1013,30 @@ class FunctionHandle(BaseHandle): elif attr_name in ('noreturn', 'always_inline', 'noinline', 'cold', 'hot', 'constructor', 'destructor', 'pure', 'const', 'malloc', 'returns_nonnull', 'used', 'naked', 'no_instrument_function', 'warn_unused_result', 'weak', 'fallthrough'): if not arg.args: fn_attrs[attr_name] = True - elif isinstance(arg.func.value, ast.Attribute) and arg.func.value.attr == 'llvm' and isinstance(arg.func.value.value, ast.Attribute) and arg.func.value.value.attr == 'attr' and isinstance(arg.func.value.value.value, ast.Name) and arg.func.value.value.value.id == 't': + elif isinstance(arg.func.value, ast.Attribute) and arg.func.value.attr == 'llvm' and isinstance(arg.func.value.value, ast.Attribute) and arg.func.value.value.attr == 'attr' and isinstance(arg.func.value.value.value, ast.Name) and IsTModule(arg.func.value.value.value.id, self.Trans.SymbolTable): llvm_attr_name = arg.func.attr if llvm_attr_name in self._LLVM_ATTR_NAMES: fn_attrs[f'llvm.{llvm_attr_name}'] = True elif isinstance(arg, ast.Attribute): - if isinstance(arg.value, ast.Attribute) and isinstance(arg.value.value, ast.Name) and arg.value.value.id == 't' and arg.value.attr == 'attr': + if isinstance(arg.value, ast.Attribute) and isinstance(arg.value.value, ast.Name) and IsTModule(arg.value.value.id, self.Trans.SymbolTable) and arg.value.attr == 'attr': attr_name = arg.attr if attr_name in ('noreturn', 'always_inline', 'noinline', 'cold', 'hot', 'constructor', 'destructor', 'pure', 'const', 'malloc', 'returns_nonnull', 'used', 'naked', 'no_instrument_function', 'warn_unused_result', 'weak', 'fallthrough', 'packed'): fn_attrs[attr_name] = True - elif isinstance(arg.value, ast.Attribute) and arg.value.attr == 'llvm' and isinstance(arg.value.value, ast.Attribute) and arg.value.value.attr == 'attr' and isinstance(arg.value.value.value, ast.Name) and arg.value.value.value.id == 't': + elif isinstance(arg.value, ast.Attribute) and arg.value.attr == 'llvm' and isinstance(arg.value.value, ast.Attribute) and arg.value.value.attr == 'attr' and isinstance(arg.value.value.value, ast.Name) and IsTModule(arg.value.value.value.id, self.Trans.SymbolTable): llvm_attr_name = arg.attr if llvm_attr_name in self._LLVM_ATTR_NAMES: fn_attrs[f'llvm.{llvm_attr_name}'] = True + # 检查 @t.TLS 装饰器(一次性初始化标记) + is_tls_func: bool = False + if Node.decorator_list: + for decorator in Node.decorator_list: + if isinstance(decorator, ast.Attribute) and isinstance(decorator.value, ast.Name): + if IsTModule(decorator.value.id, _symtab) and decorator.attr == 'TLS': + is_tls_func = True + break + elif isinstance(decorator, ast.Name) and decorator.id == 'TLS' and hasattr(t, 'TLS'): + is_tls_func = True + break if Node.returns: if isinstance(Node.returns, ast.Subscript) and isinstance(Node.returns.value, ast.Name) and Node.returns.value.id == 'tuple': slice_node = Node.returns.slice @@ -915,7 +1058,7 @@ class FunctionHandle(BaseHandle): if rt_info and rt_info.IsStr: is_str_return = True except Exception as _e: - if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": + if _config_mode == "strict": self.Trans.LogWarning(f"异常被忽略: {_e}") if is_str_return: @@ -950,7 +1093,7 @@ class FunctionHandle(BaseHandle): if SideInfo: return SideInfo except Exception as _e: - if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": + if _config_mode == "strict": self.Trans.LogWarning(f"异常被忽略: {_e}") return None found = _FindNonVoidCTypeInfo(Node.returns) @@ -984,7 +1127,41 @@ class FunctionHandle(BaseHandle): ReturnTypeInfo = CTypeInfo() ReturnTypeInfo.BaseType = t.CChar() ReturnTypeInfo.PtrCount = 1 - if ReturnTypeInfo.IsVoid and ReturnTypeInfo.PtrCount == 0 and not ReturnTypeInfo.IsState: + # 检查泛型类返回类型 (如 list[str]) + # 注意:_from_node_subscript 对未识别的泛型下标(如 list[str])返回空 CTypeInfo(BaseType=None), + # 此时 IsVoid 为 False(因为 IsVoid 仅检查 t.CVoid 实例),需额外检测 BaseType is None + if (isinstance(Node.returns, ast.Subscript) + and isinstance(Node.returns.value, ast.Name) + and hasattr(self.Trans.ClassHandler, '_generic_class_templates') + and Node.returns.value.id in self.Trans.ClassHandler._generic_class_templates + and (ReturnTypeInfo.IsVoid or ReturnTypeInfo.BaseType is None) and ReturnTypeInfo.PtrCount == 0): + ret_class: str = Node.returns.value.id + ret_slice: ast.AST = Node.returns.slice + ret_type_args: list[str] = [] + ret_type_names: list[str] = [] + if isinstance(ret_slice, ast.Tuple): + for elt in ret_slice.elts: + if isinstance(elt, ast.Name): + tn2: str = elt.id + ts2: str = tn2 + if tn2 == 'int': + ts2, tn2 = 'int', 'CInt' + ret_type_args.append(ts2) + ret_type_names.append(tn2) + elif isinstance(ret_slice, ast.Name): + tn2: str = ret_slice.id + ts2: str = tn2 + if tn2 == 'int': + ts2, tn2 = 'int', 'CInt' + ret_type_args.append(ts2) + ret_type_names.append(tn2) + spec_name2: str | None = self.Trans.ClassHandler._specialize_generic_class( + ret_class, ret_type_args, Gen, type_names=ret_type_names) + if spec_name2 and spec_name2 in Gen.structs: + ReturnTypeInfo = CTypeInfo() + ReturnTypeInfo.BaseType = t.CStruct(name=spec_name2) + ReturnTypeInfo.PtrCount = 1 + if (ReturnTypeInfo.IsVoid or ReturnTypeInfo.BaseType is None) and ReturnTypeInfo.PtrCount == 0 and not ReturnTypeInfo.IsState: ReturnTypeInfo = CTypeInfo() ReturnTypeInfo.BaseType = t.CInt() except Exception: # 回退:设置默认返回类型为 CInt @@ -1028,17 +1205,13 @@ class FunctionHandle(BaseHandle): ParamTypes = [] ParamNames = [] ParamTypeStrs = [] + auto_addr_modes_emit: list[str | None] = [] self.Trans.VarScopes.append({}) for Arg in Node.args.args: ParamIsUnsigned = False if Arg.annotation: try: - if isinstance(Arg.annotation, ast.BinOp) and isinstance(Arg.annotation.op, ast.BitOr): - ParamTypeInfo = self.Trans.TypeMergeHandler.MergeTypes(Arg.annotation) - if ParamTypeInfo is None: - ParamTypeInfo = CTypeInfo.FromNode(Arg.annotation, self.Trans.SymbolTable) - else: - ParamTypeInfo = CTypeInfo.FromNode(Arg.annotation, self.Trans.SymbolTable) + ParamTypeInfo = self.ResolveAnnotationType(Arg.annotation) if ParamTypeInfo is None: ParamTypeInfo = CTypeInfo() ParamTypeInfo.BaseType = t.CInt() @@ -1051,6 +1224,10 @@ class FunctionHandle(BaseHandle): ParamTypeInfo.BaseType = t.CChar() ParamTypeInfo.PtrCount = 1 IsPtr = True + # C 语言中数组参数退化为指针:list[type, N] → type* + if ParamTypeInfo.ArrayDims: + ParamTypeInfo.ArrayDims = [] + ParamTypeInfo.PtrCount = max(ParamTypeInfo.PtrCount, 1) ParamType = Gen._ctype_to_llvm(ParamTypeInfo) if ParamTypeInfo and ParamTypeInfo.IsFuncPtr: ParamType = ir.IntType(8).as_pointer() @@ -1066,20 +1243,23 @@ class FunctionHandle(BaseHandle): ParamTypes.append(ParamType) ParamNames.append(Arg.arg) ParamTypeStrs.append(ParamTypeInfo) + # 检测 t.CNeedPtr / t.CAutoPtr 参数注解 + auto_mode_emit: str | None = None + if ParamTypeInfo is not None and hasattr(ParamTypeInfo, 'BaseType') and ParamTypeInfo.BaseType is not None: + if isinstance(ParamTypeInfo.BaseType, t.CAutoPtr): + auto_mode_emit = 'always' + elif isinstance(ParamTypeInfo.BaseType, t.CNeedPtr): + auto_mode_emit = 'need' + auto_addr_modes_emit.append(auto_mode_emit) Gen._record_var_signedness(Arg.arg, ParamIsUnsigned) self.Trans.VarScopes[-1][Arg.arg] = ParamTypeInfo if Arg.annotation: try: - if isinstance(Arg.annotation, ast.BinOp) and isinstance(Arg.annotation.op, ast.BitOr): - PInfo = self.Trans.TypeMergeHandler.MergeTypes(Arg.annotation) - if PInfo is None: - PInfo = CTypeInfo.FromNode(Arg.annotation, self.Trans.SymbolTable) - else: - PInfo = CTypeInfo.FromNode(Arg.annotation, self.Trans.SymbolTable) + PInfo = self.ResolveAnnotationType(Arg.annotation) if PInfo and (PInfo.DataConst or PInfo.VarConst): Gen.var_const_flags[Arg.arg] = True except Exception as _e: - if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": + if _config_mode == "strict": self.Trans.LogWarning(f"异常被忽略: {_e}") if CReturnTypes: CReturnLlvmTypes = [] @@ -1134,6 +1314,11 @@ class FunctionHandle(BaseHandle): ParamTypes.append(ir.PointerType(ir.IntType(32))) ParamNames.append('__eh_code_out__') FuncType = ir.FunctionType(ReturnType, ParamTypes, var_arg=IsVariadic) + # 存储 auto_addr_modes(为额外参数补 None) + total_params_emit: int = len(ParamTypes) + while len(auto_addr_modes_emit) < total_params_emit: + auto_addr_modes_emit.append(None) + Gen._auto_addr_params[FuncName] = auto_addr_modes_emit self.Trans.FunctionDefCache[FuncName] = Node IsInlineFunc = False IsExternFunc = False @@ -1141,10 +1326,7 @@ class FunctionHandle(BaseHandle): if Node.returns: try: RetTypeInfo = None - if isinstance(Node.returns, ast.BinOp) and isinstance(Node.returns.op, ast.BitOr): - RetTypeInfo = getattr(self.Trans, 'TypeMergeHandler', None) and self.Trans.TypeMergeHandler.MergeTypes(Node.returns) - else: - RetTypeInfo = CTypeInfo.FromNode(Node.returns, self.Trans.SymbolTable) + RetTypeInfo = self.ResolveAnnotationType(Node.returns) if isinstance(RetTypeInfo, CTypeInfo) and RetTypeInfo.Storage and isinstance(RetTypeInfo.Storage, t.CInline): IsInlineFunc = True if isinstance(RetTypeInfo, CTypeInfo) and RetTypeInfo.Storage and isinstance(RetTypeInfo.Storage, t.CExport) and not RetTypeInfo.IsState: @@ -1156,8 +1338,18 @@ class FunctionHandle(BaseHandle): IsStateFunc = True Gen._export_funcs.add(FuncName) # 外部 C 函数声明必须保持原始名称 except Exception as _e: - if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": + if _config_mode == "strict": self.Trans.LogWarning(f"异常被忽略: {_e}") + # 装饰器形式的存储类标记(@t.CExport / @t.CExtern / @t.CStatic / @t.State / @t.CInline) + deco_flags: dict[str, bool] = self._extract_decorator_storage_flags(Node) + if deco_flags['is_inline']: + IsInlineFunc = True + if deco_flags['is_extern']: + IsExternFunc = True + if deco_flags['is_state']: + IsStateFunc = True + if deco_flags['is_export'] or deco_flags['is_extern'] or deco_flags['is_state']: + Gen._export_funcs.add(FuncName) MangledName = Gen._mangle_func_name(FuncName) if MangledName in Gen.functions: func = Gen.functions[MangledName] @@ -1210,8 +1402,6 @@ class FunctionHandle(BaseHandle): try: func.attributes.add(llvm_name) except Exception as _e: - from lib.core.VLogger import get_logger as _vlog - from lib.constants.config import mode as _config_mode if _config_mode == "strict": raise _vlog().warning(f"添加函数属性失败: {_e}", "Exception") @@ -1221,8 +1411,6 @@ class FunctionHandle(BaseHandle): try: func.attributes.add(llvm_attr_name) except Exception as _e: - from lib.core.VLogger import get_logger as _vlog - from lib.constants.config import mode as _config_mode if _config_mode == "strict": raise _vlog().warning(f"添加函数属性失败: {_e}", "Exception") @@ -1231,8 +1419,6 @@ class FunctionHandle(BaseHandle): try: func.attributes.add(attr_name) except Exception as _e: - from lib.core.VLogger import get_logger as _vlog - from lib.constants.config import mode as _config_mode if _config_mode == "strict": raise _vlog().warning(f"添加函数属性失败: {_e}", "Exception") @@ -1266,10 +1452,7 @@ class FunctionHandle(BaseHandle): # 这样函数内部定义的元类型变量(如 a = t.CInt32T)就能被正确处理 for stmt in Node.body: if isinstance(stmt, ast.Global): - for gname in stmt.names: - Gen.global_vars.add(gname) - if gname in Gen.module.globals: - Gen.variables[gname] = Gen.module.globals[gname] + self.Trans.ForHandler._RegisterGlobalNames(stmt.names, Gen) for param, param_name in zip(func.args, ParamNames): param.name = param_name if param_name == '__stop_iter_flag__': @@ -1337,6 +1520,38 @@ class FunctionHandle(BaseHandle): Gen.emit_va_start(va_list_ptr) Gen._variadic_info['va_start_called'] = True Gen.variables[vararg_name] = va_list_ptr + # @t.TLS 一次性初始化检查:首次调用执行函数体,后续调用直接返回 + if is_tls_func: + flag_name: str = f"__tls_init_done_{FuncName}" + flag_global = None + for gv in Gen.module.global_values: + if gv.name == flag_name: + flag_global = gv + break + if flag_global is None: + flag_global = ir.GlobalVariable(Gen.module, ir.IntType(1), name=flag_name) + flag_global.initializer = ir.Constant(ir.IntType(1), 0) + flag_global.linkage = 'internal' + flag_val = Gen.builder.load(flag_global, name="tls_flag_check") + skip_bb = func.append_basic_block("tls_skip") + cont_bb = func.append_basic_block("tls_continue") + Gen.builder.cbranch(flag_val, skip_bb, cont_bb) + Gen.builder.position_at_end(skip_bb) + ActualReturnType = func.function_type.return_type + if isinstance(ActualReturnType, ir.VoidType): + Gen.builder.ret_void() + elif isinstance(ActualReturnType, ir.IntType): + Gen.builder.ret(ir.Constant(ActualReturnType, 0)) + elif isinstance(ActualReturnType, (ir.FloatType, ir.DoubleType)): + Gen.builder.ret(ir.Constant(ActualReturnType, 0.0)) + elif isinstance(ActualReturnType, ir.PointerType): + Gen.builder.ret(ir.Constant(ActualReturnType, None)) + else: + Gen.builder.ret(ir.Constant(ActualReturnType, None)) + Gen.builder.position_at_end(cont_bb) + Gen.builder.store(ir.Constant(ir.IntType(1), 1), flag_global) + _saved_class_name = getattr(Gen, '_current_class_name', None) + Gen._current_class_name = ClassName self.Trans.BodyHandler.HandleBodyLlvm(Node.body) if not Gen.builder.block.is_terminated: if 'naked' in fn_attrs: @@ -1368,11 +1583,13 @@ class FunctionHandle(BaseHandle): Gen.builder.ret_void() Gen.builder = None Gen.func = None + Gen._current_class_name = _saved_class_name Gen.variables = {} Gen.var_signedness = {} Gen._reg_values = {} Gen._direct_values = {} Gen.var_struct_class = {} + Gen.var_ptr_element = {} Gen.var_const_flags = {} # 恢复保存的 var_type_info Gen.var_type_info = saved_var_type_info @@ -1407,8 +1624,8 @@ class FunctionHandle(BaseHandle): # property setter/deleter: 在原始 PropKey(不带后缀)下注册 MetaList if FuncMeta.PROPERTY_SETTER in func_meta or FuncMeta.PROPERTY_DELETER in func_meta: BasePropKey = f"{ClassName}.{RawFuncName}" if ClassName else RawFuncName - if self.Trans.SymbolTable.has(BasePropKey): - base_existing = self.Trans.SymbolTable[BasePropKey] + base_existing = self.Trans.SymbolTable.lookup(BasePropKey) + if base_existing: if func_meta != FuncMeta.NONE: base_existing.MetaList = base_existing.MetaList | func_meta else: diff --git a/lib/core/Handles/HandlesIf.py b/lib/core/Handles/HandlesIf.py index ef22272..40a49e0 100644 --- a/lib/core/Handles/HandlesIf.py +++ b/lib/core/Handles/HandlesIf.py @@ -1,203 +1,204 @@ -from __future__ import annotations -from typing import TYPE_CHECKING -if TYPE_CHECKING: - from lib.core.translator import Translator -from lib.core.Handles.HandlesBase import BaseHandle -import llvmlite.ir as ir -import ast - - -class IfHandle(BaseHandle): - def _get_attr_full_name(self, node): - if isinstance(node, ast.Attribute): - parts = [] - cur = node - while isinstance(cur, ast.Attribute): - parts.append(cur.attr) - cur = cur.value - if isinstance(cur, ast.Name): - parts.append(cur.id) - parts.reverse() - return '.'.join(parts) - return None - - def _is_cif_call(self, node): - if isinstance(node, ast.Call): - if isinstance(node.func, ast.Attribute): - if isinstance(node.func.value, ast.Name) and node.func.value.id == 'c': - return node.func.attr in ('CIf', 'CIfdef', 'CIfndef') - if isinstance(node.func, ast.Name): - return node.func.id in ('CIf', 'CIfdef', 'CIfndef') - return False - - def _resolve_macro_name(self, arg): - if isinstance(arg, ast.Name): - return arg.id - if isinstance(arg, ast.Constant) and isinstance(arg.value, str): - return arg.value - if isinstance(arg, ast.Attribute): - full_name = self._get_attr_full_name(arg) - if full_name: - return full_name - return None - - def _evaluate_cif_condition(self, node): - if not isinstance(node, ast.Call): - return None - args = node.args - if not args: - return False - if isinstance(node.func, ast.Attribute): - kind = node.func.attr - elif isinstance(node.func, ast.Name): - kind = node.func.id - else: - return None - if kind == 'CIfdef': - name = self._resolve_macro_name(args[0]) - if name is None: - return False - return self._is_macro_defined(name) - elif kind == 'CIfndef': - name = self._resolve_macro_name(args[0]) - if name is None: - return True - return not self._is_macro_defined(name) - elif kind == 'CIf': - return self._eval_const_expr(args[0]) - return None - - def _is_macro_defined(self, name): - Gen = self.Trans.LlvmGen - if hasattr(Gen, '_define_constants') and name in Gen._define_constants: - return True - if self.Trans.SymbolTable.is_define(name): - return True - platform_macros = self._get_platform_macros() - return name in platform_macros - - def _get_macro_value(self, name): - Gen = self.Trans.LlvmGen - if hasattr(Gen, '_define_constants') and name in Gen._define_constants: - val = Gen._define_constants[name] - if isinstance(val, (int, float)): - return val - if self.Trans.SymbolTable.has(name): - info = self.Trans.SymbolTable[name] - if info.IsDefine: - val = info.DefineValue - if isinstance(val, (int, float)): - return val - platform_macros = self._get_platform_macros() - if name in platform_macros: - return platform_macros[name] - return None - - def _get_platform_macros(self): - Gen = self.Trans.LlvmGen - macros = {} - pi = getattr(Gen, '_platform_info', {}) - ptr_size = getattr(Gen, 'ptr_size', 8) - # 根据目标平台设置宏(从三元组推导) - if pi.get('is_windows'): - macros['_WIN32'] = 1 - if not pi.get('is_32bit'): - macros['_WIN64'] = 1 - macros['WIN64'] = 1 - macros['WIN32'] = 1 - if pi.get('is_linux'): - macros['__linux__'] = 1 - if pi.get('is_macos'): - macros['__APPLE__'] = 1 - macros['__MACH__'] = 1 - if pi.get('is_x86_64'): - macros['__x86_64__'] = 1 - macros['__x86_64'] = 1 - macros['_M_X64'] = 1 - elif pi.get('is_arm64'): - macros['__aarch64__'] = 1 - macros['_M_ARM64'] = 1 - if not pi.get('is_32bit') and pi.get('is_linux'): - macros['__LP64__'] = 1 - elif pi.get('is_32bit'): - macros['_ILP32'] = 1 - macros['SIZEOF_VOID_P'] = ptr_size - macros['__SIZEOF_POINTER__'] = ptr_size - macros['NDEBUG'] = 0 - return macros - - def _eval_const_expr(self, node): - from lib.core.ConstEvaluator import ConstEvaluator, EvalContext - Gen = self.Trans.LlvmGen - ctx = EvalContext(Gen=Gen, symtab=self.Trans.SymbolTable) - result = ConstEvaluator.eval_full(node, ctx) - if result is None: - # 保留 CIf 嵌套调用处理(HandlesIf 特有逻辑) - if isinstance(node, ast.Call) and self._is_cif_call(node): - return self._evaluate_cif_condition(node) - return None - # HandlesIf 需要 bool/float → int 转换(#if 条件编译语义) - if isinstance(result, bool): - return 1 if result else 0 - if isinstance(result, float): - return 1 if result != 0.0 else 0 - return result - - def _HandleIfLlvm(self, Node): - Gen = self.Trans.LlvmGen - if self._is_cif_call(Node.test): - compile_time_val = self._evaluate_cif_condition(Node.test) - if compile_time_val is not None: - if compile_time_val: - self.Trans.BodyHandler.HandleBodyLlvm(Node.body) - elif Node.orelse: - if isinstance(Node.orelse, list) and len(Node.orelse) == 1 and isinstance(Node.orelse[0], ast.If): - self._HandleIfLlvm(Node.orelse[0]) - else: - self.Trans.BodyHandler.HandleBodyLlvm(Node.orelse) - return - Cond = self.Trans.ExprHandler.HandleExprLlvm(Node.test) - if not Cond: - return - is_const = isinstance(Cond, ir.Constant) and isinstance(Cond.type, ir.IntType) and Cond.type.width == 1 - if is_const: - if Cond.constant: - self.Trans.BodyHandler.HandleBodyLlvm(Node.body) - elif Node.orelse: - if isinstance(Node.orelse, list) and len(Node.orelse) == 1 and isinstance(Node.orelse[0], ast.If): - self._HandleIfLlvm(Node.orelse[0]) - else: - self.Trans.BodyHandler.HandleBodyLlvm(Node.orelse) - return - if not isinstance(Cond.type, ir.IntType) or Cond.type.width != 1: - ClassName = self.Trans.ExprHandler._get_var_class(Node.test, Gen) - if ClassName and Gen._has_function(f'{ClassName}.__bool__'): - obj_val = Cond - if isinstance(obj_val.type, ir.PointerType) and isinstance(obj_val.type.pointee, ir.IntType) and obj_val.type.pointee.width == 8: - obj_val = Gen.builder.bitcast(obj_val, ir.PointerType(Gen.structs[ClassName]), name=f"cast_{ClassName}") - Cond = Gen.builder.call(Gen._get_function(f'{ClassName}.__bool__'), [obj_val], name=f"call_{ClassName}.__bool__") - if isinstance(Cond.type, ir.IntType) and Cond.type.width != 1: - Cond = Gen.builder.icmp_signed('!=', Cond, Gen._ZeroConst(Cond.type), name="bool_result") - else: - if isinstance(Cond.type, (ir.FloatType, ir.DoubleType)): - Cond = Gen.builder.fcmp_ordered('!=', Cond, ir.Constant(Cond.type, 0.0), name="ifcond") - else: - Cond = Gen.builder.icmp_signed('!=', Cond, Gen._ZeroConst(Cond.type), name="ifcond") - ThenBB = Gen.func.append_basic_block(name="then") - ElseBB = Gen.func.append_basic_block(name="else") if Node.orelse else None - MergeBB = Gen.func.append_basic_block(name="endif") - if not Gen.builder.block.is_terminated: - Gen.builder.cbranch(Cond, ThenBB, ElseBB if ElseBB else MergeBB) - Gen.builder.position_at_start(ThenBB) - self.Trans.BodyHandler.HandleBodyLlvm(Node.body) - if not Gen.builder.block.is_terminated: - Gen.builder.branch(MergeBB) - if ElseBB: - Gen.builder.position_at_start(ElseBB) - self.Trans.BodyHandler.HandleBodyLlvm(Node.orelse) - if not Gen.builder.block.is_terminated: - Gen.builder.branch(MergeBB) - if not MergeBB.is_terminated: - Gen.builder.position_at_start(MergeBB) - else: - Gen.builder.position_at_end(MergeBB) +from __future__ import annotations +from typing import TYPE_CHECKING +if TYPE_CHECKING: + from lib.core.translator import Translator +import ast +import llvmlite.ir as ir +from lib.core.Handles.HandlesBase import BaseHandle +from lib.core.ConstEvaluator import ConstEvaluator, EvalContext + + +class IfHandle(BaseHandle): + def _get_attr_full_name(self, node: ast.expr) -> str | None: + if isinstance(node, ast.Attribute): + parts: list[str] = [] + cur: ast.expr = node + while isinstance(cur, ast.Attribute): + parts.append(cur.attr) + cur = cur.value + if isinstance(cur, ast.Name): + parts.append(cur.id) + parts.reverse() + return '.'.join(parts) + return None + + def _is_cif_call(self, node: ast.expr) -> bool: + if isinstance(node, ast.Call): + if isinstance(node.func, ast.Attribute): + if isinstance(node.func.value, ast.Name) and node.func.value.id == 'c': + return node.func.attr in ('CIf', 'CIfdef', 'CIfndef') + if isinstance(node.func, ast.Name): + return node.func.id in ('CIf', 'CIfdef', 'CIfndef') + return False + + def _resolve_macro_name(self, arg: ast.expr) -> str | None: + if isinstance(arg, ast.Name): + return arg.id + if isinstance(arg, ast.Constant) and isinstance(arg.value, str): + return arg.value + if isinstance(arg, ast.Attribute): + full_name: str | None = self._get_attr_full_name(arg) + if full_name: + return full_name + return None + + def _evaluate_cif_condition(self, node: ast.Call) -> int | None: + if not isinstance(node, ast.Call): + return None + args: list[ast.expr] = node.args + if not args: + return 0 + kind: str | None = None + if isinstance(node.func, ast.Attribute): + kind = node.func.attr + elif isinstance(node.func, ast.Name): + kind = node.func.id + else: + return None + if kind == 'CIfdef': + name: str | None = self._resolve_macro_name(args[0]) + if name is None: + return 0 + return 1 if self._is_macro_defined(name) else 0 + elif kind == 'CIfndef': + name: str | None = self._resolve_macro_name(args[0]) + if name is None: + return 1 + return 0 if self._is_macro_defined(name) else 1 + elif kind == 'CIf': + return self._eval_const_expr(args[0]) + return None + + def _is_macro_defined(self, name: str) -> bool: + Gen: "Translator.LlvmGen" = self.Trans.LlvmGen + if hasattr(Gen, '_define_constants') and name in Gen._define_constants: + return True + if self.Trans.SymbolTable.is_define(name): + return True + platform_macros: dict[str, int] = self._get_platform_macros() + return name in platform_macros + + def _get_macro_value(self, name: str) -> int | float | None: + Gen: "Translator.LlvmGen" = self.Trans.LlvmGen + if hasattr(Gen, '_define_constants') and name in Gen._define_constants: + val: int | float | None = Gen._define_constants[name] + if isinstance(val, (int, float)): + return val + info: "SymbolTable.SymbolInfo" = self.Trans.SymbolTable.lookup(name) + if info: + if info.IsDefine: + val: int | float | None = info.DefineValue + if isinstance(val, (int, float)): + return val + platform_macros: dict[str, int] = self._get_platform_macros() + if name in platform_macros: + return platform_macros[name] + return None + + def _get_platform_macros(self) -> dict[str, int]: + Gen: "Translator.LlvmGen" = self.Trans.LlvmGen + macros: dict[str, int] = {} + pi: dict[str, object] = getattr(Gen, '_platform_info', {}) + ptr_size: int = getattr(Gen, 'ptr_size', 8) + # 根据目标平台设置宏(从三元组推导) + if pi.get('is_windows'): + macros['_WIN32'] = 1 + if not pi.get('is_32bit'): + macros['_WIN64'] = 1 + macros['WIN64'] = 1 + macros['WIN32'] = 1 + if pi.get('is_linux'): + macros['__linux__'] = 1 + if pi.get('is_macos'): + macros['__APPLE__'] = 1 + macros['__MACH__'] = 1 + if pi.get('is_x86_64'): + macros['__x86_64__'] = 1 + macros['__x86_64'] = 1 + macros['_M_X64'] = 1 + elif pi.get('is_arm64'): + macros['__aarch64__'] = 1 + macros['_M_ARM64'] = 1 + if not pi.get('is_32bit') and pi.get('is_linux'): + macros['__LP64__'] = 1 + elif pi.get('is_32bit'): + macros['_ILP32'] = 1 + macros['SIZEOF_VOID_P'] = ptr_size + macros['__SIZEOF_POINTER__'] = ptr_size + macros['NDEBUG'] = 0 + return macros + + def _eval_const_expr(self, node: ast.expr) -> int | None: + Gen: "Translator.LlvmGen" = self.Trans.LlvmGen + ctx: EvalContext = EvalContext(Gen=Gen, symtab=self.Trans.SymbolTable, translator=self.Trans) + result: int | float | bool | None = ConstEvaluator.eval_full(node, ctx) + if result is None: + # 保留 CIf 嵌套调用处理(HandlesIf 特有逻辑) + if isinstance(node, ast.Call) and self._is_cif_call(node): + return self._evaluate_cif_condition(node) + return None + # HandlesIf 需要 bool/float → int 转换(#if 条件编译语义) + if isinstance(result, bool): + return 1 if result else 0 + if isinstance(result, float): + return 1 if result != 0.0 else 0 + return result + + def _HandleIfLlvm(self, Node: ast.If) -> None: + Gen: "Translator.LlvmGen" = self.Trans.LlvmGen + if self._is_cif_call(Node.test): + compile_time_val: int | None = self._evaluate_cif_condition(Node.test) + if compile_time_val is not None: + if compile_time_val: + self.Trans.BodyHandler.HandleBodyLlvm(Node.body) + elif Node.orelse: + if isinstance(Node.orelse, list) and len(Node.orelse) == 1 and isinstance(Node.orelse[0], ast.If): + self._HandleIfLlvm(Node.orelse[0]) + else: + self.Trans.BodyHandler.HandleBodyLlvm(Node.orelse) + return + Cond: ir.Value | None = self.Trans.ExprHandler.HandleExprLlvm(Node.test) + if not Cond: + return + is_const: bool = isinstance(Cond, ir.Constant) and isinstance(Cond.type, ir.IntType) and Cond.type.width == 1 + if is_const: + if Cond.constant: + self.Trans.BodyHandler.HandleBodyLlvm(Node.body) + elif Node.orelse: + if isinstance(Node.orelse, list) and len(Node.orelse) == 1 and isinstance(Node.orelse[0], ast.If): + self._HandleIfLlvm(Node.orelse[0]) + else: + self.Trans.BodyHandler.HandleBodyLlvm(Node.orelse) + return + if not isinstance(Cond.type, ir.IntType) or Cond.type.width != 1: + ClassName: str | None = self.Trans.ExprHandler._get_var_class(Node.test, Gen) + if ClassName and Gen._has_function(f'{ClassName}.__bool__'): + obj_val: ir.Value = Cond + if isinstance(obj_val.type, ir.PointerType) and isinstance(obj_val.type.pointee, ir.IntType) and obj_val.type.pointee.width == 8: + obj_val = Gen.builder.bitcast(obj_val, ir.PointerType(Gen.structs[ClassName]), name=f"cast_{ClassName}") + Cond = Gen.builder.call(Gen._get_function(f'{ClassName}.__bool__'), [obj_val], name=f"call_{ClassName}.__bool__") + if isinstance(Cond.type, ir.IntType) and Cond.type.width != 1: + Cond = Gen.builder.icmp_signed('!=', Cond, Gen._ZeroConst(Cond.type), name="bool_result") + else: + if isinstance(Cond.type, (ir.FloatType, ir.DoubleType)): + Cond = Gen.builder.fcmp_ordered('!=', Cond, ir.Constant(Cond.type, 0.0), name="ifcond") + else: + Cond = Gen.builder.icmp_signed('!=', Cond, Gen._ZeroConst(Cond.type), name="ifcond") + ThenBB: ir.Block = Gen.func.append_basic_block(name="then") + ElseBB: ir.Block | None = Gen.func.append_basic_block(name="else") if Node.orelse else None + MergeBB: ir.Block = Gen.func.append_basic_block(name="endif") + if not Gen.builder.block.is_terminated: + Gen.builder.cbranch(Cond, ThenBB, ElseBB if ElseBB else MergeBB) + Gen.builder.position_at_start(ThenBB) + self.Trans.BodyHandler.HandleBodyLlvm(Node.body) + if not Gen.builder.block.is_terminated: + Gen.builder.branch(MergeBB) + if ElseBB: + Gen.builder.position_at_start(ElseBB) + self.Trans.BodyHandler.HandleBodyLlvm(Node.orelse) + if not Gen.builder.block.is_terminated: + Gen.builder.branch(MergeBB) + if not MergeBB.is_terminated: + Gen.builder.position_at_start(MergeBB) + else: + Gen.builder.position_at_end(MergeBB) \ No newline at end of file diff --git a/lib/core/Handles/HandlesImports.py b/lib/core/Handles/HandlesImports.py index 3fff3e3..1a4dc6c 100644 --- a/lib/core/Handles/HandlesImports.py +++ b/lib/core/Handles/HandlesImports.py @@ -2,12 +2,19 @@ from __future__ import annotations from typing import TYPE_CHECKING if TYPE_CHECKING: from lib.core.translator import Translator -from lib.core.Handles.HandlesBase import BaseHandle, CTypeInfo, FuncMeta -from lib.includes import t + from lib.core.Translator.LlvmGenerator import LlvmGeneratorMixin import ast +import inspect import os +import re import hashlib import llvmlite.ir as ir +from lib.core.Handles.HandlesBase import BaseHandle, CTypeInfo, FuncMeta +from lib.core.VLogger import get_logger as _vlog +from lib.constants.config import mode as _config_mode +from lib.includes import t +from lib.includes.t import CTypeRegistry +from lib.core.SymbolUtils import IsTModule, ParseListAnnotation, ExtractTypeNameFromBinOp, AnnotationContainsName class ImportHandle(BaseHandle): @@ -18,13 +25,21 @@ class ImportHandle(BaseHandle): _pyi_cache_dir = None _project_root_cache = None - def _reset_file_cache(self): + def _reset_file_cache(self) -> None: self._struct_Load_cache.clear() - def _find_project_root(self): + def _find_project_root(self) -> str: if self._project_root_cache is not None: return self._project_root_cache - import os + # 优先使用 translator 上显式设置的 _temp_dir(由 Phase2Translator._translate_file 传入), + # 这样可以正确处理 include 文件——其源文件目录不在项目根目录下, + # 从源文件目录向上搜索 temp/output 会失败并回退到错误的路径。 + temp_dir_attr = getattr(self.Trans, '_temp_dir', None) + if temp_dir_attr and os.path.isdir(temp_dir_attr): + project_root = os.path.dirname(os.path.abspath(temp_dir_attr)) + if os.path.isdir(os.path.join(project_root, 'temp')) and os.path.isdir(os.path.join(project_root, 'output')): + self._project_root_cache = project_root + return project_root current_file = getattr(self.Trans, 'CurrentFile', '') or '' if current_file: current_dir = os.path.dirname(os.path.abspath(current_file)) @@ -37,17 +52,29 @@ class ImportHandle(BaseHandle): if parent == search_dir: break search_dir = parent + # 回退到当前工作目录(编译运行时的项目根目录) + cwd = os.getcwd() + if os.path.isdir(os.path.join(cwd, 'temp')) and os.path.isdir(os.path.join(cwd, 'output')): + self._project_root_cache = cwd + return cwd + if current_file: self._project_root_cache = current_dir return current_dir - self._project_root_cache = os.getcwd() - return os.getcwd() + self._project_root_cache = cwd + return cwd - def _EmitImportDeclarationsLlvm(self, Node, Gen): + def _EmitImportDeclarationsLlvm(self, Node: ast.Import, Gen: LlvmGeneratorMixin) -> None: if not getattr(self.Trans, '_ImportedModules', None): self.Trans._ImportedModules = set() for alias in Node.names: name = alias.name if name in ('c', 't'): + if alias.asname: + self.Trans.SymbolTable.import_aliases[alias.asname] = name + AliasInfo = CTypeInfo() + AliasInfo.IsModuleAlias = True + AliasInfo.ResolvedModule = name + self.Trans.SymbolTable.insert(alias.asname, AliasInfo) continue self.Trans._ImportedModules.add(name) if alias.asname: @@ -60,7 +87,7 @@ class ImportHandle(BaseHandle): current_module = self._get_current_module_name() self._EmitModuleDeclarationsLlvm(name, Gen, register_module_name=current_module) - def _RegisterFromImportAliases(self, Node, Gen, module): + def _RegisterFromImportAliases(self, Node: ast.ImportFrom, Gen: LlvmGeneratorMixin, module: str) -> None: """Register 'from module import y as z' aliases after module declarations are Loaded""" if not Node.names: return @@ -92,8 +119,9 @@ class ImportHandle(BaseHandle): Gen.functions[asname] = Gen.functions[name] if name in Gen.structs: Gen.structs[asname] = Gen.structs[name] - if self.Trans.SymbolTable.has(name): - self.Trans.SymbolTable.insert(asname, self.Trans.SymbolTable[name]) + info = self.Trans.SymbolTable.lookup(name) + if info: + self.Trans.SymbolTable.insert(asname, info) if name in Gen.variables: Gen.variables[asname] = Gen.variables[name] if name in Gen.global_vars: @@ -120,7 +148,7 @@ class ImportHandle(BaseHandle): if name in struct_sha1_map: struct_sha1_map[asname] = struct_sha1_map[name] - def _EmitImportFromDeclarationsLlvm(self, Node, Gen): + def _EmitImportFromDeclarationsLlvm(self, Node: ast.ImportFrom, Gen: LlvmGeneratorMixin) -> None: module = Node.module if Node.module else '' if module in ('c', 't'): if not getattr(self.Trans, '_ImportedModules', None): @@ -128,10 +156,17 @@ class ImportHandle(BaseHandle): self.Trans._ImportedModules.add(module) if not hasattr(self.Trans, '_t_c_imported_names'): self.Trans._t_c_imported_names = {} + # 注册 t/c 类型别名到 _t_type_symbols(CType 子类) + t_type_syms = self.Trans.SymbolTable._t_type_symbols for alias in Node.names: name = alias.name asname = alias.asname or name self.Trans._t_c_imported_names[asname] = (module, name) + # 仅注册 CType 子类(CEnum/CUnion/CStruct/REnum 等) + if module == 't': + cls = getattr(t, name, None) + if isinstance(cls, type) and issubclass(cls, t.CType): + t_type_syms[asname] = cls return if not getattr(self.Trans, '_ImportedModules', None): self.Trans._ImportedModules = set() @@ -207,7 +242,7 @@ class ImportHandle(BaseHandle): self._EmitModuleDeclarationsLlvm(module, Gen, register_module_name=current_module) self._RegisterFromImportAliases(Node, Gen, module) - def _LoadModuleDeclarationsFromFile(self, pyi_path, Gen, module_name=None, register_module_name=None, actual_module_name=None, reexport_package=None): + def _LoadModuleDeclarationsFromFile(self, pyi_path: str, Gen: LlvmGeneratorMixin, module_name: str | None = None, register_module_name: str | None = None, actual_module_name: str | None = None, reexport_package: str | None = None) -> None: if not pyi_path or not os.path.isfile(pyi_path): return try: @@ -323,16 +358,16 @@ class ImportHandle(BaseHandle): else: self._LoadModuleDeclarationsFromFile(sha1_pyi, Gen, module_name=alias.name, register_module_name=register_module_name, reexport_package=reexport_package or module_name) except Exception as _e: - if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": + if _config_mode == "strict": self.Trans.LogWarning(f"异常被忽略: {_e}") - def _get_current_module_name(self): + def _get_current_module_name(self) -> str | None: current_file = getattr(self.Trans, 'CurrentFile', '') or '' if current_file: return os.path.splitext(os.path.basename(current_file))[0] return None - def _RegisterSubModuleSha1(self, candidate_path, actual_module, short_module, Gen): + def _RegisterSubModuleSha1(self, candidate_path: str, actual_module: str, short_module: str, Gen: LlvmGeneratorMixin) -> None: """Register a submodule's SHA1 in ModuleSha1Map so cross-module class references work""" try: with open(candidate_path, 'r', encoding='utf-8') as f: @@ -343,13 +378,11 @@ class ImportHandle(BaseHandle): if short_module and short_module not in Gen.ModuleSha1Map: Gen.ModuleSha1Map[short_module] = sub_sha1 except Exception as _e: - from lib.core.VLogger import get_logger as _vlog - from lib.constants.config import mode as _config_mode if _config_mode == "strict": raise _vlog().warning(f"处理导入失败: {_e}", "Exception") - def _LoadPackageInitForRelativeImport(self, mod_dir, Gen, register_module_name): + def _LoadPackageInitForRelativeImport(self, mod_dir: str, Gen: LlvmGeneratorMixin, register_module_name: str | None) -> str: """Load __init__.py from the package directory for 'from . import name' resolution. This makes package-level names (functions, classes, constants) available. Returns the package name.""" @@ -383,14 +416,13 @@ class ImportHandle(BaseHandle): return pkg_name - def _EmitModuleDeclarationsLlvm(self, module_name, Gen, register_module_name=None): + def _EmitModuleDeclarationsLlvm(self, module_name: str, Gen: LlvmGeneratorMixin, register_module_name: str | None = None) -> None: if module_name in ('pyzlib',): source_sig_files = getattr(self.Trans, '_source_module_sig_files', None) ModulePath = module_name.replace('.', os.sep) + '.pyi' PackageInitPath = module_name.replace('.', os.sep) + os.sep + '__init__.pyi' ProjectRoot = os.path.dirname(os.path.abspath(getattr(self.Trans, 'CurrentFile', '') or '')) or os.getcwd() - - import inspect + HandlesFile = os.path.abspath(inspect.getfile(self.__class__)) TransPyCRoot = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(HandlesFile)))) @@ -592,6 +624,7 @@ class ImportHandle(BaseHandle): if module_name == 'pyzlib': node_type = type(node).__name__ name = getattr(node, 'name', getattr(node, 'attr', '?')) + _vlog().warning(f"HandlesImports: 忽略异常 {e}", exc_info=e) continue if not has_functions_or_classes and module_name: self._LoadDeclarationsFromStubLlvm(module_name, Gen) @@ -601,7 +634,7 @@ class ImportHandle(BaseHandle): if module_name: self._LoadDeclarationsFromStubLlvm(module_name, Gen) - def _EmitExternalGlobalDeclLlvm(self, Node, Gen, module_name=None, ModulePath=None): + def _EmitExternalGlobalDeclLlvm(self, Node: ast.AnnAssign | ast.Assign, Gen: LlvmGeneratorMixin, module_name: str | None = None, ModulePath: str | None = None) -> None: """Emit external global variable declaration from imported module""" if isinstance(Node, ast.AnnAssign) and isinstance(Node.target, ast.Name): VarName = Node.target.id @@ -609,66 +642,29 @@ class ImportHandle(BaseHandle): var_type = ir.IntType(32) IsPtr = False is_string_val = False + TypeInfo = None if VarName in Gen.module.globals: existing = Gen.module.globals[VarName] if isinstance(existing, ir.GlobalVariable): - old_pointee = existing.type.pointee if isinstance(existing.type, ir.PointerType) else None - if isinstance(old_pointee, ir.IdentifiedStructType): - if old_pointee.elements is not None and len(old_pointee.elements) > 0: - return - elif isinstance(old_pointee, ir.ArrayType): - return + return if Node.annotation: - if isinstance(Node.annotation, ast.Subscript) and isinstance(Node.annotation.value, ast.Name) and Node.annotation.value.id == 'list': - slice_node = Node.annotation.slice - if isinstance(slice_node, ast.Tuple) and len(slice_node.elts) == 2: - elem_type_node = slice_node.elts[0] - count_node = slice_node.elts[1] - ElemTypeInfo = CTypeInfo.FromNode(elem_type_node, self.Trans.SymbolTable) - if ElemTypeInfo: - elem_type = Gen._ctype_to_llvm(ElemTypeInfo) - if isinstance(elem_type, ir.VoidType): - elem_type = ir.IntType(8) - if isinstance(count_node, ast.Constant) and isinstance(count_node.value, int): - var_type = ir.ArrayType(elem_type, count_node.value) - elif isinstance(count_node, ast.Constant) and count_node.value is None: - var_type = ir.ArrayType(elem_type, 0) - else: - var_type = Gen._ctype_to_llvm(ElemTypeInfo) - IsPtr = False - else: - TypeInfo = CTypeInfo.FromNode(Node.annotation, self.Trans.SymbolTable) - if TypeInfo: - var_type = Gen._ctype_to_llvm(TypeInfo) - IsPtr = TypeInfo.IsPtr - elif isinstance(Node.annotation, ast.BinOp) and isinstance(Node.annotation.op, ast.BitOr): - list_node = None - for side in (Node.annotation.left, Node.annotation.right): - if isinstance(side, ast.Subscript) and isinstance(side.value, ast.Name) and side.value.id == 'list': - list_node = side - break - if list_node: - slice_node = list_node.slice - if isinstance(slice_node, ast.Tuple) and len(slice_node.elts) == 2: - elem_type_node = slice_node.elts[0] - count_node = slice_node.elts[1] - ElemTypeInfo = CTypeInfo.FromNode(elem_type_node, self.Trans.SymbolTable) - if ElemTypeInfo: - elem_type = Gen._ctype_to_llvm(ElemTypeInfo) - if isinstance(elem_type, ir.VoidType): - elem_type = ir.IntType(8) - if isinstance(count_node, ast.Constant) and isinstance(count_node.value, int): - var_type = ir.ArrayType(elem_type, count_node.value) - elif isinstance(count_node, ast.Constant) and count_node.value is None: - var_type = ir.ArrayType(elem_type, 0) - else: - var_type = Gen._ctype_to_llvm(ElemTypeInfo) - IsPtr = False - else: - TypeInfo = CTypeInfo.FromNode(Node.annotation, self.Trans.SymbolTable) - if TypeInfo: - var_type = Gen._ctype_to_llvm(TypeInfo) - IsPtr = TypeInfo.IsPtr + parse_result = ParseListAnnotation(Node.annotation) + if parse_result and not parse_result.is_pointer: + # list[type, count] 数组声明 + elem_type_node = parse_result.elem_type_node + count_node = parse_result.count_node + ElemTypeInfo = CTypeInfo.FromNode(elem_type_node, self.Trans.SymbolTable) + if ElemTypeInfo: + elem_type = Gen._ctype_to_llvm(ElemTypeInfo) + if isinstance(elem_type, ir.VoidType): + elem_type = ir.IntType(8) + if isinstance(count_node, ast.Constant) and isinstance(count_node.value, int): + var_type = ir.ArrayType(elem_type, count_node.value) + elif isinstance(count_node, ast.Constant) and count_node.value is None: + var_type = ir.ArrayType(elem_type, 0) + else: + var_type = Gen._ctype_to_llvm(ElemTypeInfo) + IsPtr = False else: TypeInfo = CTypeInfo.FromNode(Node.annotation, self.Trans.SymbolTable) if TypeInfo: @@ -710,6 +706,10 @@ class ImportHandle(BaseHandle): IsCTypedef = True if IsCTypedef: + # 检查符号是否已存在且已正确解析(OriginalType 已设置),避免覆盖 + existing_sym = self.Trans.SymbolTable.lookup(VarName) if hasattr(self.Trans.SymbolTable, 'lookup') else None + if existing_sym and isinstance(existing_sym, CTypeInfo) and existing_sym.IsTypedef and existing_sym.OriginalType: + return if Node.value: ValueTypeInfo = None if isinstance(Node.value, ast.BinOp) and isinstance(Node.value.op, ast.BitOr): @@ -757,16 +757,8 @@ class ImportHandle(BaseHandle): return gv = ir.GlobalVariable(Gen.module, var_type, name=VarName) - - if Node.value: - InitVal = self._ExtractValue(Node.value, var_type, VarName) - if InitVal is not None: - gv.initializer = InitVal - gv.linkage = 'available_externally' - else: - gv.linkage = 'external' - else: - gv.linkage = 'external' + # 外部全局变量声明:只声明不定义(external linkage),避免多重定义 + gv.linkage = 'external' elif isinstance(node, ast.Assign) and Node.targets and isinstance(Node.targets[0], ast.Name): VarName = Node.targets[0].id if VarName.startswith('_'): @@ -774,17 +766,9 @@ class ImportHandle(BaseHandle): if VarName in Gen.module.globals: return gv = ir.GlobalVariable(Gen.module, ir.IntType(32), name=VarName) - if Node.value and ModulePath: - InitVal = self._ExtractValue(Node.value, ir.IntType(32), VarName) - if InitVal is not None: - gv.initializer = InitVal - gv.linkage = 'available_externally' - else: - gv.linkage = 'external' - else: - gv.linkage = 'external' + gv.linkage = 'external' - def _ExtractValue(self, value_node, target_type, var_name=None): + def _ExtractValue(self, value_node: ast.AST, target_type: ir.Type, var_name: str | None = None) -> ir.Constant | None: """Extract constant value from AST node for global variable initializer""" # 处理负号 if isinstance(value_node, ast.UnaryOp) and isinstance(value_node.op, ast.USub): @@ -837,12 +821,10 @@ class ImportHandle(BaseHandle): return ir.Constant(target_type, 0) return None - def _ExtractConstValue(self, value_node): + def _ExtractConstValue(self, value_node: ast.AST) -> object: """Extract constant value from AST node for SymbolTable registration 支持常量、一元运算符、二元运算符和常量引用 """ - import ast - if isinstance(value_node, ast.Constant): return value_node.value elif isinstance(value_node, ast.BinOp): @@ -899,9 +881,7 @@ class ImportHandle(BaseHandle): return self._ExtractConstValue(value_node.args[0]) return None - def _ExtractTypedefOriginalType(self, value_node): - import ast - from lib.includes.t import CTypeRegistry + def _ExtractTypedefOriginalType(self, value_node: ast.AST) -> str | None: if isinstance(value_node, ast.Attribute): if getattr(value_node.value, 'id', None) == 't': llvm_str = CTypeRegistry.NameToLLVM(value_node.attr) @@ -933,9 +913,8 @@ class ImportHandle(BaseHandle): return llvm_str return None - def _RegisterCDefineSymbol(self, FullName, DefineValue, lineno, FilePath): + def _RegisterCDefineSymbol(self, FullName: str, DefineValue: object, lineno: int, FilePath: str) -> None: """Register CDefine constant to SymbolTable""" - from lib.core.Handles.HandlesBase import CTypeInfo info = CTypeInfo() info.IsDefine = True info.DefineValue = DefineValue @@ -944,20 +923,12 @@ class ImportHandle(BaseHandle): # 直接添加到 SymbolTable 字典 self.Trans.SymbolTable.insert(FullName, info) - def _check_annotation_for_state(self, annotation) -> bool: - import ast - if isinstance(annotation, ast.Attribute): - if hasattr(annotation, 'attr') and annotation.attr in ('CExport', 'CExtern', 'State'): - return True - if hasattr(annotation, 'value') and isinstance(annotation.value, ast.Name) and annotation.value.id == 't' and annotation.attr == 'State': - return True - elif isinstance(annotation, ast.BinOp) and isinstance(annotation.op, ast.BitOr): - return self._check_annotation_for_state(annotation.left) or self._check_annotation_for_state(annotation.right) - elif isinstance(annotation, ast.Name): - return annotation.id in ('CExport', 'CExtern', 'State') - return False + def _check_annotation_for_state(self, annotation: ast.AST) -> bool: + return (AnnotationContainsName(annotation, 'CExport') or + AnnotationContainsName(annotation, 'CExtern') or + AnnotationContainsName(annotation, 'State')) - def _EmitExternalFuncDeclLlvm(self, Node, Gen, is_class_method=False, source_module_name=None, register_module_name=None, reexport_module_names=None): + def _EmitExternalFuncDeclLlvm(self, Node: ast.FunctionDef, Gen: LlvmGeneratorMixin, is_class_method: bool = False, source_module_name: str | None = None, register_module_name: str | None = None, reexport_module_names: list[str] | None = None) -> None: FuncName = Node.name if Node.returns and self._check_annotation_for_state(Node.returns): Gen._export_funcs.add(FuncName) # t.State 标记的外部 C 函数必须保持原始名称,以便链接器解析 @@ -974,12 +945,7 @@ class ImportHandle(BaseHandle): ReturnTypeInfo = None if Node.returns: try: - if isinstance(Node.returns, ast.BinOp) and isinstance(Node.returns.op, ast.BitOr): - ReturnTypeInfo = getattr(self.Trans, 'TypeMergeHandler', None) and self.Trans.TypeMergeHandler.MergeTypes(Node.returns) - if not isinstance(ReturnTypeInfo, CTypeInfo): - ReturnTypeInfo = CTypeInfo.FromNode(Node.returns, self.Trans.SymbolTable) - else: - ReturnTypeInfo = CTypeInfo.FromNode(Node.returns, self.Trans.SymbolTable) + ReturnTypeInfo = self.ResolveAnnotationType(Node.returns) if ReturnTypeInfo and ReturnTypeInfo.IsStr: ReturnTypeInfo = CTypeInfo() ReturnTypeInfo.BaseType = t.CChar() @@ -988,7 +954,8 @@ class ImportHandle(BaseHandle): ReturnTypeInfo = CTypeInfo() ReturnTypeInfo.BaseType = t.CInt() IsPtr = ReturnTypeInfo.IsPtr - except Exception: # 回退:返回类型解析失败时使用默认 CInt + except Exception as e: # 回退:返回类型解析失败时使用默认 CInt + _vlog().warning(f"HandlesImports: 忽略异常 {e}", exc_info=e) ReturnTypeInfo = CTypeInfo() ReturnTypeInfo.BaseType = t.CInt() else: @@ -1021,12 +988,7 @@ class ImportHandle(BaseHandle): ParamType = ir.PointerType(Gen.structs.get(class_name_for_method or FuncName.split('.')[0], ir.IntType(8))) elif Arg.annotation: try: - if isinstance(Arg.annotation, ast.BinOp) and isinstance(Arg.annotation.op, ast.BitOr): - ParamTypeInfo = getattr(self.Trans, 'TypeMergeHandler', None) and self.Trans.TypeMergeHandler.MergeTypes(Arg.annotation) - if ParamTypeInfo is None or not isinstance(ParamTypeInfo, CTypeInfo): - ParamTypeInfo = CTypeInfo.FromNode(Arg.annotation, self.Trans.SymbolTable) - else: - ParamTypeInfo = CTypeInfo.FromNode(Arg.annotation, self.Trans.SymbolTable) + ParamTypeInfo = self.ResolveAnnotationType(Arg.annotation) if ParamTypeInfo is None: ParamTypeInfo = CTypeInfo() ParamTypeInfo.BaseType = t.CInt() @@ -1039,8 +1001,13 @@ class ImportHandle(BaseHandle): ParamTypeInfo.BaseType = t.CChar() ParamTypeInfo.PtrCount = 1 ParamIsPtr = True + # C 语言中数组参数退化为指针:list[type, N] → type* + if ParamTypeInfo.ArrayDims: + ParamTypeInfo.ArrayDims = [] + ParamTypeInfo.PtrCount = max(ParamTypeInfo.PtrCount, 1) ParamType = Gen._ctype_to_llvm(ParamTypeInfo) - except Exception: # 回退:参数类型解析失败时使用默认 i32 + except Exception as e: # 回退:参数类型解析失败时使用默认 i32 + _vlog().warning(f"HandlesImports: 忽略异常 {e}", exc_info=e) ParamType = ir.IntType(32) if isinstance(ParamType, ir.VoidType) or (isinstance(ParamType, ir.PointerType) and isinstance(ParamType.pointee, ir.VoidType)): AnnName = None @@ -1049,11 +1016,7 @@ class ImportHandle(BaseHandle): elif isinstance(Arg.annotation, ast.Attribute): AnnName = Arg.annotation.attr elif isinstance(Arg.annotation, ast.BinOp) and isinstance(Arg.annotation.op, ast.BitOr): - left = Arg.annotation.left - if isinstance(left, ast.Name): - AnnName = left.id - elif isinstance(left, ast.Attribute): - AnnName = left.attr + AnnName = ExtractTypeNameFromBinOp(Arg.annotation) if AnnName and AnnName in Gen.structs: ParamType = ir.PointerType(Gen.structs[AnnName]) else: @@ -1123,8 +1086,8 @@ class ImportHandle(BaseHandle): # property setter/deleter: 在原始 PropKey(不带后缀)下注册 MetaList if FuncMeta.PROPERTY_SETTER in func_meta or FuncMeta.PROPERTY_DELETER in func_meta: BasePropKey = FuncName.replace('$set', '').replace('$del', '') - if self.Trans.SymbolTable.has(BasePropKey): - base_existing = self.Trans.SymbolTable[BasePropKey] + base_existing = self.Trans.SymbolTable.lookup(BasePropKey) + if base_existing: if func_meta != FuncMeta.NONE: base_existing.MetaList = base_existing.MetaList | func_meta else: @@ -1143,7 +1106,7 @@ class ImportHandle(BaseHandle): if ReexportName2 not in Gen.functions: Gen.functions[ReexportName2] = func - def _EmitExternalClassDeclLlvm(self, Node, Gen, module_name=None, actual_module_name=None): + def _EmitExternalClassDeclLlvm(self, Node: ast.ClassDef, Gen: LlvmGeneratorMixin, module_name: str | None = None, actual_module_name: str | None = None) -> None: ClassName = Node.name if hasattr(Node, 'type_params') and Node.type_params: return @@ -1180,7 +1143,7 @@ class ImportHandle(BaseHandle): IsCpythonObject = True elif decorator.func.id == 'CVTable': IsCVTable = True - if ClassName.startswith('_') and not IsCpythonObject and not IsCenum: + if ClassName.startswith('__') and not IsCpythonObject and not IsCenum: return IsPacked = False if getattr(Node, 'decorator_list', None): @@ -1260,23 +1223,46 @@ class ImportHandle(BaseHandle): if ClassName not in Gen.class_member_bitoffsets: Gen.class_member_bitoffsets[ClassName] = {} has_methods = False + # 解析 __provides__/__requires__/__require_must__ 编译期元数据(跨模块加载) for item in Node.body: if isinstance(item, ast.AnnAssign) and isinstance(item.target, ast.Name): - VarName = item.target.id - try: - TypeInfo = CTypeInfo.FromNode(item.annotation, self.Trans.SymbolTable) - if TypeInfo is None: - TypeInfo = CTypeInfo() - TypeInfo.BaseType = t.CInt() - MemberType = Gen._ctype_to_llvm(TypeInfo) - if isinstance(MemberType, ir.VoidType): - MemberType = ir.PointerType(ir.IntType(8)) - if TypeInfo and TypeInfo.IsBitField: + field_name: str = item.target.id + if field_name in ('__provides__', '__requires__', '__require_must__') and item.value: + values: list[str] = [] + if isinstance(item.value, ast.List): + for elt in item.value.elts: + if isinstance(elt, ast.Constant) and isinstance(elt.value, str): + values.append(elt.value) + if field_name == '__provides__': + Gen.class_provides[ClassName] = values + elif field_name == '__requires__': + Gen.class_requires[ClassName] = values + elif field_name == '__require_must__': + Gen.class_require_must[ClassName] = values + _existing_member_names = {m[0] for m in Gen.class_members[ClassName]} + for item in Node.body: + # 跳过编译期元数据字段(__provides__/__requires__/__require_must__) + if isinstance(item, ast.AnnAssign) and isinstance(item.target, ast.Name): + if item.target.id in ('__provides__', '__requires__', '__require_must__'): + continue + parsed = self.CollectAnnAssignMember(item, Gen) + if parsed: + VarName, MemberType, TypeInfo = parsed + if TypeInfo is None: + if VarName not in _existing_member_names: + Gen.class_members[ClassName].append((VarName, MemberType)) + _existing_member_names.add(VarName) + Gen.class_member_signeds[ClassName][VarName] = None + Gen.class_member_bitfields[ClassName][VarName] = 0 + else: + if TypeInfo.IsBitField: Gen.class_member_bitfields[ClassName][VarName] = TypeInfo.BitWidth else: - Gen.class_members[ClassName].append((VarName, MemberType)) + if VarName not in _existing_member_names: + Gen.class_members[ClassName].append((VarName, MemberType)) + _existing_member_names.add(VarName) Gen.class_member_bitfields[ClassName][VarName] = 0 - if TypeInfo and TypeInfo.ByteOrder: + if TypeInfo.ByteOrder: Gen.class_member_byteorders[ClassName][VarName] = TypeInfo.ByteOrder else: Gen.class_member_byteorders[ClassName][VarName] = "" @@ -1284,10 +1270,6 @@ class ImportHandle(BaseHandle): const = self._BuildScalarConstant(item.value, MemberType, Gen) if const: Gen.class_member_defaults[ClassName][VarName] = const - except Exception: # 回退:类成员类型解析失败时使用默认 i32 - Gen.class_members[ClassName].append((VarName, ir.IntType(32))) - Gen.class_member_signeds[ClassName][VarName] = None - Gen.class_member_bitfields[ClassName][VarName] = 0 elif isinstance(item, ast.FunctionDef): has_methods = True MethodName = item.name @@ -1340,8 +1322,8 @@ class ImportHandle(BaseHandle): existing.MetaList = func_meta # setter/deleter: 同时在原始 PropKey(不带后缀)下注册 MetaList if is_item_prop_setter or is_item_prop_deleter: - if self.Trans.SymbolTable.has(FuncFullName): - base_existing = self.Trans.SymbolTable[FuncFullName] + base_existing = self.Trans.SymbolTable.lookup(FuncFullName) + if base_existing: if func_meta != FuncMeta.NONE: base_existing.MetaList = base_existing.MetaList | func_meta else: @@ -1374,18 +1356,22 @@ class ImportHandle(BaseHandle): Gen.class_member_bitoffsets[ClassName][name] = current_bit_offset current_bit_offset += bw - def _TryLoadStructFromStub(self, class_name: str, Gen): - cache_key = class_name + def _TryLoadStructFromStub(self, class_name: str, Gen: LlvmGeneratorMixin) -> None: + # 缓存键包含 Gen 实例标识,确保每个模块的 Gen 都能独立加载 struct 定义, + # 同时仍能防止同一 Gen 内的递归重入。原先使用纯 class_name 作为键会导致 + # 跨模块 struct 类型对象无法分别 set_body(每个模块有独立的 self.structs)。 + cache_key = (id(Gen), class_name) if cache_key in self._struct_Load_cache: return + # 先设置缓存防止递归重入,但如果加载失败则清除缓存允许后续重试 self._struct_Load_cache[cache_key] = True - - import os, re + ProjectRoot = self._find_project_root() temp_dir = os.path.join(ProjectRoot, 'temp') if not os.path.isdir(temp_dir): + del self._struct_Load_cache[cache_key] return - + if self._stub_cache_dir != temp_dir: self._stub_cache.clear() self._stub_cache_dir = temp_dir @@ -1408,15 +1394,14 @@ class ImportHandle(BaseHandle): if '.' in full_name: self._stub_cache.setdefault(full_name, []).append((full_name, struct_body, source_sha1)) except Exception as _e: - from lib.core.VLogger import get_logger as _vlog - from lib.constants.config import mode as _config_mode if _config_mode == "strict": raise _vlog().warning(f"处理导入失败: {_e}", "Exception") if class_name not in self._stub_cache: + del self._struct_Load_cache[cache_key] return - + for full_name, struct_body, source_sha1 in self._stub_cache[class_name]: is_packed = struct_body.startswith('<{') and struct_body.endswith('}>') if struct_body and struct_body != 'opaque': @@ -1438,8 +1423,6 @@ class ImportHandle(BaseHandle): if is_packed: Gen.class_packed.add(class_name) except Exception as _e: - from lib.core.VLogger import get_logger as _vlog - from lib.constants.config import mode as _config_mode if _config_mode == "strict": raise _vlog().warning(f"处理导入失败: {_e}", "Exception") @@ -1447,8 +1430,7 @@ class ImportHandle(BaseHandle): self._TryLoadClassMembersFromPyi(class_name, stub_filename, Gen) return - def _TryLoadClassMembersFromPyi(self, class_name: str, stub_filename: str, Gen): - import os + def _TryLoadClassMembersFromPyi(self, class_name: str, stub_filename: str, Gen: LlvmGeneratorMixin) -> None: ProjectRoot = self._find_project_root() temp_dir = os.path.join(ProjectRoot, 'temp') if class_name in Gen.class_members and len(Gen.class_members[class_name]) > 0: @@ -1467,7 +1449,8 @@ class ImportHandle(BaseHandle): try: with open(pyi_path, 'r', encoding='utf-8') as f: self._pyi_cache[pyi_path] = ast.parse(f.read()) - except Exception: + except Exception as e: + _vlog().warning(f"HandlesImports: 忽略异常 {e}", exc_info=e) self._pyi_cache[pyi_path] = None return @@ -1500,40 +1483,13 @@ class ImportHandle(BaseHandle): return return - def _BuildScalarConstant(self, value_node, target_type, Gen): - """Build a scalar constant value from AST node""" - if isinstance(target_type, ir.BaseStructType): - return None - if isinstance(value_node, ast.Constant): - if isinstance(value_node.value, int): - return ir.Constant(target_type, value_node.value) - elif isinstance(value_node.value, str): - str_val = value_node.value + '\x00' - str_bytes = str_val.encode('utf-8') - arr_type = ir.ArrayType(ir.IntType(8), len(str_bytes)) - gv_name = f"str_const_{id(value_node)}" - gv = ir.GlobalVariable(Gen.module, arr_type, name=gv_name) - gv.initializer = ir.Constant(arr_type, bytearray(str_bytes)) - gv.linkage = 'internal' - ptr_type = ir.PointerType(ir.IntType(8)) - return ir.Constant(ptr_type, gv.reference) - elif isinstance(value_node.value, bool): - return ir.Constant(target_type, 1 if value_node.value else 0) - elif isinstance(value_node, ast.Name): - if value_node.id == 'True': - return ir.Constant(target_type, 1) - elif value_node.id == 'False': - if isinstance(target_type, ir.PointerType): - return ir.Constant(target_type, None) - return ir.Constant(target_type, 0) - return None + def _BuildScalarConstant(self, value_node: ast.AST, target_type: ir.Type, Gen: LlvmGeneratorMixin) -> ir.Constant | None: + """Build a scalar constant value from AST node, delegated to unified method.""" + return self.Trans._BuildScalarConstantUnified(value_node, target_type, Gen) - def _LookupStubFuncType(self, func_name, Gen): + def _LookupStubFuncType(self, func_name: str, Gen: LlvmGeneratorMixin) -> ir.FunctionType | None: """从 stub.ll 文件中查找指定函数的 LLVM 类型""" - import os - import re - import llvmlite.ir as ir - + if not getattr(self, '_stub_func_cache', None): self._stub_func_cache = {} @@ -1571,8 +1527,6 @@ class ImportHandle(BaseHandle): stub_params = match.group(3).strip() self._stub_func_cache[stub_func_name] = (stub_ret, stub_params, '...' in stub_params, source_sha1) except Exception as _e: - from lib.core.VLogger import get_logger as _vlog - from lib.constants.config import mode as _config_mode if _config_mode == "strict": raise _vlog().warning(f"处理导入失败: {_e}", "Exception") @@ -1613,17 +1567,15 @@ class ImportHandle(BaseHandle): param_types.append(ir.PointerType(ir.IntType(8))) return ir.FunctionType(ret_type, param_types, var_arg=is_variadic) - def _strip_llvm_param_name(self, param_str): + def _strip_llvm_param_name(self, param_str: str) -> str: """剥离 LLVM IR 参数字符串中的参数名,仅保留类型部分""" - import re param_str = param_str.strip() result = re.sub(r'\s+%[\w.]+\s*$', '', param_str) return result.strip() - def _parse_simple_llvm_type(self, type_str): + def _parse_simple_llvm_type(self, type_str: str) -> ir.Type | None: """解析简单的 LLVM 类型字符串(不创建结构体,避免副作用)""" - import llvmlite.ir as ir - + type_str = type_str.strip() type_map = { @@ -1648,7 +1600,6 @@ class ImportHandle(BaseHandle): return ir.PointerType(ir.IntType(8)) if type_str.startswith('[') and ']' in type_str: - import re arr_match = re.match(r'\[(\d+)\s*x\s+(.+)\]', type_str) if arr_match: size = int(arr_match.group(1)) @@ -1661,20 +1612,17 @@ class ImportHandle(BaseHandle): return None - def _LoadDeclarationsFromStubLlvm(self, module_name: str, Gen): + def _LoadDeclarationsFromStubLlvm(self, module_name: str, Gen: LlvmGeneratorMixin) -> None: """从 stub.ll 文件加载函数声明和结构体定义到 Gen""" - import os - import re - import llvmlite.ir as ir - + ProjectRoot = self._find_project_root() temp_dir = os.path.join(ProjectRoot, 'temp') - + if not os.path.isdir(temp_dir): return - + all_stub_files = [f for f in os.listdir(temp_dir) if f.endswith('.stub.ll')] - + source_sig_files = getattr(self.Trans, '_source_module_sig_files', {}) target_sha1 = None if module_name: @@ -1685,7 +1633,7 @@ class ImportHandle(BaseHandle): if not target_sha1: ModuleSha1Map = getattr(Gen, 'ModuleSha1Map', {}) target_sha1 = ModuleSha1Map.get(module_name) - + if target_sha1: target_stub = f"{target_sha1}.stub.ll" if target_stub in all_stub_files: @@ -1694,7 +1642,7 @@ class ImportHandle(BaseHandle): stub_files = [] else: stub_files = [] - + needed_sha1s = set() for filename in stub_files: stub_path = os.path.join(temp_dir, filename) @@ -1710,8 +1658,6 @@ class ImportHandle(BaseHandle): for m in re.finditer(r'%\"?([a-f0-9]{16})\.', stripped): needed_sha1s.add(m.group(1)) except Exception as _e: - from lib.core.VLogger import get_logger as _vlog - from lib.constants.config import mode as _config_mode if _config_mode == "strict": raise _vlog().warning(f"处理导入失败: {_e}", "Exception") @@ -1721,9 +1667,9 @@ class ImportHandle(BaseHandle): dep_stub = f"{sha1}.stub.ll" if dep_stub in all_stub_files and dep_stub not in stub_files: preLoad_files.append(dep_stub) - + Load_order = preLoad_files + stub_files - + for filename in Load_order: stub_path = os.path.join(temp_dir, filename) source_sha1 = filename.replace('.stub.ll', '') @@ -1761,12 +1707,10 @@ class ImportHandle(BaseHandle): else: elem_types.append(ir.IntType(32)) st = Gen._get_or_create_struct(clean_name, source_sha1=source_sha1, packed=is_packed) - if isinstance(st, ir.IdentifiedStructType) and (st.elements is None or len(st.elements) == 0): + if isinstance(st, ir.IdentifiedStructType) and st.elements is None: try: st.set_body(*elem_types) except Exception as _e: - from lib.core.VLogger import get_logger as _vlog - from lib.constants.config import mode as _config_mode if _config_mode == "strict": raise _vlog().warning(f"处理导入失败: {_e}", "Exception") @@ -1806,24 +1750,93 @@ class ImportHandle(BaseHandle): short_name = func_name.split('.', 1)[1] Gen.functions[short_name] = func except Exception as _e: - from lib.core.VLogger import get_logger as _vlog - from lib.constants.config import mode as _config_mode if _config_mode == "strict": raise _vlog().warning(f"处理导入失败: {_e}", "Exception") except Exception as _e: - from lib.core.VLogger import get_logger as _vlog - from lib.constants.config import mode as _config_mode if _config_mode == "strict": raise _vlog().warning(f"处理导入失败: {_e}", "Exception") - def _parse_llvm_declare(self, declare_line: str, Gen): - """解析 LLVM declare 语句""" - import re - import llvmlite.ir as ir + def _TryLoadFuncDeclsFromOutputStub(self, struct_name: str, Gen: LlvmGeneratorMixin) -> bool: + """按需从 output 目录的 stub.ll 加载泛型特化方法声明。 - match = re.match(r'declare\s+(.+?)\s+@("?[\w.]+"?)\s*\((.*)\)$', declare_line) + 当 temp stub 不包含泛型特化(如 list[str].__iter__)时, + 从 output stub(由 _split_ll 从完整 IR 生成)中按需加载。 + + struct_name: 结构体名,如 '9163064cf3eb88f4.list[str]' 或 'list[str]' + 返回 True 如果找到了并加载了新函数声明。 + """ + ProjectRoot = self._find_project_root() + output_dir = os.path.join(ProjectRoot, 'output') + if not os.path.isdir(output_dir): + return False + + # 提取短名称和 SHA1 前缀 + sha1_prefix: str | None = None + if '.' in struct_name: + parts: list[str] = struct_name.split('.', 1) + if len(parts[0]) == 16 and all(c in '0123456789abcdef' for c in parts[0]): + sha1_prefix = parts[0] + short_name: str = parts[1] + else: + short_name = struct_name + else: + short_name = struct_name + + # 确定要搜索的 stub 文件列表 + stub_files_to_search: list[str] = [] + if sha1_prefix: + target_stub = f'{sha1_prefix}.stub.ll' + target_path = os.path.join(output_dir, target_stub) + if os.path.isfile(target_path): + stub_files_to_search.append(target_stub) + else: + # 没有SHA1前缀,搜索所有 output stub + for fname in os.listdir(output_dir): + if fname.endswith('.stub.ll'): + stub_files_to_search.append(fname) + + loaded_any: bool = False + for fname in stub_files_to_search: + stub_path = os.path.join(output_dir, fname) + try: + with open(stub_path, 'r', encoding='utf-8') as f: + content = f.read() + for line in content.splitlines(): + stripped = line.strip() + if not stripped.startswith('declare '): + continue + # 检查是否是目标结构体的方法 + if f'.{short_name}.' not in stripped: + continue + try: + func_type = self._parse_llvm_declare(stripped, Gen) + if func_type is None: + continue + # 提取函数名:最后一个 @ 到第一个 ( 之间的内容 + paren_pos: int = stripped.index('(') + at_pos: int = stripped.rindex('@', 0, paren_pos) + func_name: str = stripped[at_pos + 1:paren_pos].strip().strip('"') + if func_name not in Gen.functions: + func = ir.Function(Gen.module, func_type, name=func_name) + Gen.functions[func_name] = func + if '.' in func_name: + short_fn = func_name.split('.', 1)[1] + Gen.functions[short_fn] = func + loaded_any = True + except Exception: + pass + except Exception as _e: + if _config_mode == "strict": + raise + _vlog().warning(f"按需加载 output stub 失败: {_e}", "Exception") + return loaded_any + + def _parse_llvm_declare(self, declare_line: str, Gen: LlvmGeneratorMixin) -> ir.FunctionType | None: + """解析 LLVM declare 语句""" + + match = re.match(r'declare\s+(.+?)\s+@("?[^()]+"?)\s*\((.*)\)$', declare_line) if not match: return None @@ -1861,10 +1874,8 @@ class ImportHandle(BaseHandle): is_variadic = '...' in params_str return ir.FunctionType(ret_type, param_types, var_arg=is_variadic) - def _parse_llvm_type(self, type_str: str, Gen, source_sha1=None, create_structs=True): + def _parse_llvm_type(self, type_str: str, Gen: LlvmGeneratorMixin, source_sha1: str | None = None, create_structs: bool = True) -> ir.Type | None: """解析 LLVM 类型字符串""" - import re - import llvmlite.ir as ir type_str = type_str.strip() @@ -1926,7 +1937,7 @@ class ImportHandle(BaseHandle): return ir.ArrayType(elem_type, size) typedef_names = {'typedef', 'CType', 'CVolatile', 'CEnum', 'CUnion', 'CStruct', 'enum', 'REnum', 'renum'} - struct_match = re.match(r'%"?((?:[a-f0-9]+\.)?[\w.]+)"?', type_str) + struct_match = re.match(r'%"?((?:[a-f0-9]+\.)?[\w.\[\]]+)"?', type_str) if struct_match: raw_name = struct_match.group(1) actual_source_sha1 = source_sha1 @@ -1938,6 +1949,50 @@ class ImportHandle(BaseHandle): else: struct_name = raw_name if struct_name not in typedef_names: + # 泛型类特化(如 list[str]):触发特化创建结构体和方法声明 + # 使用 declare_only=True 避免在引用模块中生成方法体(定义由定义模块提供) + if '[' in struct_name and actual_source_sha1: + if struct_name in Gen.structs: + return Gen.structs[struct_name] + gc_base: str = struct_name.split('[')[0] + gc_args_raw: str = struct_name[len(gc_base):] + gc_type_args: list[str] = [] + for gc_arg_part in gc_args_raw.split(']['): + gc_arg_part = gc_arg_part.strip('[]') + if gc_arg_part: + gc_type_args.append(gc_arg_part) + if (gc_type_args + and hasattr(self.Trans, 'ClassHandler') + and hasattr(self.Trans.ClassHandler, '_generic_class_templates') + and gc_base in self.Trans.ClassHandler._generic_class_templates): + gc_type_names: list[str] = [] + for gc_ta in gc_type_args: + gc_tn: str = gc_ta + if gc_ta == 'int': + gc_tn = 'CInt' + elif gc_ta == 'double': + gc_tn = 'CDouble' + elif gc_ta == 'float': + gc_tn = 'CFloat' + elif gc_ta == 'char': + gc_tn = 'CChar' + elif gc_ta == 'bool': + gc_tn = 'CBool' + gc_type_names.append(gc_tn) + saved_module_sha1: str | None = getattr(Gen, 'module_sha1', None) + saved_trans_sha1: str | None = getattr(self.Trans, '_module_sha1', None) + Gen.module_sha1 = actual_source_sha1 + self.Trans._module_sha1 = actual_source_sha1 + try: + gc_spec: str | None = self.Trans.ClassHandler._specialize_generic_class( + gc_base, gc_type_args, Gen, type_names=gc_type_names, + declare_only=True) + except Exception: + gc_spec = None + Gen.module_sha1 = saved_module_sha1 + self.Trans._module_sha1 = saved_trans_sha1 + if gc_spec and gc_spec in Gen.structs: + return Gen.structs[gc_spec] if create_structs: return Gen._get_or_create_struct(struct_name, source_sha1=actual_source_sha1) else: @@ -1949,13 +2004,12 @@ class ImportHandle(BaseHandle): return None - def _strip_param_name(self, param_str): + def _strip_param_name(self, param_str: str) -> str: """从 LLVM 参数字符串中剥离参数名,只保留类型部分 例如: '%"sha1.struct_name"* %param_name' -> '%"sha1.struct_name"*' 'i8* %path' -> 'i8*' 'i32' -> 'i32' """ - import re param_str = param_str.strip() stripped = re.sub(r'\s+%[\w.]+\s*$', '', param_str) return stripped.strip() diff --git a/lib/core/Handles/HandlesMatch.py b/lib/core/Handles/HandlesMatch.py index 3148d3e..ea7d21e 100644 --- a/lib/core/Handles/HandlesMatch.py +++ b/lib/core/Handles/HandlesMatch.py @@ -1,332 +1,334 @@ -from __future__ import annotations -from typing import TYPE_CHECKING -if TYPE_CHECKING: - from lib.core.translator import Translator -from lib.core.Handles.HandlesBase import BaseHandle -import ast -import llvmlite.ir as ir - - -class MatchHandle(BaseHandle): - def _HandleMatchLlvm(self, Node): - Gen = self.Trans.LlvmGen - SubjectVal = self.HandleExprLlvm(Node.subject) - if not SubjectVal: - return - - IsRenumMatch = False - RenumName = None - SubjectPtr = None - if isinstance(Node.subject, ast.Name): - VarName = Node.subject.id - TypeInfo = self.Trans.SymbolTable.lookup(VarName) - if TypeInfo and TypeInfo.IsRenum: - IsRenumMatch = True - RenumName = TypeInfo.Name - SubjectPtr = Gen._loadVar(VarName) - - if not IsRenumMatch: - for case in Node.cases: - if isinstance(case.pattern, ast.MatchClass): - cls_node = case.pattern.cls - VariantName = None - if isinstance(cls_node, ast.Name): - VariantName = cls_node.id - elif isinstance(cls_node, ast.Attribute): - VariantName = cls_node.attr - if VariantName and self.Trans.SymbolTable.has(VariantName): - SymInfo = self.Trans.SymbolTable[VariantName] - if SymInfo.IsEnumMember and SymInfo.EnumName: - EnumName = SymInfo.EnumName - if self.Trans.SymbolTable.has(EnumName): - EnumInfo = self.Trans.SymbolTable[EnumName] - if EnumInfo.IsRenum: - IsRenumMatch = True - RenumName = EnumName - if SubjectPtr is None: - SubjectPtr = self.HandleExprLlvm(Node.subject) - break - - if IsRenumMatch and SubjectPtr: - self._HandleRenumMatchLlvm(Node, RenumName, SubjectPtr) - return - - if not isinstance(SubjectVal.type, ir.IntType): - try: - SubjectVal = Gen.builder.ptrtoint(SubjectVal, ir.IntType(64), name="match_subj") - SubjectVal = Gen.builder.trunc(SubjectVal, ir.IntType(32), name="match_subj_i32") - except Exception: # 回退:ptrtoint 失败时直接返回 - return - SwitchIntType = SubjectVal.type - DefaultBB = Gen.func.append_basic_block(name="match.default") - AfterBB = Gen.func.append_basic_block(name="match.end") - CaseBBs = [] - CaseValues = [] - HasDefault = False - HasNoBreak = [] - for i, case in enumerate(Node.cases): - pattern = case.pattern - if isinstance(pattern, ast.MatchValue): - Val = self.HandleExprLlvm(pattern.value) - if Val: - if isinstance(Val.type, ir.IntType): - if Val.type != SwitchIntType: - if Val.type.width > SwitchIntType.width: - CaseVal = ir.Constant(SwitchIntType, Val.constant & ((1 << SwitchIntType.width) - 1)) - else: - CaseVal = ir.Constant(SwitchIntType, Val.constant) - else: - CaseVal = Val - else: - try: - CaseVal = Gen.builder.ptrtoint(Val, SwitchIntType, name=f"case_val_{i}") - except Exception: # 回退:ptrtoint 失败时设默认值 0 - CaseVal = ir.Constant(SwitchIntType, 0) - CaseValues.append(CaseVal) - CaseBBs.append(Gen.func.append_basic_block(name=f"match.case_{i}")) - elif isinstance(pattern, ast.MatchOr): - for j, SubPattern in enumerate(pattern.patterns): - if isinstance(SubPattern, ast.MatchValue): - Val = self.HandleExprLlvm(SubPattern.value) - if Val: - if isinstance(Val.type, ir.IntType): - if Val.type != SwitchIntType: - if Val.type.width > SwitchIntType.width: - CaseVal = ir.Constant(SwitchIntType, Val.constant & ((1 << SwitchIntType.width) - 1)) - else: - CaseVal = ir.Constant(SwitchIntType, Val.constant) - else: - CaseVal = Val - else: - try: - CaseVal = Gen.builder.ptrtoint(Val, SwitchIntType, name=f"case_val_{i}_{j}") - except Exception: # 回退:ptrtoint 失败时设默认值 0 - CaseVal = ir.Constant(SwitchIntType, 0) - CaseValues.append(CaseVal) - CaseBBs.append(Gen.func.append_basic_block(name=f"match.case_{i}_{j}")) - elif isinstance(pattern, ast.MatchSingleton): - if pattern.value is None: - CaseValues.append(ir.Constant(SwitchIntType, 0)) - CaseBBs.append(Gen.func.append_basic_block(name=f"match.case_{i}")) - elif isinstance(pattern, ast.MatchAs): - if pattern.pattern is None: - HasDefault = True - CaseBBs.append(DefaultBB) - elif isinstance(pattern, ast.MatchSequence): - HasDefault = True - CaseBBs.append(DefaultBB) - def _HasNoBreak(stmts): - for stmt in stmts: - if isinstance(stmt, ast.Expr) and isinstance(stmt.value, ast.Call): - if isinstance(stmt.value.func, ast.Attribute): - if (isinstance(stmt.value.func.value, ast.Name) and - stmt.value.func.value.id == 'c' and - stmt.value.func.attr == 'NoBreak'): - return True - if getattr(stmt, 'body', None) and isinstance(stmt.body, list): - if _HasNoBreak(stmt.body): - return True - if getattr(stmt, 'orelse', None): - if isinstance(stmt.orelse, list) and _HasNoBreak(stmt.orelse): - return True - return False - HasNoBreak.append(_HasNoBreak(case.body) if case.body else False) - if not HasDefault: - CaseBBs.append(DefaultBB) - SwitchCases = [(val, bb) for val, bb in zip(CaseValues, CaseBBs) if bb != DefaultBB] - switch_instr = Gen.builder.switch(SubjectVal, DefaultBB) - for val, bb in SwitchCases: - switch_instr.add_case(val, bb) - CaseIdx = 0 - for i, case in enumerate(Node.cases): - pattern = case.pattern - if isinstance(pattern, ast.MatchOr): - NumSubCases = len(pattern.patterns) - for j in range(NumSubCases): - if CaseIdx < len(CaseBBs) and CaseBBs[CaseIdx] != DefaultBB: - Gen.builder.position_at_start(CaseBBs[CaseIdx]) - self.HandleBodyLlvm(case.body) - if not Gen.builder.block.is_terminated: - if not HasNoBreak[i]: - Gen.builder.branch(AfterBB) - CaseIdx += 1 - elif isinstance(pattern, (ast.MatchValue, ast.MatchSingleton)): - if CaseIdx < len(CaseBBs) and CaseBBs[CaseIdx] != DefaultBB: - Gen.builder.position_at_start(CaseBBs[CaseIdx]) - self.HandleBodyLlvm(case.body) - if not Gen.builder.block.is_terminated: - if not HasNoBreak[i]: - Gen.builder.branch(AfterBB) - CaseIdx += 1 - elif isinstance(pattern, ast.MatchAs): - if pattern.pattern is None: - Gen.builder.position_at_start(DefaultBB) - self.HandleBodyLlvm(case.body) - if not Gen.builder.block.is_terminated: - if not HasNoBreak[i]: - Gen.builder.branch(AfterBB) - CaseIdx += 1 - elif isinstance(pattern, ast.MatchSequence): - Gen.builder.position_at_start(DefaultBB) - self.HandleBodyLlvm(case.body) - if not Gen.builder.block.is_terminated: - if not HasNoBreak[i]: - Gen.builder.branch(AfterBB) - CaseIdx += 1 - if not HasDefault: - Gen.builder.position_at_start(DefaultBB) - Gen.builder.branch(AfterBB) - elif not any(isinstance(c.pattern, ast.MatchAs) and c.pattern.pattern is None for c in Node.cases) and not any(isinstance(c.pattern, ast.MatchSequence) for c in Node.cases): - Gen.builder.position_at_start(DefaultBB) - Gen.builder.branch(AfterBB) - Gen.builder.position_at_start(AfterBB) - - def _HandleRenumMatchLlvm(self, Node, RenumName, SubjectPtr): - Gen = self.Trans.LlvmGen - if isinstance(SubjectPtr.type, ir.PointerType) and isinstance(SubjectPtr.type.pointee, ir.PointerType): - SubjectPtr = Gen._load(SubjectPtr, name="Load_match_subj") - tag_ptr = Gen.builder.gep(SubjectPtr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), 0)], name="match_tag_ptr") - TagVal = Gen._load(tag_ptr, name="match_tag_val") - DefaultBB = Gen.func.append_basic_block(name="match.default") - AfterBB = Gen.func.append_basic_block(name="match.end") - CaseBBs = [] - CaseValues = [] - CaseBindings = [] - HasDefault = False - HasNoBreak = [] - for i, case in enumerate(Node.cases): - pattern = case.pattern - bindings = [] - if isinstance(pattern, ast.MatchClass): - cls_node = pattern.cls - VariantName = None - if isinstance(cls_node, ast.Name): - VariantName = cls_node.id - elif isinstance(cls_node, ast.Attribute): - VariantName = cls_node.attr - if VariantName: - TagValue = None - if self.Trans.SymbolTable.has(VariantName): - SymInfo = self.Trans.SymbolTable[VariantName] - if SymInfo.IsEnumMember: - TagValue = SymInfo.value - if TagValue is not None: - CaseValues.append(ir.Constant(ir.IntType(32), TagValue)) - CaseBB = Gen.func.append_basic_block(name=f"match.case_{VariantName}") - CaseBBs.append(CaseBB) - NestedStructName = f"{RenumName}_{VariantName}" - if NestedStructName in Gen.structs: - members = Gen.class_members.get(NestedStructName, []) - payLoad_members = [(n, t) for n, t in members if n != '__tag'] - for j, sub_pat in enumerate(pattern.patterns): - if isinstance(sub_pat, ast.MatchAs) and sub_pat.name and j < len(payLoad_members): - bindings.append((sub_pat.name, payLoad_members[j][0], payLoad_members[j][1], j)) - CaseBindings.append(bindings) - else: - CaseValues.append(ir.Constant(ir.IntType(32), 0)) - CaseBBs.append(Gen.func.append_basic_block(name=f"match.case_{i}")) - CaseBindings.append([]) - elif isinstance(pattern, ast.MatchValue): - Val = self.HandleExprLlvm(pattern.value) - if Val: - if isinstance(Val.type, ir.IntType): - CaseVal = Val - else: - try: - CaseVal = Gen.builder.ptrtoint(Val, ir.IntType(32), name=f"case_val_{i}") - except Exception: # 回退:ptrtoint 失败时设默认值 0 - CaseVal = ir.Constant(ir.IntType(32), 0) - CaseValues.append(CaseVal) - CaseBBs.append(Gen.func.append_basic_block(name=f"match.case_{i}")) - CaseBindings.append([]) - elif isinstance(pattern, ast.MatchAs): - if pattern.pattern is None: - HasDefault = True - CaseBBs.append(DefaultBB) - CaseBindings.append([]) - elif isinstance(pattern, ast.MatchSequence): - HasDefault = True - CaseBBs.append(DefaultBB) - CaseBindings.append([]) - def _HasNoBreak(stmts): - for stmt in stmts: - if isinstance(stmt, ast.Expr) and isinstance(stmt.value, ast.Call): - if isinstance(stmt.value.func, ast.Attribute): - if (isinstance(stmt.value.func.value, ast.Name) and - stmt.value.func.value.id == 'c' and - stmt.value.func.attr == 'NoBreak'): - return True - if getattr(stmt, 'body', None) and isinstance(stmt.body, list): - if _HasNoBreak(stmt.body): - return True - if getattr(stmt, 'orelse', None): - if isinstance(stmt.orelse, list) and _HasNoBreak(stmt.orelse): - return True - return False - HasNoBreak.append(_HasNoBreak(case.body) if case.body else False) - if not HasDefault: - CaseBBs.append(DefaultBB) - SwitchCases = [(val, bb) for val, bb in zip(CaseValues, CaseBBs) if bb != DefaultBB] - switch_instr = Gen.builder.switch(TagVal, DefaultBB) - for val, bb in SwitchCases: - switch_instr.add_case(val, bb) - CaseIdx = 0 - for i, case in enumerate(Node.cases): - pattern = case.pattern - if isinstance(pattern, ast.MatchClass): - if CaseIdx < len(CaseBBs) and CaseBBs[CaseIdx] != DefaultBB: - Gen.builder.position_at_start(CaseBBs[CaseIdx]) - bindings = CaseBindings[CaseIdx] if CaseIdx < len(CaseBindings) else [] - cls_node = pattern.cls - VariantName = None - if isinstance(cls_node, ast.Name): - VariantName = cls_node.id - elif isinstance(cls_node, ast.Attribute): - VariantName = cls_node.attr - if VariantName: - NestedStructName = f"{RenumName}_{VariantName}" - if NestedStructName in Gen.structs: - NestedStructType = Gen.structs[NestedStructName] - NestedStructPtrType = ir.PointerType(NestedStructType) - variant_ptr = Gen.builder.bitcast(SubjectPtr, NestedStructPtrType, name=f"match_cast_{VariantName}") - for bind_name, member_name, member_type, member_idx in bindings: - elem_ptr = Gen.builder.gep(variant_ptr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), member_idx + 1)], name=f"match_{bind_name}") - Gen.variables[bind_name] = elem_ptr - self.HandleBodyLlvm(case.body) - for bind_name, _, _, _ in bindings: - if bind_name in Gen.variables: - del Gen.variables[bind_name] - if not Gen.builder.block.is_terminated: - if not HasNoBreak[i]: - Gen.builder.branch(AfterBB) - CaseIdx += 1 - elif isinstance(pattern, ast.MatchValue): - if CaseIdx < len(CaseBBs) and CaseBBs[CaseIdx] != DefaultBB: - Gen.builder.position_at_start(CaseBBs[CaseIdx]) - self.HandleBodyLlvm(case.body) - if not Gen.builder.block.is_terminated: - if not HasNoBreak[i]: - Gen.builder.branch(AfterBB) - CaseIdx += 1 - elif isinstance(pattern, ast.MatchAs): - if pattern.pattern is None: - Gen.builder.position_at_start(DefaultBB) - self.HandleBodyLlvm(case.body) - if not Gen.builder.block.is_terminated: - if not HasNoBreak[i]: - Gen.builder.branch(AfterBB) - CaseIdx += 1 - elif isinstance(pattern, ast.MatchSequence): - Gen.builder.position_at_start(DefaultBB) - self.HandleBodyLlvm(case.body) - if not Gen.builder.block.is_terminated: - if not HasNoBreak[i]: - Gen.builder.branch(AfterBB) - CaseIdx += 1 - if not HasDefault: - Gen.builder.position_at_start(DefaultBB) - Gen.builder.branch(AfterBB) - elif not any(isinstance(c.pattern, ast.MatchAs) and c.pattern.pattern is None for c in Node.cases) and not any(isinstance(c.pattern, ast.MatchSequence) for c in Node.cases): - Gen.builder.position_at_start(DefaultBB) - Gen.builder.branch(AfterBB) - Gen.builder.position_at_start(AfterBB) +from __future__ import annotations +from typing import TYPE_CHECKING +if TYPE_CHECKING: + from lib.core.translator import Translator +from lib.core.Handles.HandlesBase import BaseHandle +import ast +import llvmlite.ir as ir + + +class MatchHandle(BaseHandle): + def _HandleMatchLlvm(self, Node: ast.Match) -> None: + Gen: "Translator.LlvmGen" = self.Trans.LlvmGen + SubjectVal: ir.Value | None = self.HandleExprLlvm(Node.subject) + if not SubjectVal: + return + + IsRenumMatch: bool = False + RenumName: str | None = None + SubjectPtr: ir.Value | None = None + if isinstance(Node.subject, ast.Name): + VarName: str = Node.subject.id + TypeInfo: "SymbolTable.SymbolInfo | None" = self.Trans.SymbolTable.lookup(VarName) + if TypeInfo and TypeInfo.IsRenum: + IsRenumMatch = True + RenumName = TypeInfo.Name + SubjectPtr = Gen._loadVar(VarName) + + if not IsRenumMatch: + for case in Node.cases: + if isinstance(case.pattern, ast.MatchClass): + cls_node: ast.expr = case.pattern.cls + VariantName: str | None = None + if isinstance(cls_node, ast.Name): + VariantName = cls_node.id + elif isinstance(cls_node, ast.Attribute): + VariantName = cls_node.attr + if VariantName: + SymInfo: "SymbolTable.SymbolInfo" = self.Trans.SymbolTable.lookup(VariantName) + if SymInfo and SymInfo.IsEnumMember and SymInfo.EnumName: + EnumName: str = SymInfo.EnumName + EnumInfo: "SymbolTable.SymbolInfo" = self.Trans.SymbolTable.lookup(EnumName) + if EnumInfo and EnumInfo.IsRenum: + IsRenumMatch = True + RenumName = EnumName + if SubjectPtr is None: + SubjectPtr = self.HandleExprLlvm(Node.subject) + break + + if IsRenumMatch and SubjectPtr: + self._HandleRenumMatchLlvm(Node, RenumName, SubjectPtr) + return + + if not isinstance(SubjectVal.type, ir.IntType): + try: + SubjectVal = Gen.builder.ptrtoint(SubjectVal, ir.IntType(64), name="match_subj") + SubjectVal = Gen.builder.trunc(SubjectVal, ir.IntType(32), name="match_subj_i32") + except Exception: # 回退:ptrtoint 失败时直接返回 + return + SwitchIntType: ir.IntType = SubjectVal.type + DefaultBB: ir.Block = Gen.func.append_basic_block(name="match.default") + AfterBB: ir.Block = Gen.func.append_basic_block(name="match.end") + CaseBBs: list[ir.Block] = [] + CaseValues: list[ir.Value] = [] + HasDefault: bool = False + HasNoBreak: list[bool] = [] + for i, case in enumerate(Node.cases): + pattern: ast.pattern = case.pattern + if isinstance(pattern, ast.MatchValue): + Val: ir.Value | None = self.HandleExprLlvm(pattern.value) + if Val: + CaseVal: ir.Value + if isinstance(Val.type, ir.IntType): + if Val.type != SwitchIntType: + if Val.type.width > SwitchIntType.width: + CaseVal = ir.Constant(SwitchIntType, Val.constant & ((1 << SwitchIntType.width) - 1)) + else: + CaseVal = ir.Constant(SwitchIntType, Val.constant) + else: + CaseVal = Val + else: + try: + CaseVal = Gen.builder.ptrtoint(Val, SwitchIntType, name=f"case_val_{i}") + except Exception: # 回退:ptrtoint 失败时设默认值 0 + CaseVal = ir.Constant(SwitchIntType, 0) + CaseValues.append(CaseVal) + CaseBBs.append(Gen.func.append_basic_block(name=f"match.case_{i}")) + elif isinstance(pattern, ast.MatchOr): + for j, SubPattern in enumerate(pattern.patterns): + if isinstance(SubPattern, ast.MatchValue): + Val: ir.Value | None = self.HandleExprLlvm(SubPattern.value) + if Val: + CaseVal: ir.Value + if isinstance(Val.type, ir.IntType): + if Val.type != SwitchIntType: + if Val.type.width > SwitchIntType.width: + CaseVal = ir.Constant(SwitchIntType, Val.constant & ((1 << SwitchIntType.width) - 1)) + else: + CaseVal = ir.Constant(SwitchIntType, Val.constant) + else: + CaseVal = Val + else: + try: + CaseVal = Gen.builder.ptrtoint(Val, SwitchIntType, name=f"case_val_{i}_{j}") + except Exception: # 回退:ptrtoint 失败时设默认值 0 + CaseVal = ir.Constant(SwitchIntType, 0) + CaseValues.append(CaseVal) + CaseBBs.append(Gen.func.append_basic_block(name=f"match.case_{i}_{j}")) + elif isinstance(pattern, ast.MatchSingleton): + if pattern.value is None: + CaseValues.append(ir.Constant(SwitchIntType, 0)) + CaseBBs.append(Gen.func.append_basic_block(name=f"match.case_{i}")) + elif isinstance(pattern, ast.MatchAs): + if pattern.pattern is None: + HasDefault = True + CaseBBs.append(DefaultBB) + elif isinstance(pattern, ast.MatchSequence): + HasDefault = True + CaseBBs.append(DefaultBB) + def _HasNoBreak(stmts: list[ast.stmt]) -> bool: + for stmt in stmts: + if isinstance(stmt, ast.Expr) and isinstance(stmt.value, ast.Call): + if isinstance(stmt.value.func, ast.Attribute): + if (isinstance(stmt.value.func.value, ast.Name) and + stmt.value.func.value.id == 'c' and + stmt.value.func.attr == 'NoBreak'): + return True + if getattr(stmt, 'body', None) and isinstance(stmt.body, list): + if _HasNoBreak(stmt.body): + return True + if getattr(stmt, 'orelse', None): + if isinstance(stmt.orelse, list) and _HasNoBreak(stmt.orelse): + return True + return False + HasNoBreak.append(_HasNoBreak(case.body) if case.body else False) + if not HasDefault: + CaseBBs.append(DefaultBB) + SwitchCases: list[tuple[ir.Value, ir.Block]] = [(val, bb) for val, bb in zip(CaseValues, CaseBBs) if bb != DefaultBB] + switch_instr: ir.SwitchInstr = Gen.builder.switch(SubjectVal, DefaultBB) + for val, bb in SwitchCases: + switch_instr.add_case(val, bb) + CaseIdx: int = 0 + for i, case in enumerate(Node.cases): + pattern: ast.pattern = case.pattern + if isinstance(pattern, ast.MatchOr): + NumSubCases: int = len(pattern.patterns) + for j in range(NumSubCases): + if CaseIdx < len(CaseBBs) and CaseBBs[CaseIdx] != DefaultBB: + Gen.builder.position_at_start(CaseBBs[CaseIdx]) + self.HandleBodyLlvm(case.body) + if not Gen.builder.block.is_terminated: + if not HasNoBreak[i]: + Gen.builder.branch(AfterBB) + CaseIdx += 1 + elif isinstance(pattern, (ast.MatchValue, ast.MatchSingleton)): + if CaseIdx < len(CaseBBs) and CaseBBs[CaseIdx] != DefaultBB: + Gen.builder.position_at_start(CaseBBs[CaseIdx]) + self.HandleBodyLlvm(case.body) + if not Gen.builder.block.is_terminated: + if not HasNoBreak[i]: + Gen.builder.branch(AfterBB) + CaseIdx += 1 + elif isinstance(pattern, ast.MatchAs): + if pattern.pattern is None: + Gen.builder.position_at_start(DefaultBB) + self.HandleBodyLlvm(case.body) + if not Gen.builder.block.is_terminated: + if not HasNoBreak[i]: + Gen.builder.branch(AfterBB) + CaseIdx += 1 + elif isinstance(pattern, ast.MatchSequence): + Gen.builder.position_at_start(DefaultBB) + self.HandleBodyLlvm(case.body) + if not Gen.builder.block.is_terminated: + if not HasNoBreak[i]: + Gen.builder.branch(AfterBB) + CaseIdx += 1 + if not HasDefault: + Gen.builder.position_at_start(DefaultBB) + Gen.builder.branch(AfterBB) + elif not any(isinstance(c.pattern, ast.MatchAs) and c.pattern.pattern is None for c in Node.cases) and not any(isinstance(c.pattern, ast.MatchSequence) for c in Node.cases): + Gen.builder.position_at_start(DefaultBB) + Gen.builder.branch(AfterBB) + Gen.builder.position_at_start(AfterBB) + + def _HandleRenumMatchLlvm(self, Node: ast.Match, RenumName: str, SubjectPtr: ir.Value) -> None: + Gen: "Translator.LlvmGen" = self.Trans.LlvmGen + if isinstance(SubjectPtr.type, ir.PointerType) and isinstance(SubjectPtr.type.pointee, ir.PointerType): + SubjectPtr = Gen._load(SubjectPtr, name="Load_match_subj") + tag_ptr: ir.Value = Gen.builder.gep(SubjectPtr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), 0)], name="match_tag_ptr") + TagVal: ir.Value = Gen._load(tag_ptr, name="match_tag_val") + DefaultBB: ir.Block = Gen.func.append_basic_block(name="match.default") + AfterBB: ir.Block = Gen.func.append_basic_block(name="match.end") + CaseBBs: list[ir.Block] = [] + CaseValues: list[ir.Value] = [] + CaseBindings: list[list[tuple[str, str, ir.Type, int]]] = [] + HasDefault: bool = False + HasNoBreak: list[bool] = [] + for i, case in enumerate(Node.cases): + pattern: ast.pattern = case.pattern + bindings: list[tuple[str, str, ir.Type, int]] = [] + if isinstance(pattern, ast.MatchClass): + cls_node: ast.expr = pattern.cls + VariantName: str | None = None + if isinstance(cls_node, ast.Name): + VariantName = cls_node.id + elif isinstance(cls_node, ast.Attribute): + VariantName = cls_node.attr + if VariantName: + TagValue: int | None = None + SymInfo: "SymbolTable.SymbolInfo" = self.Trans.SymbolTable.lookup(VariantName) + if SymInfo: + if SymInfo.IsEnumMember: + TagValue = SymInfo.value + if TagValue is not None: + CaseValues.append(ir.Constant(ir.IntType(32), TagValue)) + CaseBB: ir.Block = Gen.func.append_basic_block(name=f"match.case_{VariantName}") + CaseBBs.append(CaseBB) + NestedStructName: str = f"{RenumName}_{VariantName}" + if NestedStructName in Gen.structs: + members: list[tuple[str, ir.Type]] = Gen.class_members.get(NestedStructName, []) + payLoad_members: list[tuple[str, ir.Type]] = [(n, t) for n, t in members if n != '__tag'] + for j, sub_pat in enumerate(pattern.patterns): + if isinstance(sub_pat, ast.MatchAs) and sub_pat.name and j < len(payLoad_members): + bindings.append((sub_pat.name, payLoad_members[j][0], payLoad_members[j][1], j)) + CaseBindings.append(bindings) + else: + CaseValues.append(ir.Constant(ir.IntType(32), 0)) + CaseBBs.append(Gen.func.append_basic_block(name=f"match.case_{i}")) + CaseBindings.append([]) + elif isinstance(pattern, ast.MatchValue): + Val: ir.Value | None = self.HandleExprLlvm(pattern.value) + if Val: + CaseVal: ir.Value + if isinstance(Val.type, ir.IntType): + CaseVal = Val + else: + try: + CaseVal = Gen.builder.ptrtoint(Val, ir.IntType(32), name=f"case_val_{i}") + except Exception: # 回退:ptrtoint 失败时设默认值 0 + CaseVal = ir.Constant(ir.IntType(32), 0) + CaseValues.append(CaseVal) + CaseBBs.append(Gen.func.append_basic_block(name=f"match.case_{i}")) + CaseBindings.append([]) + elif isinstance(pattern, ast.MatchAs): + if pattern.pattern is None: + HasDefault = True + CaseBBs.append(DefaultBB) + CaseBindings.append([]) + elif isinstance(pattern, ast.MatchSequence): + HasDefault = True + CaseBBs.append(DefaultBB) + CaseBindings.append([]) + def _HasNoBreak(stmts: list[ast.stmt]) -> bool: + for stmt in stmts: + if isinstance(stmt, ast.Expr) and isinstance(stmt.value, ast.Call): + if isinstance(stmt.value.func, ast.Attribute): + if (isinstance(stmt.value.func.value, ast.Name) and + stmt.value.func.value.id == 'c' and + stmt.value.func.attr == 'NoBreak'): + return True + if getattr(stmt, 'body', None) and isinstance(stmt.body, list): + if _HasNoBreak(stmt.body): + return True + if getattr(stmt, 'orelse', None): + if isinstance(stmt.orelse, list) and _HasNoBreak(stmt.orelse): + return True + return False + HasNoBreak.append(_HasNoBreak(case.body) if case.body else False) + if not HasDefault: + CaseBBs.append(DefaultBB) + SwitchCases: list[tuple[ir.Value, ir.Block]] = [(val, bb) for val, bb in zip(CaseValues, CaseBBs) if bb != DefaultBB] + switch_instr: ir.SwitchInstr = Gen.builder.switch(TagVal, DefaultBB) + for val, bb in SwitchCases: + switch_instr.add_case(val, bb) + CaseIdx: int = 0 + for i, case in enumerate(Node.cases): + pattern: ast.pattern = case.pattern + if isinstance(pattern, ast.MatchClass): + if CaseIdx < len(CaseBBs) and CaseBBs[CaseIdx] != DefaultBB: + Gen.builder.position_at_start(CaseBBs[CaseIdx]) + bindings: list[tuple[str, str, ir.Type, int]] = CaseBindings[CaseIdx] if CaseIdx < len(CaseBindings) else [] + cls_node: ast.expr = pattern.cls + VariantName: str | None = None + if isinstance(cls_node, ast.Name): + VariantName = cls_node.id + elif isinstance(cls_node, ast.Attribute): + VariantName = cls_node.attr + if VariantName: + NestedStructName: str = f"{RenumName}_{VariantName}" + if NestedStructName in Gen.structs: + NestedStructType: ir.Type = Gen.structs[NestedStructName] + NestedStructPtrType: ir.PointerType = ir.PointerType(NestedStructType) + variant_ptr: ir.Value = Gen.builder.bitcast(SubjectPtr, NestedStructPtrType, name=f"match_cast_{VariantName}") + for bind_name, member_name, member_type, member_idx in bindings: + elem_ptr: ir.Value = Gen.builder.gep(variant_ptr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), member_idx + 1)], name=f"match_{bind_name}") + Gen.variables[bind_name] = elem_ptr + self.HandleBodyLlvm(case.body) + for bind_name, _, _, _ in bindings: + if bind_name in Gen.variables: + del Gen.variables[bind_name] + if not Gen.builder.block.is_terminated: + if not HasNoBreak[i]: + Gen.builder.branch(AfterBB) + CaseIdx += 1 + elif isinstance(pattern, ast.MatchValue): + if CaseIdx < len(CaseBBs) and CaseBBs[CaseIdx] != DefaultBB: + Gen.builder.position_at_start(CaseBBs[CaseIdx]) + self.HandleBodyLlvm(case.body) + if not Gen.builder.block.is_terminated: + if not HasNoBreak[i]: + Gen.builder.branch(AfterBB) + CaseIdx += 1 + elif isinstance(pattern, ast.MatchAs): + if pattern.pattern is None: + Gen.builder.position_at_start(DefaultBB) + self.HandleBodyLlvm(case.body) + if not Gen.builder.block.is_terminated: + if not HasNoBreak[i]: + Gen.builder.branch(AfterBB) + CaseIdx += 1 + elif isinstance(pattern, ast.MatchSequence): + Gen.builder.position_at_start(DefaultBB) + self.HandleBodyLlvm(case.body) + if not Gen.builder.block.is_terminated: + if not HasNoBreak[i]: + Gen.builder.branch(AfterBB) + CaseIdx += 1 + if not HasDefault: + Gen.builder.position_at_start(DefaultBB) + Gen.builder.branch(AfterBB) + elif not any(isinstance(c.pattern, ast.MatchAs) and c.pattern.pattern is None for c in Node.cases) and not any(isinstance(c.pattern, ast.MatchSequence) for c in Node.cases): + Gen.builder.position_at_start(DefaultBB) + Gen.builder.branch(AfterBB) + Gen.builder.position_at_start(AfterBB) \ No newline at end of file diff --git a/lib/core/Handles/HandlesRaise.py b/lib/core/Handles/HandlesRaise.py index b48ad65..f167d88 100644 --- a/lib/core/Handles/HandlesRaise.py +++ b/lib/core/Handles/HandlesRaise.py @@ -1,135 +1,143 @@ -from __future__ import annotations -from typing import TYPE_CHECKING -if TYPE_CHECKING: - from lib.core.translator import Translator -from lib.core.Handles.HandlesBase import BaseHandle, EXCEPTION_CODE_MAP -import ast -import llvmlite.ir as ir - - -class RaiseHandle(BaseHandle): - def _get_exception_code(self, ExcName): - if ExcName in EXCEPTION_CODE_MAP: - return EXCEPTION_CODE_MAP[ExcName] - if ExcName in self.Trans.exception_registry: - return self.Trans.exception_registry[ExcName] - return 1 - - def _HandleRaiseLlvm(self, Node): - Gen = self.Trans.LlvmGen - exc_val = ir.Constant(ir.IntType(32), 1) - exc_msg = None - IsStopIteration = False - if Node.exc: - if isinstance(Node.exc, ast.Constant) and isinstance(Node.exc.value, int): - exc_val = ir.Constant(ir.IntType(32), Node.exc.value) - elif isinstance(Node.exc, ast.Name): - ExcName = Node.exc.id - if ExcName == 'StopIteration': - IsStopIteration = True - exc_val = ir.Constant(ir.IntType(32), self._get_exception_code(ExcName)) - elif isinstance(Node.exc, ast.Call) and isinstance(Node.exc.func, ast.Name): - ExcName = Node.exc.func.id - if ExcName == 'StopIteration': - IsStopIteration = True - exc_val = ir.Constant(ir.IntType(32), self._get_exception_code(ExcName)) - if Node.exc.args: - first_arg = Node.exc.args[0] - if isinstance(first_arg, ast.Constant) and isinstance(first_arg.value, str): - exc_msg = self.HandleExprLlvm(first_arg) - elif isinstance(first_arg, (ast.Name, ast.Call, ast.Attribute)): - arg_val = self.HandleExprLlvm(first_arg) - if arg_val: - if isinstance(arg_val.type, ir.PointerType): - if self._is_char_pointer(arg_val): - exc_msg = arg_val - else: - try: - exc_msg = Gen.builder.bitcast(arg_val, ir.PointerType(ir.IntType(8)), name="exc_msg_cast") - except Exception as _e: - if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": - self.Trans.LogWarning(f"异常被忽略: {_e}") - else: - try: - exc_msg = Gen.builder.inttoptr(arg_val, ir.PointerType(ir.IntType(8)), name="exc_msg_ptr") - except Exception as _e: - if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": - self.Trans.LogWarning(f"异常被忽略: {_e}") - else: - val = self.HandleExprLlvm(Node.exc) - if val: - if isinstance(val.type, ir.IntType): - if val.type.width != 32: - try: - val = Gen.builder.trunc(val, ir.IntType(32), name="exc_trunc") - except Exception: # 回退:trunc 失败时设默认值 1 - val = ir.Constant(ir.IntType(32), 1) - exc_val = val - else: - try: - val = Gen.builder.ptrtoint(val, ir.IntType(32), name="exc_ptr2int") - exc_val = val - except Exception as _e: - if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": - self.Trans.LogWarning(f"异常被忽略: {_e}") - if IsStopIteration: - if Gen._stop_iter_flag_param is not None: - Gen.builder.store(ir.Constant(ir.IntType(1), 1), Gen._stop_iter_flag_param) - if Gen.func and Gen.func.type.pointee.return_type != ir.VoidType(): - ret_type = Gen.func.type.pointee.return_type - Gen.builder.ret(ir.Constant(ret_type, 0)) - else: - Gen.builder.ret_void() - return - if Gen.eh_except_block_stack: - ExceptBB, EndBB, exception_code, eh_message = Gen.eh_except_block_stack[-1] - Gen._store(exc_val, exception_code) - if exc_msg: - Gen._store(exc_msg, eh_message) - else: - null_ptr = ir.Constant(ir.PointerType(ir.IntType(8)), None) - Gen._store(null_ptr, eh_message) - if Gen.func and ExceptBB and ExceptBB.function is Gen.func: - Gen.builder.branch(ExceptBB) - else: - eh_msg_arg = None - eh_code_arg = None - if Gen.func: - for arg in Gen.func.args: - if arg.name == '__eh_msg_out__': - eh_msg_arg = arg - elif arg.name == '__eh_code_out__': - eh_code_arg = arg - if eh_msg_arg is not None: - if exc_msg: - Gen.builder.store(exc_msg, eh_msg_arg) - else: - null_ptr = ir.Constant(ir.PointerType(ir.IntType(8)), None) - Gen.builder.store(null_ptr, eh_msg_arg) - if eh_code_arg is not None: - Gen.builder.store(exc_val, eh_code_arg) - if Gen.func and Gen.func.type.pointee.return_type == ir.IntType(32): - Gen.builder.ret(ir.Constant(ir.IntType(32), 1)) - else: - Gen.builder.ret_void() - else: - eh_msg_arg = None - eh_code_arg = None - if Gen.func: - for arg in Gen.func.args: - if arg.name == '__eh_msg_out__': - eh_msg_arg = arg - elif arg.name == '__eh_code_out__': - eh_code_arg = arg - if eh_msg_arg is not None: - if exc_msg: - Gen.builder.store(exc_msg, eh_msg_arg) - else: - null_ptr = ir.Constant(ir.PointerType(ir.IntType(8)), None) - Gen.builder.store(null_ptr, eh_msg_arg) - if eh_code_arg is not None: - Gen.builder.store(exc_val, eh_code_arg) - if Gen.func and Gen.func.type.pointee.return_type == ir.IntType(32): - Gen.builder.ret(ir.Constant(ir.IntType(32), 1)) - else: +from __future__ import annotations +from typing import TYPE_CHECKING +if TYPE_CHECKING: + from lib.core.translator import Translator +import ast +import llvmlite.ir as ir +from lib.core.Handles.HandlesBase import BaseHandle, EXCEPTION_CODE_MAP +from lib.constants.config import mode as _config_mode + + +class RaiseHandle(BaseHandle): + def _get_exception_code(self, ExcName: str) -> int: + if ExcName in EXCEPTION_CODE_MAP: + return EXCEPTION_CODE_MAP[ExcName] + if ExcName in self.Trans.exception_registry: + return self.Trans.exception_registry[ExcName] + return 1 + + def _HandleRaiseLlvm(self, Node: ast.Raise) -> None: + Gen: "Translator.LlvmGen" = self.Trans.LlvmGen + exc_val: ir.Constant = ir.Constant(ir.IntType(32), 1) + exc_msg: ir.Value | None = None + IsStopIteration: bool = False + if Node.exc: + if isinstance(Node.exc, ast.Constant) and isinstance(Node.exc.value, int): + exc_val = ir.Constant(ir.IntType(32), Node.exc.value) + elif isinstance(Node.exc, ast.Name): + ExcName: str = Node.exc.id + if ExcName == 'StopIteration': + IsStopIteration = True + exc_val = ir.Constant(ir.IntType(32), self._get_exception_code(ExcName)) + elif isinstance(Node.exc, ast.Call) and isinstance(Node.exc.func, ast.Name): + ExcName: str = Node.exc.func.id + if ExcName == 'StopIteration': + IsStopIteration = True + exc_val = ir.Constant(ir.IntType(32), self._get_exception_code(ExcName)) + if Node.exc.args: + first_arg: ast.expr = Node.exc.args[0] + if isinstance(first_arg, ast.Constant) and isinstance(first_arg.value, str): + exc_msg = self.HandleExprLlvm(first_arg) + elif isinstance(first_arg, (ast.Name, ast.Call, ast.Attribute)): + arg_val: ir.Value | None = self.HandleExprLlvm(first_arg) + if arg_val: + if isinstance(arg_val.type, ir.PointerType): + if self._is_char_pointer(arg_val): + exc_msg = arg_val + else: + try: + exc_msg = Gen.builder.bitcast(arg_val, ir.PointerType(ir.IntType(8)), name="exc_msg_cast") + except Exception as _e: + if _config_mode == "strict": + self.Trans.LogWarning(f"异常被忽略: {_e}") + else: + try: + exc_msg = Gen.builder.inttoptr(arg_val, ir.PointerType(ir.IntType(8)), name="exc_msg_ptr") + except Exception as _e: + if _config_mode == "strict": + self.Trans.LogWarning(f"异常被忽略: {_e}") + else: + val: ir.Value | None = self.HandleExprLlvm(Node.exc) + if val: + if isinstance(val.type, ir.IntType): + if val.type.width != 32: + try: + val = Gen.builder.trunc(val, ir.IntType(32), name="exc_trunc") + except Exception: # 回退:trunc 失败时设默认值 1 + val = ir.Constant(ir.IntType(32), 1) + exc_val = val + else: + try: + val = Gen.builder.ptrtoint(val, ir.IntType(32), name="exc_ptr2int") + exc_val = val + except Exception as _e: + if _config_mode == "strict": + self.Trans.LogWarning(f"异常被忽略: {_e}") + if IsStopIteration: + if Gen._stop_iter_flag_param is not None: + Gen.builder.store(ir.Constant(ir.IntType(1), 1), Gen._stop_iter_flag_param) + if Gen.func and Gen.func.type.pointee.return_type != ir.VoidType(): + ret_type: ir.Type = Gen.func.type.pointee.return_type + # 指针类型用 null,整数类型用 0 + if isinstance(ret_type, ir.PointerType): + Gen.builder.ret(ir.Constant(ret_type, None)) + else: + Gen.builder.ret(ir.Constant(ret_type, 0)) + else: + Gen.builder.ret_void() + return + if Gen.eh_except_block_stack: + ExceptBB: ir.Block = Gen.eh_except_block_stack[-1][0] + EndBB: ir.Block | None = Gen.eh_except_block_stack[-1][1] + exception_code: ir.AllocaInstr = Gen.eh_except_block_stack[-1][2] + eh_message: ir.AllocaInstr = Gen.eh_except_block_stack[-1][3] + Gen._store(exc_val, exception_code) + if exc_msg: + Gen._store(exc_msg, eh_message) + else: + null_ptr: ir.Constant = ir.Constant(ir.PointerType(ir.IntType(8)), None) + Gen._store(null_ptr, eh_message) + if Gen.func and ExceptBB and ExceptBB.function is Gen.func: + Gen.builder.branch(ExceptBB) + else: + eh_msg_arg: ir.Argument | None = None + eh_code_arg: ir.Argument | None = None + if Gen.func: + for arg in Gen.func.args: + if arg.name == '__eh_msg_out__': + eh_msg_arg = arg + elif arg.name == '__eh_code_out__': + eh_code_arg = arg + if eh_msg_arg is not None: + if exc_msg: + Gen.builder.store(exc_msg, eh_msg_arg) + else: + null_ptr = ir.Constant(ir.PointerType(ir.IntType(8)), None) + Gen.builder.store(null_ptr, eh_msg_arg) + if eh_code_arg is not None: + Gen.builder.store(exc_val, eh_code_arg) + if Gen.func and Gen.func.type.pointee.return_type == ir.IntType(32): + Gen.builder.ret(ir.Constant(ir.IntType(32), 1)) + else: + Gen.builder.ret_void() + else: + eh_msg_arg: ir.Argument | None = None + eh_code_arg: ir.Argument | None = None + if Gen.func: + for arg in Gen.func.args: + if arg.name == '__eh_msg_out__': + eh_msg_arg = arg + elif arg.name == '__eh_code_out__': + eh_code_arg = arg + if eh_msg_arg is not None: + if exc_msg: + Gen.builder.store(exc_msg, eh_msg_arg) + else: + null_ptr: ir.Constant = ir.Constant(ir.PointerType(ir.IntType(8)), None) + Gen.builder.store(null_ptr, eh_msg_arg) + if eh_code_arg is not None: + Gen.builder.store(exc_val, eh_code_arg) + if Gen.func and Gen.func.type.pointee.return_type == ir.IntType(32): + Gen.builder.ret(ir.Constant(ir.IntType(32), 1)) + else: Gen.builder.ret_void() \ No newline at end of file diff --git a/lib/core/Handles/HandlesReturn.py b/lib/core/Handles/HandlesReturn.py index 95b76ff..3bde22d 100644 --- a/lib/core/Handles/HandlesReturn.py +++ b/lib/core/Handles/HandlesReturn.py @@ -1,155 +1,165 @@ -from __future__ import annotations -from typing import TYPE_CHECKING -if TYPE_CHECKING: - from lib.core.translator import Translator -from lib.core.Handles.HandlesBase import BaseHandle, CTypeInfo, CTypeHelper -import ast -import llvmlite.ir as ir - - -class ReturnHandle(BaseHandle): - def _find_active_finally(self, Gen): - for item in reversed(Gen.eh_finally_stack): - if item is not None and item[0] is not None: - return item - return None - - def _HandleReturnLlvm(self, Node): - Gen = self.Trans.LlvmGen - active_finally = self._find_active_finally(Gen) - if getattr(self.Trans, 'CurrentCReturnTypes', None) and self.Trans.CurrentCReturnTypes and Node.value: - return_values = [] - if isinstance(Node.value, ast.Tuple): - return_values = Node.value.elts - else: - return_values = [Node.value] - if len(return_values) == len(self.Trans.CurrentCReturnTypes): - llvm_vals = [] - expected_types = [] - for i, val in enumerate(return_values): - ReturnTypeInfo = CTypeInfo.FromNode(self.Trans.CurrentCReturnTypes[i], self.Trans.SymbolTable) - IsRetPtr = ReturnTypeInfo.IsPtr if ReturnTypeInfo else False - if (isinstance(ReturnTypeInfo, CTypeInfo) and ReturnTypeInfo.IsStr) or (isinstance(self.Trans.CurrentCReturnTypes[i], ast.Name) and self.Trans.CurrentCReturnTypes[i].id == 'str'): - IsRetPtr = True - ExpectedType = ReturnTypeInfo.ToLLVM(Gen) if ReturnTypeInfo and ReturnTypeInfo.BaseType else Gen._CType2LLVM('int', IsRetPtr) - expected_types.append(ExpectedType) - Val = self.HandleExprLlvm(val) - if Val is None: - if isinstance(ExpectedType, ir.PointerType): - Val = ir.Constant(ExpectedType, None) - elif isinstance(ExpectedType, ir.IntType): - Val = ir.Constant(ExpectedType, 0) - else: - Val = ir.Constant(ExpectedType, ir.Undefined) - else: - if Val.type != ExpectedType: - if isinstance(ExpectedType, ir.IntType) and isinstance(Val.type, ir.IntType): - if Val.type.width < ExpectedType.width: - Val = Gen.builder.zext(Val, ExpectedType, name=f"zext_ret_{i}") - elif Val.type.width > ExpectedType.width: - Val = Gen.builder.trunc(Val, ExpectedType, name=f"trunc_ret_{i}") - elif isinstance(ExpectedType, ir.PointerType) and isinstance(Val.type, ir.PointerType): - Val = Gen.builder.bitcast(Val, ExpectedType, name=f"cast_ret_{i}") - llvm_vals.append(Val) - if llvm_vals: - struct_type = ir.LiteralStructType(expected_types) - result = ir.Constant(struct_type, ir.Undefined) - for i, val in enumerate(llvm_vals): - result = Gen.builder.insert_value(result, val, i, name=f"ret_field_{i}") - if active_finally: - FinallyBB, pending_ret_flag, pending_ret_val = active_finally - if pending_ret_val: - Gen._store(result, pending_ret_val) - Gen._store(ir.Constant(ir.IntType(32), 1), pending_ret_flag) - Gen.builder.branch(FinallyBB) - else: - Gen.emit_return(result) - return - if Node.value: - Val = self.HandleExprLlvm(Node.value) - if Val: - ret_type = getattr(Gen.func, 'ftype', None) and Gen.func.ftype.return_type if getattr(Gen, 'func', None) else None - if isinstance(ret_type, ir.IdentifiedStructType) and isinstance(Val, ir.Constant) and isinstance(Val.type, ir.PointerType) and Val.constant is None: - if ret_type.elements: - zero_val = ir.Constant(ret_type, [ - ir.Constant(et, None) if isinstance(et, (ir.PointerType, ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)) - else ir.Constant(et, 0) if isinstance(et, (ir.IntType, ir.FloatType, ir.DoubleType)) - else ir.Constant(et, ir.Undefined) for et in ret_type.elements]) - else: - zero_val = ir.Constant(ret_type, None) - if active_finally: - FinallyBB, pending_ret_flag, pending_ret_val = active_finally - if pending_ret_val: - Gen._store(zero_val, pending_ret_val) - Gen._store(ir.Constant(ir.IntType(32), 1), pending_ret_flag) - Gen.builder.branch(FinallyBB) - else: - Gen.emit_return(zero_val) - return - if getattr(self.Trans, 'CurrentCReturnTypes', None) and self.Trans.CurrentCReturnTypes: - struct_type = Gen.func.ftype.return_type - if isinstance(struct_type, ir.LiteralStructType): - result = ir.Constant(struct_type, ir.Undefined) - if isinstance(Val.type, ir.PointerType) and len(struct_type.elements) > 0 and isinstance(struct_type.elements[0], ir.PointerType): - result = Gen.builder.insert_value(result, Val, 0, name="ret_field_0") - for j in range(1, len(struct_type.elements)): - elem_type = struct_type.elements[j] - zero_val = ir.Constant(elem_type, 0 if isinstance(elem_type, ir.IntType) else None) - result = Gen.builder.insert_value(result, zero_val, j, name=f"ret_field_{j}") - else: - for j, elem_type in enumerate(struct_type.elements): - if j == 0: - if Val.type == elem_type: - result = Gen.builder.insert_value(result, Val, j, name=f"ret_field_{j}") - elif isinstance(elem_type, ir.IntType) and isinstance(Val.type, ir.IntType): - if Val.type.width < elem_type.width: - Val = Gen.builder.zext(Val, elem_type, name=f"zext_ret_{j}") - elif Val.type.width > elem_type.width: - Val = Gen.builder.trunc(Val, elem_type, name=f"trunc_ret_{j}") - result = Gen.builder.insert_value(result, Val, j, name=f"ret_field_{j}") - else: - zero_val = ir.Constant(elem_type, 0 if isinstance(elem_type, ir.IntType) else None) - result = Gen.builder.insert_value(result, zero_val, j, name=f"ret_field_{j}") - else: - zero_val = ir.Constant(elem_type, 0 if isinstance(elem_type, ir.IntType) else None) - result = Gen.builder.insert_value(result, zero_val, j, name=f"ret_field_{j}") - if active_finally: - FinallyBB, pending_ret_flag, pending_ret_val = active_finally - if pending_ret_val: - Gen._store(result, pending_ret_val) - Gen._store(ir.Constant(ir.IntType(32), 1), pending_ret_flag) - Gen.builder.branch(FinallyBB) - else: - Gen.emit_return(result) - return - if active_finally: - FinallyBB, pending_ret_flag, pending_ret_val = active_finally - if pending_ret_val: - Gen._store(Val, pending_ret_val) - Gen._store(ir.Constant(ir.IntType(32), 1), pending_ret_flag) - Gen.builder.branch(FinallyBB) - else: - Gen.emit_return(Val) - else: - if active_finally: - FinallyBB, pending_ret_flag, pending_ret_val = active_finally - Gen._store(ir.Constant(ir.IntType(32), 1), pending_ret_flag) - Gen.builder.branch(FinallyBB) - else: - ret_type = getattr(Gen.func, 'ftype', None) and Gen.func.ftype.return_type if getattr(Gen, 'func', None) else None - if isinstance(ret_type, ir.IntType): - Gen.builder.ret(ir.Constant(ret_type, 0)) - elif isinstance(ret_type, ir.PointerType): - Gen.builder.ret(ir.Constant(ret_type, None)) - elif isinstance(ret_type, (ir.FloatType, ir.DoubleType)): - Gen.builder.ret(ir.Constant(ret_type, 0.0)) - elif isinstance(ret_type, ir.IdentifiedStructType): - if ret_type.elements: - zero_val = ir.Constant(ret_type, [ir.Constant(et, None) if isinstance(et, (ir.PointerType, ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)) else ir.Constant(et, 0) if isinstance(et, (ir.IntType, ir.FloatType, ir.DoubleType)) else ir.Constant(et, ir.Undefined) for et in ret_type.elements]) - else: - zero_val = ir.Constant(ret_type, None) - Gen.builder.ret(zero_val) - elif isinstance(ret_type, ir.ArrayType): - Gen.builder.ret(ir.Constant(ret_type, None)) - else: +from __future__ import annotations +from typing import TYPE_CHECKING +if TYPE_CHECKING: + from lib.core.translator import Translator +from lib.core.Handles.HandlesBase import BaseHandle, CTypeInfo, CTypeHelper +import ast +import llvmlite.ir as ir + + +class ReturnHandle(BaseHandle): + def _find_active_finally(self, Gen: "Translator.LlvmGen") -> tuple[ir.Block, ir.AllocaInstr, ir.AllocaInstr | None] | None: + for item in reversed(Gen.eh_finally_stack): + if item is not None and item[0] is not None: + return item + return None + + def _HandleReturnLlvm(self, Node: ast.Return) -> None: + Gen: "Translator.LlvmGen" = self.Trans.LlvmGen + active_finally: tuple[ir.Block, ir.AllocaInstr, ir.AllocaInstr | None] | None = self._find_active_finally(Gen) + if getattr(self.Trans, 'CurrentCReturnTypes', None) and self.Trans.CurrentCReturnTypes and Node.value: + return_values: list[ast.expr] = [] + if isinstance(Node.value, ast.Tuple): + return_values = Node.value.elts + else: + return_values = [Node.value] + if len(return_values) == len(self.Trans.CurrentCReturnTypes): + llvm_vals: list[ir.Value] = [] + expected_types: list[ir.Type] = [] + for i, val in enumerate(return_values): + ReturnTypeInfo: CTypeInfo | None = CTypeInfo.FromNode(self.Trans.CurrentCReturnTypes[i], self.Trans.SymbolTable) + IsRetPtr: bool = ReturnTypeInfo.IsPtr if ReturnTypeInfo else False + if (isinstance(ReturnTypeInfo, CTypeInfo) and ReturnTypeInfo.IsStr) or (isinstance(self.Trans.CurrentCReturnTypes[i], ast.Name) and self.Trans.CurrentCReturnTypes[i].id == 'str'): + IsRetPtr = True + ExpectedType: ir.Type = ReturnTypeInfo.ToLLVM(Gen) if ReturnTypeInfo and ReturnTypeInfo.BaseType else Gen._CType2LLVM('int', IsRetPtr) + expected_types.append(ExpectedType) + Val: ir.Value | None = self.HandleExprLlvm(val) + if Val is None: + if isinstance(ExpectedType, ir.PointerType): + Val = ir.Constant(ExpectedType, None) + elif isinstance(ExpectedType, ir.IntType): + Val = ir.Constant(ExpectedType, 0) + else: + Val = ir.Constant(ExpectedType, ir.Undefined) + else: + if Val.type != ExpectedType: + if isinstance(ExpectedType, ir.IntType) and isinstance(Val.type, ir.IntType): + if Val.type.width < ExpectedType.width: + Val = Gen.builder.zext(Val, ExpectedType, name=f"zext_ret_{i}") + elif Val.type.width > ExpectedType.width: + Val = Gen.builder.trunc(Val, ExpectedType, name=f"trunc_ret_{i}") + elif isinstance(ExpectedType, ir.PointerType) and isinstance(Val.type, ir.PointerType): + Val = Gen.builder.bitcast(Val, ExpectedType, name=f"cast_ret_{i}") + llvm_vals.append(Val) + if llvm_vals: + struct_type: ir.LiteralStructType = ir.LiteralStructType(expected_types) + result: ir.Value = ir.Constant(struct_type, ir.Undefined) + for i, val in enumerate(llvm_vals): + result = Gen.builder.insert_value(result, val, i, name=f"ret_field_{i}") + if active_finally: + FinallyBB: ir.Block = active_finally[0] + pending_ret_flag: ir.AllocaInstr = active_finally[1] + pending_ret_val: ir.AllocaInstr | None = active_finally[2] + if pending_ret_val: + Gen._store(result, pending_ret_val) + Gen._store(ir.Constant(ir.IntType(32), 1), pending_ret_flag) + Gen.builder.branch(FinallyBB) + else: + Gen.emit_return(result) + return + if Node.value: + Val: ir.Value | None = self.HandleExprLlvm(Node.value) + if Val: + ret_type: ir.Type | None = getattr(Gen.func, 'ftype', None) and Gen.func.ftype.return_type if getattr(Gen, 'func', None) else None + if isinstance(ret_type, ir.IdentifiedStructType) and isinstance(Val, ir.Constant) and isinstance(Val.type, ir.PointerType) and Val.constant is None: + if ret_type.elements: + zero_val: ir.Constant = ir.Constant(ret_type, [ + ir.Constant(et, None) if isinstance(et, (ir.PointerType, ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)) + else ir.Constant(et, 0) if isinstance(et, (ir.IntType, ir.FloatType, ir.DoubleType)) + else ir.Constant(et, ir.Undefined) for et in ret_type.elements]) + else: + zero_val = ir.Constant(ret_type, None) + if active_finally: + FinallyBB: ir.Block = active_finally[0] + pending_ret_flag: ir.AllocaInstr = active_finally[1] + pending_ret_val: ir.AllocaInstr | None = active_finally[2] + if pending_ret_val: + Gen._store(zero_val, pending_ret_val) + Gen._store(ir.Constant(ir.IntType(32), 1), pending_ret_flag) + Gen.builder.branch(FinallyBB) + else: + Gen.emit_return(zero_val) + return + if getattr(self.Trans, 'CurrentCReturnTypes', None) and self.Trans.CurrentCReturnTypes: + struct_type: ir.Type = Gen.func.ftype.return_type + if isinstance(struct_type, ir.LiteralStructType): + result: ir.Value = ir.Constant(struct_type, ir.Undefined) + if isinstance(Val.type, ir.PointerType) and len(struct_type.elements) > 0 and isinstance(struct_type.elements[0], ir.PointerType): + result = Gen.builder.insert_value(result, Val, 0, name="ret_field_0") + for j in range(1, len(struct_type.elements)): + elem_type: ir.Type = struct_type.elements[j] + zero_val: ir.Constant = ir.Constant(elem_type, 0 if isinstance(elem_type, ir.IntType) else None) + result = Gen.builder.insert_value(result, zero_val, j, name=f"ret_field_{j}") + else: + for j, elem_type in enumerate(struct_type.elements): + if j == 0: + if Val.type == elem_type: + result = Gen.builder.insert_value(result, Val, j, name=f"ret_field_{j}") + elif isinstance(elem_type, ir.IntType) and isinstance(Val.type, ir.IntType): + if Val.type.width < elem_type.width: + Val = Gen.builder.zext(Val, elem_type, name=f"zext_ret_{j}") + elif Val.type.width > elem_type.width: + Val = Gen.builder.trunc(Val, elem_type, name=f"trunc_ret_{j}") + result = Gen.builder.insert_value(result, Val, j, name=f"ret_field_{j}") + else: + zero_val = ir.Constant(elem_type, 0 if isinstance(elem_type, ir.IntType) else None) + result = Gen.builder.insert_value(result, zero_val, j, name=f"ret_field_{j}") + else: + zero_val = ir.Constant(elem_type, 0 if isinstance(elem_type, ir.IntType) else None) + result = Gen.builder.insert_value(result, zero_val, j, name=f"ret_field_{j}") + if active_finally: + FinallyBB: ir.Block = active_finally[0] + pending_ret_flag: ir.AllocaInstr = active_finally[1] + pending_ret_val: ir.AllocaInstr | None = active_finally[2] + if pending_ret_val: + Gen._store(result, pending_ret_val) + Gen._store(ir.Constant(ir.IntType(32), 1), pending_ret_flag) + Gen.builder.branch(FinallyBB) + else: + Gen.emit_return(result) + return + if active_finally: + FinallyBB: ir.Block = active_finally[0] + pending_ret_flag: ir.AllocaInstr = active_finally[1] + pending_ret_val: ir.AllocaInstr | None = active_finally[2] + if pending_ret_val: + Gen._store(Val, pending_ret_val) + Gen._store(ir.Constant(ir.IntType(32), 1), pending_ret_flag) + Gen.builder.branch(FinallyBB) + else: + Gen.emit_return(Val) + else: + if active_finally: + FinallyBB: ir.Block = active_finally[0] + pending_ret_flag: ir.AllocaInstr = active_finally[1] + pending_ret_val: ir.AllocaInstr | None = active_finally[2] + Gen._store(ir.Constant(ir.IntType(32), 1), pending_ret_flag) + Gen.builder.branch(FinallyBB) + else: + ret_type: ir.Type | None = getattr(Gen.func, 'ftype', None) and Gen.func.ftype.return_type if getattr(Gen, 'func', None) else None + if isinstance(ret_type, ir.IntType): + Gen.builder.ret(ir.Constant(ret_type, 0)) + elif isinstance(ret_type, ir.PointerType): + Gen.builder.ret(ir.Constant(ret_type, None)) + elif isinstance(ret_type, (ir.FloatType, ir.DoubleType)): + Gen.builder.ret(ir.Constant(ret_type, 0.0)) + elif isinstance(ret_type, ir.IdentifiedStructType): + if ret_type.elements: + zero_val: ir.Constant = ir.Constant(ret_type, [ir.Constant(et, None) if isinstance(et, (ir.PointerType, ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)) else ir.Constant(et, 0) if isinstance(et, (ir.IntType, ir.FloatType, ir.DoubleType)) else ir.Constant(et, ir.Undefined) for et in ret_type.elements]) + else: + zero_val = ir.Constant(ret_type, None) + Gen.builder.ret(zero_val) + elif isinstance(ret_type, ir.ArrayType): + Gen.builder.ret(ir.Constant(ret_type, None)) + else: Gen.emit_return() \ No newline at end of file diff --git a/lib/core/Handles/HandlesSpecialCall.py b/lib/core/Handles/HandlesSpecialCall.py index 29520a1..9fe0724 100644 --- a/lib/core/Handles/HandlesSpecialCall.py +++ b/lib/core/Handles/HandlesSpecialCall.py @@ -1,17 +1,22 @@ from __future__ import annotations from typing import TYPE_CHECKING -if TYPE_CHECKING: - from lib.core.translator import Translator -from lib.core.Handles.HandlesBase import BaseHandle import ast import llvmlite.ir as ir +if TYPE_CHECKING: + from lib.core.translator import Translator + from lib.core.Translator.LlvmGenerator import LlvmGeneratorMixin +from lib.core.Handles.HandlesBase import BaseHandle, BuiltinTypeMap +from lib.includes.t import CTypeRegistry +from lib.core.SymbolUtils import IsTModule +from lib.core.VLogger import get_logger as _vlog +from lib.constants.config import mode as _config_mode class CSpecialCallHandle(BaseHandle): - def _HandleCIfLlvm(self, Node): - Gen = self.Trans.LlvmGen + def _HandleCIfLlvm(self, Node: ast.Call) -> ir.Value: + Gen: LlvmGeneratorMixin = self.Trans.LlvmGen if Node.args: - ArgVal = self.HandleExprLlvm(Node.args[0]) + ArgVal: ir.Value | None = self.HandleExprLlvm(Node.args[0]) if ArgVal: if isinstance(ArgVal, ir.Constant) and isinstance(ArgVal.type, ir.IntType): return ir.Constant(ir.IntType(1), 1 if ArgVal.constant != 0 else 0) @@ -20,8 +25,8 @@ class CSpecialCallHandle(BaseHandle): if isinstance(ArgVal.type, ir.PointerType): return Gen.builder.icmp_signed('!=', ArgVal, Gen._ZeroConst(ArgVal.type), name="cif_cond") return ir.Constant(ir.IntType(1), 0) - def _HandleCAddrLlvm(self, Node): - Gen = self.Trans.LlvmGen + def _HandleCAddrLlvm(self, Node: ast.Call) -> ir.Value: + Gen: LlvmGeneratorMixin = self.Trans.LlvmGen if not Node.args: return ir.Constant(ir.IntType(8).as_pointer(), None) Arg = Node.args[0] @@ -36,7 +41,9 @@ class CSpecialCallHandle(BaseHandle): if isinstance(StructType, ir.PointerType): StructType = StructType.pointee ObjPtr = Gen._allocaEntry(StructType, name=f"{ClassName}_obj") - Gen.builder.store(ir.Constant(StructType, None), ObjPtr) + zero_val = Gen._zero_value_for_type(StructType) + if zero_val is not None: + Gen.builder.store(zero_val, ObjPtr) ConstructorName = f"{ClassName}.__init__" if ConstructorName in Gen.functions: func = Gen.functions[ConstructorName] @@ -95,12 +102,12 @@ class CSpecialCallHandle(BaseHandle): return Gen.builder.bitcast(ArgVal, ir.IntType(8).as_pointer(), name="addr_bitcast") return ir.Constant(ir.IntType(8).as_pointer(), None) - def _HandleCSetLlvm(self, Node): - Gen = self.Trans.LlvmGen + def _HandleCSetLlvm(self, Node: ast.Call) -> ir.Value: + Gen: LlvmGeneratorMixin = self.Trans.LlvmGen if len(Node.args) >= 2: - target_arg = Node.args[0] - value_arg = Node.args[1] - target_ptr = None + target_arg: ast.expr = Node.args[0] + value_arg: ast.expr = Node.args[1] + target_ptr: ir.Value | None = None if isinstance(target_arg, ast.Call) and isinstance(target_arg.func, ast.Attribute): if isinstance(target_arg.func.value, ast.Name) and target_arg.func.value.id == 'c': if target_arg.func.attr == 'Deref' and target_arg.args: @@ -116,7 +123,7 @@ class CSpecialCallHandle(BaseHandle): target_ptr = inner_value elif target_arg.func.attr == 'Addr' and target_arg.args: target_ptr = self.HandleExprLlvm(target_arg) - elif isinstance(target_arg.func.value, ast.Name) and target_arg.func.value.id == 't': + elif isinstance(target_arg.func.value, ast.Name) and IsTModule(target_arg.func.value.id, self.Trans.SymbolTable): type_attr = target_arg.func.attr resolved_cname = self.Trans.TSpecialCallHandle._ResolveTAttrToCName(type_attr) if target_arg.args and resolved_cname is not None: @@ -158,12 +165,12 @@ class CSpecialCallHandle(BaseHandle): Gen._store(ValToStore, target_ptr) return ir.Constant(ir.IntType(32), 1) - def _HandleCLoadLlvm(self, Node): - Gen = self.Trans.LlvmGen + def _HandleCLoadLlvm(self, Node: ast.Call) -> ir.Value: + Gen: LlvmGeneratorMixin = self.Trans.LlvmGen if len(Node.args) < 2: return ir.Constant(ir.IntType(32), 0) - src_val = self.HandleExprLlvm(Node.args[0]) - dst_val = self.HandleExprLlvm(Node.args[1]) + src_val: ir.Value | None = self.HandleExprLlvm(Node.args[0]) + dst_val: ir.Value | None = self.HandleExprLlvm(Node.args[1]) if not src_val or not dst_val: return ir.Constant(ir.IntType(32), 0) if not isinstance(src_val.type, ir.PointerType) or not isinstance(dst_val.type, ir.PointerType): @@ -189,24 +196,80 @@ class CSpecialCallHandle(BaseHandle): Gen._store(val_to_store, dst_val) return ir.Constant(ir.IntType(32), 1) - def _HandleCDerefLlvm(self, Node): - Gen = self.Trans.LlvmGen + def _HandleCDerefLlvm(self, Node: ast.Call) -> ir.Value: + Gen: LlvmGeneratorMixin = self.Trans.LlvmGen if not Node.args: return ir.Constant(ir.IntType(64), 0) - arg_val = self.HandleExprLlvm(Node.args[0]) + arg_val: ir.Value | None = self.HandleExprLlvm(Node.args[0]) if arg_val is None: return ir.Constant(ir.IntType(32), 0) if isinstance(arg_val.type, ir.PointerType): + pointee: ir.Type = arg_val.type.pointee + # void* (i8*) 需要根据赋值目标类型推断加载类型 + if isinstance(pointee, ir.IntType) and pointee.width == 8: + target_type: ir.Type | None = self._infer_deref_target_type(Gen) + if target_type is not None and not isinstance(target_type, ir.IntType): + # bitcast i8* -> target_type* then load + casted: ir.Value = Gen.builder.bitcast(arg_val, ir.PointerType(target_type), name="deref_cast") + Loaded = Gen._load(casted, name="deref") + if Loaded is not None: + return Loaded + elif target_type is not None and isinstance(target_type, ir.IntType): + # 目标是整数类型 (如 i32/i64): bitcast 并加载 + if target_type.width != 8: + casted: ir.Value = Gen.builder.bitcast(arg_val, ir.PointerType(target_type), name="deref_cast") + Loaded = Gen._load(casted, name="deref") + if Loaded is not None: + return Loaded Loaded = Gen._load(arg_val, name="deref") if Loaded is not None: return Loaded return arg_val - def _HandleCPtrToIntLlvm(self, Node): - Gen = self.Trans.LlvmGen + def _infer_deref_target_type(self, Gen: LlvmGeneratorMixin) -> ir.Type | None: + """从当前赋值上下文推断 c.Deref 的目标加载类型。 + 当用户写 v: int = c.Deref(ptr) 时,从赋值注解推断目标类型。""" + assign_node: ast.AST | None = getattr(self.Trans, '_current_assign_node', None) + if not assign_node: + return None + ann: ast.AST | None = getattr(assign_node, 'annotation', None) + if not ann: + return None + ann_name: str | None = None + if isinstance(ann, ast.Name): + ann_name = ann.id + elif isinstance(ann, ast.Attribute): + ann_name = ann.attr + elif isinstance(ann, ast.BinOp) and isinstance(ann.op, ast.BitOr): + # 处理 int | t.CPtr 形式的联合类型注解 + for side in (ann.left, ann.right): + if isinstance(side, ast.Name): + ann_name = side.id + break + elif isinstance(side, ast.Attribute): + ann_name = side.attr + break + if not ann_name: + return None + # 使用 BuiltinTypeMap 统一查询(同时支持 Python 类名和字符串速记) + entry: tuple[type, int] | None = BuiltinTypeMap.Get(ann_name) + if entry is not None: + ctype_cls: type = entry[0] + llvm_str: str | None = CTypeRegistry.CTypeToLLVM(ctype_cls) + if llvm_str: + resolved: ir.Type | None = Gen._type_str_to_llvm(llvm_str) + if resolved: + return resolved + # 检查是否是已注册的结构体类型 + if ann_name in Gen.structs: + return Gen.structs[ann_name] + return None + + def _HandleCPtrToIntLlvm(self, Node: ast.Call) -> ir.Value: + Gen: LlvmGeneratorMixin = self.Trans.LlvmGen if not Node.args: return ir.Constant(ir.IntType(64), 0) - arg_val = self.HandleExprLlvm(Node.args[0]) + arg_val: ir.Value | None = self.HandleExprLlvm(Node.args[0]) if arg_val is None: return ir.Constant(ir.IntType(64), 0) if isinstance(arg_val.type, ir.PointerType): @@ -223,38 +286,35 @@ class CSpecialCallHandle(BaseHandle): class TSpecialCallHandle(BaseHandle): @staticmethod - def _ResolveTAttrToCName(attr: str) -> str: - from lib.includes.t import CTypeRegistry - ctype_cls = CTypeRegistry.GetClassByName(attr) + def _ResolveTAttrToCName(attr: str) -> str | None: + ctype_cls: type | None = CTypeRegistry.GetClassByName(attr) if ctype_cls is not None: try: inst = ctype_cls() - cname = getattr(inst, 'CName', '') + cname = type(inst).__name__ if cname: return cname except Exception as _e: - from lib.core.VLogger import get_logger as _vlog - from lib.constants.config import mode as _config_mode if _config_mode == "strict": raise _vlog().warning(f"处理函数调用失败: {_e}", "Exception") return None - def _HandleTSpecialCallLlvm(self, Node): - Gen = self.Trans.LlvmGen + def _HandleTSpecialCallLlvm(self, Node: ast.Call) -> ir.Value | None: + Gen: LlvmGeneratorMixin = self.Trans.LlvmGen if not Node.args: return None - attr = Node.func.attr + attr: str = Node.func.attr if attr == 'CType': return self._HandleCTypeLlvm(Node) - target_type = self._ResolveTAttrToCName(attr) + target_type: str | None = self._ResolveTAttrToCName(attr) if target_type is not None: IsPtr_cast = False if len(Node.args) >= 2: second_arg = Node.args[1] - if isinstance(second_arg, ast.Attribute) and isinstance(second_arg.value, ast.Name) and second_arg.value.id == 't' and second_arg.attr == 'CPtr': + if isinstance(second_arg, ast.Attribute) and isinstance(second_arg.value, ast.Name) and IsTModule(second_arg.value.id, self.Trans.SymbolTable) and second_arg.attr == 'CPtr': IsPtr_cast = True elif isinstance(second_arg, ast.Name) and second_arg.id == 'CPtr': IsPtr_cast = True @@ -265,20 +325,20 @@ class TSpecialCallHandle(BaseHandle): return self.Trans.ExprCallHandle._HandleTypeCastLlvm(Node.args[0], target_type) return None - def _HandleCTypeLlvm(self, Node): - Gen = self.Trans.LlvmGen - arg_val = self.HandleExprLlvm(Node.args[0]) + def _HandleCTypeLlvm(self, Node: ast.Call) -> ir.Value | None: + Gen: LlvmGeneratorMixin = self.Trans.LlvmGen + arg_val: ir.Value | None = self.HandleExprLlvm(Node.args[0]) if not arg_val: return None - target_type_str = 'unsigned long long' + target_type_str: str = 'unsigned long long' if len(Node.args) >= 2: - type_parts = [] - ptr_count = 0 + type_parts: list[str] = [] + ptr_count: int = 0 for i in range(1, len(Node.args)): type_arg = Node.args[i] - if isinstance(type_arg, ast.Attribute) and isinstance(type_arg.value, ast.Name) and type_arg.value.id == 't': + if isinstance(type_arg, ast.Attribute) and isinstance(type_arg.value, ast.Name) and IsTModule(type_arg.value.id, self.Trans.SymbolTable): type_attr = type_arg.attr - _PREFIX_MAP = { + _PREFIX_MAP: dict[str, str] = { 'CUnsigned': 'unsigned', 'CSigned': 'signed', 'CConst': 'const', 'CVolatile': 'volatile', } @@ -299,12 +359,11 @@ class TSpecialCallHandle(BaseHandle): return int_val return self.Trans.ExprCallHandle._HandleTypeCastLlvm(Node.args[0], target_type_str) - def _HandleTPtrCastLlvm(self, Node, attr): - Gen = self.Trans.LlvmGen - from lib.includes.t import CTypeRegistry + def _HandleTPtrCastLlvm(self, Node: ast.Call, attr: str) -> ir.Value | None: + Gen: LlvmGeneratorMixin = self.Trans.LlvmGen if attr in ('CChar', 'CUnsignedChar'): first_arg = Node.args[0] - if isinstance(first_arg, ast.Call) and isinstance(first_arg.func, ast.Attribute) and isinstance(first_arg.func.value, ast.Name) and first_arg.func.value.id == 't' and first_arg.func.attr == 'CInt' and first_arg.args: + if isinstance(first_arg, ast.Call) and isinstance(first_arg.func, ast.Attribute) and isinstance(first_arg.func.value, ast.Name) and IsTModule(first_arg.func.value.id, self.Trans.SymbolTable) and first_arg.func.attr == 'CInt' and first_arg.args: inner_val = self.HandleExprLlvm(first_arg.args[0]) if isinstance(inner_val.type, ir.PointerType): return Gen.builder.bitcast(inner_val, ir.PointerType(ir.IntType(8)), name=f"c{attr.lower()}_ptr_from_cint") diff --git a/lib/core/Handles/HandlesTry.py b/lib/core/Handles/HandlesTry.py index 0c8cc86..1fd04e7 100644 --- a/lib/core/Handles/HandlesTry.py +++ b/lib/core/Handles/HandlesTry.py @@ -1,211 +1,214 @@ -from __future__ import annotations -from typing import TYPE_CHECKING -if TYPE_CHECKING: - from lib.core.translator import Translator -from lib.core.Handles.HandlesBase import BaseHandle, EXCEPTION_CODE_MAP -import ast -import llvmlite.ir as ir - - -class TryHandle(BaseHandle): - def _get_exception_type_code(self, type_node): - if isinstance(type_node, ast.Name): - name = type_node.id - if name in EXCEPTION_CODE_MAP: - return EXCEPTION_CODE_MAP[name] - if name in self.Trans.exception_registry: - return self.Trans.exception_registry[name] - return 1 - if isinstance(type_node, ast.Attribute): - name = type_node.attr - if name in EXCEPTION_CODE_MAP: - return EXCEPTION_CODE_MAP[name] - if name in self.Trans.exception_registry: - return self.Trans.exception_registry[name] - return 1 - if isinstance(type_node, ast.Tuple): - for elt in type_node.elts: - code = self._get_exception_type_code(elt) - if code != 1: - return code - return 1 - return 1 - - def _get_exception_name(self, type_node): - if isinstance(type_node, ast.Name): - return type_node.id - if isinstance(type_node, ast.Attribute): - return type_node.attr - return None - - def _get_all_match_codes(self, type_node): - name = self._get_exception_name(type_node) - if name is None: - return [self._get_exception_type_code(type_node)] - if name not in self.Trans.exception_registry: - return [self._get_exception_type_code(type_node)] - codes = [self.Trans.exception_registry[name]] - self._collect_descendant_codes(name, codes) - return codes - - def _collect_descendant_codes(self, parent_name, codes): - for child_name, parent in self.Trans.exception_parents.items(): - if parent == parent_name: - child_code = self.Trans.exception_registry.get(child_name) - if child_code is not None and child_code not in codes: - codes.append(child_code) - self._collect_descendant_codes(child_name, codes) - - def _HandleTryLlvm(self, Node): - Gen = self.Trans.LlvmGen - if not Gen.func: - return - exception_code = Gen._allocaEntry(ir.IntType(32), name="eh_code") - eh_message = Gen._allocaEntry(ir.PointerType(ir.IntType(8)), name="eh_message") - Gen._store(ir.Constant(ir.IntType(32), 0), exception_code) - Gen._store(ir.Constant(ir.PointerType(ir.IntType(8)), None), eh_message) - HasFinally = bool(Node.finalbody) - if HasFinally: - Gen.eh_finally_stack.append((None, None, None)) - else: - Gen.eh_finally_stack.append(None) - DispatchBB = Gen.func.append_basic_block(name="try.dispatch") - AfterBB = Gen.func.append_basic_block(name="try.after") - except_blocks = [] - for i, handler in enumerate(Node.handlers): - ExcTypeCodes = [1] - if handler.type: - ExcTypeCodes = self._get_all_match_codes(handler.type) - ExceptBB = Gen.func.append_basic_block(name=f"try.except_{i}") - Gen.eh_except_block_stack.append((DispatchBB, None, exception_code, eh_message)) - except_blocks.append((ExceptBB, ExcTypeCodes, handler)) - TryBB = Gen.func.append_basic_block(name="try.body") - ElseBB = None - if Node.orelse: - ElseBB = Gen.func.append_basic_block(name="try.else") - Gen.builder.branch(TryBB) - Gen.builder.position_at_start(TryBB) - self.HandleBodyLlvm(Node.body) - if not Gen.builder.block.is_terminated: - Gen._store(ir.Constant(ir.IntType(32), 0), exception_code) - if ElseBB: - Gen.builder.branch(ElseBB) - else: - Gen.builder.branch(AfterBB) - Gen.builder.position_at_start(DispatchBB) - eh_code_val = Gen._load(exception_code, name="Load_eh_code") - next_check_bb = None - handler_var_map = {} - UnhandledBB = Gen.func.append_basic_block(name="try.unhandled") - for i, (ExceptBB, ExcTypeCodes, handler) in enumerate(except_blocks): - MatchBB = Gen.func.append_basic_block(name=f"try.match_{i}") - if i > 0 and next_check_bb is not None: - Gen.builder.position_at_start(next_check_bb) - eh_code_val = Gen._load(exception_code, name=f"Load_eh_code_{i}") - if handler.type is None: - Gen.builder.branch(MatchBB) - else: - match_cond = None - for code in ExcTypeCodes: - is_code_match = Gen.builder.icmp_signed('==', eh_code_val, ir.Constant(ir.IntType(32), code), name=f"eh_match_{i}_c{code}") - if match_cond is None: - match_cond = is_code_match - else: - match_cond = Gen.builder.or_(match_cond, is_code_match, name=f"eh_match_any_{i}") - if i < len(except_blocks) - 1: - next_check_bb = Gen.func.append_basic_block(name=f"try.check_{i}") - else: - next_check_bb = UnhandledBB - Gen.builder.cbranch(match_cond, MatchBB, next_check_bb) - Gen.builder.position_at_start(MatchBB) - if handler.name: - var_alloca = Gen._allocaEntry(ir.IntType(8).as_pointer(), name=handler.name) - eh_msg_val = Gen._load(eh_message, name=f"Load_eh_msg_{handler.name}") - Gen._store(eh_msg_val, var_alloca) - handler_var_map[i] = (handler.name, var_alloca, Gen.variables.get(handler.name)) - Gen.builder.branch(ExceptBB) - Gen.builder.position_at_start(UnhandledBB) - eh_msg_out_arg = None - eh_code_out_arg = None - if Gen.func and len(Gen.func.args) > 0: - for arg in Gen.func.args: - if arg.name == '__eh_msg_out__': - eh_msg_out_arg = arg - elif arg.name == '__eh_code_out__': - eh_code_out_arg = arg - if eh_msg_out_arg is not None and eh_code_out_arg is not None: - eh_msg_val = Gen._load(eh_message, name="Load_eh_msg_propagate") - eh_code_val_prop = Gen._load(exception_code, name="Load_eh_code_propagate") - Gen._store(eh_msg_val, eh_msg_out_arg) - Gen._store(eh_code_val_prop, eh_code_out_arg) - ret_type = getattr(Gen.func, 'ftype', None) and Gen.func.ftype.return_type if getattr(Gen, 'func', None) else None - if isinstance(ret_type, ir.IdentifiedStructType): - if ret_type.elements: - zero_val = ir.Constant(ret_type, [ - ir.Constant(et, None) if isinstance(et, (ir.PointerType, ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)) - else ir.Constant(et, 0) if isinstance(et, (ir.IntType, ir.FloatType, ir.DoubleType)) - else ir.Constant(et, ir.Undefined) for et in ret_type.elements]) - else: - zero_val = ir.Constant(ret_type, None) - Gen.builder.ret(zero_val) - elif isinstance(ret_type, ir.PointerType): - Gen.builder.ret(ir.Constant(ret_type, None)) - elif isinstance(ret_type, (ir.FloatType, ir.DoubleType)): - Gen.builder.ret(ir.Constant(ret_type, 0.0)) - elif isinstance(ret_type, ir.IntType): - Gen.builder.ret(ir.Constant(ret_type, 1)) - elif isinstance(ret_type, ir.VoidType): - Gen.builder.ret_void() - else: - Gen.builder.ret(ir.Constant(ir.IntType(32), 1)) - else: - Gen._store(ir.Constant(ir.IntType(32), 0), exception_code) - Gen.builder.branch(AfterBB) - for idx, (ExceptBB, ExcTypeCodes, handler) in enumerate(except_blocks): - Gen.builder.position_at_start(ExceptBB) - old_var = None - if idx in handler_var_map: - hname, var_alloca, old_var = handler_var_map[idx] - Gen.variables[hname] = var_alloca - self.HandleBodyLlvm(handler.body) - if idx in handler_var_map: - hname, _, old_var = handler_var_map[idx] - if old_var is not None: - Gen.variables[hname] = old_var - elif hname in Gen.variables: - del Gen.variables[hname] - if not Gen.builder.block.is_terminated: - Gen.builder.branch(AfterBB) - Gen.eh_except_block_stack.pop() - if ElseBB: - Gen.builder.position_at_start(ElseBB) - self.HandleBodyLlvm(Node.orelse) - if not Gen.builder.block.is_terminated: - Gen.builder.branch(AfterBB) - Gen.builder.position_at_start(AfterBB) - if HasFinally: - Gen.eh_finally_stack.pop() - if Node.finalbody: - FinallyBB = Gen.func.append_basic_block(name="try.finally") - pending_ret_flag = Gen._allocaEntry(ir.IntType(32), name="pending_ret_flag") - pending_ret_val = Gen._allocaEntry(ir.IntType(32), name="pending_ret_val") if Gen.func.type.pointee.return_type == ir.IntType(32) else None - Gen.eh_finally_stack.append((FinallyBB, pending_ret_flag, pending_ret_val)) - Gen.builder.branch(FinallyBB) - Gen.builder.position_at_start(FinallyBB) - Gen._store(ir.Constant(ir.IntType(32), 0), pending_ret_flag) - self.HandleBodyLlvm(Node.finalbody) - if Gen.eh_finally_stack: - _, pending_ret_flag, pending_ret_val = Gen.eh_finally_stack[-1] - Gen.eh_finally_stack.pop() - ret_flag_val = Gen._load(pending_ret_flag, name="Load_ret_flag") - ret_flag_is_set = Gen.builder.icmp_signed('!=', ret_flag_val, ir.Constant(ir.IntType(32), 0), name="check_ret_flag") - RetBB = Gen.func.append_basic_block(name="finally.ret") - ContinueBB = Gen.func.append_basic_block(name="try.continue") - Gen.builder.cbranch(ret_flag_is_set, RetBB, ContinueBB) - Gen.builder.position_at_start(RetBB) - if pending_ret_val: - ret_val = Gen._load(pending_ret_val, name="Load_ret_val") - Gen.builder.ret(ret_val) - else: - Gen.builder.ret_void() +from __future__ import annotations +from typing import TYPE_CHECKING +if TYPE_CHECKING: + from lib.core.translator import Translator +from lib.core.Handles.HandlesBase import BaseHandle, EXCEPTION_CODE_MAP +import ast +import llvmlite.ir as ir + + +class TryHandle(BaseHandle): + def _get_exception_type_code(self, type_node: ast.expr) -> int: + if isinstance(type_node, ast.Name): + name: str = type_node.id + if name in EXCEPTION_CODE_MAP: + return EXCEPTION_CODE_MAP[name] + if name in self.Trans.exception_registry: + return self.Trans.exception_registry[name] + return 1 + if isinstance(type_node, ast.Attribute): + name: str = type_node.attr + if name in EXCEPTION_CODE_MAP: + return EXCEPTION_CODE_MAP[name] + if name in self.Trans.exception_registry: + return self.Trans.exception_registry[name] + return 1 + if isinstance(type_node, ast.Tuple): + for elt in type_node.elts: + code: int = self._get_exception_type_code(elt) + if code != 1: + return code + return 1 + return 1 + + def _get_exception_name(self, type_node: ast.expr) -> str | None: + if isinstance(type_node, ast.Name): + return type_node.id + if isinstance(type_node, ast.Attribute): + return type_node.attr + return None + + def _get_all_match_codes(self, type_node: ast.expr) -> list[int]: + name: str | None = self._get_exception_name(type_node) + if name is None: + return [self._get_exception_type_code(type_node)] + if name not in self.Trans.exception_registry: + return [self._get_exception_type_code(type_node)] + codes: list[int] = [self.Trans.exception_registry[name]] + self._collect_descendant_codes(name, codes) + return codes + + def _collect_descendant_codes(self, parent_name: str, codes: list[int]) -> None: + for child_name, parent in self.Trans.exception_parents.items(): + if parent == parent_name: + child_code: int | None = self.Trans.exception_registry.get(child_name) + if child_code is not None and child_code not in codes: + codes.append(child_code) + self._collect_descendant_codes(child_name, codes) + + def _HandleTryLlvm(self, Node: ast.Try) -> None: + Gen: "Translator.LlvmGen" = self.Trans.LlvmGen + if not Gen.func: + return + exception_code: ir.AllocaInstr = Gen._allocaEntry(ir.IntType(32), name="eh_code") + eh_message: ir.AllocaInstr = Gen._allocaEntry(ir.PointerType(ir.IntType(8)), name="eh_message") + Gen._store(ir.Constant(ir.IntType(32), 0), exception_code) + Gen._store(ir.Constant(ir.PointerType(ir.IntType(8)), None), eh_message) + HasFinally: bool = bool(Node.finalbody) + if HasFinally: + Gen.eh_finally_stack.append((None, None, None)) + else: + Gen.eh_finally_stack.append(None) + DispatchBB: ir.Block = Gen.func.append_basic_block(name="try.dispatch") + AfterBB: ir.Block = Gen.func.append_basic_block(name="try.after") + except_blocks: list[tuple[ir.Block, list[int], ast.ExceptHandler]] = [] + for i, handler in enumerate(Node.handlers): + ExcTypeCodes: list[int] = [1] + if handler.type: + ExcTypeCodes = self._get_all_match_codes(handler.type) + ExceptBB: ir.Block = Gen.func.append_basic_block(name=f"try.except_{i}") + Gen.eh_except_block_stack.append((DispatchBB, None, exception_code, eh_message)) + except_blocks.append((ExceptBB, ExcTypeCodes, handler)) + TryBB: ir.Block = Gen.func.append_basic_block(name="try.body") + ElseBB: ir.Block | None = None + if Node.orelse: + ElseBB = Gen.func.append_basic_block(name="try.else") + Gen.builder.branch(TryBB) + Gen.builder.position_at_start(TryBB) + self.HandleBodyLlvm(Node.body) + if not Gen.builder.block.is_terminated: + Gen._store(ir.Constant(ir.IntType(32), 0), exception_code) + if ElseBB: + Gen.builder.branch(ElseBB) + else: + Gen.builder.branch(AfterBB) + Gen.builder.position_at_start(DispatchBB) + eh_code_val: ir.Value = Gen._load(exception_code, name="Load_eh_code") + next_check_bb: ir.Block | None = None + handler_var_map: dict[int, tuple[str, ir.AllocaInstr, ir.Value | None]] = {} + UnhandledBB: ir.Block = Gen.func.append_basic_block(name="try.unhandled") + for i, (ExceptBB, ExcTypeCodes, handler) in enumerate(except_blocks): + MatchBB: ir.Block = Gen.func.append_basic_block(name=f"try.match_{i}") + if i > 0 and next_check_bb is not None: + Gen.builder.position_at_start(next_check_bb) + eh_code_val = Gen._load(exception_code, name=f"Load_eh_code_{i}") + if handler.type is None: + Gen.builder.branch(MatchBB) + else: + match_cond: ir.Value | None = None + for code in ExcTypeCodes: + is_code_match: ir.Value = Gen.builder.icmp_signed('==', eh_code_val, ir.Constant(ir.IntType(32), code), name=f"eh_match_{i}_c{code}") + if match_cond is None: + match_cond = is_code_match + else: + match_cond = Gen.builder.or_(match_cond, is_code_match, name=f"eh_match_any_{i}") + if i < len(except_blocks) - 1: + next_check_bb = Gen.func.append_basic_block(name=f"try.check_{i}") + else: + next_check_bb = UnhandledBB + Gen.builder.cbranch(match_cond, MatchBB, next_check_bb) + Gen.builder.position_at_start(MatchBB) + if handler.name: + var_alloca: ir.AllocaInstr = Gen._allocaEntry(ir.IntType(8).as_pointer(), name=handler.name) + eh_msg_val: ir.Value = Gen._load(eh_message, name=f"Load_eh_msg_{handler.name}") + Gen._store(eh_msg_val, var_alloca) + handler_var_map[i] = (handler.name, var_alloca, Gen.variables.get(handler.name)) + Gen.builder.branch(ExceptBB) + Gen.builder.position_at_start(UnhandledBB) + eh_msg_out_arg: ir.Argument | None = None + eh_code_out_arg: ir.Argument | None = None + if Gen.func and len(Gen.func.args) > 0: + for arg in Gen.func.args: + if arg.name == '__eh_msg_out__': + eh_msg_out_arg = arg + elif arg.name == '__eh_code_out__': + eh_code_out_arg = arg + if eh_msg_out_arg is not None and eh_code_out_arg is not None: + eh_msg_val: ir.Value = Gen._load(eh_message, name="Load_eh_msg_propagate") + eh_code_val_prop: ir.Value = Gen._load(exception_code, name="Load_eh_code_propagate") + Gen._store(eh_msg_val, eh_msg_out_arg) + Gen._store(eh_code_val_prop, eh_code_out_arg) + ret_type: ir.Type | None = getattr(Gen.func, 'ftype', None) and Gen.func.ftype.return_type if getattr(Gen, 'func', None) else None + if isinstance(ret_type, ir.IdentifiedStructType): + if ret_type.elements: + zero_val: ir.Constant = ir.Constant(ret_type, [ + ir.Constant(et, None) if isinstance(et, (ir.PointerType, ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)) + else ir.Constant(et, 0) if isinstance(et, (ir.IntType, ir.FloatType, ir.DoubleType)) + else ir.Constant(et, ir.Undefined) for et in ret_type.elements]) + else: + zero_val = ir.Constant(ret_type, None) + Gen.builder.ret(zero_val) + elif isinstance(ret_type, ir.PointerType): + Gen.builder.ret(ir.Constant(ret_type, None)) + elif isinstance(ret_type, (ir.FloatType, ir.DoubleType)): + Gen.builder.ret(ir.Constant(ret_type, 0.0)) + elif isinstance(ret_type, ir.IntType): + Gen.builder.ret(ir.Constant(ret_type, 1)) + elif isinstance(ret_type, ir.VoidType): + Gen.builder.ret_void() + else: + Gen.builder.ret(ir.Constant(ir.IntType(32), 1)) + else: + Gen._store(ir.Constant(ir.IntType(32), 0), exception_code) + Gen.builder.branch(AfterBB) + for idx, (ExceptBB, ExcTypeCodes, handler) in enumerate(except_blocks): + Gen.builder.position_at_start(ExceptBB) + old_var: ir.Value | None = None + if idx in handler_var_map: + hname: str = handler_var_map[idx][0] + var_alloca: ir.AllocaInstr = handler_var_map[idx][1] + old_var = handler_var_map[idx][2] + Gen.variables[hname] = var_alloca + self.HandleBodyLlvm(handler.body) + if idx in handler_var_map: + hname = handler_var_map[idx][0] + old_var = handler_var_map[idx][2] + if old_var is not None: + Gen.variables[hname] = old_var + elif hname in Gen.variables: + del Gen.variables[hname] + if not Gen.builder.block.is_terminated: + Gen.builder.branch(AfterBB) + Gen.eh_except_block_stack.pop() + if ElseBB: + Gen.builder.position_at_start(ElseBB) + self.HandleBodyLlvm(Node.orelse) + if not Gen.builder.block.is_terminated: + Gen.builder.branch(AfterBB) + Gen.builder.position_at_start(AfterBB) + if HasFinally: + Gen.eh_finally_stack.pop() + if Node.finalbody: + FinallyBB: ir.Block = Gen.func.append_basic_block(name="try.finally") + pending_ret_flag: ir.AllocaInstr = Gen._allocaEntry(ir.IntType(32), name="pending_ret_flag") + pending_ret_val: ir.AllocaInstr | None = Gen._allocaEntry(ir.IntType(32), name="pending_ret_val") if Gen.func.type.pointee.return_type == ir.IntType(32) else None + Gen.eh_finally_stack.append((FinallyBB, pending_ret_flag, pending_ret_val)) + Gen.builder.branch(FinallyBB) + Gen.builder.position_at_start(FinallyBB) + Gen._store(ir.Constant(ir.IntType(32), 0), pending_ret_flag) + self.HandleBodyLlvm(Node.finalbody) + if Gen.eh_finally_stack: + _, pending_ret_flag, pending_ret_val = Gen.eh_finally_stack[-1] + Gen.eh_finally_stack.pop() + ret_flag_val: ir.Value = Gen._load(pending_ret_flag, name="Load_ret_flag") + ret_flag_is_set: ir.Value = Gen.builder.icmp_signed('!=', ret_flag_val, ir.Constant(ir.IntType(32), 0), name="check_ret_flag") + RetBB: ir.Block = Gen.func.append_basic_block(name="finally.ret") + ContinueBB: ir.Block = Gen.func.append_basic_block(name="try.continue") + Gen.builder.cbranch(ret_flag_is_set, RetBB, ContinueBB) + Gen.builder.position_at_start(RetBB) + if pending_ret_val: + ret_val: ir.Value = Gen._load(pending_ret_val, name="Load_ret_val") + Gen.builder.ret(ret_val) + else: + Gen.builder.ret_void() Gen.builder.position_at_start(ContinueBB) \ No newline at end of file diff --git a/lib/core/Handles/HandlesTypeMerge.py b/lib/core/Handles/HandlesTypeMerge.py index 9b49f05..c8b1f98 100644 --- a/lib/core/Handles/HandlesTypeMerge.py +++ b/lib/core/Handles/HandlesTypeMerge.py @@ -4,6 +4,7 @@ if TYPE_CHECKING: from lib.core.translator import Translator from typing import List from lib.core.Handles.HandlesBase import BaseHandle, CTypeHelper, CTypeInfo, StrictMode +from lib.core.SymbolUtils import IsTModule, IsListAnnotation, ExtractListFromBinOp from lib.includes import t import importlib import ast @@ -34,17 +35,14 @@ class HandlesTypeMerge(BaseHandle): else: return self._MakeVoidCTypeInfo() - def _GetCTypeInfoInternal(self, Node: ast.AST): + def _GetCTypeInfoInternal(self, Node: ast.AST) -> CTypeInfo | str | None: """鍐呴儴鏂规硶锛岃繑鍥?CTypeInfo""" LineNum = getattr(Node, 'lineno', None) self.Trans.DebugPrint(f"[GetCTypeInfo] Node type: {type(Node).__name__}, dump: {ast.dump(Node)[:60]}...") - if isinstance(Node, (ast.Constant, ast.Str)): - if isinstance(Node, ast.Constant): - TypeName = Node.value - else: - TypeName = Node.s + if isinstance(Node, ast.Constant): + TypeName = Node.value return self._MakeCTypeInfoFromName(TypeName) if isinstance(Node, ast.Name): @@ -59,37 +57,44 @@ class HandlesTypeMerge(BaseHandle): ) ast.copy_location(virtual_attr, Node) return self.GetCTypeInfo(virtual_attr) - if self.Trans.SymbolTable.has(TypeName): - Entry = self.Trans.SymbolTable[TypeName] - if Entry and Entry.IsTypedef: - if isinstance(Entry, CTypeInfo) and Entry.BaseType: - if not isinstance(Entry.BaseType, (t._CTypedef,)) or Entry.PtrCount > 0: - Result = Entry.Copy() - Result.IsTypedef = True - Result.Name = TypeName - return Result - if Entry.OriginalType: - if isinstance(Entry.OriginalType, CTypeInfo) and Entry.OriginalType.IsFuncPtr: - Result = CTypeInfo() - Result.IsFuncPtr = True - Result.FuncPtrReturn = Entry.OriginalType.FuncPtrReturn or CTypeInfo.VoidTypeInfo() - Result.FuncPtrParams = list(Entry.OriginalType.FuncPtrParams) if Entry.OriginalType.FuncPtrParams else [] - Result.IsTypedef = True - Result.Name = TypeName - return Result - elif isinstance(Entry.OriginalType, CTypeInfo): - Resolved = Entry.OriginalType.Copy() - Resolved.IsTypedef = True - Resolved.Name = TypeName - return Resolved - return Entry - if isinstance(Entry, CTypeInfo) and Entry.IsEnum: - return Entry.Copy() - if isinstance(Entry, dict) and Entry.get('IsEnum'): - Result = CTypeInfo() - Result.BaseType = t.CEnum(TypeName) - Result.IsEnum = True - return Result + Entry = self.Trans.SymbolTable.lookup(TypeName) + if Entry and Entry.IsTypedef: + if isinstance(Entry, CTypeInfo) and Entry.BaseType: + if not isinstance(Entry.BaseType, (t._CTypedef,)) or Entry.PtrCount > 0: + Result = Entry.Copy() + Result.IsTypedef = True + Result.Name = TypeName + return Result + if Entry.OriginalType: + if isinstance(Entry.OriginalType, CTypeInfo) and Entry.OriginalType.IsFuncPtr: + Result = CTypeInfo() + Result.IsFuncPtr = True + Result.FuncPtrReturn = Entry.OriginalType.FuncPtrReturn or CTypeInfo.VoidTypeInfo() + Result.FuncPtrParams = list(Entry.OriginalType.FuncPtrParams) if Entry.OriginalType.FuncPtrParams else [] + Result.IsTypedef = True + Result.Name = TypeName + return Result + elif isinstance(Entry.OriginalType, CTypeInfo): + Resolved = Entry.OriginalType.Copy() + Resolved.IsTypedef = True + Resolved.Name = TypeName + return Resolved + return Entry + if isinstance(Entry, CTypeInfo) and Entry.IsEnum: + return Entry.Copy() + if isinstance(Entry, dict) and Entry.get('IsEnum'): + Result = CTypeInfo() + Result.BaseType = t.CEnum(TypeName) + Result.IsEnum = True + return Result + # 检测结构体类型 (CTypeInfo with IsStruct=True, 来自 _InsertClassSymbol) + if isinstance(Entry, CTypeInfo) and Entry.IsStruct: + Result = Entry.Copy() + if Result.BaseType is None: + Result.BaseType = t.CStruct(name=TypeName) + Result.Name = TypeName + Result.PtrCount = 1 # struct 变量默认为指针 + return Result return self._MakeCTypeInfoFromName(TypeName) elif isinstance(Node, ast.Attribute): @@ -118,12 +123,11 @@ class HandlesTypeMerge(BaseHandle): ModulePath = import_aliases[ModulePath] else: # 也尝试在符号表中查找模块别名 - if self.Trans.SymbolTable.has(ModulePath): - entry = self.Trans.SymbolTable[ModulePath] - if isinstance(entry, CTypeInfo) and entry.IsModuleAlias: - resolved = entry.ResolvedModule - if resolved: - ModulePath = resolved + entry = self.Trans.SymbolTable.lookup(ModulePath) + if isinstance(entry, CTypeInfo) and entry.IsModuleAlias: + resolved = entry.ResolvedModule + if resolved: + ModulePath = resolved self.Trans.DebugPrint(f"[GetCTypeInfo-Attribute] 查询: '{TypeName}' ModulePath: {ModulePath}") @@ -176,6 +180,11 @@ class HandlesTypeMerge(BaseHandle): Info.Storage = t.CExport() Info.BaseType = t.CVoid return Info + elif TypeClass in (t.BigEndian, t.LittleEndian): + Info = CTypeInfo() + Info.BaseType = t.CInt() + Info.ByteOrder = 'big' if TypeClass == t.BigEndian else 'little' + return Info elif TypeClass: Info = CTypeInfo() Info.BaseType = TypeClass @@ -185,71 +194,68 @@ class HandlesTypeMerge(BaseHandle): FullName = f"{ModulePath}.{TypeName}" if ModulePath else TypeName - if self.Trans.SymbolTable.has(TypeName): - Entry = self.Trans.SymbolTable[TypeName] - if Entry and Entry.IsTypedef: - if isinstance(Entry, CTypeInfo) and Entry.BaseType: - if not isinstance(Entry.BaseType, (t._CTypedef,)) or Entry.PtrCount > 0: - Result = Entry.Copy() - Result.IsTypedef = True - Result.Name = TypeName - return Result - if Entry.OriginalType: - if isinstance(Entry.OriginalType, CTypeInfo): - Resolved = Entry.OriginalType.Copy() - Resolved.IsTypedef = True - Resolved.Name = TypeName - return Resolved - Result = CTypeInfo() - Result.BaseType = t._CTypedef(TypeName) - Result.IsTypedef = True - return Result - if Entry: - # If BaseType is None but this is a class/struct, set BaseType to CStruct - Result = Entry.Copy() - if Result.BaseType is None: - Result.BaseType = t.CStruct(name=TypeName) - Result.IsStruct = True - return Result - return CTypeInfo() - - if self.Trans.SymbolTable.has(FullName): - Info = self.Trans.SymbolTable[FullName] - if Info and Info.IsTypedef: - if isinstance(Info, CTypeInfo) and Info.BaseType and (not isinstance(Info.BaseType, (t._CTypedef,)) or Info.PtrCount > 0): - Result = Info.Copy() + Entry = self.Trans.SymbolTable.lookup(TypeName) + if Entry and Entry.IsTypedef: + if isinstance(Entry, CTypeInfo) and Entry.BaseType: + if not isinstance(Entry.BaseType, (t._CTypedef,)) or Entry.PtrCount > 0: + Result = Entry.Copy() Result.IsTypedef = True Result.Name = TypeName return Result - if Info.OriginalType: - if isinstance(Info.OriginalType, CTypeInfo): - Resolved = Info.OriginalType.Copy() - Resolved.IsTypedef = True - Resolved.Name = TypeName - return Resolved - Result = CTypeInfo() - Result.BaseType = t._CTypedef(TypeName) + if Entry.OriginalType: + if isinstance(Entry.OriginalType, CTypeInfo): + Resolved = Entry.OriginalType.Copy() + Resolved.IsTypedef = True + Resolved.Name = TypeName + return Resolved + Result = CTypeInfo() + Result.BaseType = t._CTypedef(TypeName) + Result.IsTypedef = True + return Result + if Entry: + # If BaseType is None but this is a class/struct, set BaseType to CStruct + Result = Entry.Copy() + if Result.BaseType is None: + Result.BaseType = t.CStruct(name=TypeName) + Result.IsStruct = True + return Result + return CTypeInfo() + + Info = self.Trans.SymbolTable.lookup(FullName) + if Info and Info.IsTypedef: + if isinstance(Info, CTypeInfo) and Info.BaseType and (not isinstance(Info.BaseType, (t._CTypedef,)) or Info.PtrCount > 0): + Result = Info.Copy() Result.IsTypedef = True + Result.Name = TypeName return Result - return Info.Copy() if Info else CTypeInfo() + if Info.OriginalType: + if isinstance(Info.OriginalType, CTypeInfo): + Resolved = Info.OriginalType.Copy() + Resolved.IsTypedef = True + Resolved.Name = TypeName + return Resolved + Result = CTypeInfo() + Result.BaseType = t._CTypedef(TypeName) + Result.IsTypedef = True + return Result + return Info.Copy() if Info else CTypeInfo() if not self.Trans.SymbolTable.has(TypeName): if not self._IsTModuleType(TypeName) and not (ModulePath and ModulePath.startswith(('t.', 'c.'))): IsEnumMember = False FirstName = ModuleParts[0] - if self.Trans.SymbolTable.has(FirstName): - Entry = self.Trans.SymbolTable[FirstName] - if Entry and Entry.IsEnum: - IsEnumMember = True + Entry = self.Trans.SymbolTable.lookup(FirstName) + if Entry and Entry.IsEnum: + IsEnumMember = True - if not IsEnumMember and self.Trans.SymbolTable.has(FullName): - Entry = self.Trans.SymbolTable[FullName] + if not IsEnumMember: + Entry = self.Trans.SymbolTable.lookup(FullName) if Entry and Entry.IsEnumMember: IsEnumMember = True IsVariable = False - if not IsEnumMember and self.Trans.SymbolTable.has(FullName): - Entry = self.Trans.SymbolTable[FullName] + if not IsEnumMember: + Entry = self.Trans.SymbolTable.lookup(FullName) if Entry and Entry.TypeCls is not None: IsVariable = True @@ -263,63 +269,60 @@ class HandlesTypeMerge(BaseHandle): FirstName = ModuleParts[0] FullName = f"{ModulePath}.{TypeName}" if ModulePath else TypeName - if self.Trans.SymbolTable.has(FullName): - Info = self.Trans.SymbolTable[FullName] - if Info and Info.IsEnumMember: - Result = CTypeInfo() - Result.BaseType = t._CTypedef(TypeName) - Result.IsEnumMember = True - return Result - if Info and Info.IsTypedef: - if isinstance(Info, CTypeInfo) and Info.BaseType and (not isinstance(Info.BaseType, (t._CTypedef,)) or Info.PtrCount > 0): - Result = Info.Copy() - Result.IsTypedef = True - Result.Name = TypeName - return Result - if Info.OriginalType: - if isinstance(Info.OriginalType, CTypeInfo): - Resolved = Info.OriginalType.Copy() - Resolved.IsTypedef = True - Resolved.Name = TypeName - return Resolved - Result = CTypeInfo() - Result.BaseType = t._CTypedef(TypeName) + Info = self.Trans.SymbolTable.lookup(FullName) + if Info and Info.IsEnumMember: + Result = CTypeInfo() + Result.BaseType = t._CTypedef(TypeName) + Result.IsEnumMember = True + return Result + if Info and Info.IsTypedef: + if isinstance(Info, CTypeInfo) and Info.BaseType and (not isinstance(Info.BaseType, (t._CTypedef,)) or Info.PtrCount > 0): + Result = Info.Copy() Result.IsTypedef = True + Result.Name = TypeName return Result - return Info.Copy() if Info else CTypeInfo() + if Info.OriginalType: + if isinstance(Info.OriginalType, CTypeInfo): + Resolved = Info.OriginalType.Copy() + Resolved.IsTypedef = True + Resolved.Name = TypeName + return Resolved + Result = CTypeInfo() + Result.BaseType = t._CTypedef(TypeName) + Result.IsTypedef = True + return Result + return Info.Copy() if Info else CTypeInfo() - if self.Trans.SymbolTable.has(FirstName): - Entry = self.Trans.SymbolTable[FirstName] - if Entry: - Result = CTypeInfo() - if Entry.IsEnum: - Result.BaseType = t.CEnum(TypeName) - return Result - if Entry.IsTypedef and Entry.OriginalType: - if isinstance(Entry.OriginalType, CTypeInfo): - if Entry.OriginalType.IsEnum: - EnumName = TypeName - elif isinstance(Entry.OriginalType.BaseType, t.CEnum): - EnumName = Entry.OriginalType.BaseType.name or TypeName - elif isinstance(Entry.OriginalType.BaseType, t.CStruct): - EnumName = Entry.OriginalType.BaseType.name or TypeName - else: - EnumName = None + Entry = self.Trans.SymbolTable.lookup(FirstName) + if Entry: + Result = CTypeInfo() + if Entry.IsEnum: + Result.BaseType = t.CEnum(TypeName) + return Result + if Entry.IsTypedef and Entry.OriginalType: + if isinstance(Entry.OriginalType, CTypeInfo): + if Entry.OriginalType.IsEnum: + EnumName = TypeName + elif isinstance(Entry.OriginalType.BaseType, t.CEnum): + EnumName = Entry.OriginalType.BaseType.name or TypeName + elif isinstance(Entry.OriginalType.BaseType, t.CStruct): + EnumName = Entry.OriginalType.BaseType.name or TypeName else: - EnumName = CTypeHelper.StripTypePrefix(Entry.OriginalType) - if EnumName and self.Trans.SymbolTable.has(EnumName): - EnumEntry = self.Trans.SymbolTable[EnumName] - if EnumEntry and EnumEntry.IsEnum: - Result.BaseType = t._CTypedef(TypeName) - Result.IsEnumMember = True - return Result + EnumName = None + else: + EnumName = CTypeHelper.StripTypePrefix(Entry.OriginalType) + if EnumName: + EnumEntry = self.Trans.SymbolTable.lookup(EnumName) + if EnumEntry and EnumEntry.IsEnum: + Result.BaseType = t._CTypedef(TypeName) + Result.IsEnumMember = True + return Result if FirstName in self.Trans.GeneratedTypes: - if self.Trans.SymbolTable.has(FirstName): - Entry = self.Trans.SymbolTable[FirstName] - if Entry and Entry.IsEnum: - Result.BaseType = t.CEnum(TypeName) - return Result + Entry = self.Trans.SymbolTable.lookup(FirstName) + if Entry and Entry.IsEnum: + Result.BaseType = t.CEnum(TypeName) + return Result if len(ModuleParts) >= 2 and ModuleParts[-1] == 'State' and ModuleParts[-2] == 't': Result = CTypeInfo() @@ -356,53 +359,51 @@ class HandlesTypeMerge(BaseHandle): OriginalInfo.BaseType = inst AttrInfo.OriginalType = OriginalInfo except Exception: - AttrInfo.OriginalType = self._MakeCTypeInfoFromName(Attr().CName) if hasattr(Attr(), 'CName') else None + AttrInfo.OriginalType = self._MakeCTypeInfoFromName(Attr.__name__) if (isinstance(Attr, type) and issubclass(Attr, t.CType)) else None self.Trans.SymbolTable.insert(AttrName, AttrInfo) except Exception as e: self.Trans._UserTypeModules[ModuleName] = None FullName = f'{ModulePath}.{TypeName}' if ModulePath else TypeName - if self.Trans.SymbolTable.has(FullName): - Entry = self.Trans.SymbolTable[FullName] - if Entry and Entry.IsTypedef: - if isinstance(Entry, CTypeInfo) and Entry.BaseType: - if not isinstance(Entry.BaseType, (t._CTypedef,)) or Entry.PtrCount > 0: - Result = Entry.Copy() - Result.IsTypedef = True - Result.Name = TypeName - return Result - if Entry.OriginalType: - if isinstance(Entry.OriginalType, CTypeInfo): - Resolved = Entry.OriginalType.Copy() - Resolved.IsTypedef = True - Resolved.Name = TypeName - return Resolved - Result = CTypeInfo() - Result.BaseType = t._CTypedef(TypeName) - Result.IsTypedef = True - return Result - return Entry.Copy() if Entry else CTypeInfo() + Entry = self.Trans.SymbolTable.lookup(FullName) + if Entry and Entry.IsTypedef: + if isinstance(Entry, CTypeInfo) and Entry.BaseType: + if not isinstance(Entry.BaseType, (t._CTypedef,)) or Entry.PtrCount > 0: + Result = Entry.Copy() + Result.IsTypedef = True + Result.Name = TypeName + return Result + if Entry.OriginalType: + if isinstance(Entry.OriginalType, CTypeInfo): + Resolved = Entry.OriginalType.Copy() + Resolved.IsTypedef = True + Resolved.Name = TypeName + return Resolved + Result = CTypeInfo() + Result.BaseType = t._CTypedef(TypeName) + Result.IsTypedef = True + return Result + return Entry.Copy() if Entry else CTypeInfo() - if self.Trans.SymbolTable.has(TypeName): - Entry = self.Trans.SymbolTable[TypeName] - if Entry and Entry.IsTypedef: - if isinstance(Entry, CTypeInfo) and Entry.BaseType: - if not isinstance(Entry.BaseType, (t._CTypedef,)) or Entry.PtrCount > 0: - Result = Entry.Copy() - Result.IsTypedef = True - Result.Name = TypeName - return Result - if Entry.OriginalType: - if isinstance(Entry.OriginalType, CTypeInfo): - Resolved = Entry.OriginalType.Copy() - Resolved.IsTypedef = True - Resolved.Name = TypeName - return Resolved - Result = CTypeInfo() - Result.BaseType = t._CTypedef(TypeName) - Result.IsTypedef = True - return Result - return Entry.Copy() if Entry else CTypeInfo() + Entry = self.Trans.SymbolTable.lookup(TypeName) + if Entry and Entry.IsTypedef: + if isinstance(Entry, CTypeInfo) and Entry.BaseType: + if not isinstance(Entry.BaseType, (t._CTypedef,)) or Entry.PtrCount > 0: + Result = Entry.Copy() + Result.IsTypedef = True + Result.Name = TypeName + return Result + if Entry.OriginalType: + if isinstance(Entry.OriginalType, CTypeInfo): + Resolved = Entry.OriginalType.Copy() + Resolved.IsTypedef = True + Resolved.Name = TypeName + return Resolved + Result = CTypeInfo() + Result.BaseType = t._CTypedef(TypeName) + Result.IsTypedef = True + return Result + return Entry.Copy() if Entry else CTypeInfo() if ModuleName == 't': TypeObj = CTypeHelper.GetTModuleCType(TypeName) @@ -417,10 +418,9 @@ class HandlesTypeMerge(BaseHandle): IsEnumMember = False if ModuleParts and len(ModuleParts) >= 2: FirstName = ModuleParts[0] - if self.Trans.SymbolTable.has(FirstName): - Entry = self.Trans.SymbolTable[FirstName] - if Entry and Entry.IsEnum: - return TypeName + Entry = self.Trans.SymbolTable.lookup(FirstName) + if Entry and Entry.IsEnum: + return TypeName FullTypeName = f'{ModuleName}.{TypeName}' @@ -494,18 +494,18 @@ class HandlesTypeMerge(BaseHandle): if AttrModule == 't' and getattr(t, AttrName, None): TypeObj = getattr(t, AttrName) if isinstance(TypeObj, type) and issubclass(TypeObj, t.CType): - return TypeObj().CName + return TypeObj.__name__ return AttrName elif isinstance(TypeArg, ast.Constant): return str(TypeArg.value) if ModuleName in self.Trans._UserTypeModules: module = self.Trans._UserTypeModules[ModuleName] - if getattr(module, TypeName, None): - TypeObj = getattr(module, TypeName) - if isinstance(TypeObj, type): - if issubclass(TypeObj, t.CType): - return TypeObj().CName + if getattr(module, TypeName, None): + TypeObj = getattr(module, TypeName) + if isinstance(TypeObj, type): + if issubclass(TypeObj, t.CType): + return TypeObj.__name__ if ModuleName == 't': TypeObj = CTypeHelper.GetTModuleCType(TypeName) @@ -537,7 +537,7 @@ class HandlesTypeMerge(BaseHandle): elif isinstance(Node, ast.Subscript): if (isinstance(Node.value, ast.Attribute) and isinstance(Node.value.value, ast.Name) - and Node.value.value.id == 't' + and IsTModule(Node.value.value.id, self.Trans.SymbolTable) and Node.value.attr == 'Bit'): if isinstance(Node.slice, ast.Constant) and isinstance(Node.slice.value, int): Result = CTypeInfo() @@ -565,7 +565,7 @@ class HandlesTypeMerge(BaseHandle): return self._MakeVoidCTypeInfo() - def _HandleSubscript(self, Node): + def _HandleSubscript(self, Node: ast.Subscript) -> CTypeInfo: """澶勭悊 Subscript 鑺傜偣锛屼娇鐢?CTypeInfo 鏍戝舰缁撴瀯鍒嗘瀽 AST 例如? @@ -574,7 +574,7 @@ class HandlesTypeMerge(BaseHandle): t.CArrayPtr[t.CArrayPtr] -> void *(*)[] t.CPtr[t.CArrayPtr[t.CArrayPtr]] -> void *(*(*))[] """ - def CollectAll(node, ParentIsArrayPtr=False) -> CTypeInfo: + def CollectAll(node: ast.AST, ParentIsArrayPtr: bool = False) -> CTypeInfo: """鏀堕泦绫诲瀷淇℃伅锛岃繑鍥?CTypeInfo""" if isinstance(node, ast.Subscript): value_node = node.value @@ -583,7 +583,7 @@ class HandlesTypeMerge(BaseHandle): if isinstance(value_node, ast.Attribute): VtInfo = self.GetCTypeInfo(value_node) - if isinstance(value_node, ast.Attribute) and value_node.attr == 'Callable' and isinstance(value_node.value, ast.Name) and value_node.value.id == 't': + if isinstance(value_node, ast.Attribute) and value_node.attr == 'Callable' and isinstance(value_node.value, ast.Name) and IsTModule(value_node.value.id, self.Trans.SymbolTable): if isinstance(slice_node, ast.Tuple) and len(slice_node.elts) == 2: params_list = slice_node.elts[0] return_node = slice_node.elts[1] @@ -761,7 +761,7 @@ class HandlesTypeMerge(BaseHandle): ResultInfo.ArrayDims.append('N') elif isinstance(value_node, ast.Name): ResultInfo = CTypeInfo() - if value_node.id == 'list': + if IsListAnnotation(node): if not isinstance(slice_node, ast.Tuple): ElementType = self._GetCTypeInfoInternal(slice_node) if ElementType and isinstance(ElementType, CTypeInfo): @@ -794,25 +794,40 @@ class HandlesTypeMerge(BaseHandle): else: ResultInfo.BaseType = CTypeInfo.CreateFromTypeName(value_node.id).BaseType else: - ResultInfo.BaseType = CTypeInfo.CreateFromTypeName(value_node.id).BaseType - if isinstance(slice_node, ast.Constant): - ResultInfo.ArrayDims.append(str(slice_node.value)) - elif isinstance(slice_node, ast.Name): - SliceType = getattr(t, slice_node.id, None) - if SliceType == t.CPtr: - ResultInfo.PtrCount += 1 - elif SliceType == t.CArrayPtr: - ResultInfo.ArrayPtr = CTypeInfo() - else: - ResultInfo.ArrayDims.append(slice_node.id) - elif isinstance(slice_node, ast.BinOp): - try: - ResultInfo.ArrayDims.append(ast.unparse(slice_node)) - except Exception: # 回退:unparse 失败时用 'N' - ResultInfo.ArrayDims.append('N') - elif isinstance(slice_node, ast.Subscript): - InnerNode = CollectAll(slice_node) - ResultInfo.ArrayDims.extend(InnerNode.ArrayDims) + # 检查是否为泛型类特化(如 list[str]) + _is_generic_template: bool = ( + hasattr(self.Trans, 'ClassHandler') + and hasattr(self.Trans.ClassHandler, '_generic_class_templates') + and value_node.id in self.Trans.ClassHandler._generic_class_templates + ) + if _is_generic_template: + # 使用完整特化名(如 'list[str]')作为结构体名, + # 这样 _get_or_create_struct 会找到 stub 中已存在的特化结构体 + full_spec_name: str = ast.unparse(node) + ResultInfo.BaseType = t.CStruct(name=full_spec_name) + ResultInfo.Name = full_spec_name + ResultInfo.IsStruct = True + ResultInfo.PtrCount = 1 + else: + ResultInfo.BaseType = CTypeInfo.CreateFromTypeName(value_node.id).BaseType + if isinstance(slice_node, ast.Constant): + ResultInfo.ArrayDims.append(str(slice_node.value)) + elif isinstance(slice_node, ast.Name): + SliceType = getattr(t, slice_node.id, None) + if SliceType == t.CPtr: + ResultInfo.PtrCount += 1 + elif SliceType == t.CArrayPtr: + ResultInfo.ArrayPtr = CTypeInfo() + else: + ResultInfo.ArrayDims.append(slice_node.id) + elif isinstance(slice_node, ast.BinOp): + try: + ResultInfo.ArrayDims.append(ast.unparse(slice_node)) + except Exception: # 回退:unparse 失败时用 'N' + ResultInfo.ArrayDims.append('N') + elif isinstance(slice_node, ast.Subscript): + InnerNode = CollectAll(slice_node) + ResultInfo.ArrayDims.extend(InnerNode.ArrayDims) else: ResultInfo = CTypeInfo() @@ -871,7 +886,7 @@ class HandlesTypeMerge(BaseHandle): elif isinstance(Node, ast.Subscript): if (isinstance(Node.value, ast.Attribute) and isinstance(Node.value.value, ast.Name) - and Node.value.value.id == 't' + and IsTModule(Node.value.value.id, self.Trans.SymbolTable) and Node.value.attr == 'Bit'): if isinstance(Node.slice, ast.Constant) and isinstance(Node.slice.value, int): Result = CTypeInfo() @@ -1050,3 +1065,5 @@ class HandlesTypeMerge(BaseHandle): Target.FuncPtrReturn = Source.FuncPtrReturn if Source.Storage and not Target.Storage: Target.Storage = Source.Storage + if Source.ByteOrder and not Target.ByteOrder: + Target.ByteOrder = Source.ByteOrder diff --git a/lib/core/Handles/HandlesWhile.py b/lib/core/Handles/HandlesWhile.py index 754b026..b7b4eb4 100644 --- a/lib/core/Handles/HandlesWhile.py +++ b/lib/core/Handles/HandlesWhile.py @@ -1,54 +1,54 @@ -from __future__ import annotations -from typing import TYPE_CHECKING -if TYPE_CHECKING: - from lib.core.translator import Translator -from lib.core.Handles.HandlesBase import BaseHandle -import llvmlite.ir as ir - - -class WhileHandle(BaseHandle): - def _HandleWhileLlvm(self, Node): - Gen = self.Trans.LlvmGen - if Gen._direct_values: - for var_name in list(Gen._direct_values.keys()): - OldVal = Gen._direct_values.pop(var_name) - if var_name not in Gen.variables or Gen.variables.get(var_name) is None: - saved_block = Gen.builder.block - entry_block = Gen.func.entry_basic_block - Gen.builder.position_at_start(entry_block) - var = Gen.builder.alloca(OldVal.type, name=var_name) - Gen._store(OldVal, var) - Gen.builder.position_at_end(saved_block) - Gen.variables[var_name] = var - CondBB = Gen.func.append_basic_block(name="while.cond") - BodyBB = Gen.func.append_basic_block(name="while.body") - ElseBB = Gen.func.append_basic_block(name="while.else") if Node.orelse else None - AfterBB = Gen.func.append_basic_block(name="while.end") - Gen.loop_break_targets.append(AfterBB) - Gen.loop_continue_targets.append(CondBB) - Gen.builder.branch(CondBB) - Gen.builder.position_at_start(CondBB) - Cond = self.HandleExprLlvm(Node.test) - if Cond: - if not isinstance(Cond.type, ir.IntType) or Cond.type.width != 1: - if isinstance(Cond.type, (ir.FloatType, ir.DoubleType)): - Cond = Gen.builder.fcmp_ordered('!=', Cond, ir.Constant(Cond.type, 0.0), name="whilecond") - else: - Cond = Gen.builder.icmp_signed('!=', Cond, Gen._ZeroConst(Cond.type), name="whilecond") - if not Gen.builder.block.is_terminated: - Gen.builder.cbranch(Cond, BodyBB, ElseBB if ElseBB else AfterBB) - else: - if not Gen.builder.block.is_terminated: - Gen.builder.branch(ElseBB if ElseBB else AfterBB) - Gen.builder.position_at_start(BodyBB) - self.HandleBodyLlvm(Node.body) - if not Gen.builder.block.is_terminated: - Gen.builder.branch(CondBB) - Gen.loop_break_targets.pop() - Gen.loop_continue_targets.pop() - if ElseBB: - Gen.builder.position_at_start(ElseBB) - self.HandleBodyLlvm(Node.orelse) - if not Gen.builder.block.is_terminated: - Gen.builder.branch(AfterBB) - Gen.builder.position_at_start(AfterBB) +from __future__ import annotations +from typing import TYPE_CHECKING +if TYPE_CHECKING: + from lib.core.translator import Translator +from lib.core.Handles.HandlesBase import BaseHandle +import llvmlite.ir as ir + + +class WhileHandle(BaseHandle): + def _HandleWhileLlvm(self, Node: ast.While) -> None: + Gen: "Translator.LlvmGen" = self.Trans.LlvmGen + if Gen._direct_values: + for var_name in list(Gen._direct_values.keys()): + OldVal: ir.Value = Gen._direct_values.pop(var_name) + if var_name not in Gen.variables or Gen.variables.get(var_name) is None: + saved_block: ir.Block = Gen.builder.block + entry_block: ir.Block = Gen.func.entry_basic_block + Gen.builder.position_at_start(entry_block) + var: ir.AllocaInstr = Gen.builder.alloca(OldVal.type, name=var_name) + Gen._store(OldVal, var) + Gen.builder.position_at_end(saved_block) + Gen.variables[var_name] = var + CondBB: ir.Block = Gen.func.append_basic_block(name="while.cond") + BodyBB: ir.Block = Gen.func.append_basic_block(name="while.body") + ElseBB: ir.Block | None = Gen.func.append_basic_block(name="while.else") if Node.orelse else None + AfterBB: ir.Block = Gen.func.append_basic_block(name="while.end") + Gen.loop_break_targets.append(AfterBB) + Gen.loop_continue_targets.append(CondBB) + Gen.builder.branch(CondBB) + Gen.builder.position_at_start(CondBB) + Cond: ir.Value | None = self.HandleExprLlvm(Node.test) + if Cond: + if not isinstance(Cond.type, ir.IntType) or Cond.type.width != 1: + if isinstance(Cond.type, (ir.FloatType, ir.DoubleType)): + Cond = Gen.builder.fcmp_ordered('!=', Cond, ir.Constant(Cond.type, 0.0), name="whilecond") + else: + Cond = Gen.builder.icmp_signed('!=', Cond, Gen._ZeroConst(Cond.type), name="whilecond") + if not Gen.builder.block.is_terminated: + Gen.builder.cbranch(Cond, BodyBB, ElseBB if ElseBB else AfterBB) + else: + if not Gen.builder.block.is_terminated: + Gen.builder.branch(ElseBB if ElseBB else AfterBB) + Gen.builder.position_at_start(BodyBB) + self.HandleBodyLlvm(Node.body) + if not Gen.builder.block.is_terminated: + Gen.builder.branch(CondBB) + Gen.loop_break_targets.pop() + Gen.loop_continue_targets.pop() + if ElseBB: + Gen.builder.position_at_start(ElseBB) + self.HandleBodyLlvm(Node.orelse) + if not Gen.builder.block.is_terminated: + Gen.builder.branch(AfterBB) + Gen.builder.position_at_start(AfterBB) \ No newline at end of file diff --git a/lib/core/Handles/HandlesWith.py b/lib/core/Handles/HandlesWith.py index 639b981..91bfea4 100644 --- a/lib/core/Handles/HandlesWith.py +++ b/lib/core/Handles/HandlesWith.py @@ -1,138 +1,172 @@ -from __future__ import annotations -from typing import TYPE_CHECKING -if TYPE_CHECKING: - from lib.core.translator import Translator -from lib.core.Handles.HandlesBase import BaseHandle -import ast -import llvmlite.ir as ir - - -class WithHandle(BaseHandle): - def _HandleWithLlvm(self, Node): - Gen = self.Trans.LlvmGen - for item in Node.items: - context_expr = item.context_expr - asname = None - target = getattr(item, 'optional_vars', getattr(item, 'target', getattr(item, 'asname', None))) - if target and isinstance(target, ast.Name): - asname = target.id - ClassName = None - if isinstance(context_expr, ast.Call): - if isinstance(context_expr.func, ast.Name): - ClassName = context_expr.func.id - elif isinstance(context_expr.func, ast.Attribute): - ClassName = context_expr.func.attr - if ClassName and ClassName not in Gen.structs: - if self.Trans.SymbolTable.has(ClassName): - SymInfo = self.Trans.SymbolTable[ClassName] - if SymInfo.IsStruct or SymInfo.IsRenum: - pass - else: - ClassName = None - else: - ClassName = None - elif isinstance(context_expr, ast.Name): - VarName = context_expr.id - if VarName in Gen.var_struct_class: - ClassName = Gen.var_struct_class[VarName] - ctx_val = self.HandleExprLlvm(context_expr) - if not ctx_val: - continue - original_ctx_val = ctx_val - if ClassName and isinstance(ctx_val.type, ir.PointerType): - pointee = ctx_val.type.pointee - if isinstance(pointee, (ir.LiteralStructType, ir.IdentifiedStructType)): - found = Gen.find_struct_by_pointee(pointee) - if found: - CN, ST = found - ClassName = CN - StructPtrType = ir.PointerType(Gen.structs[ClassName]) if ClassName and ClassName in Gen.structs else None - if StructPtrType and isinstance(ctx_val.type, ir.PointerType) and ctx_val.type.pointee != Gen.structs.get(ClassName): - ctx_val = Gen.builder.bitcast(ctx_val, StructPtrType, name="cast_with_ctx") - ctx_alloca = Gen._allocaEntry(ctx_val.type, name="__with_ctx") - Gen._store(ctx_val, ctx_alloca) - Gen._UnregisterTempPtr(ctx_val) - if ClassName: - Gen.var_struct_class['__with_ctx'] = ClassName - Gen._var_to_heap_ptr['__with_ctx'] = ctx_val - original_asname_heap_ptr = Gen._var_to_heap_ptr.get(asname) if asname else None - ctx_is_var_ref = isinstance(context_expr, ast.Name) - enter_result = None - if ClassName: - EnterFuncName = f'{ClassName}.__enter__' - if EnterFuncName in Gen.functions: - ctx_Loaded = Gen._load(ctx_alloca, name="__with_ctx") - enter_call = Gen.builder.call(Gen.functions[EnterFuncName], [ctx_Loaded], name="call_enter") - enter_result = enter_call - if isinstance(enter_call.type, ir.PointerType): - pointee = enter_call.type.pointee - if isinstance(pointee, ir.PointerType) and isinstance(pointee.pointee, (ir.LiteralStructType, ir.IdentifiedStructType)): - enter_result = Gen._load(enter_call, name="enter_deref") - elif self._is_char_pointer(enter_call) and StructPtrType: - enter_result = Gen.builder.bitcast(enter_call, StructPtrType, name="cast_enter") - if asname and enter_result: - if isinstance(enter_result.type, ir.PointerType) and isinstance(enter_result.type.pointee, (ir.LiteralStructType, ir.IdentifiedStructType)): - found = Gen.find_struct_by_pointee(enter_result.type.pointee) - if found: - CN, ST = found - Gen.var_struct_class[asname] = CN - Gen._var_to_heap_ptr[asname] = enter_result - Gen._register_local_heap_ptr(enter_result, VarName=asname) - if asname in Gen._reg_values: - OldVal = Gen._reg_values[asname] - var = Gen._allocaEntry(OldVal.type, name=asname) - Gen._store(OldVal, var) - Gen.variables[asname] = var - del Gen._reg_values[asname] - if asname in Gen.variables and Gen.variables[asname] is not None: - VarPtr = Gen.variables[asname] - if VarPtr.type.pointee == enter_result.type: - Gen._store(enter_result, VarPtr) - elif isinstance(VarPtr.type.pointee, ir.PointerType) and isinstance(enter_result.type, ir.PointerType): - CastedVal = Gen.builder.bitcast(enter_result, VarPtr.type.pointee, name=f"cast_{asname}") - Gen._store(CastedVal, VarPtr) - else: - NewVar = Gen._alloca(enter_result.type, name=asname) - Gen._store(enter_result, NewVar) - Gen.variables[asname] = NewVar - else: - Gen._reg_values[asname] = enter_result - Gen.variables[asname] = None - self.Trans.VarScopes.append({}) - if asname: - self.Trans.VarScopes[-1][asname] = True - self.HandleBodyLlvm(Node.body) - if self.Trans.VarScopes: - self.Trans.VarScopes.pop() - if ClassName: - ExitFuncName = f'{ClassName}.__exit__' - if ExitFuncName in Gen.functions: - ctx_Loaded = Gen._load(ctx_alloca, name="__with_ctx") - Gen.builder.call(Gen.functions[ExitFuncName], [ctx_Loaded], name="call_exit") - Gen._unregister_local_heap_ptr(original_ctx_val) - if ctx_val is not original_ctx_val: - Gen._unregister_local_heap_ptr(ctx_val) - if ctx_is_var_ref and original_asname_heap_ptr and original_asname_heap_ptr is not original_ctx_val and original_asname_heap_ptr is not ctx_val: - Gen._unregister_local_heap_ptr(original_asname_heap_ptr) - if '__with_ctx' in Gen._var_to_heap_ptr: - del Gen._var_to_heap_ptr['__with_ctx'] - if asname and enter_result is not None and isinstance(ctx_val.type, ir.PointerType) and isinstance(enter_result.type, ir.PointerType): - ctx_int = Gen.builder.ptrtoint(ctx_val, ir.IntType(64), name="ctx_int") - enter_int = Gen.builder.ptrtoint(enter_result, ir.IntType(64), name="enter_int") - same_ptr = Gen.builder.icmp_unsigned('==', ctx_int, enter_int, name="same_ptr_check") - with_free_bb = Gen.func.append_basic_block("with_free_ctx") - with_skip_bb = Gen.func.append_basic_block("with_skip_free") - Gen.builder.cbranch(same_ptr, with_skip_bb, with_free_bb) - Gen.builder.position_at_start(with_free_bb) - raw = Gen.builder.bitcast(ctx_val, ir.PointerType(ir.IntType(8)), name="with_free_cast") - free_func = Gen.get_or_declare_c_func('free', ir.FunctionType(ir.VoidType(), [ir.PointerType(ir.IntType(8))])) - Gen.builder.call(free_func, [raw]) - Gen.builder.branch(with_skip_bb) - Gen.builder.position_at_start(with_skip_bb) - Gen._unregister_local_heap_ptr(enter_result) - Gen._unregister_local_heap_ptr(original_ctx_val) - elif isinstance(ctx_val.type, ir.PointerType): - raw = Gen.builder.bitcast(ctx_val, ir.PointerType(ir.IntType(8)), name="with_free_cast") - free_func = Gen.get_or_declare_c_func('free', ir.FunctionType(ir.VoidType(), [ir.PointerType(ir.IntType(8))])) - Gen.builder.call(free_func, [raw]) +from __future__ import annotations +from typing import TYPE_CHECKING +if TYPE_CHECKING: + from lib.core.translator import Translator +from lib.core.Handles.HandlesBase import BaseHandle +import ast +import llvmlite.ir as ir + + +class WithHandle(BaseHandle): + def _HandleWithLlvm(self, Node: ast.With) -> None: + Gen: "Translator.LlvmGen" = self.Trans.LlvmGen + for item in Node.items: + context_expr: ast.expr = item.context_expr + asname: str | None = None + target: ast.expr | None = getattr(item, 'optional_vars', getattr(item, 'target', getattr(item, 'asname', None))) + if target and isinstance(target, ast.Name): + asname = target.id + ClassName: str | None = None + if isinstance(context_expr, ast.Call): + if isinstance(context_expr.func, ast.Name): + ClassName = context_expr.func.id + elif isinstance(context_expr.func, ast.Attribute): + ClassName = context_expr.func.attr + if ClassName and ClassName not in Gen.structs: + SymInfo: "SymbolTable.SymbolInfo" = self.Trans.SymbolTable.lookup(ClassName) + if SymInfo: + if SymInfo.IsStruct or SymInfo.IsRenum: + pass + else: + ClassName = None + else: + ClassName = None + elif isinstance(context_expr, ast.Name): + VarName: str = context_expr.id + if VarName in Gen.var_struct_class: + ClassName = Gen.var_struct_class[VarName] + ctx_val: ir.Value | None = self.HandleExprLlvm(context_expr) + if not ctx_val: + continue + original_ctx_val: ir.Value = ctx_val + if ClassName and isinstance(ctx_val.type, ir.PointerType): + pointee: ir.Type = ctx_val.type.pointee + if isinstance(pointee, (ir.LiteralStructType, ir.IdentifiedStructType)): + found: tuple[str, ir.Type] | None = Gen.find_struct_by_pointee(pointee) + if found: + CN: str = found[0] + ST: ir.Type = found[1] + ClassName = CN + StructPtrType: ir.PointerType | None = ir.PointerType(Gen.structs[ClassName]) if ClassName and ClassName in Gen.structs else None + if StructPtrType and isinstance(ctx_val.type, ir.PointerType) and ctx_val.type.pointee != Gen.structs.get(ClassName): + ctx_val = Gen.builder.bitcast(ctx_val, StructPtrType, name="cast_with_ctx") + ctx_alloca: ir.AllocaInstr = Gen._allocaEntry(ctx_val.type, name="__with_ctx") + Gen._store(ctx_val, ctx_alloca) + Gen._UnregisterTempPtr(ctx_val) + if ClassName: + Gen.var_struct_class['__with_ctx'] = ClassName + Gen._var_to_heap_ptr['__with_ctx'] = ctx_val + original_asname_heap_ptr: ir.Value | None = Gen._var_to_heap_ptr.get(asname) if asname else None + ctx_is_var_ref: bool = isinstance(context_expr, ast.Name) + enter_result: ir.Value | None = None + if ClassName: + EnterFuncName: str = f'{ClassName}.__enter__' + if EnterFuncName in Gen.functions: + ctx_Loaded: ir.Value = Gen._load(ctx_alloca, name="__with_ctx") + enter_call: ir.CallInstr = Gen.builder.call(Gen.functions[EnterFuncName], [ctx_Loaded], name="call_enter") + enter_result = enter_call + if isinstance(enter_call.type, ir.PointerType): + pointee: ir.Type = enter_call.type.pointee + if isinstance(pointee, ir.PointerType) and isinstance(pointee.pointee, (ir.LiteralStructType, ir.IdentifiedStructType)): + enter_result = Gen._load(enter_call, name="enter_deref") + elif self._is_char_pointer(enter_call) and StructPtrType: + enter_result = Gen.builder.bitcast(enter_call, StructPtrType, name="cast_enter") + if asname and enter_result: + if isinstance(enter_result.type, ir.PointerType) and isinstance(enter_result.type.pointee, (ir.LiteralStructType, ir.IdentifiedStructType)): + found: tuple[str, ir.Type] | None = Gen.find_struct_by_pointee(enter_result.type.pointee) + if found: + CN: str = found[0] + ST: ir.Type = found[1] + Gen.var_struct_class[asname] = CN + Gen._var_to_heap_ptr[asname] = enter_result + Gen._register_local_heap_ptr(enter_result, VarName=asname) + if asname in Gen._reg_values: + OldVal: ir.Value = Gen._reg_values[asname] + var: ir.AllocaInstr = Gen._allocaEntry(OldVal.type, name=asname) + Gen._store(OldVal, var) + Gen.variables[asname] = var + del Gen._reg_values[asname] + if asname in Gen.variables and Gen.variables[asname] is not None: + VarPtr: ir.Value = Gen.variables[asname] + if VarPtr.type.pointee == enter_result.type: + Gen._store(enter_result, VarPtr) + elif isinstance(VarPtr.type.pointee, ir.PointerType) and isinstance(enter_result.type, ir.PointerType): + CastedVal: ir.Value = Gen.builder.bitcast(enter_result, VarPtr.type.pointee, name=f"cast_{asname}") + Gen._store(CastedVal, VarPtr) + else: + NewVar: ir.AllocaInstr = Gen._alloca(enter_result.type, name=asname) + Gen._store(enter_result, NewVar) + Gen.variables[asname] = NewVar + else: + Gen._reg_values[asname] = enter_result + Gen.variables[asname] = None + # 如果类有 __provides__,自动生成 push 代码 + if ClassName and ClassName in Gen.class_provides: + # 编译期检查: with provider 栈深度是否超过 _MAX_PROVIDER_DEPTH (32) + # _with_provides_stack 只反映当前嵌套路径,顺序执行的 with 会在退出时弹栈 + current_depth: int = sum(len(pl) for pl in Gen._with_provides_stack) + new_fields: int = len(Gen.class_provides[ClassName]) + if current_depth + new_fields > 32: + raise SyntaxError( + f"[TransPyC] with provider stack overflow at line {Node.lineno}: " + f"current depth {current_depth} + new {new_fields} fields > max 32. " + f"Class '{ClassName}' provides too many fields or with nesting too deep." + ) + # 编译期压栈:记录当前 with 上下文提供的字段名,供 __require_must__ 静态检查 + Gen._with_provides_stack.append(Gen.class_provides[ClassName]) + ctx_Loaded: ir.Value = Gen._load(ctx_alloca, name="__with_ctx") + ctx_i8: ir.Value = ctx_Loaded + if isinstance(ctx_Loaded.type, ir.PointerType) and ctx_Loaded.type != ir.PointerType(ir.IntType(8)): + ctx_i8 = Gen.builder.bitcast(ctx_Loaded, ir.PointerType(ir.IntType(8)), name="ctx_push_i8") + for field_name in Gen.class_provides[ClassName]: + field_str: ir.Value = Gen._create_string_global(field_name) + push_func = Gen.functions.get('_push_provider') + if push_func: + Gen.builder.call(push_func, [field_str, ctx_i8], name="call_push_provider") + self.Trans.VarScopes.append({}) + if asname: + self.Trans.VarScopes[-1][asname] = True + self.HandleBodyLlvm(Node.body) + if self.Trans.VarScopes: + self.Trans.VarScopes.pop() + # 如果类有 __provides__,自动生成 pop 代码 + if ClassName and ClassName in Gen.class_provides: + for _ in Gen.class_provides[ClassName]: + pop_func = Gen.functions.get('_pop_provider') + if pop_func: + Gen.builder.call(pop_func, [], name="call_pop_provider") + # 编译期弹栈 + if Gen._with_provides_stack: + Gen._with_provides_stack.pop() + if ClassName: + ExitFuncName: str = f'{ClassName}.__exit__' + if ExitFuncName in Gen.functions: + ctx_Loaded: ir.Value = Gen._load(ctx_alloca, name="__with_ctx") + Gen.builder.call(Gen.functions[ExitFuncName], [ctx_Loaded], name="call_exit") + Gen._unregister_local_heap_ptr(original_ctx_val) + if ctx_val is not original_ctx_val: + Gen._unregister_local_heap_ptr(ctx_val) + if ctx_is_var_ref and original_asname_heap_ptr and original_asname_heap_ptr is not original_ctx_val and original_asname_heap_ptr is not ctx_val: + Gen._unregister_local_heap_ptr(original_asname_heap_ptr) + if '__with_ctx' in Gen._var_to_heap_ptr: + del Gen._var_to_heap_ptr['__with_ctx'] + if asname and enter_result is not None and isinstance(ctx_val.type, ir.PointerType) and isinstance(enter_result.type, ir.PointerType): + ctx_int: ir.Value = Gen.builder.ptrtoint(ctx_val, ir.IntType(64), name="ctx_int") + enter_int: ir.Value = Gen.builder.ptrtoint(enter_result, ir.IntType(64), name="enter_int") + same_ptr: ir.Value = Gen.builder.icmp_unsigned('==', ctx_int, enter_int, name="same_ptr_check") + with_free_bb: ir.Block = Gen.func.append_basic_block("with_free_ctx") + with_skip_bb: ir.Block = Gen.func.append_basic_block("with_skip_free") + Gen.builder.cbranch(same_ptr, with_skip_bb, with_free_bb) + Gen.builder.position_at_start(with_free_bb) + raw: ir.Value = Gen.builder.bitcast(ctx_val, ir.PointerType(ir.IntType(8)), name="with_free_cast") + free_func: ir.Function = Gen.get_or_declare_c_func('free', ir.FunctionType(ir.VoidType(), [ir.PointerType(ir.IntType(8))])) + Gen.builder.call(free_func, [raw]) + Gen.builder.branch(with_skip_bb) + Gen.builder.position_at_start(with_skip_bb) + Gen._unregister_local_heap_ptr(enter_result) + Gen._unregister_local_heap_ptr(original_ctx_val) + elif isinstance(ctx_val.type, ir.PointerType): + raw: ir.Value = Gen.builder.bitcast(ctx_val, ir.PointerType(ir.IntType(8)), name="with_free_cast") + free_func: ir.Function = Gen.get_or_declare_c_func('free', ir.FunctionType(ir.VoidType(), [ir.PointerType(ir.IntType(8))])) + Gen.builder.call(free_func, [raw]) Gen._unregister_local_heap_ptr(original_ctx_val) \ No newline at end of file diff --git a/lib/core/LLVMCG/BaseGen.py b/lib/core/LLVMCG/BaseGen.py index edf28d5..f874648 100644 --- a/lib/core/LLVMCG/BaseGen.py +++ b/lib/core/LLVMCG/BaseGen.py @@ -1,416 +1,491 @@ -from __future__ import annotations -import re -import ast -import os -import hashlib -import llvmlite.ir as ir -from llvmlite.ir.values import _Undefined - - -class VaArgInstruction(ir.Instruction): - def descr(self, buf): - ptr = self.operands[0] - buf.append("va_arg {0} {1}, {2}\n".format( - ptr.type, ptr.get_reference(), self.type)) - - -class BaseGenMixin: - - @staticmethod - def _parse_triple(triple): - """解析目标三元组,返回平台信息字典""" - info = { - 'is_windows': False, 'is_linux': False, 'is_macos': False, - 'is_x86_64': False, 'is_arm64': False, 'is_32bit': False, - 'ptr_size': 8, 'long_size': 8, 'wchar_t_size': 32, - } - if not triple: - return info - triple_lower = triple.lower() - # 检测操作系统 - if 'windows' in triple_lower or 'win32' in triple_lower or 'mingw' in triple_lower or 'msvc' in triple_lower or 'cygwin' in triple_lower: - info['is_windows'] = True - # Windows LLP64: long = 32 位, wchar_t = 16 位 - info['long_size'] = 32 - info['wchar_t_size'] = 16 - elif 'linux' in triple_lower: - info['is_linux'] = True - elif 'darwin' in triple_lower or 'macos' in triple_lower or 'apple' in triple_lower: - info['is_macos'] = True - # 检测架构 - if 'x86_64' in triple_lower or 'amd64' in triple_lower or 'x64' in triple_lower: - info['is_x86_64'] = True - elif 'aarch64' in triple_lower or 'arm64' in triple_lower: - info['is_arm64'] = True - elif 'i386' in triple_lower or 'i686' in triple_lower or 'arm' in triple_lower: - info['is_32bit'] = True - info['ptr_size'] = 4 - info['long_size'] = 32 - if info['is_windows']: - info['wchar_t_size'] = 16 - else: - info['wchar_t_size'] = 32 - return info - - def __init__(self, triple=None, datalayout=None): - self.module = ir.Module(name="transpyc_module") - if triple: - self.module.triple = triple - else: - self.module.triple = "x86_64-none-elf" - if datalayout: - self.module.data_layout = datalayout - else: - self.module.data_layout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - - # 解析目标平台信息 - self._platform_info = self._parse_triple(self.module.triple) - self.ptr_size = self._platform_info['ptr_size'] - # 根据目标平台配置 t 模块中的平台相关类型大小 - import t as _t - _t.configure_platform(self.module.triple) - self.builder = None - self.func = None - self.functions = {} - self.variables = {} - self._direct_values = {} - self._reg_values = {} - self.var_signedness = {} - self._unsigned_results = {} - self.string_const_counter = 0 - self.Vtables = {} - self.class_methods = {} - self.class_members = {} - self.class_member_defaults = {} - self.class_member_signeds = {} - self.class_member_bitfields = {} - self.class_member_byteorders = {} - self.class_member_element_class = {} - self.class_member_bitoffsets = {} - self.structs = {} - self.typedef_int_widths = {} # typedef名称 -> 底层整数位宽 (如 'UINT' -> 32, 'BYTE' -> 8) - self._cross_module_vtable_classes = set() - self.class_vtable = set() - self.class_parent = {} - # Store member annotations for deferred type resolution (cross-module class references) - self.class_member_annotations = {} - self.loop_break_targets = [] - self.loop_continue_targets = [] - self.eh_jmp_buf_stack = [] - self.eh_except_block_stack = [] - self.eh_finally_stack = [] - self.global_vars = set() - self.nonlocal_params = {} - self._variable_scope_stack = [] # Stack of outer scope variables for nested function nonlocal lookup - self.var_struct_class = {} - self.global_struct_class = {} - self.var_type_info = {} - self.var_const_flags = {} - self._current_source_file = None - self._current_source_lines = [] - self._ns_cache = {} - self._type_cache = {} - self._typedef_cache = {} - self._func_sig_cache = {} - self.var_type_assignments = {} - self._temp_struct_ptrs = [] - self._stop_iter_flag_param = None - self._local_heap_ptrs = [] - self._var_to_heap_ptr = {} - self.known_return_types = {} - self._current_lineno = 0 - self._current_node_info = "" - self.module_sha1 = None - self.ModuleSha1Map = {} - self._temp_dir = None - self._export_funcs = set() - self._export_extern_funcs = set() - self._current_module_func_names = set() - self.class_packed = set() - self._define_constants = {} - pi = self._platform_info - # 根据目标平台设置宏(声明式,从三元组推导) - if pi['is_windows']: - self._define_constants['_WIN32'] = 1 - if not pi['is_32bit']: - self._define_constants['_WIN64'] = 1 - self._define_constants['WIN64'] = 1 - self._define_constants['WIN32'] = 1 - if pi['is_linux']: - self._define_constants['__linux__'] = 1 - if pi['is_macos']: - self._define_constants['__APPLE__'] = 1 - self._define_constants['__MACH__'] = 1 - if pi['is_x86_64']: - self._define_constants['__x86_64__'] = 1 - self._define_constants['__x86_64'] = 1 - self._define_constants['_M_X64'] = 1 - elif pi['is_arm64']: - self._define_constants['__aarch64__'] = 1 - self._define_constants['_M_ARM64'] = 1 - if not pi['is_32bit'] and pi['is_linux']: - self._define_constants['__LP64__'] = 1 - elif pi['is_32bit']: - self._define_constants['_ILP32'] = 1 - self._define_constants['SIZEOF_VOID_P'] = pi['ptr_size'] - self._define_constants['__SIZEOF_POINTER__'] = pi['ptr_size'] - - def find_struct_by_pointee(self, pointee): - """根据 pointee 类型查找匹配的结构体,返回 (class_name, struct_type) 或 None""" - for class_name, struct_type in self.structs.items(): - if pointee == struct_type: - return (class_name, struct_type) - return None - - def _get_or_create_struct(self, name, source_sha1=None, packed=False): - clean_name = name.replace(' *', '').replace('*', '').replace(' ', '_').replace('const', 'const_').replace('volatile', 'volatile_') - if clean_name in self.structs: - existing = self.structs[clean_name] - if packed and isinstance(existing, ir.IdentifiedStructType) and not existing.packed: - existing.packed = True - return existing - if clean_name in {'typedef', 'CType', 'CVolatile', 'CEnum', 'CUnion', 'CStruct', 'enum', 'REnum', 'renum', 'Void', 'void'}: - return ir.IntType(8) - if hasattr(self, 'SymbolTable') and self.SymbolTable and self.SymbolTable.has(clean_name): - Entry = self.SymbolTable[clean_name] - if Entry.IsTypedef: - resolved_str = self._resolve_typedef(clean_name) - if resolved_str != clean_name: - return self._type_str_to_llvm(resolved_str) - if Entry.BaseType: - from lib.includes import t as _t - if not isinstance(Entry.BaseType, (_t._CTypedef,)) or Entry.PtrCount > 0: - resolved = self._resolve_ctype_to_str(Entry) - if resolved: - return self._type_str_to_llvm(resolved) - if Entry.IsRenum: - if clean_name in self.structs: - return self.structs[clean_name] - if Entry.IsEnum: - return ir.IntType(32) - if Entry.IsExceptionClass: - return ir.IntType(32) - if Entry.IsFunction: - return ir.PointerType(ir.IntType(8)) - if Entry.IsVariable: - return ir.PointerType(ir.IntType(8)) - if Entry.BaseType: - from lib.includes import t as _t - if isinstance(Entry.BaseType, type) and issubclass(Entry.BaseType, _t.CEnum): - return ir.IntType(32) - if Entry.BaseType is _t.CEnum: - return ir.IntType(32) - if source_sha1: - ns_name = f"{source_sha1}.{clean_name}" - elif hasattr(self, '_struct_sha1_map') and clean_name in self._struct_sha1_map: - ns_name = f"{self._struct_sha1_map[clean_name]}.{clean_name}" - else: - ns_name = self._mangle_name(clean_name) - st = ir.IdentifiedStructType(self.module, name=ns_name, packed=packed) - self.structs[clean_name] = st - # 尝试解析 typedef 的底层整数位宽 - width = self._resolve_typedef_int_width(clean_name) - if width is not None: - self.typedef_int_widths[clean_name] = width - return st - - def _resolve_typedef_int_width(self, name: str): - """解析 typedef 名称的底层整数位宽 - - 通过 CTypeRegistry 和 BuiltinTypeMap 动态解析, - 替代硬编码的 TYPEDEF_NAMES 映射表。 - 返回 int 位宽或 None(无法解析)。 - """ - from lib.includes.t import CTypeRegistry - from lib.core.Handles.HandlesBase import BuiltinTypeMap - - # 1. 先查 BuiltinTypeMap(覆盖 BYTEPTR 等指针别名) - bm = BuiltinTypeMap.Get(name) - if bm: - ctype_cls, ptr_count = bm - if ptr_count > 0: - return None # 指针类型,不是整数 typedef - llvm_str = CTypeRegistry.CTypeToLLVM(ctype_cls) - if llvm_str and llvm_str.startswith('i') and llvm_str[1:].isdigit(): - return int(llvm_str[1:]) - - # 2. 再查 SymbolTable(用户定义的 typedef) - if hasattr(self, 'SymbolTable') and self.SymbolTable and self.SymbolTable.has(name): - Entry = self.SymbolTable[name] - if Entry.IsTypedef: - if Entry.BaseType: - from lib.includes import t as _t - if not isinstance(Entry.BaseType, (_t._CTypedef,)) and Entry.PtrCount == 0: - llvm_str = CTypeRegistry.CTypeToLLVM(type(Entry.BaseType) if isinstance(Entry.BaseType, _t.CType) else Entry.BaseType) - if llvm_str and llvm_str.startswith('i') and llvm_str[1:].isdigit(): - return int(llvm_str[1:]) - if Entry.OriginalType: - from lib.core.Handles.HandlesBase import CTypeInfo as _CTypeInfo - if isinstance(Entry.OriginalType, _CTypeInfo) and Entry.OriginalType.BaseType: - if not isinstance(Entry.OriginalType.BaseType, (_t._CTypedef,)) and Entry.OriginalType.PtrCount == 0: - llvm_str = CTypeRegistry.CTypeToLLVM(type(Entry.OriginalType.BaseType) if isinstance(Entry.OriginalType.BaseType, _t.CType) else Entry.OriginalType.BaseType) - if llvm_str and llvm_str.startswith('i') and llvm_str[1:].isdigit(): - return int(llvm_str[1:]) - - # 3. 尝试 CTypeRegistry 直接按名称查找 - ctype_cls = CTypeRegistry.GetClassByName(name) - if ctype_cls: - llvm_str = CTypeRegistry.CTypeToLLVM(ctype_cls) - if llvm_str and llvm_str.startswith('i') and llvm_str[1:].isdigit(): - return int(llvm_str[1:]) - - # 4. 特殊名称(非整数类型,但需要标记为 typedef 以跳过 opaque 定义) - _SPECIAL_TYPEDEFS = { - 'typedef', 'CType', 'CVolatile', 'CEnum', 'CUnion', - 'CStruct', 'enum', 'REnum', 'renum', - 'list', 'dict', 'tuple', 'set', 'str', 'bytes', 'array', 'type', - } - if name in _SPECIAL_TYPEDEFS: - return 0 # 标记为 typedef,但位宽为 0(非整数) - - return None - - def _set_node_info(self, node, extra_info=""): - if hasattr(node, 'lineno'): - self._current_lineno = node.lineno - else: - self._current_lineno = 0 - if hasattr(node, 'col_offset'): - self._current_node_info = f"line {self._current_lineno}, col {node.col_offset}" - else: - self._current_node_info = f"line {self._current_lineno}" - if extra_info: - self._current_node_info += f" ({extra_info})" - - def _set_source_info(self, filepath): - self._current_source_file = filepath - try: - with open(filepath, 'r', encoding='utf-8') as f: - self._current_source_lines = f.readlines() - except Exception: # 文件读取失败时回退为空行列表 - self._current_source_lines = [] - - def _ns_hash(self): - if 'workspace' in self._ns_cache: - return self._ns_cache['workspace'] - cwd = os.getcwd().replace('\\', '/').lower() - digest = hashlib.sha1(cwd.encode('utf-8')).hexdigest()[:12] - self._ns_cache['workspace'] = digest - return digest - - def _skip_mangle(self, name): - skip_prefixes = ('llvm.', 'str_const_', 'printf', 'memset_pattern') - if any(name.startswith(p) for p in skip_prefixes): - return True - if '.' in name: - parts = name.split('.', 1) - if len(parts[0]) >= 8 and all(c in '0123456789abcdef' for c in parts[0]): - return True - return False - - def _mangle_name(self, name): - if self._skip_mangle(name): - return name - if name in self._export_funcs: - return name - if self.module_sha1: - return f"{self.module_sha1}.{name}" - return name - - def _find_function(self, name): - if name in self.functions: - return self.functions[name] - g = self.module.globals.get(name) - if g and isinstance(g, ir.Function): - self.functions[name] = g - return g - mangled = self._mangle_func_name(name) - if mangled != name: - if mangled in self.functions: - self.functions[name] = self.functions[mangled] - return self.functions[mangled] - g = self.module.globals.get(mangled) - if g and isinstance(g, ir.Function): - self.functions[mangled] = g - self.functions[name] = g - return g - for sha1 in self.ModuleSha1Map.values(): - prefixed = f"{sha1}.{name}" - if prefixed in self.functions: - self.functions[name] = self.functions[prefixed] - return self.functions[prefixed] - g = self.module.globals.get(prefixed) - if g and isinstance(g, ir.Function): - self.functions[prefixed] = g - self.functions[name] = g - return g - return None - - def _has_function(self, name): - return self._find_function(name) is not None - - def _get_or_declare_function(self, mangled_name, func_type): - for g in self.module.globals: - if isinstance(g, ir.Function) and g.name == mangled_name: - return g - return ir.Function(self.module, func_type, name=mangled_name) - - def _get_function(self, name): - func = self._find_function(name) - return func - - def _mangle_func_name(self, name, module_name=None): - if name in self._export_funcs: - return name - if name in self._export_extern_funcs and name not in self._current_module_func_names: - return name - # main 函数作为程序入口点,永远不混淆 - if name == 'main': - return name - # Try class_sha1_map first for class methods (e.g., 'md5.__init__' -> class 'md5') - class_sha1_map = getattr(self, 'class_sha1_map', {}) - if class_sha1_map: - if '.' in name: - base_class = name.split('.')[0] - if base_class in class_sha1_map: - sha1 = class_sha1_map[base_class] - return f"{sha1}.{name}" - elif name in class_sha1_map: - sha1 = class_sha1_map[name] - return f"{sha1}.{name}" - # If module_name is already a SHA1 hash (16 hex chars), use it directly - if module_name and len(module_name) == 16 and all(c in '0123456789abcdef' for c in module_name): - return f"{module_name}.{name}" - if module_name and module_name in self.ModuleSha1Map: - sha1 = self.ModuleSha1Map[module_name] - return f"{sha1}.{name}" - # Try parent package name (e.g., 'hashlib' -> 'hashlib.__init__') - if module_name: - init_name = f"{module_name}.__init__" - if init_name in self.ModuleSha1Map: - sha1 = self.ModuleSha1Map[init_name] - return f"{sha1}.{name}" - if self._skip_mangle(name): - return name - if self.module_sha1: - return f"{self.module_sha1}.{name}" - return name - - def _get_source_line(self, lineno): - if 0 < lineno <= len(self._current_source_lines): - return self._current_source_lines[lineno - 1].rstrip('\r\n') - return None - - def _get_node_info(self): - info = "" - if self._current_node_info: - info = f" [{self._current_node_info}]" - if self._current_source_file: - info += f" in {self._current_source_file}" - lineno = self._current_lineno - if lineno > 0: - info += f", line {lineno}:" - source_line = self._get_source_line(lineno) - if source_line: - info += f"\n → {source_line}" - return info +from __future__ import annotations +from typing import Any +import re +import ast +import os +import hashlib +import llvmlite.ir as ir +from llvmlite.ir.values import _Undefined +from lib.includes import t as _t +from lib.includes.t import CTypeRegistry +from lib.core.Handles.HandlesBase import CTypeInfo as _CTypeInfo, BuiltinTypeMap +from lib.constants.config import mode as _config_mode + + +class VaArgInstruction(ir.Instruction): + def descr(self, buf: list[str]) -> None: + ptr: ir.Value = self.operands[0] + buf.append("va_arg {0} {1}, {2}\n".format( + ptr.type, ptr.get_reference(), self.type)) + + +class BaseGenMixin: + + @staticmethod + def _parse_triple(triple: str | None) -> dict[str, bool | int]: + """解析目标三元组,返回平台信息字典""" + info: dict[str, bool | int] = { + 'is_windows': False, 'is_linux': False, 'is_macos': False, + 'is_x86_64': False, 'is_arm64': False, 'is_32bit': False, + 'ptr_size': 8, 'long_size': 8, 'wchar_t_size': 32, + } + if not triple: + return info + triple_lower: str = triple.lower() + # 检测操作系统 + if 'windows' in triple_lower or 'win32' in triple_lower or 'mingw' in triple_lower or 'msvc' in triple_lower or 'cygwin' in triple_lower: + info['is_windows'] = True + # Windows LLP64: long = 32 位, wchar_t = 16 位 + info['long_size'] = 32 + info['wchar_t_size'] = 16 + elif 'linux' in triple_lower: + info['is_linux'] = True + elif 'darwin' in triple_lower or 'macos' in triple_lower or 'apple' in triple_lower: + info['is_macos'] = True + # 检测架构 + if 'x86_64' in triple_lower or 'amd64' in triple_lower or 'x64' in triple_lower: + info['is_x86_64'] = True + elif 'aarch64' in triple_lower or 'arm64' in triple_lower: + info['is_arm64'] = True + elif 'i386' in triple_lower or 'i686' in triple_lower or 'arm' in triple_lower: + info['is_32bit'] = True + info['ptr_size'] = 4 + info['long_size'] = 32 + if info['is_windows']: + info['wchar_t_size'] = 16 + else: + info['wchar_t_size'] = 32 + return info + + def __init__(self, triple: str | None = None, datalayout: str | None = None) -> None: + self.module: ir.Module = ir.Module(name="transpyc_module") + if triple: + self.module.triple = triple + else: + self.module.triple = "x86_64-none-elf" + if datalayout: + self.module.data_layout = datalayout + else: + self.module.data_layout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" + + # 解析目标平台信息 + self._platform_info: dict[str, bool | int] = self._parse_triple(self.module.triple) + self.ptr_size: int = self._platform_info['ptr_size'] + # 根据目标平台配置 t 模块中的平台相关类型大小 + _t.configure_platform(self.module.triple) + self.builder: ir.IRBuilder | None = None + self.func: ir.Function | None = None + self.functions: dict[str, ir.Function] = {} + self.variables: dict[str, ir.Value | None] = {} + self._direct_values: dict[str, ir.Value] = {} + self._reg_values: dict[str, ir.Value] = {} + self.var_signedness: dict[str, bool] = {} + self._unsigned_results: set[int] = {} + self.string_const_counter: int = 0 + self.Vtables: dict[str, ir.GlobalVariable] = {} + self.class_methods: dict[str, list[str]] = {} + self.class_members: dict[str, list[tuple[str, ir.Type]]] = {} + self.class_member_defaults: dict[str, dict[str, Any]] = {} + self.class_member_signeds: dict[str, dict[str, bool]] = {} + self.class_member_bitfields: dict[str, dict[str, int]] = {} + self.class_member_byteorders: dict[str, dict[str, str]] = {} + self.local_var_byteorders: dict[str, str] = {} + self.class_member_element_class: dict[str, dict[str, str]] = {} + self.class_member_bitoffsets: dict[str, dict[str, int]] = {} + self.structs: dict[str, ir.IdentifiedStructType] = {} + self.typedef_int_widths: dict[str, int] = {} # typedef名称 -> 底层整数位宽 (如 'UINT' -> 32, 'BYTE' -> 8) + self._cross_module_vtable_classes: set[str] = set() + self.class_vtable: set[str] = set() + self._class_graph: dict[str, Any] = {} + self.class_parent: dict[str, str] = {} + # Store member annotations for deferred type resolution (cross-module class references) + self.class_member_annotations: dict[str, dict[str, Any]] = {} + self.loop_break_targets: list[ir.Block] = [] + self.loop_continue_targets: list[ir.Block] = [] + self.eh_jmp_buf_stack: list[ir.Value] = [] + self.eh_except_block_stack: list[ir.Block] = [] + self.eh_finally_stack: list[Any] = [] + self.global_vars: set[str] = set() + self.nonlocal_params: dict[str, Any] = {} + self._variable_scope_stack: list[dict[str, Any]] = [] # Stack of outer scope variables for nested function nonlocal lookup + self.var_struct_class: dict[str, str] = {} + self.var_ptr_element: dict[str, bool] = {} + self.class_provides: dict[str, list[str]] = {} + self.class_requires: dict[str, list[str]] = {} + self.class_require_must: dict[str, list[str]] = {} + # 编译期 with 上下文栈:记录当前嵌套 with 链中所有可用的 provides 字段名 + # 用于 __require_must__ 的纯编译期静态可达性检查 + self._with_provides_stack: list[list[str]] = [] + # 函数参数自动取地址模式: func_name -> [None, None, 'need', 'always', ...] + # 'need': t.CNeedPtr — 仅对非指针值取地址 + # 'always': t.CAutoPtr — 无条件取地址 + self._auto_addr_params: dict[str, list[str | None]] = {} + self.global_struct_class: dict[str, str] = {} + self.var_type_info: dict[str, Any] = {} + self.var_const_flags: dict[str, bool] = {} + self._current_source_file: str | None = None + self._current_source_lines: list[str] = [] + self._ns_cache: dict[str, str] = {} + self._type_cache: dict[tuple[str, bool], ir.Type] = {} + self._typedef_cache: dict[str, Any] = {} + self._func_sig_cache: dict[str, Any] = {} + self.var_type_assignments: dict[str, Any] = {} + self._temp_struct_ptrs: list[ir.Value] = [] + self._stop_iter_flag_param: ir.Value | None = None + self._local_heap_ptrs: list[tuple[ir.Value, str, str | None]] = [] + self._var_to_heap_ptr: dict[str, ir.Value] = {} + self.known_return_types: dict[str, ir.Type] = {} + self._current_lineno: int = 0 + self._current_node_info: str = "" + self.module_sha1: str | None = None + self.ModuleSha1Map: dict[str, str] = {} + self._temp_dir: str | None = None + self._export_funcs: set[str] = set() + self._export_extern_funcs: set[str] = set() + self._current_module_func_names: set[str] = set() + self.class_packed: set[str] = set() + self._define_constants: dict[str, int] = {} + pi: dict[str, bool | int] = self._platform_info + # 根据目标平台设置宏(声明式,从三元组推导) + if pi['is_windows']: + self._define_constants['_WIN32'] = 1 + if not pi['is_32bit']: + self._define_constants['_WIN64'] = 1 + self._define_constants['WIN64'] = 1 + self._define_constants['WIN32'] = 1 + if pi['is_linux']: + self._define_constants['__linux__'] = 1 + if pi['is_macos']: + self._define_constants['__APPLE__'] = 1 + self._define_constants['__MACH__'] = 1 + if pi['is_x86_64']: + self._define_constants['__x86_64__'] = 1 + self._define_constants['__x86_64'] = 1 + self._define_constants['_M_X64'] = 1 + elif pi['is_arm64']: + self._define_constants['__aarch64__'] = 1 + self._define_constants['_M_ARM64'] = 1 + if not pi['is_32bit'] and pi['is_linux']: + self._define_constants['__LP64__'] = 1 + elif pi['is_32bit']: + self._define_constants['_ILP32'] = 1 + self._define_constants['SIZEOF_VOID_P'] = pi['ptr_size'] + self._define_constants['__SIZEOF_POINTER__'] = pi['ptr_size'] + + def find_struct_by_pointee(self, pointee: ir.Type) -> tuple[str, ir.IdentifiedStructType] | None: + """根据 pointee 类型查找匹配的结构体,返回 (class_name, struct_type) 或 None""" + for class_name, struct_type in self.structs.items(): + if pointee == struct_type: + return (class_name, struct_type) + return None + + def _get_or_create_struct(self, name: str, source_sha1: str | None = None, packed: bool = False) -> ir.IdentifiedStructType: + clean_name: str = name.replace(' *', '').replace('*', '').replace(' ', '_').replace('const', 'const_').replace('volatile', 'volatile_') + # 如果名称包含模块前缀(如 "a9fa0f6200c09e65.zbit_writer"), + # 先尝试用短名称(如 "zbit_writer")查找已注册的 struct, + # 避免为同一 struct 创建多个不同的类型对象导致跨模块引用类型不一致 + if '.' in clean_name and clean_name not in self.structs: + parts: list[str] = clean_name.split('.', 1) + if len(parts[0]) == 16 and all(c in '0123456789abcdef' for c in parts[0]): + short_name: str = parts[1] + if short_name in self.structs: + return self.structs[short_name] + if clean_name in self.structs: + existing: ir.IdentifiedStructType = self.structs[clean_name] + if packed and isinstance(existing, ir.IdentifiedStructType) and not existing.packed: + existing.packed = True + return existing + if clean_name in {'typedef', 'CType', 'CVolatile', 'CEnum', 'CUnion', 'CStruct', 'enum', 'REnum', 'renum', 'Void', 'void'}: + return ir.IntType(8) + if hasattr(self, 'SymbolTable') and self.SymbolTable: + Entry: _CTypeInfo | None = self.SymbolTable.lookup(clean_name) + if Entry and Entry.IsTypedef: + resolved_str: str = self._resolve_typedef(clean_name) + if resolved_str != clean_name: + return self._type_str_to_llvm(resolved_str) + if Entry.BaseType: + if not isinstance(Entry.BaseType, (_t._CTypedef,)) or Entry.PtrCount > 0: + resolved: str = self._resolve_ctype_to_str(Entry) + if resolved: + return self._type_str_to_llvm(resolved) + if Entry and Entry.IsRenum: + if clean_name in self.structs: + return self.structs[clean_name] + if Entry and Entry.IsEnum: + return ir.IntType(32) + if Entry and Entry.IsExceptionClass: + return ir.IntType(32) + if Entry and Entry.IsFunction: + return ir.PointerType(ir.IntType(8)) + if Entry and Entry.IsVariable: + return ir.PointerType(ir.IntType(8)) + if Entry and Entry.BaseType: + if isinstance(Entry.BaseType, type) and issubclass(Entry.BaseType, _t.CEnum): + return ir.IntType(32) + if Entry.BaseType is _t.CEnum: + return ir.IntType(32) + ns_name: str + if source_sha1: + ns_name = f"{source_sha1}.{clean_name}" + elif hasattr(self, '_struct_sha1_map') and clean_name in self._struct_sha1_map: + ns_name = f"{self._struct_sha1_map[clean_name]}.{clean_name}" + else: + ns_name = self._mangle_name(clean_name) + st: ir.IdentifiedStructType = ir.IdentifiedStructType(self.module, name=ns_name, packed=packed) + self.structs[clean_name] = st + # 尝试解析 typedef 的底层整数位宽 + width: int | None = self._resolve_typedef_int_width(clean_name) + if width is not None: + self.typedef_int_widths[clean_name] = width + return st + + def _resolve_typedef_int_width(self, name: str) -> int | None: + """解析 typedef 名称的底层整数位宽 + + 通过 CTypeRegistry 和 BuiltinTypeMap 动态解析, + 替代硬编码的 TYPEDEF_NAMES 映射表。 + 返回 int 位宽或 None(无法解析)。 + """ + # 1. 先查 BuiltinTypeMap(覆盖 BYTEPTR 等指针别名) + bm: Any = BuiltinTypeMap.Get(name) + if bm: + ctype_cls: Any + ptr_count: int + ctype_cls, ptr_count = bm + if ptr_count > 0: + return None # 指针类型,不是整数 typedef + llvm_str: str = CTypeRegistry.CTypeToLLVM(ctype_cls) + if llvm_str and llvm_str.startswith('i') and llvm_str[1:].isdigit(): + return int(llvm_str[1:]) + + # 2. 再查 SymbolTable(用户定义的 typedef) + if hasattr(self, 'SymbolTable') and self.SymbolTable: + Entry: _CTypeInfo | None = self.SymbolTable.lookup(name) + if Entry and Entry.IsTypedef: + if Entry.BaseType: + if not isinstance(Entry.BaseType, (_t._CTypedef,)) and Entry.PtrCount == 0: + llvm_str: str = CTypeRegistry.CTypeToLLVM(type(Entry.BaseType) if isinstance(Entry.BaseType, _t.CType) else Entry.BaseType) + if llvm_str and llvm_str.startswith('i') and llvm_str[1:].isdigit(): + return int(llvm_str[1:]) + if Entry.OriginalType: + if isinstance(Entry.OriginalType, _CTypeInfo) and Entry.OriginalType.BaseType: + if not isinstance(Entry.OriginalType.BaseType, (_t._CTypedef,)) and Entry.OriginalType.PtrCount == 0: + llvm_str: str = CTypeRegistry.CTypeToLLVM(type(Entry.OriginalType.BaseType) if isinstance(Entry.OriginalType.BaseType, _t.CType) else Entry.OriginalType.BaseType) + if llvm_str and llvm_str.startswith('i') and llvm_str[1:].isdigit(): + return int(llvm_str[1:]) + + # 3. 尝试 CTypeRegistry 直接按名称查找 + ctype_cls: Any = CTypeRegistry.GetClassByName(name) + if ctype_cls: + llvm_str: str = CTypeRegistry.CTypeToLLVM(ctype_cls) + if llvm_str and llvm_str.startswith('i') and llvm_str[1:].isdigit(): + return int(llvm_str[1:]) + + # 4. 特殊名称(非整数类型,但需要标记为 typedef 以跳过 opaque 定义) + _SPECIAL_TYPEDEFS: set[str] = { + 'typedef', 'CType', 'CVolatile', 'CEnum', 'CUnion', + 'CStruct', 'enum', 'REnum', 'renum', + 'list', 'dict', 'tuple', 'set', 'str', 'bytes', 'array', 'type', 'CArray', + } + if name in _SPECIAL_TYPEDEFS: + return 0 # 标记为 typedef,但位宽为 0(非整数) + + return None + + def _set_node_info(self, node: ast.AST, extra_info: str = "") -> None: + if hasattr(node, 'lineno'): + self._current_lineno = node.lineno + else: + self._current_lineno = 0 + if hasattr(node, 'col_offset'): + self._current_node_info = f"line {self._current_lineno}, col {node.col_offset}" + else: + self._current_node_info = f"line {self._current_lineno}" + if extra_info: + self._current_node_info += f" ({extra_info})" + + def _set_source_info(self, filepath: str) -> None: + self._current_source_file = filepath + try: + with open(filepath, 'r', encoding='utf-8') as f: + self._current_source_lines = f.readlines() + except Exception: # 文件读取失败时回退为空行列表 + self._current_source_lines = [] + + def _ns_hash(self) -> str: + if 'workspace' in self._ns_cache: + return self._ns_cache['workspace'] + cwd: str = os.getcwd().replace('\\', '/').lower() + digest: str = hashlib.sha1(cwd.encode('utf-8')).hexdigest()[:12] + self._ns_cache['workspace'] = digest + return digest + + def _skip_mangle(self, name: str) -> bool: + skip_prefixes: tuple[str, ...] = ('llvm.', 'str_const_', 'printf', 'memset_pattern') + if any(name.startswith(p) for p in skip_prefixes): + return True + if '.' in name: + parts: list[str] = name.split('.', 1) + if len(parts[0]) >= 8 and all(c in '0123456789abcdef' for c in parts[0]): + return True + return False + + def _mangle_name(self, name: str) -> str: + if self._skip_mangle(name): + return name + if name in self._export_funcs: + return name + if self.module_sha1: + return f"{self.module_sha1}.{name}" + return name + + def _find_function(self, name: str) -> ir.Function | None: + if name in self.functions: + return self.functions[name] + g: Any = self.module.globals.get(name) + if g and isinstance(g, ir.Function): + self.functions[name] = g + return g + mangled: str = self._mangle_func_name(name) + if mangled != name: + if mangled in self.functions: + self.functions[name] = self.functions[mangled] + return self.functions[mangled] + g = self.module.globals.get(mangled) + if g and isinstance(g, ir.Function): + self.functions[mangled] = g + self.functions[name] = g + return g + for sha1 in self.ModuleSha1Map.values(): + prefixed: str = f"{sha1}.{name}" + if prefixed in self.functions: + self.functions[name] = self.functions[prefixed] + return self.functions[prefixed] + g = self.module.globals.get(prefixed) + if g and isinstance(g, ir.Function): + self.functions[prefixed] = g + self.functions[name] = g + return g + return None + + def _has_function(self, name: str) -> bool: + return self._find_function(name) is not None + + def _get_or_declare_function(self, mangled_name: str, func_type: ir.FunctionType) -> ir.Function: + for g in self.module.globals: + if isinstance(g, ir.Function) and g.name == mangled_name: + return g + return ir.Function(self.module, func_type, name=mangled_name) + + def _get_function(self, name: str) -> ir.Function | None: + func: ir.Function | None = self._find_function(name) + return func + + def _mangle_func_name(self, name: str, module_name: str | None = None) -> str: + if name in self._export_funcs: + return name + if name in self._export_extern_funcs and name not in self._current_module_func_names: + return name + # main 函数作为程序入口点,永远不混淆 + if name == 'main': + return name + # Try class_sha1_map first for class methods (e.g., 'md5.__init__' -> class 'md5') + class_sha1_map: dict[str, str] = getattr(self, 'class_sha1_map', {}) + if class_sha1_map: + if '.' in name: + base_class: str = name.split('.')[0] + if base_class in class_sha1_map: + sha1: str = class_sha1_map[base_class] + return f"{sha1}.{name}" + elif name in class_sha1_map: + sha1: str = class_sha1_map[name] + return f"{sha1}.{name}" + # If module_name is already a SHA1 hash (16 hex chars), use it directly + if module_name and len(module_name) == 16 and all(c in '0123456789abcdef' for c in module_name): + return f"{module_name}.{name}" + if module_name and module_name in self.ModuleSha1Map: + sha1: str = self.ModuleSha1Map[module_name] + return f"{sha1}.{name}" + # Try parent package name (e.g., 'hashlib' -> 'hashlib.__init__') + if module_name: + init_name: str = f"{module_name}.__init__" + if init_name in self.ModuleSha1Map: + sha1: str = self.ModuleSha1Map[init_name] + return f"{sha1}.{name}" + if self._skip_mangle(name): + return name + if self.module_sha1: + return f"{self.module_sha1}.{name}" + return name + + def _get_source_line(self, lineno: int) -> str | None: + if 0 < lineno <= len(self._current_source_lines): + return self._current_source_lines[lineno - 1].rstrip('\r\n') + return None + + def _get_node_info(self) -> str: + info: str = "" + if self._current_node_info: + info = f" [{self._current_node_info}]" + if self._current_source_file: + info += f" in {self._current_source_file}" + lineno: int = self._current_lineno + if lineno > 0: + info += f", line {lineno}:" + source_line: str | None = self._get_source_line(lineno) + if source_line: + info += f"\n → {source_line}" + return info + + # ========== 统一工具方法 ========== + + def _create_string_global(self, s: str, name: str | None = None) -> ir.Constant: + """创建字符串全局变量并返回 i8* 指针。 + + 统一字符串全局变量创建模式:编码为 utf-8 + '\\x00' 终止符, + 创建 internal linkage 的 GlobalVariable,返回 i8* 指针常量。 + """ + str_val: str = s + '\x00' + str_bytes: bytes = str_val.encode('utf-8') + arr_type: ir.ArrayType = ir.ArrayType(ir.IntType(8), len(str_bytes)) + gv_name: str = name or f"str_const_{self.string_const_counter}" + self.string_const_counter += 1 + gv: ir.GlobalVariable = ir.GlobalVariable(self.module, arr_type, name=gv_name) + gv.initializer = ir.Constant(arr_type, bytearray(str_bytes)) + gv.linkage = 'internal' + return ir.Constant(ir.PointerType(ir.IntType(8)), gv.get_reference()) + + def _apply_bswap_if_big(self, val: ir.Value, byte_order: str, name: str) -> ir.Value: + """大端字节序时对整数应用 bswap,否则原值返回。 + + 仅对 16/32/64 位整数生效,统一 bswap 逻辑。 + """ + if byte_order == 'big' and isinstance(val.type, ir.IntType) and val.type.width in (16, 32, 64): + return self.builder.bswap(val, name=name) + return val + + def _zero_value_for_type(self, llvm_type: ir.Type) -> ir.Constant | None: + """为指定 LLVM 类型生成零值常量。 + + 合并原 HandlesAssign._zero_value 与 StructGen._zero_value_for_type 的逻辑。 + 返回 ir.Constant 或 None(无法生成零值的类型,如 opaque struct)。 + """ + if isinstance(llvm_type, ir.IntType): + return ir.Constant(llvm_type, 0) + elif isinstance(llvm_type, (ir.FloatType, ir.DoubleType)): + return ir.Constant(llvm_type, 0.0) + elif isinstance(llvm_type, ir.PointerType): + return ir.Constant(llvm_type, None) + elif isinstance(llvm_type, ir.ArrayType): + elem_zv: ir.Constant | None = self._zero_value_for_type(llvm_type.element) + if elem_zv is None: + return None + return ir.Constant(llvm_type, [elem_zv] * llvm_type.count) + elif isinstance(llvm_type, ir.BaseStructType): + if llvm_type.elements is not None and len(llvm_type.elements) > 0: + elem_zvs: list[ir.Constant | None] = [self._zero_value_for_type(m) for m in llvm_type.elements] + if any(zv is None for zv in elem_zvs): + return None + return ir.Constant(llvm_type, elem_zvs) + return None + return None \ No newline at end of file diff --git a/lib/core/LLVMCG/ExprGen.py b/lib/core/LLVMCG/ExprGen.py index 78202d4..c761dd4 100644 --- a/lib/core/LLVMCG/ExprGen.py +++ b/lib/core/LLVMCG/ExprGen.py @@ -1,353 +1,365 @@ -from __future__ import annotations -import llvmlite.ir as ir - - -class ExprGenMixin: - def emit_constant(self, value, type_name='int'): - if type_name == 'int': - return ir.Constant(ir.IntType(32), int(value)) - elif type_name == 'uint64_t' or type_name == 'unsigned long long': - return ir.Constant(ir.IntType(64), int(value)) - elif type_name == 'uint32_t' or type_name == 'unsigned int': - return ir.Constant(ir.IntType(32), int(value)) - elif type_name == 'uint16_t' or type_name == 'unsigned short': - return ir.Constant(ir.IntType(16), int(value)) - elif type_name == 'uint8_t' or type_name == 'unsigned char': - return ir.Constant(ir.IntType(8), int(value)) - elif type_name == 'int64_t' or type_name == 'long long': - return ir.Constant(ir.IntType(64), int(value)) - elif type_name == 'int32_t' or type_name == 'int': - return ir.Constant(ir.IntType(32), int(value)) - elif type_name == 'int16_t' or type_name == 'short': - return ir.Constant(ir.IntType(16), int(value)) - elif type_name == 'int8_t' or type_name == 'char': - return ir.Constant(ir.IntType(8), int(value)) - elif type_name == 'float' or type_name == 'float32_t' or type_name == 'FLOAT32': - return ir.Constant(ir.FloatType(), float(value)) - elif type_name == 'double' or type_name == 'float64_t' or type_name == 'FLOAT64': - return ir.Constant(ir.DoubleType(), float(value)) - elif type_name == 'float16_t' or type_name == 'FLOAT16': - return ir.Constant(ir.IntType(16), int(value)) - elif type_name == 'float8_t' or type_name == 'FLOAT8': - return ir.Constant(ir.IntType(8), int(value)) - elif type_name == 'float128_t' or type_name == 'FLOAT128': - return ir.Constant(ir.IntType(128), int(value)) - elif type_name == 'string': - encoded = value.encode('utf-8') + b'\x00' - str_type = ir.ArrayType(ir.IntType(8), len(encoded)) - str_const = ir.Constant(str_type, bytearray(encoded)) - global_var = ir.GlobalVariable(self.module, str_type, name=f"str_const_{self.string_const_counter}") - self.string_const_counter += 1 - global_var.initializer = str_const - global_var.linkage = 'internal' - return self.builder.bitcast(global_var, ir.PointerType(ir.IntType(8)), name="str") - return ir.Constant(ir.IntType(32), int(value)) - - def emit_binary_op(self, op, left, right, is_unsigned=False): - # 处理指针和整数之间的类型转换 - if isinstance(left.type, ir.PointerType) and isinstance(right.type, ir.IntType): - right = self.builder.zext(right, ir.IntType(64), name="int2ptrint") - if op == '+' or op == 'Add': - return self.builder.gep(left, [right], name="ptr_add") - elif op == '-' or op == 'Sub': - return self.builder.gep(left, [self.builder.neg(right, name="neg")], name="ptr_sub") - if isinstance(left.type, ir.IntType) and isinstance(right.type, ir.PointerType): - left = self.builder.zext(left, ir.IntType(64), name="int2ptrint2") - if op == '+' or op == 'Add': - return self.builder.gep(right, [left], name="ptr_add_rev") - is_float = isinstance(left.type, (ir.FloatType, ir.DoubleType)) or \ - isinstance(right.type, (ir.FloatType, ir.DoubleType)) - if is_float: - if isinstance(left.type, (ir.FloatType, ir.DoubleType)): - ftype = left.type - elif isinstance(right.type, (ir.FloatType, ir.DoubleType)): - ftype = right.type - else: - ftype = ir.DoubleType() - if not isinstance(left.type, (ir.FloatType, ir.DoubleType)): - left = self._to_float(left, ftype) - elif left.type != ftype: - if isinstance(left.type, ir.FloatType) and isinstance(ftype, ir.DoubleType): - left = self.builder.fpext(left, ftype, name="fpext_l") - else: - left = self.builder.fptrunc(left, ftype, name="fptrunc_l") - if not isinstance(right.type, (ir.FloatType, ir.DoubleType)): - right = self._to_float(right, ftype) - elif right.type != ftype: - if isinstance(right.type, ir.FloatType) and isinstance(ftype, ir.DoubleType): - right = self.builder.fpext(right, ftype, name="fpext_r") - else: - right = self.builder.fptrunc(right, ftype, name="fptrunc_r") - float_ops = { - '+': self.builder.fadd, 'Add': self.builder.fadd, - '-': self.builder.fsub, 'Sub': self.builder.fsub, - '*': self.builder.fmul, 'Mult': self.builder.fmul, - '/': self.builder.fdiv, 'Div': self.builder.fdiv, - '%': self.builder.frem, 'Mod': self.builder.frem, - } - float_cmp_ops = { - '==': '==', 'Eq': '==', '!=': '!=', 'NotEq': '!=', - '<': '<', 'Lt': '<', '<=': '<=', 'LtE': '<=', - '>': '>', 'Gt': '>', '>=': '>=', 'GtE': '>=', - } - if op in float_ops: - return float_ops[op](left, right, name=op) - if op in float_cmp_ops: - return self.builder.fcmp_ordered(float_cmp_ops[op], left, right, name=op) - if is_unsigned: - ops = { - '+': self.builder.add, 'Add': self.builder.add, - '-': self.builder.sub, 'Sub': self.builder.sub, - '*': self.builder.mul, 'Mult': self.builder.mul, - '/': self.builder.udiv, 'Div': self.builder.udiv, - '%': self.builder.urem, 'Mod': self.builder.urem, - '//': self.builder.udiv, 'FloorDiv': self.builder.udiv, - } - else: - ops = { - '+': self.builder.add, 'Add': self.builder.add, - '-': self.builder.sub, 'Sub': self.builder.sub, - '*': self.builder.mul, 'Mult': self.builder.mul, - '/': self.builder.sdiv, 'Div': self.builder.sdiv, - '%': self.builder.srem, 'Mod': self.builder.srem, - '//': self.builder.sdiv, 'FloorDiv': self.builder.sdiv, - } - cmp_ops = { - '==': '==', 'Eq': '==', '!=': '!=', 'NotEq': '!=', - '<': '<', 'Lt': '<', '<=': '<=', 'LtE': '<=', - '>': '>', 'Gt': '>', '>=': '>=', 'GtE': '>=', - } - logic_ops = { - '&&': self.builder.and_, 'And': self.builder.and_, - '||': self.builder.or_, 'Or': self.builder.or_, - } - if op in ('>>', 'RShift') and not is_unsigned: - if isinstance(left.type, ir.IntType): - if left.type.width == 8: - is_unsigned = True - elif left.type.width == 16: - is_unsigned = True - elif left.type.width == 32: - if hasattr(self, '_last_var_name') and self._last_var_name: - is_unsigned = self._is_var_unsigned(self._last_var_name) - elif left.type.width == 64: - if hasattr(self, '_last_var_name') and self._last_var_name: - is_unsigned = self._is_var_unsigned(self._last_var_name) - shift_ops = { - '>>': self.builder.lshr if is_unsigned else self.builder.ashr, - 'RShift': self.builder.lshr if is_unsigned else self.builder.ashr, - '<<': self.builder.shl, 'LShift': self.builder.shl, - } - bit_ops = { - '&': self.builder.and_, - '|': self.builder.or_, - '^': self.builder.xor, - } - if op == '**' or op == 'Pow': - if isinstance(left, ir.Constant) and isinstance(right, ir.Constant): - try: - lv = left.constant - rv = right.constant - if isinstance(lv, int) and isinstance(rv, int) and rv >= 0: - result = lv ** rv - return ir.Constant(left.type, result) - except Exception as _e: - if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": - import logging; logging.warning(f"异常被忽略: {_e}") - pass - if isinstance(left.type, (ir.FloatType, ir.DoubleType)): - ftype = left.type - elif isinstance(right.type, (ir.FloatType, ir.DoubleType)): - ftype = right.type - else: - ftype = ir.DoubleType() - lf = self._to_float(left, ftype) - rf = self._to_float(right, ftype) - powf = self.module.globals.get('llvm.pow.f64') - if not powf: - fnty = ir.FunctionType(ir.DoubleType(), [ir.DoubleType(), ir.DoubleType()]) - powf = ir.Function(self.module, fnty, name='llvm.pow.f64') - if lf.type != ir.DoubleType(): - lf = self.builder.fpext(lf, ir.DoubleType(), name="ext_f64") - if rf.type != ir.DoubleType(): - rf = self.builder.fpext(rf, ir.DoubleType(), name="ext_f64") - result = self.builder.call(powf, [lf, rf], name="pow") - both_int = isinstance(left.type, ir.IntType) and isinstance(right.type, ir.IntType) - right_is_pos_int_const = isinstance(right, ir.Constant) and isinstance(right.constant, int) and right.constant >= 0 - if both_int and right_is_pos_int_const: - return self.builder.fptosi(result, left.type, name="pow2int") - if isinstance(left.type, ir.FloatType): - return self.builder.fptrunc(result, ir.FloatType(), name="pow2f32") - return result - if op in ops: - try: - return ops[op](left, right, name=op) - except Exception as e: - raise ValueError(f"{e}{self._get_node_info()}") - if op in shift_ops: - try: - return shift_ops[op](left, right, name=op) - except Exception as e: - raise ValueError(f"{e}{self._get_node_info()}") - if op in bit_ops: - try: - return bit_ops[op](left, right, name=op) - except Exception as e: - raise ValueError(f"{e}{self._get_node_info()}") - if op in cmp_ops: - try: - if is_unsigned: - return self.builder.icmp_unsigned(cmp_ops[op], left, right, name=op) - return self.builder.icmp_signed(cmp_ops[op], left, right, name=op) - except Exception as e: - raise ValueError(f"{e}{self._get_node_info()}") - if op in logic_ops: - try: - return logic_ops[op](left, right, name=op) - except Exception as e: - raise ValueError(f"{e}{self._get_node_info()}") - return left - - def _to_float(self, val, ftype=None): - if ftype is None: - ftype = ir.DoubleType() - if isinstance(val.type, (ir.FloatType, ir.DoubleType)): - if val.type == ftype: - return val - if isinstance(val.type, ir.FloatType) and isinstance(ftype, ir.DoubleType): - return self.builder.fpext(val, ftype, name="fpext") - return self.builder.fptrunc(val, ftype, name="fptrunc") - if isinstance(val.type, ir.IntType): - if val.type.width == 1: - val = self.builder.zext(val, ir.IntType(32), name="bool2i32") - return self.builder.sitofp(val, ftype, name="int2float") - return val - - def emit_return(self, value=None): - if not self.builder or self.builder.block.is_terminated: - return - if value is not None: - self._unregister_local_heap_ptr(value) - self._emit_local_heap_frees() - if hasattr(self, '_variadic_info') and self._variadic_info and self._variadic_info.get('va_start_called'): - va_list_ptr = self._variadic_info['va_list_ptr'] - self.emit_va_end(va_list_ptr) - if value is None: - if self.func and hasattr(self.func, 'ftype'): - ret_type = self.func.ftype.return_type - if isinstance(ret_type, ir.IntType): - self.builder.ret(ir.Constant(ret_type, 0)) - elif isinstance(ret_type, ir.PointerType): - self.builder.ret(ir.Constant(ret_type, None)) - elif isinstance(ret_type, (ir.FloatType, ir.DoubleType)): - self.builder.ret(ir.Constant(ret_type, 0.0)) - elif isinstance(ret_type, ir.IdentifiedStructType): - if ret_type.elements: - zero_val = ir.Constant(ret_type, [ir.Constant(et, None) if isinstance(et, (ir.PointerType, ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)) else ir.Constant(et, 0) if isinstance(et, (ir.IntType, ir.FloatType, ir.DoubleType)) else ir.Constant(et, ir.Undefined) for et in ret_type.elements]) - else: - zero_val = ir.Constant(ret_type, None) - self.builder.ret(zero_val) - elif isinstance(ret_type, ir.ArrayType): - self.builder.ret(ir.Constant(ret_type, None)) - else: - self.builder.ret_void() - else: - self.builder.ret_void() - else: - if self.func and hasattr(self.func, 'ftype'): - ret_type = self.func.ftype.return_type - if ret_type != value.type: - if isinstance(ret_type, ir.PointerType) and isinstance(value.type, ir.PointerType): - if value.type.pointee == ret_type: - value = self._load(value, name="ret_Load") - else: - value = self.builder.bitcast(value, ret_type, name="ret_cast") - elif isinstance(value.type, ir.PointerType) and not isinstance(ret_type, ir.PointerType): - if isinstance(value.type.pointee, ir.IntType) and isinstance(ret_type, ir.IntType) and value.type.pointee.width == ret_type.width: - value = self._load(value, name="ret_Load") - elif isinstance(ret_type, ir.IntType): - value = self.builder.ptrtoint(value, ret_type, name="ret_ptrtoint") - elif isinstance(value.type.pointee, ret_type.__class__) and not isinstance(value.type.pointee, ir.IntType): - value = self._load(value, name="ret_Load") - elif isinstance(value.type.pointee, ir.PointerType): - Loaded = self._load(value, name="ret_deref") - if Loaded.type == ret_type: - value = Loaded - elif isinstance(ret_type, ir.IntType): - value = self.builder.ptrtoint(Loaded, ret_type, name="ret_ptrtoint") - elif isinstance(ret_type, ir.IntType) and isinstance(value.type, ir.IntType): - if value.type.width < ret_type.width: - # 有符号值用 sext,无符号值用 zext - is_unsigned = id(value) in self._unsigned_results - if is_unsigned: - value = self.builder.zext(value, ret_type, name="ret_zext") - else: - value = self.builder.sext(value, ret_type, name="ret_sext") - elif value.type.width > ret_type.width: - value = self.builder.trunc(value, ret_type, name="ret_trunc") - elif isinstance(ret_type, ir.PointerType) and isinstance(value.type, ir.IntType): - value = self.builder.inttoptr(value, ret_type, name="ret_inttoptr") - elif isinstance(ret_type, (ir.FloatType, ir.DoubleType)) and isinstance(value.type, ir.IntType): - value = self.builder.sitofp(value, ret_type, name="ret_int2float") - elif isinstance(ret_type, (ir.FloatType, ir.DoubleType)) and isinstance(value.type, (ir.FloatType, ir.DoubleType)): - if ret_type != value.type: - value = self.builder.fpext(value, ret_type, name="ret_fpext") - self.builder.ret(value) - - def _emit_printf(self, args, unsigned_flags=None, sep=" ", end="\n"): - if not args: - return None - if unsigned_flags is None: - unsigned_flags = [] - format_str = "" - cast_args = [] - for i, arg in enumerate(args): - is_u = i < len(unsigned_flags) and unsigned_flags[i] - if isinstance(arg.type, ir.IntType): - if arg.type.width == 8: - format_str += "%c" - ext = self.builder.zext(arg, ir.IntType(32), name="char2int") - cast_args.append(ext) - elif arg.type.width == 64: - format_str += "%llu" if is_u else "%lld" - cast_args.append(arg) - else: - format_str += "%u" if is_u else "%d" - cast_args.append(arg) - elif isinstance(arg.type, (ir.FloatType, ir.DoubleType)): - format_str += "%f" - cast_args.append(arg) - elif isinstance(arg.type, ir.PointerType): - if isinstance(arg.type.pointee, ir.IntType) and arg.type.pointee.width == 8: - format_str += "%s" - cast_args.append(arg) - else: - format_str += "%d" - int_val = self.builder.ptrtoint(arg, ir.IntType(64), name="ptr2int") - trunc_val = self.builder.trunc(int_val, ir.IntType(32), name="trunc") - cast_args.append(trunc_val) - else: - format_str += "%d" - cast_args.append(arg) - if sep is not None and i < len(args) - 1: - format_str += sep - if end is not None: - format_str += end - string_type = ir.ArrayType(ir.IntType(8), len(format_str.encode('utf-8')) + 1) - string_const = ir.Constant(string_type, bytearray(format_str + '\x00', 'utf-8')) - global_var = ir.GlobalVariable(self.module, string_type, name=f"str_const_{self.string_const_counter}") - self.string_const_counter += 1 - global_var.initializer = string_const - global_var.linkage = 'internal' - format_ptr = self.builder.bitcast(global_var, ir.PointerType(ir.IntType(8))) - call_args = [format_ptr] + cast_args - printf_func = self.get_or_declare_c_func('printf', ir.FunctionType(ir.IntType(32), [ir.PointerType(ir.IntType(8))], var_arg=True)) - return self.builder.call(printf_func, call_args, name="call_printf") - - def emit_sizeof(self, type_name): - for class_name, struct_type in self.structs.items(): - if type_name == class_name: - size = self._get_struct_size(struct_type) - if size > 0: - return ir.Constant(ir.IntType(64), size) - return ir.Constant(ir.IntType(64), 4) +from __future__ import annotations +from typing import Any +import logging +import llvmlite.ir as ir +from lib.constants.config import mode as _config_mode + + +class ExprGenMixin: + def emit_constant(self, value: Any, type_name: str = 'int') -> ir.Value: + if type_name == 'int': + return ir.Constant(ir.IntType(32), int(value)) + elif type_name == 'uint64_t' or type_name == 'unsigned long long': + return ir.Constant(ir.IntType(64), int(value)) + elif type_name == 'uint32_t' or type_name == 'unsigned int': + return ir.Constant(ir.IntType(32), int(value)) + elif type_name == 'uint16_t' or type_name == 'unsigned short': + return ir.Constant(ir.IntType(16), int(value)) + elif type_name == 'uint8_t' or type_name == 'unsigned char': + return ir.Constant(ir.IntType(8), int(value)) + elif type_name == 'int64_t' or type_name == 'long long': + return ir.Constant(ir.IntType(64), int(value)) + elif type_name == 'int32_t' or type_name == 'int': + return ir.Constant(ir.IntType(32), int(value)) + elif type_name == 'int16_t' or type_name == 'short': + return ir.Constant(ir.IntType(16), int(value)) + elif type_name == 'int8_t' or type_name == 'char': + return ir.Constant(ir.IntType(8), int(value)) + elif type_name == 'float' or type_name == 'float32_t' or type_name == 'FLOAT32': + return ir.Constant(ir.FloatType(), float(value)) + elif type_name == 'double' or type_name == 'float64_t' or type_name == 'FLOAT64': + return ir.Constant(ir.DoubleType(), float(value)) + elif type_name == 'float16_t' or type_name == 'FLOAT16': + return ir.Constant(ir.IntType(16), int(value)) + elif type_name == 'float8_t' or type_name == 'FLOAT8': + return ir.Constant(ir.IntType(8), int(value)) + elif type_name == 'float128_t' or type_name == 'FLOAT128': + return ir.Constant(ir.IntType(128), int(value)) + elif type_name == 'string': + encoded: bytes = value.encode('utf-8') + b'\x00' + str_type: ir.ArrayType = ir.ArrayType(ir.IntType(8), len(encoded)) + str_const: ir.Constant = ir.Constant(str_type, bytearray(encoded)) + global_var: ir.GlobalVariable = ir.GlobalVariable(self.module, str_type, name=f"str_const_{self.string_const_counter}") + self.string_const_counter += 1 + global_var.initializer = str_const + global_var.linkage = 'internal' + return self.builder.bitcast(global_var, ir.PointerType(ir.IntType(8)), name="str") + return ir.Constant(ir.IntType(32), int(value)) + + def emit_binary_op(self, op: str, left: ir.Value, right: ir.Value, is_unsigned: bool = False) -> ir.Value: + if isinstance(left.type, ir.PointerType) and isinstance(right.type, ir.IntType): + # 数组指针需要先 decay 为元素指针,否则 GEP 会以整个数组为步长 + # 例如 [64 x i8]* + 1 会前进 64 字节而非 1 字节 + if isinstance(left.type.pointee, ir.ArrayType): + zero: ir.Constant = ir.Constant(ir.IntType(32), 0) + left = self.builder.gep(left, [zero, zero], name="array_decay") + right = self.builder.zext(right, ir.IntType(64), name="int2ptrint") + if op == '+' or op == 'Add': + return self.builder.gep(left, [right], name="ptr_add") + elif op == '-' or op == 'Sub': + return self.builder.gep(left, [self.builder.neg(right, name="neg")], name="ptr_sub") + if isinstance(left.type, ir.IntType) and isinstance(right.type, ir.PointerType): + if isinstance(right.type.pointee, ir.ArrayType): + zero: ir.Constant = ir.Constant(ir.IntType(32), 0) + right = self.builder.gep(right, [zero, zero], name="array_decay_rev") + left = self.builder.zext(left, ir.IntType(64), name="int2ptrint2") + if op == '+' or op == 'Add': + return self.builder.gep(right, [left], name="ptr_add_rev") + is_float: bool = isinstance(left.type, (ir.FloatType, ir.DoubleType)) or \ + isinstance(right.type, (ir.FloatType, ir.DoubleType)) + if is_float: + ftype: ir.Type + if isinstance(left.type, (ir.FloatType, ir.DoubleType)): + ftype = left.type + elif isinstance(right.type, (ir.FloatType, ir.DoubleType)): + ftype = right.type + else: + ftype = ir.DoubleType() + if not isinstance(left.type, (ir.FloatType, ir.DoubleType)): + left = self._to_float(left, ftype) + elif left.type != ftype: + if isinstance(left.type, ir.FloatType) and isinstance(ftype, ir.DoubleType): + left = self.builder.fpext(left, ftype, name="fpext_l") + else: + left = self.builder.fptrunc(left, ftype, name="fptrunc_l") + if not isinstance(right.type, (ir.FloatType, ir.DoubleType)): + right = self._to_float(right, ftype) + elif right.type != ftype: + if isinstance(right.type, ir.FloatType) and isinstance(ftype, ir.DoubleType): + right = self.builder.fpext(right, ftype, name="fpext_r") + else: + right = self.builder.fptrunc(right, ftype, name="fptrunc_r") + float_ops: dict[str, Any] = { + '+': self.builder.fadd, 'Add': self.builder.fadd, + '-': self.builder.fsub, 'Sub': self.builder.fsub, + '*': self.builder.fmul, 'Mult': self.builder.fmul, + '/': self.builder.fdiv, 'Div': self.builder.fdiv, + '%': self.builder.frem, 'Mod': self.builder.frem, + } + float_cmp_ops: dict[str, str] = { + '==': '==', 'Eq': '==', '!=': '!=', 'NotEq': '!=', + '<': '<', 'Lt': '<', '<=': '<=', 'LtE': '<=', + '>': '>', 'Gt': '>', '>=': '>=', 'GtE': '>=', + } + if op in float_ops: + return float_ops[op](left, right, name=op) + if op in float_cmp_ops: + return self.builder.fcmp_ordered(float_cmp_ops[op], left, right, name=op) + ops: dict[str, Any] + if is_unsigned: + ops = { + '+': self.builder.add, 'Add': self.builder.add, + '-': self.builder.sub, 'Sub': self.builder.sub, + '*': self.builder.mul, 'Mult': self.builder.mul, + '/': self.builder.udiv, 'Div': self.builder.udiv, + '%': self.builder.urem, 'Mod': self.builder.urem, + '//': self.builder.udiv, 'FloorDiv': self.builder.udiv, + } + else: + ops = { + '+': self.builder.add, 'Add': self.builder.add, + '-': self.builder.sub, 'Sub': self.builder.sub, + '*': self.builder.mul, 'Mult': self.builder.mul, + '/': self.builder.sdiv, 'Div': self.builder.sdiv, + '%': self.builder.srem, 'Mod': self.builder.srem, + '//': self.builder.sdiv, 'FloorDiv': self.builder.sdiv, + } + cmp_ops: dict[str, str] = { + '==': '==', 'Eq': '==', '!=': '!=', 'NotEq': '!=', + '<': '<', 'Lt': '<', '<=': '<=', 'LtE': '<=', + '>': '>', 'Gt': '>', '>=': '>=', 'GtE': '>=', + } + logic_ops: dict[str, Any] = { + '&&': self.builder.and_, 'And': self.builder.and_, + '||': self.builder.or_, 'Or': self.builder.or_, + } + if op in ('>>', 'RShift') and not is_unsigned: + if isinstance(left.type, ir.IntType): + if left.type.width == 8: + is_unsigned = True + elif left.type.width == 16: + is_unsigned = True + elif left.type.width == 32: + if hasattr(self, '_last_var_name') and self._last_var_name: + is_unsigned = self._is_var_unsigned(self._last_var_name) + elif left.type.width == 64: + if hasattr(self, '_last_var_name') and self._last_var_name: + is_unsigned = self._is_var_unsigned(self._last_var_name) + shift_ops: dict[str, Any] = { + '>>': self.builder.lshr if is_unsigned else self.builder.ashr, + 'RShift': self.builder.lshr if is_unsigned else self.builder.ashr, + '<<': self.builder.shl, 'LShift': self.builder.shl, + } + bit_ops: dict[str, Any] = { + '&': self.builder.and_, + '|': self.builder.or_, + '^': self.builder.xor, + } + if op == '**' or op == 'Pow': + if isinstance(left, ir.Constant) and isinstance(right, ir.Constant): + try: + lv: Any = left.constant + rv: Any = right.constant + if isinstance(lv, int) and isinstance(rv, int) and rv >= 0: + result: int = lv ** rv + return ir.Constant(left.type, result) + except Exception as _e: + if _config_mode == "strict": + logging.warning(f"异常被忽略: {_e}") + pass + ftype: ir.Type + if isinstance(left.type, (ir.FloatType, ir.DoubleType)): + ftype = left.type + elif isinstance(right.type, (ir.FloatType, ir.DoubleType)): + ftype = right.type + else: + ftype = ir.DoubleType() + lf: ir.Value = self._to_float(left, ftype) + rf: ir.Value = self._to_float(right, ftype) + powf: ir.Function | None = self.module.globals.get('llvm.pow.f64') + if not powf: + fnty: ir.FunctionType = ir.FunctionType(ir.DoubleType(), [ir.DoubleType(), ir.DoubleType()]) + powf = ir.Function(self.module, fnty, name='llvm.pow.f64') + if lf.type != ir.DoubleType(): + lf = self.builder.fpext(lf, ir.DoubleType(), name="ext_f64") + if rf.type != ir.DoubleType(): + rf = self.builder.fpext(rf, ir.DoubleType(), name="ext_f64") + result: ir.Value = self.builder.call(powf, [lf, rf], name="pow") + both_int: bool = isinstance(left.type, ir.IntType) and isinstance(right.type, ir.IntType) + right_is_pos_int_const: bool = isinstance(right, ir.Constant) and isinstance(right.constant, int) and right.constant >= 0 + if both_int and right_is_pos_int_const: + return self.builder.fptosi(result, left.type, name="pow2int") + if isinstance(left.type, ir.FloatType): + return self.builder.fptrunc(result, ir.FloatType(), name="pow2f32") + return result + if op in ops: + try: + return ops[op](left, right, name=op) + except Exception as e: + raise ValueError(f"{e}{self._get_node_info()}") + if op in shift_ops: + try: + return shift_ops[op](left, right, name=op) + except Exception as e: + raise ValueError(f"{e}{self._get_node_info()}") + if op in bit_ops: + try: + return bit_ops[op](left, right, name=op) + except Exception as e: + raise ValueError(f"{e}{self._get_node_info()}") + if op in cmp_ops: + try: + if is_unsigned: + return self.builder.icmp_unsigned(cmp_ops[op], left, right, name=op) + return self.builder.icmp_signed(cmp_ops[op], left, right, name=op) + except Exception as e: + raise ValueError(f"{e}{self._get_node_info()}") + if op in logic_ops: + try: + return logic_ops[op](left, right, name=op) + except Exception as e: + raise ValueError(f"{e}{self._get_node_info()}") + return left + + def _to_float(self, val: ir.Value, ftype: ir.Type | None = None) -> ir.Value: + if ftype is None: + ftype = ir.DoubleType() + if isinstance(val.type, (ir.FloatType, ir.DoubleType)): + if val.type == ftype: + return val + if isinstance(val.type, ir.FloatType) and isinstance(ftype, ir.DoubleType): + return self.builder.fpext(val, ftype, name="fpext") + return self.builder.fptrunc(val, ftype, name="fptrunc") + if isinstance(val.type, ir.IntType): + if val.type.width == 1: + val = self.builder.zext(val, ir.IntType(32), name="bool2i32") + return self.builder.sitofp(val, ftype, name="int2float") + return val + + def emit_return(self, value: ir.Value | None = None) -> None: + if not self.builder or self.builder.block.is_terminated: + return + if value is not None: + self._unregister_local_heap_ptr(value) + self._emit_local_heap_frees() + if hasattr(self, '_variadic_info') and self._variadic_info and self._variadic_info.get('va_start_called'): + va_list_ptr: ir.Value = self._variadic_info['va_list_ptr'] + self.emit_va_end(va_list_ptr) + if value is None: + if self.func and hasattr(self.func, 'ftype'): + ret_type: ir.Type = self.func.ftype.return_type + if isinstance(ret_type, ir.IntType): + self.builder.ret(ir.Constant(ret_type, 0)) + elif isinstance(ret_type, ir.PointerType): + self.builder.ret(ir.Constant(ret_type, None)) + elif isinstance(ret_type, (ir.FloatType, ir.DoubleType)): + self.builder.ret(ir.Constant(ret_type, 0.0)) + elif isinstance(ret_type, ir.IdentifiedStructType): + if ret_type.elements: + zero_val: ir.Constant = ir.Constant(ret_type, [ir.Constant(et, None) if isinstance(et, (ir.PointerType, ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)) else ir.Constant(et, 0) if isinstance(et, (ir.IntType, ir.FloatType, ir.DoubleType)) else ir.Constant(et, ir.Undefined) for et in ret_type.elements]) + else: + zero_val = ir.Constant(ret_type, None) + self.builder.ret(zero_val) + elif isinstance(ret_type, ir.ArrayType): + self.builder.ret(ir.Constant(ret_type, None)) + else: + self.builder.ret_void() + else: + self.builder.ret_void() + else: + if self.func and hasattr(self.func, 'ftype'): + ret_type: ir.Type = self.func.ftype.return_type + if ret_type != value.type: + if isinstance(ret_type, ir.PointerType) and isinstance(value.type, ir.PointerType): + if value.type.pointee == ret_type: + value = self._load(value, name="ret_Load") + else: + value = self.builder.bitcast(value, ret_type, name="ret_cast") + elif isinstance(value.type, ir.PointerType) and not isinstance(ret_type, ir.PointerType): + if isinstance(value.type.pointee, ir.IntType) and isinstance(ret_type, ir.IntType) and value.type.pointee.width == ret_type.width: + value = self._load(value, name="ret_Load") + elif isinstance(ret_type, ir.IntType): + value = self.builder.ptrtoint(value, ret_type, name="ret_ptrtoint") + elif isinstance(value.type.pointee, ret_type.__class__) and not isinstance(value.type.pointee, ir.IntType): + value = self._load(value, name="ret_Load") + elif isinstance(value.type.pointee, ir.PointerType): + Loaded: ir.Value = self._load(value, name="ret_deref") + if Loaded.type == ret_type: + value = Loaded + elif isinstance(ret_type, ir.IntType): + value = self.builder.ptrtoint(Loaded, ret_type, name="ret_ptrtoint") + elif isinstance(ret_type, ir.IntType) and isinstance(value.type, ir.IntType): + if value.type.width < ret_type.width: + is_unsigned: bool = id(value) in self._unsigned_results + if is_unsigned: + value = self.builder.zext(value, ret_type, name="ret_zext") + else: + value = self.builder.sext(value, ret_type, name="ret_sext") + elif value.type.width > ret_type.width: + value = self.builder.trunc(value, ret_type, name="ret_trunc") + elif isinstance(ret_type, ir.PointerType) and isinstance(value.type, ir.IntType): + value = self.builder.inttoptr(value, ret_type, name="ret_inttoptr") + elif isinstance(ret_type, (ir.FloatType, ir.DoubleType)) and isinstance(value.type, ir.IntType): + value = self.builder.sitofp(value, ret_type, name="ret_int2float") + elif isinstance(ret_type, (ir.FloatType, ir.DoubleType)) and isinstance(value.type, (ir.FloatType, ir.DoubleType)): + if ret_type != value.type: + value = self.builder.fpext(value, ret_type, name="ret_fpext") + self.builder.ret(value) + + def _emit_printf(self, args: list[ir.Value], unsigned_flags: list[bool] | None = None, sep: str = " ", end: str = "\n") -> ir.Value | None: + if not args: + return None + if unsigned_flags is None: + unsigned_flags = [] + format_str: str = "" + cast_args: list[ir.Value] = [] + for i, arg in enumerate(args): + is_u: bool = i < len(unsigned_flags) and unsigned_flags[i] + if isinstance(arg.type, ir.IntType): + if arg.type.width == 8: + format_str += "%c" + ext: ir.Value = self.builder.zext(arg, ir.IntType(32), name="char2int") + cast_args.append(ext) + elif arg.type.width == 64: + format_str += "%llu" if is_u else "%lld" + cast_args.append(arg) + else: + format_str += "%u" if is_u else "%d" + cast_args.append(arg) + elif isinstance(arg.type, (ir.FloatType, ir.DoubleType)): + format_str += "%f" + cast_args.append(arg) + elif isinstance(arg.type, ir.PointerType): + if isinstance(arg.type.pointee, ir.IntType) and arg.type.pointee.width == 8: + format_str += "%s" + cast_args.append(arg) + else: + format_str += "%d" + int_val: ir.Value = self.builder.ptrtoint(arg, ir.IntType(64), name="ptr2int") + trunc_val: ir.Value = self.builder.trunc(int_val, ir.IntType(32), name="trunc") + cast_args.append(trunc_val) + else: + format_str += "%d" + cast_args.append(arg) + if sep is not None and i < len(args) - 1: + format_str += sep + if end is not None: + format_str += end + string_type: ir.ArrayType = ir.ArrayType(ir.IntType(8), len(format_str.encode('utf-8')) + 1) + string_const: ir.Constant = ir.Constant(string_type, bytearray(format_str + '\x00', 'utf-8')) + global_var: ir.GlobalVariable = ir.GlobalVariable(self.module, string_type, name=f"str_const_{self.string_const_counter}") + self.string_const_counter += 1 + global_var.initializer = string_const + global_var.linkage = 'internal' + format_ptr: ir.Value = self.builder.bitcast(global_var, ir.PointerType(ir.IntType(8))) + call_args: list[ir.Value] = [format_ptr] + cast_args + printf_func: ir.Function | None = self.get_or_declare_c_func('printf', ir.FunctionType(ir.IntType(32), [ir.PointerType(ir.IntType(8))], var_arg=True)) + return self.builder.call(printf_func, call_args, name="call_printf") + + def emit_sizeof(self, type_name: str) -> ir.Constant: + for class_name, struct_type in self.structs.items(): + if type_name == class_name: + size: int = self._get_struct_size(struct_type) + if size > 0: + return ir.Constant(ir.IntType(64), size) + return ir.Constant(ir.IntType(64), 4) \ No newline at end of file diff --git a/lib/core/LLVMCG/FuncGen.py b/lib/core/LLVMCG/FuncGen.py index 8f77325..2c30d92 100644 --- a/lib/core/LLVMCG/FuncGen.py +++ b/lib/core/LLVMCG/FuncGen.py @@ -1,390 +1,437 @@ -from __future__ import annotations -import ast -import os -import llvmlite.ir as ir -from lib.core.Handles.HandlesBase import CTypeInfo - - -class FuncGenMixin: - - def setup_from_symbol_table(self, SymbolTable): - self.SymbolTable = SymbolTable - for name, info in SymbolTable.items(): - if isinstance(info, CTypeInfo): - # CTypeInfo 对象:struct/union 由 StructGen 处理,此处只处理 dict 格式 - continue - if not isinstance(info, dict): - if hasattr(info, 'get'): - info = dict(info) if hasattr(info, '__iter__') else {} - else: - continue - TypeKind = info.get('type', '') - if TypeKind == 'struct': - ClassName = name - self.class_methods[ClassName] = [] - self.class_members[ClassName] = [] - members = info.get('members', {}) - if members: - for MemberName, MemberInfo in members.items(): - if isinstance(MemberInfo, dict): - MemberType = self._type_str_to_llvm(MemberInfo.get('type', 'int'), MemberInfo.get('IsPtr', False)) - self.class_members[ClassName].append((MemberName, MemberType)) - elif isinstance(MemberInfo, CTypeInfo): - MemberType = self._ctype_to_llvm(MemberInfo) - if MemberType is None: - MemberType = self._type_str_to_llvm(MemberInfo.ToString(), MemberInfo.IsPtr) - self.class_members[ClassName].append((MemberName, MemberType)) - self._generate_structs() - self._create_Vtable_globals() - - def register_method(self, ClassName, MethodName): - if ClassName not in self.class_methods: - self.class_methods[ClassName] = [] - if ClassName not in self.class_members: - self.class_members[ClassName] = [] - self._generate_structs() - self._create_Vtable_globals() - if MethodName not in self.class_methods[ClassName]: - self.class_methods[ClassName].append(MethodName) - - def _adjust_args(self, args, func): - adjusted = [] - for i, (arg, param) in enumerate(zip(args, func.args)): - if arg.type != param.type: - if isinstance(arg.type, ir.PointerType) and isinstance(param.type, (ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)): - if arg.type.pointee == param.type or (hasattr(arg.type.pointee, 'name') and hasattr(param.type, 'name') and arg.type.pointee.name == param.type.name): - adjusted.append(self._load(arg, name=f"Load_arg_{i}")) - continue - try: - if isinstance(arg.type, ir.IntType) and isinstance(param.type, ir.PointerType): - if isinstance(param.type.pointee, ir.IntType) and param.type.pointee.width == 8 and arg.type.width == 8: - # 当参数是 i8(字符值)而函数期望 i8*(字符串指针)时 - # 为字符值分配内存,创建 null-terminated 字符串 - tmp = self._alloca(ir.ArrayType(ir.IntType(8), 2), name=f"char2str_arg_{i}") - zero = ir.Constant(ir.IntType(32), 0) - char_ptr = self.builder.gep(tmp, [zero, zero], name=f"char2str_ptr_{i}") - self._store(arg, char_ptr) - null_ptr = self.builder.gep(tmp, [zero, ir.Constant(ir.IntType(32), 1)], name=f"char2str_null_{i}") - self._store(ir.Constant(ir.IntType(8), 0), null_ptr) - adjusted.append(char_ptr) - else: - if isinstance(arg.type, ir.PointerType) and isinstance(param.type, ir.IntType): - # 当参数是指针而函数期望整数时,使用 ptrtoint - adjusted.append(self.builder.ptrtoint(arg, param.type, name=f"ptrtoint_arg_{i}")) - else: - if arg.type.width < 32: - arg = self.builder.zext(arg, ir.IntType(32), name=f"zext_arg_{i}") - adjusted.append(self.builder.inttoptr(arg, param.type, name=f"inttoptr_arg_{i}")) - elif isinstance(arg.type, ir.PointerType) and isinstance(param.type, ir.IntType): - # 当参数是指针而函数期望整数时,使用 ptrtoint - adjusted.append(self.builder.ptrtoint(arg, param.type, name=f"ptrtoint_arg_{i}")) - elif isinstance(arg.type, ir.PointerType) and isinstance(param.type, ir.PointerType): - if isinstance(arg.type.pointee, ir.PointerType) and isinstance(param.type.pointee, ir.IntType): - Loaded = self._load(arg, name=f"Load_arg_{i}") - adjusted.append(Loaded) - elif isinstance(arg.type.pointee, ir.ArrayType) and isinstance(param.type.pointee, (ir.IntType, ir.FloatType, ir.DoubleType)): - zero = ir.Constant(ir.IntType(32), 0) - elem_ptr = self.builder.gep(arg, [zero, zero], name=f"array_decay_arg_{i}") - if elem_ptr.type != param.type: - adjusted.append(self.builder.bitcast(elem_ptr, param.type, name=f"cast_arg_{i}")) - else: - adjusted.append(elem_ptr) - elif isinstance(arg.type.pointee, ir.ArrayType) and isinstance(param.type.pointee, ir.PointerType): - zero = ir.Constant(ir.IntType(32), 0) - elem_ptr = self.builder.gep(arg, [zero, zero], name=f"array_decay_arg_{i}") - if elem_ptr.type != param.type: - adjusted.append(self.builder.bitcast(elem_ptr, param.type, name=f"cast_arg_{i}")) - else: - adjusted.append(elem_ptr) - else: - adjusted.append(self.builder.bitcast(arg, param.type, name=f"cast_arg_{i}")) - else: - if isinstance(arg.type, ir.PointerType) and isinstance(param.type, (ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)): - if arg.type.pointee == param.type or (hasattr(arg.type.pointee, 'name') and hasattr(param.type, 'name') and arg.type.pointee.name == param.type.name): - adjusted.append(self._load(arg, name=f"Load_arg_{i}")) - elif isinstance(arg.type.pointee, (ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)): - tmp = self._alloca(param.type, name=f"temp_arg_{i}") - Loaded = self.builder.bitcast(arg, ir.PointerType(param.type), name=f"cast_arg_{i}") - Loaded_val = self._load(Loaded, name=f"Load_arg_{i}") - self._store(Loaded_val, tmp) - adjusted.append(self._load(tmp, name=f"reLoad_arg_{i}")) - else: - tmp = self._alloca(param.type, name=f"temp_arg_{i}") - cast_ptr = self.builder.bitcast(arg, ir.PointerType(param.type), name=f"cast_arg_{i}") - Loaded_val = self._load(cast_ptr, name=f"Load_arg_{i}") - self._store(Loaded_val, tmp) - adjusted.append(self._load(tmp, name=f"reLoad_arg_{i}")) - elif isinstance(arg.type, ir.PointerType) and arg.type.pointee == param.type: - adjusted.append(self._load(arg, name=f"Load_arg_{i}")) - elif isinstance(param.type, ir.PointerType) and param.type.pointee == arg.type: - tmp = self._alloca(arg.type, name=f"temp_arg_{i}") - self._store(arg, tmp) - adjusted.append(tmp) - elif isinstance(arg.type, ir.IntType) and isinstance(param.type, ir.IntType): - if arg.type.width < param.type.width: - # 整数扩展:使用 sext(符号扩展)以正确处理负数 - adjusted.append(self.builder.sext(arg, param.type, name=f"sext_arg_{i}")) - else: - adjusted.append(self.builder.trunc(arg, param.type, name=f"trunc_arg_{i}")) - elif isinstance(arg.type, (ir.FloatType, ir.DoubleType)) and isinstance(param.type, (ir.FloatType, ir.DoubleType)): - if isinstance(arg.type, ir.DoubleType) and isinstance(param.type, ir.FloatType): - adjusted.append(self.builder.fptrunc(arg, param.type, name=f"fptrunc_arg_{i}")) - elif isinstance(arg.type, ir.FloatType) and isinstance(param.type, ir.DoubleType): - adjusted.append(self.builder.fpext(arg, param.type, name=f"fpext_arg_{i}")) - else: - adjusted.append(arg) - elif isinstance(arg.type, (ir.FloatType, ir.DoubleType)) and isinstance(param.type, ir.IntType): - adjusted.append(self.builder.fptosi(arg, param.type, name=f"fptosi_arg_{i}")) - elif isinstance(arg.type, ir.IntType) and isinstance(param.type, (ir.FloatType, ir.DoubleType)): - adjusted.append(self.builder.sitofp(arg, param.type, name=f"sitofp_arg_{i}")) - elif isinstance(arg.type, ir.IntType) and isinstance(param.type, ir.PointerType): - # 整数转指针:inttoptr - if arg.type.width < 64: - i64_val = self.builder.sext(arg, ir.IntType(64), name=f"sext_arg_{i}") - adjusted.append(self.builder.inttoptr(i64_val, param.type, name=f"inttoptr_arg_{i}")) - else: - adjusted.append(self.builder.inttoptr(arg, param.type, name=f"inttoptr_arg_{i}")) - elif isinstance(arg.type, ir.PointerType) and isinstance(param.type, ir.IntType): - # 指针转整数:ptrtoint - i64_val = self.builder.ptrtoint(arg, ir.IntType(64), name=f"ptrtoint_arg_{i}") - if i64_val.type.width > param.type.width: - adjusted.append(self.builder.trunc(i64_val, param.type, name=f"trunc_arg_{i}")) - elif i64_val.type.width < param.type.width: - adjusted.append(self.builder.sext(i64_val, param.type, name=f"sext_arg_{i}")) - else: - adjusted.append(i64_val) - else: - adjusted.append(self.builder.bitcast(arg, param.type, name=f"cast_arg_{i}")) - except Exception: # 参数类型调整失败时使用简化回退逻辑 - if isinstance(arg.type, ir.PointerType) and isinstance(param.type, (ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)): - if arg.type.pointee == param.type or (hasattr(arg.type.pointee, 'name') and hasattr(param.type, 'name') and arg.type.pointee.name == param.type.name): - adjusted.append(self._load(arg, name=f"Load_arg_{i}")) - else: - adjusted.append(self.builder.bitcast(arg, param.type, name=f"cast_arg_{i}")) - elif isinstance(arg.type, ir.PointerType) and arg.type.pointee == param.type: - adjusted.append(self._load(arg, name=f"Load_arg_{i}")) - elif isinstance(param.type, ir.PointerType) and param.type.pointee == arg.type: - tmp = self._alloca(arg.type, name=f"temp_arg_{i}") - self._store(arg, tmp) - adjusted.append(tmp) - else: - adjusted.append(arg) - else: - adjusted.append(arg) - while len(adjusted) < len(func.args): - missing_idx = len(adjusted) - param = func.args[missing_idx] - param_type = param.type if hasattr(param, 'type') else param - if isinstance(param_type, ir.PointerType): - adjusted.append(ir.Constant(param_type, None)) - elif isinstance(param_type, ir.IntType): - adjusted.append(ir.Constant(param_type, 0)) - elif isinstance(param_type, (ir.FloatType, ir.DoubleType)): - adjusted.append(ir.Constant(param_type, 0.0)) - else: - adjusted.append(ir.Constant(ir.IntType(32), 0)) - if func.type.pointee.var_arg: - for i in range(len(func.args), len(args)): - arg = args[i] - adjusted.append(arg) - return adjusted - - def _get_member_offset(self, field_name, ClassName=None): - has_vtable = ClassName and (ClassName in self.class_vtable or ClassName in self._cross_module_vtable_classes) - base = 1 if has_vtable else 0 - if ClassName and ClassName in self.structs: - struct_type = self.structs[ClassName] - if isinstance(struct_type, ir.IdentifiedStructType) and struct_type.elements is not None and len(struct_type.elements) > 0: - if ClassName in self.class_members: - expected_fields = len(self.class_members[ClassName]) - actual_elements = len(struct_type.elements) - if base > 0 and actual_elements == expected_fields: - base = 0 - if ClassName and ClassName in self.class_members: - for i, (name, _) in enumerate(self.class_members[ClassName]): - if name == field_name: - return base + i - short_name = ClassName.split('.')[-1] if ClassName and '.' in ClassName else None - if short_name and short_name in self.class_members: - for i, (name, _) in enumerate(self.class_members[short_name]): - if name == field_name: - return base + i - if ClassName and field_name: - if ClassName not in self.class_members or field_name not in [n for n, _ in self.class_members.get(ClassName, [])]: - if hasattr(self, '_Trans') and self._Trans and hasattr(self._Trans, 'ImportHandler'): - sha1_map = getattr(self, 'ModuleSha1Map', {}) - for mod_name, mod_sha1 in sha1_map.items(): - stub_name = f"{mod_sha1}.stub.ll" - self._Trans.ImportHandler._TryLoadClassMembersFromPyi(ClassName, stub_name, self) - if ClassName in self.class_members and len(self.class_members[ClassName]) > 0: - for i, (name, _) in enumerate(self.class_members[ClassName]): - if name == field_name: - return base + i - break - if short_name: - for mod_name, mod_sha1 in sha1_map.items(): - stub_name = f"{mod_sha1}.stub.ll" - self._Trans.ImportHandler._TryLoadClassMembersFromPyi(short_name, stub_name, self) - if short_name in self.class_members and len(self.class_members[short_name]) > 0: - for i, (name, _) in enumerate(self.class_members[short_name]): - if name == field_name: - return base + i - break - if ClassName and field_name: - for cn_key in self.class_members: - if cn_key == ClassName or cn_key.endswith(f'.{ClassName}') or (short_name and (cn_key == short_name or cn_key.endswith(f'.{short_name}'))): - for i, (name, _) in enumerate(self.class_members[cn_key]): - if name == field_name: - return base + i - if ClassName and ClassName in self.structs: - struct_type = self.structs[ClassName] - if isinstance(struct_type, ir.IdentifiedStructType) and struct_type.elements is not None and len(struct_type.elements) > 0: - for cn_key, members in self.class_members.items(): - if cn_key == short_name or (short_name and cn_key.endswith(f'.{short_name}')): - for i, (name, _) in enumerate(members): - if name == field_name and i < len(struct_type.elements): - return i - break - else: - if short_name: - for cn_key, members in self.class_members.items(): - sn = cn_key.split('.')[-1] if '.' in cn_key else cn_key - if sn == short_name: - for i, (name, _) in enumerate(members): - if name == field_name and i < len(struct_type.elements): - return i - break - if ClassName and field_name and ClassName not in self.class_members: - if hasattr(self, '_Trans') and self._Trans and hasattr(self._Trans, 'ImportHandler'): - for temp_dir_candidate in [getattr(self, '_temp_dir', None)]: - if temp_dir_candidate and os.path.isdir(temp_dir_candidate): - for pyi_file in os.listdir(temp_dir_candidate): - if pyi_file.endswith('.pyi'): - stub_name = pyi_file.replace('.pyi', '.stub.ll') - short_cn = short_name if short_name else ClassName - self._Trans.ImportHandler._TryLoadClassMembersFromPyi(short_cn, stub_name, self) - if short_cn in self.class_members and len(self.class_members[short_cn]) > 0: - for i, (name, _) in enumerate(self.class_members[short_cn]): - if name == field_name: - return base + i - break - if ClassName and ClassName in self.structs and (ClassName not in self.class_members or len(self.class_members.get(ClassName, [])) == 0): - struct_type = self.structs[ClassName] - if isinstance(struct_type, ir.IdentifiedStructType) and struct_type.elements is not None: - if hasattr(self, '_Trans') and self._Trans and hasattr(self._Trans, 'ClassHandler'): - class_handler = self._Trans.ClassHandler - if hasattr(self, '_current_tree') and self._current_tree: - for node in ast.iter_child_nodes(self._current_tree): - if isinstance(node, ast.ClassDef) and (node.name == ClassName or node.name == short_name): - if node.name not in self.class_members: - self.class_members[node.name] = [] - if len(self.class_members[node.name]) == 0: - class_handler._PreRegisterClassMembers(node, self) - if ClassName in self.class_members: - for i, (name, _) in enumerate(self.class_members[ClassName]): - if name == field_name: - return base + i - if short_name and short_name in self.class_members: - for i, (name, _) in enumerate(self.class_members[short_name]): - if name == field_name: - return base + i - break - return None - - def _resolve_class_for_var(self, var_name): - for ClassName in self.class_methods: - if var_name == ClassName or var_name.startswith(f"__with_{ClassName}_"): - return ClassName - if var_name in self.variables: - var = self.variables[var_name] - if isinstance(var.type, ir.PointerType): - for ClassName, struct_type in self.structs.items(): - if var.type.pointee == struct_type: - return ClassName - if isinstance(var.type.pointee, ir.PointerType) and var.type.pointee.pointee == struct_type: - return ClassName - return None - - def _GetOrCreateFunc(self, FuncName, ArgTypes): - mangled_name = self._mangle_func_name(FuncName) - if mangled_name in self.functions: - return self.functions[mangled_name] - FuncType = self._InferFuncTypeForCall(FuncName, ArgTypes) - try: - func = ir.Function(self.module, FuncType, name=mangled_name) - except Exception: # 函数名冲突时添加前缀重试 - func = ir.Function(self.module, FuncType, name=f"_{mangled_name}") - self.functions[mangled_name] = func - return func - - def _resolve_method_class(self, MethodName): - for ClassName, methods in self.class_methods.items(): - if MethodName in methods: - return ClassName - full_name = f"{ClassName}.{MethodName}" - if full_name in methods: - return ClassName - return None - - def _infer_return_type(self, FuncName): - if FuncName in self.functions: - return self.functions[FuncName].type.pointee.return_type - if FuncName in self.known_return_types: - return self.known_return_types[FuncName] - for ClassName, methods in self.class_methods.items(): - for method in methods: - if FuncName == method: - return ir.VoidType() - return ir.IntType(32) - - def _InferFuncTypeForCall(self, FuncName, ArgTypes): - return_type = self._infer_return_type(FuncName) - if not ArgTypes: - for ClassName, methods in self.class_methods.items(): - if FuncName in methods: - if ClassName in self.structs: - ArgTypes = [ir.PointerType(self.structs[ClassName])] - else: - ArgTypes = [ir.PointerType(ir.LiteralStructType([ir.PointerType(ir.IntType(8)), ir.IntType(32)]))] - break - else: - ArgTypes = [ir.IntType(32)] - return ir.FunctionType(return_type, ArgTypes) - - def _get_or_declare_func(self, name, func_type): - import re - for fname, fobj in self.functions.items(): - if fname == name: - return fobj - if re.match(r'^[0-9a-f]{16,}\.' + re.escape(name) + r'$', fname): - return fobj - func_decl = ir.Function(self.module, func_type, name=name) - self.functions[name] = func_decl - return func_decl - - def get_or_declare_c_func(self, name, fallback_type=None): - if name in self.functions: - return self.functions[name] - import re - for fname, fobj in self.functions.items(): - if re.match(r'^[0-9a-f]{16,}\.' + re.escape(name) + r'$', fname): - return fobj - stub_func_type = None - if hasattr(self, '_import_handler_ref') and self._import_handler_ref: - try: - stub_func_type = self._import_handler_ref._LookupStubFuncType(name, self) - except Exception as _e: - from lib.core.VLogger import get_logger as _vlog - from lib.constants.config import mode as _config_mode - if _config_mode == "strict": - raise - _vlog().warning(f"查找桩函数类型失败: {_e}", "Exception") - if stub_func_type: - func_decl = ir.Function(self.module, stub_func_type, name=name) - self.functions[name] = func_decl - return func_decl - if fallback_type is not None: - func_decl = ir.Function(self.module, fallback_type, name=name) - self.functions[name] = func_decl - return func_decl - return None +from __future__ import annotations +from typing import Any +import ast +import os +import re +import llvmlite.ir as ir +from lib.core.Handles.HandlesBase import CTypeInfo +from lib.core.VLogger import get_logger as _vlog +from lib.constants.config import mode as _config_mode + + +class FuncGenMixin: + + def setup_from_symbol_table(self, SymbolTable: Any) -> None: + self.SymbolTable: Any = SymbolTable + for name, info in SymbolTable.items(): + if isinstance(info, CTypeInfo): + # CTypeInfo 对象:struct/union 由 StructGen 处理,此处只处理 dict 格式 + continue + if not isinstance(info, dict): + if hasattr(info, 'get'): + info = dict(info) if hasattr(info, '__iter__') else {} + else: + continue + TypeKind: str = info.get('type', '') + if TypeKind == 'struct': + ClassName: str = name + self.class_methods[ClassName] = [] + self.class_members[ClassName] = [] + members: dict[str, Any] = info.get('members', {}) + if members: + for MemberName, MemberInfo in members.items(): + if isinstance(MemberInfo, dict): + MemberType: ir.Type = self._type_str_to_llvm(MemberInfo.get('type', 'int'), MemberInfo.get('IsPtr', False)) + self.class_members[ClassName].append((MemberName, MemberType)) + elif isinstance(MemberInfo, CTypeInfo): + MemberType: ir.Type = self._ctype_to_llvm(MemberInfo) + if MemberType is None: + MemberType = self._type_str_to_llvm(MemberInfo.ToString(), MemberInfo.IsPtr) + self.class_members[ClassName].append((MemberName, MemberType)) + self._generate_structs() + self._create_Vtable_globals() + + def register_method(self, ClassName: str, MethodName: str) -> None: + if ClassName not in self.class_methods: + self.class_methods[ClassName] = [] + if ClassName not in self.class_members: + self.class_members[ClassName] = [] + self._generate_structs() + self._create_Vtable_globals() + if MethodName not in self.class_methods[ClassName]: + self.class_methods[ClassName].append(MethodName) + + def _apply_auto_addr(self, func_name: str, args: list[ir.Value]) -> list[ir.Value]: + """对函数参数应用自动取地址逻辑(t.CNeedPtr / t.CAutoPtr)。 + + 在调用前对标记为 auto-addr 的参数自动取地址: + - 'need' (t.CNeedPtr): 仅对非指针值取地址(alloca + store + get pointer) + - 'always' (t.CAutoPtr): 无条件取地址 + """ + modes: list[str | None] | None = self._auto_addr_params.get(func_name) + if not modes: + return args + new_args: list[ir.Value] = list(args) + for i, mode in enumerate(modes): + if i >= len(new_args) or mode is None: + continue + arg: ir.Value = new_args[i] + is_ptr: bool = isinstance(arg.type, ir.PointerType) + if mode == 'always' or (mode == 'need' and not is_ptr): + # alloca + store + get pointer + slot: ir.Value = self.builder.alloca(arg.type) + self.builder.store(arg, slot) + new_args[i] = slot + return new_args + + def _adjust_args(self, args: list[ir.Value], func: ir.Function) -> list[ir.Value]: + adjusted: list[ir.Value] = [] + for i, (arg, param) in enumerate(zip(args, func.args)): + if arg.type != param.type: + if isinstance(arg.type, ir.PointerType) and isinstance(param.type, (ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)): + if arg.type.pointee == param.type or (hasattr(arg.type.pointee, 'name') and hasattr(param.type, 'name') and arg.type.pointee.name == param.type.name): + # C 语言中数组参数退化为指针,不做 load 而是退化为元素指针 + if isinstance(param.type, ir.ArrayType): + zero: ir.Constant = ir.Constant(ir.IntType(32), 0) + elem_ptr: ir.Value = self.builder.gep(arg, [zero, zero], name=f"array_decay_arg_{i}") + adjusted.append(elem_ptr) + else: + adjusted.append(self._load(arg, name=f"Load_arg_{i}")) + continue + try: + if isinstance(arg.type, ir.IntType) and isinstance(param.type, ir.PointerType): + if isinstance(param.type.pointee, ir.IntType) and param.type.pointee.width == 8 and arg.type.width == 8: + # 当参数是 i8(字符值)而函数期望 i8*(字符串指针)时 + # 为字符值分配内存,创建 null-terminated 字符串 + tmp: ir.AllocaInstr = self._alloca(ir.ArrayType(ir.IntType(8), 2), name=f"char2str_arg_{i}") + zero: ir.Constant = ir.Constant(ir.IntType(32), 0) + char_ptr: ir.Value = self.builder.gep(tmp, [zero, zero], name=f"char2str_ptr_{i}") + self._store(arg, char_ptr) + null_ptr: ir.Value = self.builder.gep(tmp, [zero, ir.Constant(ir.IntType(32), 1)], name=f"char2str_null_{i}") + self._store(ir.Constant(ir.IntType(8), 0), null_ptr) + adjusted.append(char_ptr) + else: + if isinstance(arg.type, ir.PointerType) and isinstance(param.type, ir.IntType): + # 当参数是指针而函数期望整数时,使用 ptrtoint + adjusted.append(self.builder.ptrtoint(arg, param.type, name=f"ptrtoint_arg_{i}")) + else: + if arg.type.width < 32: + arg = self.builder.zext(arg, ir.IntType(32), name=f"zext_arg_{i}") + adjusted.append(self.builder.inttoptr(arg, param.type, name=f"inttoptr_arg_{i}")) + elif isinstance(arg.type, ir.PointerType) and isinstance(param.type, ir.IntType): + # 当参数是指针而函数期望整数时,使用 ptrtoint + adjusted.append(self.builder.ptrtoint(arg, param.type, name=f"ptrtoint_arg_{i}")) + elif isinstance(arg.type, ir.PointerType) and isinstance(param.type, ir.PointerType): + if isinstance(arg.type.pointee, ir.PointerType) and isinstance(param.type.pointee, ir.IntType): + Loaded: ir.Value = self._load(arg, name=f"Load_arg_{i}") + adjusted.append(Loaded) + elif isinstance(arg.type.pointee, ir.ArrayType) and isinstance(param.type.pointee, (ir.IntType, ir.FloatType, ir.DoubleType)): + zero: ir.Constant = ir.Constant(ir.IntType(32), 0) + elem_ptr: ir.Value = self.builder.gep(arg, [zero, zero], name=f"array_decay_arg_{i}") + if elem_ptr.type != param.type: + adjusted.append(self.builder.bitcast(elem_ptr, param.type, name=f"cast_arg_{i}")) + else: + adjusted.append(elem_ptr) + elif isinstance(arg.type.pointee, ir.ArrayType) and isinstance(param.type.pointee, ir.PointerType): + zero: ir.Constant = ir.Constant(ir.IntType(32), 0) + elem_ptr: ir.Value = self.builder.gep(arg, [zero, zero], name=f"array_decay_arg_{i}") + if elem_ptr.type != param.type: + adjusted.append(self.builder.bitcast(elem_ptr, param.type, name=f"cast_arg_{i}")) + else: + adjusted.append(elem_ptr) + else: + adjusted.append(self.builder.bitcast(arg, param.type, name=f"cast_arg_{i}")) + else: + if isinstance(arg.type, ir.PointerType) and isinstance(param.type, (ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)): + if arg.type.pointee == param.type or (hasattr(arg.type.pointee, 'name') and hasattr(param.type, 'name') and arg.type.pointee.name == param.type.name): + adjusted.append(self._load(arg, name=f"Load_arg_{i}")) + elif isinstance(arg.type.pointee, (ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)): + tmp: ir.AllocaInstr = self._alloca(param.type, name=f"temp_arg_{i}") + Loaded: ir.Value = self.builder.bitcast(arg, ir.PointerType(param.type), name=f"cast_arg_{i}") + Loaded_val: ir.Value = self._load(Loaded, name=f"Load_arg_{i}") + self._store(Loaded_val, tmp) + adjusted.append(self._load(tmp, name=f"reLoad_arg_{i}")) + else: + tmp: ir.AllocaInstr = self._alloca(param.type, name=f"temp_arg_{i}") + cast_ptr: ir.Value = self.builder.bitcast(arg, ir.PointerType(param.type), name=f"cast_arg_{i}") + Loaded_val: ir.Value = self._load(cast_ptr, name=f"Load_arg_{i}") + self._store(Loaded_val, tmp) + adjusted.append(self._load(tmp, name=f"reLoad_arg_{i}")) + elif isinstance(arg.type, ir.PointerType) and arg.type.pointee == param.type: + adjusted.append(self._load(arg, name=f"Load_arg_{i}")) + elif isinstance(param.type, ir.PointerType) and param.type.pointee == arg.type: + tmp: ir.AllocaInstr = self._alloca(arg.type, name=f"temp_arg_{i}") + self._store(arg, tmp) + adjusted.append(tmp) + elif isinstance(arg.type, ir.IntType) and isinstance(param.type, ir.IntType): + if arg.type.width < param.type.width: + # 整数扩展:使用 sext(符号扩展)以正确处理负数 + adjusted.append(self.builder.sext(arg, param.type, name=f"sext_arg_{i}")) + else: + adjusted.append(self.builder.trunc(arg, param.type, name=f"trunc_arg_{i}")) + elif isinstance(arg.type, (ir.FloatType, ir.DoubleType)) and isinstance(param.type, (ir.FloatType, ir.DoubleType)): + if isinstance(arg.type, ir.DoubleType) and isinstance(param.type, ir.FloatType): + adjusted.append(self.builder.fptrunc(arg, param.type, name=f"fptrunc_arg_{i}")) + elif isinstance(arg.type, ir.FloatType) and isinstance(param.type, ir.DoubleType): + adjusted.append(self.builder.fpext(arg, param.type, name=f"fpext_arg_{i}")) + else: + adjusted.append(arg) + elif isinstance(arg.type, (ir.FloatType, ir.DoubleType)) and isinstance(param.type, ir.IntType): + adjusted.append(self.builder.fptosi(arg, param.type, name=f"fptosi_arg_{i}")) + elif isinstance(arg.type, ir.IntType) and isinstance(param.type, (ir.FloatType, ir.DoubleType)): + adjusted.append(self.builder.sitofp(arg, param.type, name=f"sitofp_arg_{i}")) + elif isinstance(arg.type, ir.IntType) and isinstance(param.type, ir.PointerType): + # 整数转指针:inttoptr + if arg.type.width < 64: + i64_val: ir.Value = self.builder.sext(arg, ir.IntType(64), name=f"sext_arg_{i}") + adjusted.append(self.builder.inttoptr(i64_val, param.type, name=f"inttoptr_arg_{i}")) + else: + adjusted.append(self.builder.inttoptr(arg, param.type, name=f"inttoptr_arg_{i}")) + elif isinstance(arg.type, ir.PointerType) and isinstance(param.type, ir.IntType): + # 指针转整数:ptrtoint + i64_val: ir.Value = self.builder.ptrtoint(arg, ir.IntType(64), name=f"ptrtoint_arg_{i}") + if i64_val.type.width > param.type.width: + adjusted.append(self.builder.trunc(i64_val, param.type, name=f"trunc_arg_{i}")) + elif i64_val.type.width < param.type.width: + adjusted.append(self.builder.sext(i64_val, param.type, name=f"sext_arg_{i}")) + else: + adjusted.append(i64_val) + else: + adjusted.append(self.builder.bitcast(arg, param.type, name=f"cast_arg_{i}")) + except Exception: # 参数类型调整失败时使用简化回退逻辑 + if isinstance(arg.type, ir.PointerType) and isinstance(param.type, (ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)): + if arg.type.pointee == param.type or (hasattr(arg.type.pointee, 'name') and hasattr(param.type, 'name') and arg.type.pointee.name == param.type.name): + adjusted.append(self._load(arg, name=f"Load_arg_{i}")) + else: + adjusted.append(self.builder.bitcast(arg, param.type, name=f"cast_arg_{i}")) + elif isinstance(arg.type, ir.PointerType) and arg.type.pointee == param.type: + adjusted.append(self._load(arg, name=f"Load_arg_{i}")) + elif isinstance(param.type, ir.PointerType) and param.type.pointee == arg.type: + tmp: ir.AllocaInstr = self._alloca(arg.type, name=f"temp_arg_{i}") + self._store(arg, tmp) + adjusted.append(tmp) + else: + adjusted.append(arg) + else: + adjusted.append(arg) + while len(adjusted) < len(func.args): + missing_idx: int = len(adjusted) + param: ir.Argument = func.args[missing_idx] + param_type: ir.Type = param.type if hasattr(param, 'type') else param + if isinstance(param_type, ir.PointerType): + adjusted.append(ir.Constant(param_type, None)) + elif isinstance(param_type, ir.IntType): + adjusted.append(ir.Constant(param_type, 0)) + elif isinstance(param_type, (ir.FloatType, ir.DoubleType)): + adjusted.append(ir.Constant(param_type, 0.0)) + else: + adjusted.append(ir.Constant(ir.IntType(32), 0)) + if func.type.pointee.var_arg: + for i in range(len(func.args), len(args)): + arg: ir.Value = args[i] + adjusted.append(arg) + return adjusted + + def _get_member_offset(self, field_name: str, ClassName: str | None = None) -> int | None: + has_vtable: bool = ClassName and (ClassName in self.class_vtable or ClassName in self._cross_module_vtable_classes) + base: int = 1 if has_vtable else 0 + if ClassName and ClassName in self.structs: + struct_type: ir.IdentifiedStructType = self.structs[ClassName] + if isinstance(struct_type, ir.IdentifiedStructType) and struct_type.elements is not None and len(struct_type.elements) > 0: + if ClassName in self.class_members: + expected_fields: int = len(self.class_members[ClassName]) + actual_elements: int = len(struct_type.elements) + if base > 0 and actual_elements == expected_fields: + base = 0 + if ClassName and ClassName in self.class_members: + for i, (name, _) in enumerate(self.class_members[ClassName]): + if name == field_name: + return base + i + short_name: str | None = ClassName.split('.')[-1] if ClassName and '.' in ClassName else None + if short_name and short_name in self.class_members: + for i, (name, _) in enumerate(self.class_members[short_name]): + if name == field_name: + return base + i + if ClassName and field_name: + if ClassName not in self.class_members or field_name not in [n for n, _ in self.class_members.get(ClassName, [])]: + if hasattr(self, '_Trans') and self._Trans and hasattr(self._Trans, 'ImportHandler'): + sha1_map: dict[str, str] = getattr(self, 'ModuleSha1Map', {}) + for mod_name, mod_sha1 in sha1_map.items(): + stub_name: str = f"{mod_sha1}.stub.ll" + self._Trans.ImportHandler._TryLoadClassMembersFromPyi(ClassName, stub_name, self) + if ClassName in self.class_members and len(self.class_members[ClassName]) > 0: + for i, (name, _) in enumerate(self.class_members[ClassName]): + if name == field_name: + return base + i + break + if short_name: + for mod_name, mod_sha1 in sha1_map.items(): + stub_name: str = f"{mod_sha1}.stub.ll" + self._Trans.ImportHandler._TryLoadClassMembersFromPyi(short_name, stub_name, self) + if short_name in self.class_members and len(self.class_members[short_name]) > 0: + for i, (name, _) in enumerate(self.class_members[short_name]): + if name == field_name: + return base + i + break + if ClassName and field_name: + for cn_key in self.class_members: + if cn_key == ClassName or cn_key.endswith(f'.{ClassName}') or (short_name and (cn_key == short_name or cn_key.endswith(f'.{short_name}'))): + for i, (name, _) in enumerate(self.class_members[cn_key]): + if name == field_name: + return base + i + if ClassName and ClassName in self.structs: + struct_type: ir.IdentifiedStructType = self.structs[ClassName] + if isinstance(struct_type, ir.IdentifiedStructType) and struct_type.elements is not None and len(struct_type.elements) > 0: + for cn_key, members in self.class_members.items(): + if cn_key == short_name or (short_name and cn_key.endswith(f'.{short_name}')): + for i, (name, _) in enumerate(members): + if name == field_name and i < len(struct_type.elements): + return i + break + else: + if short_name: + for cn_key, members in self.class_members.items(): + sn: str = cn_key.split('.')[-1] if '.' in cn_key else cn_key + if sn == short_name: + for i, (name, _) in enumerate(members): + if name == field_name and i < len(struct_type.elements): + return i + break + if ClassName and field_name and ClassName not in self.class_members: + if hasattr(self, '_Trans') and self._Trans and hasattr(self._Trans, 'ImportHandler'): + for temp_dir_candidate in [getattr(self, '_temp_dir', None)]: + if temp_dir_candidate and os.path.isdir(temp_dir_candidate): + for pyi_file in os.listdir(temp_dir_candidate): + if pyi_file.endswith('.pyi'): + stub_name: str = pyi_file.replace('.pyi', '.stub.ll') + short_cn: str = short_name if short_name else ClassName + self._Trans.ImportHandler._TryLoadClassMembersFromPyi(short_cn, stub_name, self) + if short_cn in self.class_members and len(self.class_members[short_cn]) > 0: + for i, (name, _) in enumerate(self.class_members[short_cn]): + if name == field_name: + return base + i + break + if ClassName and ClassName in self.structs and (ClassName not in self.class_members or len(self.class_members.get(ClassName, [])) == 0): + struct_type: ir.IdentifiedStructType = self.structs[ClassName] + if isinstance(struct_type, ir.IdentifiedStructType) and struct_type.elements is not None: + if hasattr(self, '_Trans') and self._Trans and hasattr(self._Trans, 'ClassHandler'): + class_handler: Any = self._Trans.ClassHandler + if hasattr(self, '_current_tree') and self._current_tree: + for node in ast.iter_child_nodes(self._current_tree): + if isinstance(node, ast.ClassDef) and (node.name == ClassName or node.name == short_name): + if node.name not in self.class_members: + self.class_members[node.name] = [] + if len(self.class_members[node.name]) == 0: + class_handler._PreRegisterClassMembers(node, self) + if ClassName in self.class_members: + for i, (name, _) in enumerate(self.class_members[ClassName]): + if name == field_name: + return base + i + if short_name and short_name in self.class_members: + for i, (name, _) in enumerate(self.class_members[short_name]): + if name == field_name: + return base + i + break + return None + + def _resolve_class_for_var(self, var_name: str) -> str | None: + for ClassName in self.class_methods: + if var_name == ClassName or var_name.startswith(f"__with_{ClassName}_"): + return ClassName + if var_name in self.variables: + var: ir.Value = self.variables[var_name] + if isinstance(var.type, ir.PointerType): + for ClassName, struct_type in self.structs.items(): + if var.type.pointee == struct_type: + return ClassName + if isinstance(var.type.pointee, ir.PointerType) and var.type.pointee.pointee == struct_type: + return ClassName + return None + + def _GetOrCreateFunc(self, FuncName: str, ArgTypes: list[ir.Type]) -> ir.Function: + mangled_name: str = self._mangle_func_name(FuncName) + if mangled_name in self.functions: + return self.functions[mangled_name] + FuncType: ir.FunctionType = self._InferFuncTypeForCall(FuncName, ArgTypes) + try: + func: ir.Function = ir.Function(self.module, FuncType, name=mangled_name) + except Exception: # 函数名冲突时添加前缀重试 + func = ir.Function(self.module, FuncType, name=f"_{mangled_name}") + self.functions[mangled_name] = func + return func + + def _resolve_method_class(self, MethodName: str) -> str | None: + for ClassName, methods in self.class_methods.items(): + if MethodName in methods: + return ClassName + full_name: str = f"{ClassName}.{MethodName}" + if full_name in methods: + return ClassName + return None + + def _infer_return_type(self, FuncName: str) -> ir.Type: + if FuncName in self.functions: + return self.functions[FuncName].type.pointee.return_type + # 也尝试混淆后的名称 + mangled: str = self._mangle_func_name(FuncName) + if mangled != FuncName and mangled in self.functions: + return self.functions[mangled].type.pointee.return_type + if FuncName in self.known_return_types: + return self.known_return_types[FuncName] + if mangled != FuncName and mangled in self.known_return_types: + return self.known_return_types[mangled] + for ClassName, methods in self.class_methods.items(): + for method in methods: + if FuncName == method: + return ir.VoidType() + if hasattr(self, '_import_handler_ref') and self._import_handler_ref: + try: + # 先用原始名称查找,再用混淆名称查找 + stub_func_type: Any = self._import_handler_ref._LookupStubFuncType(FuncName, self) + if stub_func_type is None and mangled != FuncName: + stub_func_type = self._import_handler_ref._LookupStubFuncType(mangled, self) + if stub_func_type and hasattr(stub_func_type, 'return_type'): + return stub_func_type.return_type + except Exception as _e: + if _config_mode == "strict": + raise + _vlog().warning(f"查找桩函数返回类型失败: {_e}", "Exception") + return ir.IntType(32) + + def _InferFuncTypeForCall(self, FuncName: str, ArgTypes: list[ir.Type]) -> ir.FunctionType: + return_type: ir.Type = self._infer_return_type(FuncName) + if not ArgTypes: + for ClassName, methods in self.class_methods.items(): + if FuncName in methods: + if ClassName in self.structs: + ArgTypes = [ir.PointerType(self.structs[ClassName])] + else: + ArgTypes = [ir.PointerType(ir.LiteralStructType([ir.PointerType(ir.IntType(8)), ir.IntType(32)]))] + break + else: + ArgTypes = [ir.IntType(32)] + return ir.FunctionType(return_type, ArgTypes) + + def _get_or_declare_func(self, name: str, func_type: ir.FunctionType) -> ir.Function: + for fname, fobj in self.functions.items(): + if fname == name: + return fobj + if re.match(r'^[0-9a-f]{16,}\.' + re.escape(name) + r'$', fname): + return fobj + func_decl: ir.Function = ir.Function(self.module, func_type, name=name) + self.functions[name] = func_decl + return func_decl + + def get_or_declare_c_func(self, name: str, fallback_type: ir.FunctionType | None = None) -> ir.Function | None: + if name in self.functions: + return self.functions[name] + for fname, fobj in self.functions.items(): + if re.match(r'^[0-9a-f]{16,}\.' + re.escape(name) + r'$', fname): + return fobj + stub_func_type: ir.FunctionType | None = None + if hasattr(self, '_import_handler_ref') and self._import_handler_ref: + try: + stub_func_type = self._import_handler_ref._LookupStubFuncType(name, self) + except Exception as _e: + if _config_mode == "strict": + raise + _vlog().warning(f"查找桩函数类型失败: {_e}", "Exception") + if stub_func_type: + func_decl: ir.Function = ir.Function(self.module, stub_func_type, name=name) + self.functions[name] = func_decl + return func_decl + if fallback_type is not None: + func_decl: ir.Function = ir.Function(self.module, fallback_type, name=name) + self.functions[name] = func_decl + return func_decl + return None \ No newline at end of file diff --git a/lib/core/LLVMCG/MemoryOps.py b/lib/core/LLVMCG/MemoryOps.py index 7945429..5b7a7eb 100644 --- a/lib/core/LLVMCG/MemoryOps.py +++ b/lib/core/LLVMCG/MemoryOps.py @@ -1,312 +1,305 @@ -from __future__ import annotations -import llvmlite.ir as ir - - -class MemoryOpsMixin: - - def _register_local_heap_ptr(self, val, ClassName=None, VarName=None): - if isinstance(val.type, ir.PointerType): - pointee = val.type.pointee - if isinstance(pointee, (ir.LiteralStructType, ir.IdentifiedStructType)): - self._local_heap_ptrs.append((val, 'struct', ClassName)) - elif isinstance(pointee, ir.IntType) and pointee.width == 8: - self._local_heap_ptrs.append((val, 'i8', ClassName)) - if VarName: - self._var_to_heap_ptr[VarName] = val - - def _unregister_local_heap_ptr(self, val): - self._local_heap_ptrs = [(v, t, cn) for v, t, cn in self._local_heap_ptrs if v is not val] - - def _emit_local_heap_frees(self): - if not self._local_heap_ptrs or not self.builder: - return - # 创建一个集合来跟踪已经删除的对象 - deleted_objects = set() - for ptr, ptr_type, ClassName in self._local_heap_ptrs: - # 先检查指针是否为 null - if ptr_type == 'i8': - # 对于 i8* 类型的指针,加载其值并检查是否为 null - Loaded_ptr = self.builder.load(ptr, name="load_ptr") - null_ptr = ir.Constant(ir.PointerType(ir.IntType(8)), None) - is_null = self.builder.icmp_unsigned('==', Loaded_ptr, null_ptr, name="is_null") - # 创建一个基本块来处理非 null 的情况 - not_null_block = self.builder.append_basic_block(name="not_null") - # 创建一个基本块来处理下一个对象 - next_block = self.builder.append_basic_block(name="next") - # 如果指针为 null,跳转到下一个对象 - self.builder.cbranch(is_null, next_block, not_null_block) - # 切换到非 null 的基本块 - self.builder.position_at_end(not_null_block) - # 然后调用 __del__ 方法 - if ClassName and self._has_function(f'{ClassName}.__del__'): - if isinstance(ptr.type, ir.PointerType) and isinstance(ptr.type.pointee, ir.IntType) and ptr.type.pointee.width == 8: - cast_ptr = self.builder.bitcast(ptr, ir.PointerType(self.structs[ClassName]), name=f"cast_{ClassName}") - else: - cast_ptr = ptr - if cast_ptr not in deleted_objects: - self.builder.call(self._get_function(f'{ClassName}.__del__'), [cast_ptr], name=f"call_{ClassName}.__del__") - deleted_objects.add(cast_ptr) - # 最后释放内存 - if ptr_type == 'struct': - raw = self.builder.bitcast(ptr, ir.PointerType(ir.IntType(8)), name="local_free_cast") - elif ptr_type == 'i8': - raw = ptr - else: - continue - free_type = ir.FunctionType(ir.VoidType(), [ir.PointerType(ir.IntType(8))]) - free_func = self._get_or_declare_func('free', free_type) - self.builder.call(free_func, [raw]) - # 如果是 i8* 类型的指针,跳转到下一个对象 - if ptr_type == 'i8': - self.builder.branch(next_block) - # 切换到下一个对象的基本块 - self.builder.position_at_end(next_block) - self._local_heap_ptrs = [] - - def _RegisterTempPtr(self, val): - if isinstance(val.type, ir.PointerType): - pointee = val.type.pointee - if isinstance(pointee, (ir.LiteralStructType, ir.IdentifiedStructType)): - for CN, ST in self.structs.items(): - if pointee == ST: - self._temp_struct_ptrs.append(val) - return - elif isinstance(pointee, ir.IntType) and pointee.width == 8: - self._temp_struct_ptrs.append(val) - - def _UnregisterTempPtr(self, val): - self._temp_struct_ptrs = [t for t in self._temp_struct_ptrs if t is not val] - - def _EmitTempFrees(self): - if not self._temp_struct_ptrs or not self.builder: - return - for ptr in self._temp_struct_ptrs: - if isinstance(ptr.type, ir.PointerType) and isinstance(ptr.type.pointee, (ir.LiteralStructType, ir.IdentifiedStructType)): - raw = self.builder.bitcast(ptr, ir.PointerType(ir.IntType(8)), name="free_cast") - elif isinstance(ptr.type, ir.PointerType) and isinstance(ptr.type.pointee, ir.IntType) and ptr.type.pointee.width == 8: - raw = ptr - else: - continue - free_type = ir.FunctionType(ir.VoidType(), [ir.PointerType(ir.IntType(8))]) - free_func = self._get_or_declare_func('free', free_type) - self.builder.call(free_func, [raw]) - self._temp_struct_ptrs = [] - - def _ZeroConst(self, typ): - if isinstance(typ, ir.PointerType): - return ir.Constant(typ, None) - return ir.Constant(typ, 0) - - def _alloca(self, typ, name='', align=None, size=None): - if align is None: - align = self._get_align(typ) - if size is not None: - instr = self.builder.alloca(typ, size=size, name=name) - else: - instr = self.builder.alloca(typ, name=name) - if align: - instr.align = align - return instr - - def _allocaEntry(self, typ, name='', align=None): - if align is None: - align = self._get_align(typ) - saved_block = self.builder.block - entry_block = self.func.entry_basic_block - if entry_block.instructions: - first_instr = entry_block.instructions[0] - self.builder.position_before(first_instr) - instr = self.builder.alloca(typ, name=name) - if align: - instr.align = align - self.builder.position_at_end(saved_block) - else: - self.builder.position_at_start(entry_block) - instr = self.builder.alloca(typ, name=name) - if align: - instr.align = align - self.builder.position_at_end(saved_block) - return instr - - def _load(self, ptr, name='', align=None): - if align is None: - if isinstance(ptr.type, ir.PointerType): - align = self._get_align(ptr.type.pointee) - else: - align = 0 - if isinstance(ptr.type, ir.PointerType): - pointee_type = ptr.type.pointee - if isinstance(pointee_type, ir.IdentifiedStructType) and pointee_type.name in self.typedef_int_widths: - width = self.typedef_int_widths[pointee_type.name] - if width > 0: - actual_type = ir.IntType(width) - bitcast_ptr = self.builder.bitcast(ptr, ir.PointerType(actual_type), name="typedef_bitcast_Load") - return self.builder.load(bitcast_ptr, name=name, align=align) - return self.builder.load(ptr, name=name, align=align) - - def _Load_var(self, name): - if name in self._direct_values: - return self._direct_values[name] - if name in self.variables and self.variables[name] is not None: - VarPtr = self.variables[name] - if isinstance(VarPtr, ir.GlobalVariable) and isinstance(VarPtr.type, ir.PointerType) and isinstance(VarPtr.type.pointee, (ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)): - return VarPtr - if isinstance(VarPtr.type, ir.PointerType) and isinstance(VarPtr.type.pointee, (ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)): - return VarPtr - return self._load(VarPtr, name=name) - if name in self.global_vars and name in self.module.globals: - GVar = self.module.globals[name] - self.variables[name] = GVar - if isinstance(GVar, ir.Function): - return GVar - if isinstance(GVar.type, ir.PointerType) and isinstance(GVar.type.pointee, (ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)): - return GVar - return self._load(GVar, name=name) - if name in self.module.globals: - GVar = self.module.globals[name] - self.variables[name] = GVar - if isinstance(GVar, ir.Function): - return GVar - if isinstance(GVar.type, ir.PointerType) and isinstance(GVar.type.pointee, (ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)): - return GVar - return self._load(GVar, name=name) - return None - - def _store_var(self, name, value): - if name in self._direct_values: - old_val = self._direct_values.pop(name) - if name not in self.variables or self.variables[name] is None: - var = self.builder.alloca(old_val.type, name=name) - self._store(old_val, var) - self.variables[name] = var - if name in self.variables and self.variables[name] is not None: - self._store(value, self.variables[name]) - else: - var = self.builder.alloca(value.type, name=name) - self._store(value, var) - self.variables[name] = var - - def _ensure_alloca(self, name, llvm_type): - if name in self._direct_values: - val = self._direct_values.pop(name) - var = self.builder.alloca(llvm_type, name=name) - self._store(val, var) - self.variables[name] = var - return var - if name in self.variables and self.variables[name] is not None: - return self.variables[name] - var = self.builder.alloca(llvm_type, name=name) - self.variables[name] = var - return var - - def _coerce_value(self, val, target_type): - if val.type == target_type: - return val - if isinstance(target_type, ir.IdentifiedStructType) and target_type.name in self.typedef_int_widths: - if isinstance(val.type, ir.IntType): - return val - if isinstance(target_type, ir.IntType) and isinstance(val.type, ir.IntType): - if target_type.width < val.type.width: - return self.builder.trunc(val, target_type, name="trunc_store") - else: - # 使用 sext(符号扩展)以正确处理负数 - return self.builder.sext(val, target_type, name="sext_store") - if isinstance(target_type, ir.PointerType) and isinstance(val.type, ir.PointerType): - if isinstance(val, ir.Constant) and val.constant is None: - return ir.Constant(target_type, None) - return self.builder.bitcast(val, target_type, name="ptr_bitcast_store") - if isinstance(target_type, ir.PointerType) and isinstance(val.type, ir.IntType): - if val.type.width < 64: - val = self.builder.zext(val, ir.IntType(64), name="zext_ptr_store") - return self.builder.inttoptr(val, target_type, name="int_to_ptr_store") - if isinstance(target_type, ir.IntType) and isinstance(val.type, ir.PointerType): - if isinstance(val.type.pointee, ir.IntType) and val.type.pointee.width == target_type.width: - return self.builder.load(val, name="load_ptr_as_int_store") - if target_type.width <= 8 and isinstance(val.type.pointee, ir.IntType): - Loaded = self.builder.load(val, name="load_ptr_byte_store") - if Loaded.type != target_type: - if isinstance(Loaded.type, ir.IntType) and isinstance(target_type, ir.IntType): - if target_type.width < Loaded.type.width: - return self.builder.trunc(Loaded, target_type, name="trunc_ptr_byte_store") - return self.builder.zext(Loaded, target_type, name="zext_ptr_byte_store") - return Loaded - return self.builder.ptrtoint(val, target_type, name="ptr_to_int_store") - if isinstance(target_type, ir.FloatType) and isinstance(val.type, ir.DoubleType): - return self.builder.fptrunc(val, target_type, name="fptrunc_store") - if isinstance(target_type, ir.DoubleType) and isinstance(val.type, ir.FloatType): - return self.builder.fpext(val, target_type, name="fpext_store") - if isinstance(target_type, ir.IntType) and isinstance(val.type, (ir.FloatType, ir.DoubleType)): - return self.builder.fptosi(val, target_type, name="fptosi_store") - if isinstance(target_type, (ir.FloatType, ir.DoubleType)) and isinstance(val.type, ir.IntType): - return self.builder.sitofp(val, target_type, name="sitofp_store") - if isinstance(target_type, ir.ArrayType) and isinstance(val.type, ir.ArrayType): - if target_type.count == val.type.count and target_type.element == val.type.element: - return val - if (isinstance(target_type.element, ir.IntType) and target_type.element.width == 8 - and isinstance(val.type.element, ir.IntType) and val.type.element.width == 8): - if target_type.count > val.type.count: - padded = list(val.constant) if hasattr(val, 'constant') else [] - if padded and len(padded) == val.type.count: - padded.extend([ir.Constant(ir.IntType(8), 0)] * (target_type.count - val.type.count)) - return ir.Constant(target_type, padded) - elif target_type.count < val.type.count: - trimmed = list(val.constant) if hasattr(val, 'constant') else [] - if trimmed and len(trimmed) == val.type.count: - return ir.Constant(target_type, trimmed[:target_type.count]) - if isinstance(val.type, ir.PointerType) and not isinstance(target_type, ir.PointerType): - if val.type.pointee == target_type: - return self.builder.load(val, name="Load_struct_for_store") - if isinstance(val.type.pointee, ir.IdentifiedStructType) and isinstance(target_type, ir.IdentifiedStructType): - if val.type.pointee.name == target_type.name: - Loaded = self.builder.load(val, name="Load_struct_for_store") - if Loaded.type == target_type: - return Loaded - return None - - def _store(self, val, ptr, align=None): - if align is None: - if isinstance(ptr.type, ir.PointerType): - align = self._get_align(ptr.type.pointee) - else: - align = 0 - if isinstance(ptr.type, ir.PointerType): - target_type = ptr.type.pointee - if isinstance(target_type, ir.IdentifiedStructType) and target_type.name in self.typedef_int_widths: - if isinstance(val.type, ir.IntType): - width = self.typedef_int_widths[target_type.name] - if width > 0: - actual_type = ir.IntType(width) - bitcast_ptr = self.builder.bitcast(ptr, ir.PointerType(actual_type), name="typedef_bitcast") - if val.type.width != actual_type.width: - if val.type.width > actual_type.width: - val = self.builder.trunc(val, actual_type, name="trunc_typedef") - else: - val = self.builder.zext(val, actual_type, name="zext_typedef") - return self.builder.store(val, bitcast_ptr, align=align) - if val.type != target_type: - if isinstance(val, ir.Constant) and val.constant is None: - if isinstance(target_type, ir.PointerType): - val = ir.Constant(target_type, None) - elif isinstance(target_type, ir.IdentifiedStructType): - val = ir.Constant(ir.PointerType(target_type), None) - ptr = self.builder.bitcast(ptr, ir.PointerType(ir.PointerType(target_type)), name="null_struct_ptr_cast") - else: - coerced = self._coerce_value(val, target_type) - if coerced is not None: - val = coerced - else: - src_info = self._get_node_info() - raise TypeError(f"cannot store {val.type} to {ptr.type}: mismatching types{src_info}") - return self.builder.store(val, ptr, align=align) - - def _get_var_ptr(self, name): - if name in self._reg_values: - val = self._reg_values[name] - var = self._alloca(val.type, name=name) - self._store(val, var) - self.variables[name] = var - del self._reg_values[name] - return var - if name in self.variables and self.variables[name] is not None: - return self.variables[name] - return None +from __future__ import annotations +import llvmlite.ir as ir + + +class MemoryOpsMixin: + + def _register_local_heap_ptr(self, val: ir.Value, ClassName: str | None = None, VarName: str | None = None) -> None: + if isinstance(val.type, ir.PointerType): + pointee: ir.Type = val.type.pointee + if isinstance(pointee, (ir.LiteralStructType, ir.IdentifiedStructType)): + self._local_heap_ptrs.append((val, 'struct', ClassName)) + elif isinstance(pointee, ir.IntType) and pointee.width == 8: + self._local_heap_ptrs.append((val, 'i8', ClassName)) + if VarName: + self._var_to_heap_ptr[VarName] = val + + def _unregister_local_heap_ptr(self, val: ir.Value) -> None: + self._local_heap_ptrs = [(v, t, cn) for v, t, cn in self._local_heap_ptrs if v is not val] + + def _emit_local_heap_frees(self) -> None: + if not self._local_heap_ptrs or not self.builder: + return + deleted_objects: set[ir.Value] = set() + for ptr, ptr_type, ClassName in self._local_heap_ptrs: + if ptr_type == 'i8': + Loaded_ptr: ir.Value = self.builder.load(ptr, name="load_ptr") + null_ptr: ir.Constant = ir.Constant(ir.PointerType(ir.IntType(8)), None) + is_null: ir.Value = self.builder.icmp_unsigned('==', Loaded_ptr, null_ptr, name="is_null") + not_null_block: ir.Block = self.builder.append_basic_block(name="not_null") + next_block: ir.Block = self.builder.append_basic_block(name="next") + self.builder.cbranch(is_null, next_block, not_null_block) + self.builder.position_at_end(not_null_block) + if ClassName and self._has_function(f'{ClassName}.__del__'): + cast_ptr: ir.Value + if isinstance(ptr.type, ir.PointerType) and isinstance(ptr.type.pointee, ir.IntType) and ptr.type.pointee.width == 8: + cast_ptr = self.builder.bitcast(ptr, ir.PointerType(self.structs[ClassName]), name=f"cast_{ClassName}") + else: + cast_ptr = ptr + if cast_ptr not in deleted_objects: + self.builder.call(self._get_function(f'{ClassName}.__del__'), [cast_ptr], name=f"call_{ClassName}.__del__") + deleted_objects.add(cast_ptr) + raw: ir.Value + if ptr_type == 'struct': + raw = self.builder.bitcast(ptr, ir.PointerType(ir.IntType(8)), name="local_free_cast") + elif ptr_type == 'i8': + raw = ptr + else: + continue + free_type: ir.FunctionType = ir.FunctionType(ir.VoidType(), [ir.PointerType(ir.IntType(8))]) + free_func: ir.Function = self._get_or_declare_func('free', free_type) + self.builder.call(free_func, [raw]) + if ptr_type == 'i8': + self.builder.branch(next_block) + self.builder.position_at_end(next_block) + self._local_heap_ptrs = [] + + def _RegisterTempPtr(self, val: ir.Value) -> None: + if isinstance(val.type, ir.PointerType): + pointee: ir.Type = val.type.pointee + if isinstance(pointee, (ir.LiteralStructType, ir.IdentifiedStructType)): + for CN, ST in self.structs.items(): + if pointee == ST: + self._temp_struct_ptrs.append(val) + return + elif isinstance(pointee, ir.IntType) and pointee.width == 8: + self._temp_struct_ptrs.append(val) + + def _UnregisterTempPtr(self, val: ir.Value) -> None: + self._temp_struct_ptrs = [t for t in self._temp_struct_ptrs if t is not val] + + def _EmitTempFrees(self) -> None: + if not self._temp_struct_ptrs or not self.builder: + return + for ptr in self._temp_struct_ptrs: + raw: ir.Value + if isinstance(ptr.type, ir.PointerType) and isinstance(ptr.type.pointee, (ir.LiteralStructType, ir.IdentifiedStructType)): + raw = self.builder.bitcast(ptr, ir.PointerType(ir.IntType(8)), name="free_cast") + elif isinstance(ptr.type, ir.PointerType) and isinstance(ptr.type.pointee, ir.IntType) and ptr.type.pointee.width == 8: + raw = ptr + else: + continue + free_type: ir.FunctionType = ir.FunctionType(ir.VoidType(), [ir.PointerType(ir.IntType(8))]) + free_func: ir.Function = self._get_or_declare_func('free', free_type) + self.builder.call(free_func, [raw]) + self._temp_struct_ptrs = [] + + def _ZeroConst(self, typ: ir.Type) -> ir.Constant: + if isinstance(typ, ir.PointerType): + return ir.Constant(typ, None) + return ir.Constant(typ, 0) + + def _alloca(self, typ: ir.Type, name: str = '', align: int | None = None, size: ir.Value | None = None) -> ir.AllocaInstr: + if align is None: + align = self._get_align(typ) + instr: ir.AllocaInstr + if size is not None: + instr = self.builder.alloca(typ, size=size, name=name) + else: + instr = self.builder.alloca(typ, name=name) + if align: + instr.align = align + return instr + + def _allocaEntry(self, typ: ir.Type, name: str = '', align: int | None = None) -> ir.AllocaInstr: + if align is None: + align = self._get_align(typ) + saved_block: ir.Block = self.builder.block + entry_block: ir.Block = self.func.entry_basic_block + instr: ir.AllocaInstr + if entry_block.instructions: + first_instr: ir.Instruction = entry_block.instructions[0] + self.builder.position_before(first_instr) + instr = self.builder.alloca(typ, name=name) + if align: + instr.align = align + self.builder.position_at_end(saved_block) + else: + self.builder.position_at_start(entry_block) + instr = self.builder.alloca(typ, name=name) + if align: + instr.align = align + self.builder.position_at_end(saved_block) + return instr + + def _load(self, ptr: ir.Value, name: str = '', align: int | None = None) -> ir.LoadInstr: + if align is None: + if isinstance(ptr.type, ir.PointerType): + align = self._get_align(ptr.type.pointee) + else: + align = 0 + if isinstance(ptr.type, ir.PointerType): + pointee_type: ir.Type = ptr.type.pointee + if isinstance(pointee_type, ir.IdentifiedStructType) and pointee_type.name in self.typedef_int_widths: + width: int = self.typedef_int_widths[pointee_type.name] + if width > 0: + actual_type: ir.IntType = ir.IntType(width) + bitcast_ptr: ir.Value = self.builder.bitcast(ptr, ir.PointerType(actual_type), name="typedef_bitcast_Load") + return self.builder.load(bitcast_ptr, name=name, align=align) + return self.builder.load(ptr, name=name, align=align) + + def _Load_var(self, name: str) -> ir.Value | None: + if name in self._direct_values: + return self._direct_values[name] + if name in self.variables and self.variables[name] is not None: + VarPtr: ir.Value = self.variables[name] + if isinstance(VarPtr, ir.GlobalVariable) and isinstance(VarPtr.type, ir.PointerType) and isinstance(VarPtr.type.pointee, (ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)): + return VarPtr + if isinstance(VarPtr.type, ir.PointerType) and isinstance(VarPtr.type.pointee, (ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)): + return VarPtr + return self._load(VarPtr, name=name) + if name in self.global_vars and name in self.module.globals: + GVar: ir.GlobalVariable = self.module.globals[name] + self.variables[name] = GVar + if isinstance(GVar, ir.Function): + return GVar + if isinstance(GVar.type, ir.PointerType) and isinstance(GVar.type.pointee, (ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)): + return GVar + return self._load(GVar, name=name) + if name in self.module.globals: + GVar = self.module.globals[name] + self.variables[name] = GVar + if isinstance(GVar, ir.Function): + return GVar + if isinstance(GVar.type, ir.PointerType) and isinstance(GVar.type.pointee, (ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)): + return GVar + return self._load(GVar, name=name) + return None + + def _store_var(self, name: str, value: ir.Value) -> None: + if name in self._direct_values: + old_val: ir.Value = self._direct_values.pop(name) + if name not in self.variables or self.variables[name] is None: + var: ir.AllocaInstr = self.builder.alloca(old_val.type, name=name) + self._store(old_val, var) + self.variables[name] = var + if name in self.variables and self.variables[name] is not None: + self._store(value, self.variables[name]) + else: + var: ir.AllocaInstr = self.builder.alloca(value.type, name=name) + self._store(value, var) + self.variables[name] = var + + def _ensure_alloca(self, name: str, llvm_type: ir.Type) -> ir.AllocaInstr: + if name in self._direct_values: + val: ir.Value = self._direct_values.pop(name) + var: ir.AllocaInstr = self.builder.alloca(llvm_type, name=name) + self._store(val, var) + self.variables[name] = var + return var + if name in self.variables and self.variables[name] is not None: + return self.variables[name] + var: ir.AllocaInstr = self.builder.alloca(llvm_type, name=name) + self.variables[name] = var + return var + + def _coerce_value(self, val: ir.Value, target_type: ir.Type) -> ir.Value | None: + if val.type == target_type: + return val + if isinstance(target_type, ir.IdentifiedStructType) and target_type.name in self.typedef_int_widths: + if isinstance(val.type, ir.IntType): + return val + if isinstance(target_type, ir.IntType) and isinstance(val.type, ir.IntType): + if target_type.width < val.type.width: + return self.builder.trunc(val, target_type, name="trunc_store") + else: + return self.builder.sext(val, target_type, name="sext_store") + if isinstance(target_type, ir.PointerType) and isinstance(val.type, ir.PointerType): + if isinstance(val, ir.Constant) and val.constant is None: + return ir.Constant(target_type, None) + return self.builder.bitcast(val, target_type, name="ptr_bitcast_store") + if isinstance(target_type, ir.PointerType) and isinstance(val.type, ir.IntType): + if val.type.width < 64: + val = self.builder.zext(val, ir.IntType(64), name="zext_ptr_store") + return self.builder.inttoptr(val, target_type, name="int_to_ptr_store") + if isinstance(target_type, ir.IntType) and isinstance(val.type, ir.PointerType): + if isinstance(val.type.pointee, ir.IntType) and val.type.pointee.width == target_type.width: + return self.builder.load(val, name="load_ptr_as_int_store") + if target_type.width <= 8 and isinstance(val.type.pointee, ir.IntType): + Loaded: ir.Value = self.builder.load(val, name="load_ptr_byte_store") + if Loaded.type != target_type: + if isinstance(Loaded.type, ir.IntType) and isinstance(target_type, ir.IntType): + if target_type.width < Loaded.type.width: + return self.builder.trunc(Loaded, target_type, name="trunc_ptr_byte_store") + return self.builder.zext(Loaded, target_type, name="zext_ptr_byte_store") + return Loaded + return self.builder.ptrtoint(val, target_type, name="ptr_to_int_store") + if isinstance(target_type, ir.FloatType) and isinstance(val.type, ir.DoubleType): + return self.builder.fptrunc(val, target_type, name="fptrunc_store") + if isinstance(target_type, ir.DoubleType) and isinstance(val.type, ir.FloatType): + return self.builder.fpext(val, target_type, name="fpext_store") + if isinstance(target_type, ir.IntType) and isinstance(val.type, (ir.FloatType, ir.DoubleType)): + return self.builder.fptosi(val, target_type, name="fptosi_store") + if isinstance(target_type, (ir.FloatType, ir.DoubleType)) and isinstance(val.type, ir.IntType): + return self.builder.sitofp(val, target_type, name="sitofp_store") + if isinstance(target_type, ir.ArrayType) and isinstance(val.type, ir.ArrayType): + if target_type.count == val.type.count and target_type.element == val.type.element: + return val + if (isinstance(target_type.element, ir.IntType) and target_type.element.width == 8 + and isinstance(val.type.element, ir.IntType) and val.type.element.width == 8): + if target_type.count > val.type.count: + padded: list[ir.Constant] = list(val.constant) if hasattr(val, 'constant') else [] + if padded and len(padded) == val.type.count: + padded.extend([ir.Constant(ir.IntType(8), 0)] * (target_type.count - val.type.count)) + return ir.Constant(target_type, padded) + elif target_type.count < val.type.count: + trimmed: list[ir.Constant] = list(val.constant) if hasattr(val, 'constant') else [] + if trimmed and len(trimmed) == val.type.count: + return ir.Constant(target_type, trimmed[:target_type.count]) + if isinstance(val.type, ir.PointerType) and not isinstance(target_type, ir.PointerType): + if val.type.pointee == target_type: + return self.builder.load(val, name="Load_struct_for_store") + if isinstance(val.type.pointee, ir.IdentifiedStructType) and isinstance(target_type, ir.IdentifiedStructType): + if val.type.pointee.name == target_type.name: + Loaded: ir.Value = self.builder.load(val, name="Load_struct_for_store") + if Loaded.type == target_type: + return Loaded + return None + + def _store(self, val: ir.Value, ptr: ir.Value, align: int | None = None) -> ir.StoreInstr: + if align is None: + if isinstance(ptr.type, ir.PointerType): + align = self._get_align(ptr.type.pointee) + else: + align = 0 + if isinstance(ptr.type, ir.PointerType): + target_type: ir.Type = ptr.type.pointee + if isinstance(target_type, ir.IdentifiedStructType) and target_type.name in self.typedef_int_widths: + if isinstance(val.type, ir.IntType): + width: int = self.typedef_int_widths[target_type.name] + if width > 0: + actual_type: ir.IntType = ir.IntType(width) + bitcast_ptr: ir.Value = self.builder.bitcast(ptr, ir.PointerType(actual_type), name="typedef_bitcast") + if val.type.width != actual_type.width: + if val.type.width > actual_type.width: + val = self.builder.trunc(val, actual_type, name="trunc_typedef") + else: + val = self.builder.zext(val, actual_type, name="zext_typedef") + return self.builder.store(val, bitcast_ptr, align=align) + if val.type != target_type: + if isinstance(val, ir.Constant) and val.constant is None: + if isinstance(target_type, ir.PointerType): + val = ir.Constant(target_type, None) + elif isinstance(target_type, ir.IdentifiedStructType): + val = ir.Constant(ir.PointerType(target_type), None) + ptr = self.builder.bitcast(ptr, ir.PointerType(ir.PointerType(target_type)), name="null_struct_ptr_cast") + else: + coerced: ir.Value | None = self._coerce_value(val, target_type) + if coerced is not None: + val = coerced + else: + src_info: str = self._get_node_info() + raise TypeError(f"cannot store {val.type} to {ptr.type}: mismatching types{src_info}") + return self.builder.store(val, ptr, align=align) + + def _get_var_ptr(self, name: str) -> ir.Value | None: + if name in self._reg_values: + val: ir.Value = self._reg_values[name] + var: ir.AllocaInstr = self._alloca(val.type, name=name) + self._store(val, var) + self.variables[name] = var + del self._reg_values[name] + return var + if name in self.variables and self.variables[name] is not None: + return self.variables[name] + return None \ No newline at end of file diff --git a/lib/core/LLVMCG/StructGen.py b/lib/core/LLVMCG/StructGen.py index 5d52e39..31c034f 100644 --- a/lib/core/LLVMCG/StructGen.py +++ b/lib/core/LLVMCG/StructGen.py @@ -1,13 +1,15 @@ from __future__ import annotations +from typing import Any, Callable import re import ast import llvmlite.ir as ir from llvmlite.ir.values import _Undefined +from lib.includes import t as _t class StructGenMixin: - def _get_align(self, llvm_type): + def _get_align(self, llvm_type: ir.Type) -> int: if isinstance(llvm_type, ir.IntType): return max(1, llvm_type.width // 8) if isinstance(llvm_type, ir.FloatType): @@ -28,7 +30,53 @@ class StructGenMixin: return 0 return 4 - def _get_struct_size(self, llvm_type): + def _resolve_opaque_struct(self, llvm_type: ir.Type) -> ir.Type: + """尝试从 Gen.structs 中查找已解析的同名 struct,解决跨模块 struct 类型对象不一致的问题""" + if not isinstance(llvm_type, ir.IdentifiedStructType): + return llvm_type + if llvm_type.elements is not None and len(llvm_type.elements) > 0: + return llvm_type + # opaque struct,尝试通过名称在 Gen.structs 中查找已解析的版本 + st_name: str + try: + st_name = llvm_type.name + except Exception: + return llvm_type + if not st_name: + return llvm_type + # 提取短名称 + short_name: str = st_name + if '.' in st_name: + short_name = st_name.split('.', 1)[1] + # 尝试短名称查找 + if short_name in self.structs: + resolved: ir.IdentifiedStructType = self.structs[short_name] + if isinstance(resolved, ir.IdentifiedStructType) and resolved.elements is not None and len(resolved.elements) > 0: + return resolved + # 尝试全名查找 + if st_name in self.structs: + resolved: ir.IdentifiedStructType = self.structs[st_name] + if isinstance(resolved, ir.IdentifiedStructType) and resolved.elements is not None and len(resolved.elements) > 0: + return resolved + # 尝试通过导入处理器从 stub 文件加载 struct 定义 + import_handler: Any = getattr(self, '_import_handler_ref', None) + if import_handler is not None: + try: + import_handler._TryLoadStructFromStub(short_name, self) + except Exception: + pass + # 加载后再次查找 + if short_name in self.structs: + resolved = self.structs[short_name] + if isinstance(resolved, ir.IdentifiedStructType) and resolved.elements is not None and len(resolved.elements) > 0: + return resolved + if st_name in self.structs: + resolved = self.structs[st_name] + if isinstance(resolved, ir.IdentifiedStructType) and resolved.elements is not None and len(resolved.elements) > 0: + return resolved + return llvm_type + + def _get_struct_size(self, llvm_type: ir.Type) -> int: if isinstance(llvm_type, ir.IntType): return max(1, llvm_type.width // 8) if isinstance(llvm_type, ir.FloatType): @@ -40,11 +88,11 @@ class StructGenMixin: if isinstance(llvm_type, ir.ArrayType): return self._get_struct_size(llvm_type.element) * llvm_type.count if isinstance(llvm_type, ir.LiteralStructType): - total = 0 - max_align = 1 + total: int = 0 + max_align: int = 1 for f in llvm_type.fields: - fa = self._get_align(f) - fs = self._get_struct_size(f) + fa: int = self._get_align(f) + fs: int = self._get_struct_size(f) max_align = max(max_align, fa) if fa > 1: total = (total + fa - 1) // fa * fa @@ -53,13 +101,15 @@ class StructGenMixin: total = (total + max_align - 1) // max_align * max_align return total if isinstance(llvm_type, ir.IdentifiedStructType): + # 尝试解析 opaque struct 为已注册的版本 + llvm_type = self._resolve_opaque_struct(llvm_type) if llvm_type.elements is None or len(llvm_type.elements) == 0: return self.ptr_size # opaque struct, assume pointer size - total = 0 - max_align = 1 + total: int = 0 + max_align: int = 1 for f in llvm_type.elements: - fa = self._get_align(f) - fs = self._get_struct_size(f) + fa: int = self._get_align(f) + fs: int = self._get_struct_size(f) max_align = max(max_align, fa) if fa > 1: total = (total + fa - 1) // fa * fa @@ -70,10 +120,10 @@ class StructGenMixin: return 4 @staticmethod - def _strip_unnecessary_quotes(ir_str): - def _unquote(m): - prefix = m.group(1) - name = m.group(2) + def _strip_unnecessary_quotes(ir_str: str) -> str: + def _unquote(m: re.Match) -> str: + prefix: str = m.group(1) + name: str = m.group(2) if '.' in name: return m.group(0) if re.match(r'^[a-zA-Z_$][a-zA-Z0-9_$]*$', name): @@ -81,9 +131,10 @@ class StructGenMixin: return m.group(0) return re.sub(r'([@%])"([^"]+)"', _unquote, ir_str) - def finalize(self): + def finalize(self) -> str: self._set_Vtable_initializers() self._fix_global_var_init() + ir_text: str try: ir_text = str(self.module) except TypeError as e: @@ -96,11 +147,12 @@ class StructGenMixin: pass raise ir_text = self._strip_unnecessary_quotes(ir_text) - struct_defs = [] - struct_names = set() + struct_defs: list[str] = [] + struct_names: set[str] = set() for ClassName, struct_type in self.structs.items(): if isinstance(struct_type, ir.IdentifiedStructType): - sname = struct_type.name + sname: str = struct_type.name + sname_ir: str if sname[0].isdigit() or '.' in sname or not sname.replace('_', '').replace('.', '').isalnum(): sname_ir = f'%"{sname}"' else: @@ -110,19 +162,20 @@ class StructGenMixin: struct_names.add(sname) struct_defs.append(f'{sname_ir} = type opaque') continue - elems = ', '.join(str(e) for e in struct_type.elements) + elems: str = ', '.join(str(e) for e in struct_type.elements) if struct_type.packed: struct_defs.append(f'{sname_ir} = type <{{ {elems} }}>') else: struct_defs.append(f'{sname_ir} = type {{ {elems} }}') struct_names.add(sname) if struct_defs: - lines = ir_text.split('\n') - filtered = [] + lines: list[str] = ir_text.split('\n') + filtered: list[str] = [] for line in lines: - stripped = line.strip() - skip = False + stripped: str = line.strip() + skip: bool = False for name in struct_names: + patterns: list[str] if name[0].isdigit() or '.' in name or not name.replace('_', '').replace('.', '').isalnum(): patterns = [f'%"{name}" = type', f'%"{name}"=type', f'%{name} = type', f'%{name}=type'] else: @@ -136,17 +189,17 @@ class StructGenMixin: if not skip: filtered.append(line) ir_text = '\n'.join(filtered) - header_end = ir_text.find('\ndefine') + header_end: int = ir_text.find('\ndefine') if header_end == -1: header_end = ir_text.find('\ndeclare') if header_end == -1: header_end = ir_text.find('\n@') if header_end == -1: header_end = len(ir_text) - insert_pos = ir_text.rfind('\n', 0, header_end) + insert_pos: int = ir_text.rfind('\n', 0, header_end) if insert_pos == -1: insert_pos = header_end - struct_block = '\n'.join(struct_defs) + '\n' + struct_block: str = '\n'.join(struct_defs) + '\n' ir_text = ir_text[:insert_pos + 1] + struct_block + ir_text[insert_pos + 1:] for name in struct_names: if name[0].isdigit() or '.' in name: @@ -158,13 +211,13 @@ class StructGenMixin: return ir_text - def _collect_classes_and_methods(self, ast_nodes, parent=None): - current_class = None + def _collect_classes_and_methods(self, ast_nodes: list[ast.AST], parent: ast.AST | None = None) -> None: + current_class: str | None = None for node in ast_nodes: if isinstance(node, str): continue node.parent = parent - node_type = type(node).__name__ + node_type: str = type(node).__name__ if node_type == 'Struct': if hasattr(node, 'name'): current_class = node.name @@ -173,11 +226,11 @@ class StructGenMixin: if hasattr(node, 'decls') and node.decls: for decl in node.decls: if type(decl).__name__ == 'Decl' and hasattr(decl, 'name'): - member_type = self._get_type(decl.type) if hasattr(decl, 'type') else ir.IntType(32) + member_type: ir.Type = self._get_type(decl.type) if hasattr(decl, 'type') else ir.IntType(32) self.class_members[current_class].append((decl.name, member_type)) elif node_type == 'FuncDef': if current_class and current_class in self.class_methods: - MethodName = node.decl.name if hasattr(node.decl, 'name') else 'unknown_method' + MethodName: str = node.decl.name if hasattr(node.decl, 'name') else 'unknown_method' if not MethodName.startswith(f"{current_class}."): MethodName = f"{current_class}.{MethodName}" self.class_methods[current_class].append(MethodName) @@ -186,10 +239,10 @@ class StructGenMixin: elif hasattr(node, 'BlockItems') and node.BlockItems: self._collect_classes_and_methods(node.BlockItems, parent=node) - def _generate_structs(self): - all_classes = set(self.class_methods.keys()) | set(self.class_members.keys()) + def _generate_structs(self) -> None: + all_classes: set[str] = set(self.class_methods.keys()) | set(self.class_members.keys()) - preserved_structs = {} + preserved_structs: dict[str, ir.IdentifiedStructType] = {} for name, st in self.structs.items(): if name not in all_classes: preserved_structs[name] = st @@ -204,25 +257,24 @@ class StructGenMixin: # Step 1: 先为所有类创建空的 struct,确保后面可以正确引用 all_classes = set(self.class_methods.keys()) | set(self.class_members.keys()) for ClassName in all_classes: - is_packed = ClassName in self.class_packed - if hasattr(self, 'SymbolTable') and self.SymbolTable and self.SymbolTable.has(ClassName): - Entry = self.SymbolTable[ClassName] - if Entry.IsExceptionClass: + is_packed: bool = ClassName in self.class_packed + if hasattr(self, 'SymbolTable') and self.SymbolTable: + Entry = self.SymbolTable.lookup(ClassName) + if Entry and Entry.IsExceptionClass: continue - if Entry.IsEnum: + if Entry and Entry.IsEnum: if not Entry.IsRenum: continue - if Entry.IsTypedef: + if Entry and Entry.IsTypedef: if Entry.BaseType and not isinstance(Entry.BaseType, (type(None),)): - import lib.includes.t as _t if not isinstance(Entry.BaseType, (_t._CTypedef,)): continue if ClassName in self.structs: if is_packed: self.structs[ClassName].packed = True continue - mangled_name = self._mangle_name(ClassName) - struct_type = ir.IdentifiedStructType(self.module, mangled_name, packed=is_packed) + mangled_name: str = self._mangle_name(ClassName) + struct_type: ir.IdentifiedStructType = ir.IdentifiedStructType(self.module, mangled_name, packed=is_packed) self.structs[ClassName] = struct_type # Step 2: 解析跨模块的成员类型 @@ -231,30 +283,30 @@ class StructGenMixin: continue for i, (member_name, member_type) in enumerate(self.class_members[ClassName]): if member_name in annotations: - annotation = annotations[member_name] - ResolvedType = None + annotation: Any = annotations[member_name] + ResolvedType: ir.Type | None = None if isinstance(annotation, ast.Attribute): - ClassTypeName = annotation.attr + ClassTypeName: str = annotation.attr if ClassTypeName in self.structs: ResolvedType = self.structs[ClassTypeName] elif isinstance(annotation, ast.BinOp) and isinstance(annotation.op, ast.BitOr): - left = annotation.left + left: Any = annotation.left if isinstance(left, ast.Attribute): - ClassTypeName = left.attr + ClassTypeName: str = left.attr if ClassTypeName in self.structs: ResolvedType = self.structs[ClassTypeName] if ResolvedType: self.class_members[ClassName][i] = (member_name, ResolvedType) - struct_name_map = {} + struct_name_map: dict[str, ir.IdentifiedStructType] = {} for struct_name, struct in self.structs.items(): try: struct_name_map[struct.name] = struct except AssertionError: struct_name_map[struct_name] = struct - orig = getattr(struct, '_original_name', None) + orig: Any = getattr(struct, '_original_name', None) if orig: struct_name_map[orig] = struct @@ -264,81 +316,85 @@ class StructGenMixin: continue for i, (member_name, member_type) in enumerate(self.class_members[ClassName]): if isinstance(member_type, ir.PointerType): - pointee = member_type.pointee + pointee: ir.Type = member_type.pointee if isinstance(pointee, ir.IdentifiedStructType): + pname: str | None try: pname = pointee.name except AssertionError: pname = None - struct = struct_name_map.get(pname) if pname else None + struct: ir.IdentifiedStructType | None = struct_name_map.get(pname) if pname else None if struct is None: - orig = getattr(pointee, '_original_name', None) + orig: Any = getattr(pointee, '_original_name', None) struct = struct_name_map.get(orig) if orig else None if struct is not None: self.class_members[ClassName][i] = (member_name, ir.PointerType(struct)) else: - raw_name = pname or '' + raw_name: str = pname or '' if raw_name.startswith('struct.'): raw_name = raw_name[7:] - new_struct = self._get_or_create_struct(raw_name) + new_struct: ir.IdentifiedStructType = self._get_or_create_struct(raw_name) self.class_members[ClassName][i] = (member_name, ir.PointerType(new_struct)) elif isinstance(member_type, ir.IdentifiedStructType): + mname: str | None try: mname = member_type.name except AssertionError: mname = None - struct = struct_name_map.get(mname) if mname else None + struct: ir.IdentifiedStructType | None = struct_name_map.get(mname) if mname else None if struct is None: - orig = getattr(member_type, '_original_name', None) + orig: Any = getattr(member_type, '_original_name', None) struct = struct_name_map.get(orig) if orig else None if struct is not None: self.class_members[ClassName][i] = (member_name, struct) else: - raw_name = mname or '' + raw_name: str = mname or '' if raw_name.startswith('struct.'): raw_name = raw_name[7:] - new_struct = self._get_or_create_struct(raw_name) + new_struct: ir.IdentifiedStructType = self._get_or_create_struct(raw_name) self.class_members[ClassName][i] = (member_name, new_struct) # Step 4: 创建最终的 structs 并设置正确的成员类型 for ClassName in all_classes: - if hasattr(self, 'SymbolTable') and self.SymbolTable and self.SymbolTable.has(ClassName): - Entry = self.SymbolTable[ClassName] - if Entry.IsExceptionClass: + if hasattr(self, 'SymbolTable') and self.SymbolTable: + Entry = self.SymbolTable.lookup(ClassName) + if Entry and Entry.IsExceptionClass: continue - if Entry.IsEnum: + if Entry and Entry.IsEnum: if not Entry.IsRenum: continue - existing_st = self.structs.get(ClassName) + existing_st: ir.IdentifiedStructType | None = self.structs.get(ClassName) if isinstance(existing_st, ir.IdentifiedStructType) and existing_st.elements is not None and len(existing_st.elements) > 0: # 即使 struct 已有元素,也需要修正 packed 属性 if ClassName in self.class_packed and not existing_st.packed: existing_st.packed = True continue - has_vtable = ClassName in self.class_vtable or ClassName in self._cross_module_vtable_classes + has_vtable: bool = ClassName in self.class_vtable or ClassName in self._cross_module_vtable_classes if not has_vtable: - p = self.class_parent.get(ClassName) + p: str | None = self.class_parent.get(ClassName) while p: if p in self.class_vtable or p in self._cross_module_vtable_classes: has_vtable = True self.class_vtable.add(ClassName) break p = self.class_parent.get(p) - has_bitfield = ClassName in self.class_member_bitfields and any( + has_bitfield: bool = ClassName in self.class_member_bitfields and any( self.class_member_bitfields[ClassName].get(name, 0) > 0 for name, _ in self.class_members.get(ClassName, []) ) - all_members = self.class_members.get(ClassName, []) - all_bitfield = all( + all_members: list[tuple[str, ir.Type]] = self.class_members.get(ClassName, []) + all_bitfield: bool = all( self.class_member_bitfields.get(ClassName, {}).get(name, 0) > 0 for name, _ in all_members ) if all_members else False - mangled_name = self._mangle_name(ClassName) + mangled_name: str = self._mangle_name(ClassName) + member_types: list[ir.Type] if has_bitfield and all_bitfield: - total_bits = sum(self.class_member_bitfields.get(ClassName, {}).get(name, 0) + total_bits: int = sum(self.class_member_bitfields.get(ClassName, {}).get(name, 0) for name, _ in all_members) + storage_type: ir.IntType if total_bits <= 8: storage_type = ir.IntType(8) elif total_bits <= 16: @@ -348,10 +404,10 @@ class StructGenMixin: else: storage_type = ir.IntType(64) member_types = [storage_type] - bitfield_offsets = {} - current_bit_offset = 0 + bitfield_offsets: dict[str, int] = {} + current_bit_offset: int = 0 for name, _ in all_members: - bit_width = self.class_member_bitfields.get(ClassName, {}).get(name, 0) + bit_width: int = self.class_member_bitfields.get(ClassName, {}).get(name, 0) bitfield_offsets[name] = current_bit_offset current_bit_offset += bit_width self.class_member_bitoffsets[ClassName] = bitfield_offsets @@ -368,14 +424,14 @@ class StructGenMixin: member_types = [ir.IntType(8)] # 获取之前创建的 struct 并设置成员 - struct_type = self.structs[ClassName] + struct_type: ir.IdentifiedStructType = self.structs[ClassName] if ClassName in self.class_packed: struct_type.packed = True # 只在未设置 body 时设置,避免重复定义错误 if struct_type.elements is None: struct_type.set_body(*member_types) - def _create_Vtable_globals(self): + def _create_Vtable_globals(self) -> None: for ClassName, methods in self.class_methods.items(): if ClassName in self.Vtables: continue @@ -383,19 +439,19 @@ class StructGenMixin: continue if ClassName not in self.class_vtable and ClassName not in self._cross_module_vtable_classes: continue - VtableType = ir.ArrayType(ir.PointerType(ir.IntType(8)), len(methods)) - Vtable = ir.GlobalVariable(self.module, VtableType, name=self._mangle_name(f"{ClassName}_Vtable")) + VtableType: ir.ArrayType = ir.ArrayType(ir.PointerType(ir.IntType(8)), len(methods)) + Vtable: ir.GlobalVariable = ir.GlobalVariable(self.module, VtableType, name=self._mangle_name(f"{ClassName}_Vtable")) Vtable.initializer = ir.Constant(VtableType, [ir.Constant(ir.PointerType(ir.IntType(8)), None)] * len(methods)) Vtable.linkage = 'internal' self.Vtables[ClassName] = Vtable - def _fix_global_var_init(self): + def _fix_global_var_init(self) -> None: for gv_name, gv in list(self.module.globals.items()): if not isinstance(gv, ir.GlobalVariable): continue if gv.linkage in ('external', 'extern_weak'): continue - needs_fix = False + needs_fix: bool = False if gv.initializer is None: needs_fix = True elif hasattr(gv.initializer, 'constant') and isinstance(gv.initializer.constant, _Undefined): @@ -410,48 +466,27 @@ class StructGenMixin: if gv_name.startswith('str_const_') or gv_name.endswith('_Vtable') or gv_name.endswith('_str'): gv.linkage = 'internal' - def _zero_value_for_type(self, var_type): - if isinstance(var_type, ir.IntType): - return ir.Constant(var_type, 0) - elif isinstance(var_type, (ir.FloatType, ir.DoubleType)): - return ir.Constant(var_type, 0.0) - elif isinstance(var_type, ir.PointerType): - return ir.Constant(var_type, None) - elif isinstance(var_type, ir.ArrayType): - elem_zv = self._zero_value_for_type(var_type.element) - if elem_zv is None: - return None - return ir.Constant(var_type, [elem_zv] * var_type.count) - elif isinstance(var_type, ir.BaseStructType): - if var_type.elements is not None and len(var_type.elements) > 0: - elem_zvs = [self._zero_value_for_type(m) for m in var_type.elements] - if any(zv is None for zv in elem_zvs): - return None - return ir.Constant(var_type, elem_zvs) - return None - return None - - def _set_Vtable_initializers(self): + def _set_Vtable_initializers(self) -> None: for ClassName, methods in self.class_methods.items(): if ClassName not in self.Vtables: continue if not methods: continue - struct_type = self.structs.get(ClassName) + struct_type: ir.IdentifiedStructType | None = self.structs.get(ClassName) if not struct_type: continue - Vtable = self.Vtables[ClassName] - Vtable_entries = [] + Vtable: ir.GlobalVariable = self.Vtables[ClassName] + Vtable_entries: list[ir.Constant] = [] for MethodName in methods: - short_name = MethodName.split('.')[-1] if '.' in MethodName else MethodName - full_MethodName = f"{ClassName}.{short_name}" - func = None + short_name: str = MethodName.split('.')[-1] if '.' in MethodName else MethodName + full_MethodName: str = f"{ClassName}.{short_name}" + func: ir.Function | None = None if full_MethodName in self.functions: func = self.functions[full_MethodName] if func is None: - parent_cls = self.class_parent.get(ClassName) + parent_cls: str | None = self.class_parent.get(ClassName) while parent_cls: - parent_full = f"{parent_cls}.{short_name}" + parent_full: str = f"{parent_cls}.{short_name}" if parent_full in self.functions: func = self.functions[parent_full] break @@ -460,4 +495,4 @@ class StructGenMixin: Vtable_entries.append(ir.Constant(ir.PointerType(ir.IntType(8)), None)) continue Vtable_entries.append(func.bitcast(ir.PointerType(ir.IntType(8)))) - Vtable.initializer = ir.Constant(Vtable.type.pointee, Vtable_entries) + Vtable.initializer = ir.Constant(Vtable.type.pointee, Vtable_entries) \ No newline at end of file diff --git a/lib/core/LLVMCG/TypeConvert.py b/lib/core/LLVMCG/TypeConvert.py index 1453b1f..bf0fee5 100644 --- a/lib/core/LLVMCG/TypeConvert.py +++ b/lib/core/LLVMCG/TypeConvert.py @@ -1,618 +1,710 @@ -from __future__ import annotations -import ast -import llvmlite.ir as ir - - -class TypeConvertMixin: - - def _ctype_to_llvm(self, type_info): - from lib.includes import t as _t - from lib.includes.t import CTypeRegistry - from lib.core.Handles.HandlesBase import CTypeInfo as _CTypeInfo - - if type_info is None: - return ir.IntType(32) - - if isinstance(type_info, str): - return self._type_str_to_llvm(type_info) - - if not isinstance(type_info, _CTypeInfo): - return ir.IntType(32) - - if type_info.IsFuncPtr: - return ir.IntType(8).as_pointer() - - if type_info.IsState and type_info.PtrCount == 0 and not type_info.IsTypedef: - if type_info.BaseType is None or (isinstance(type_info.BaseType, type) and issubclass(type_info.BaseType, _t.CVoid)) or isinstance(type_info.BaseType, _t.CVoid): - return ir.VoidType() - - if type_info.IsTypedef and type_info.Name: - resolved = self._resolve_typedef_ctype(type_info) - if resolved is not None: - return resolved - - BaseType = self._base_ctype_to_llvm(type_info.BaseType, type_info) - - result = BaseType - for _ in range(type_info.PtrCount): - if isinstance(result, ir.VoidType): - result = ir.IntType(8).as_pointer() - else: - result = ir.PointerType(result) - - for dim in reversed(type_info.ArrayDims): - try: - dim_val = int(dim) - if dim_val > 0: - result = ir.ArrayType(result, dim_val) - except (ValueError, TypeError): - pass - - return result - - def _resolve_typedef_ctype(self, type_info): - from lib.includes import t as _t - from lib.core.Handles.HandlesBase import CTypeInfo as _CTypeInfo - - name = type_info.Name - if not name or not hasattr(self, 'SymbolTable') or not self.SymbolTable: - return None - - entry = self.SymbolTable.lookup(name) - if not entry or not isinstance(entry, _CTypeInfo): - return None - - if entry.BaseType and (not isinstance(entry.BaseType, _t._CTypedef) or entry.PtrCount > 0): - resolved = entry.Copy() - resolved.IsTypedef = False - if type_info.PtrCount > resolved.PtrCount: - resolved.PtrCount = type_info.PtrCount - return self._ctype_to_llvm(resolved) - - if entry.OriginalType: - if isinstance(entry.OriginalType, _CTypeInfo): - resolved = entry.OriginalType.Copy() - resolved.IsTypedef = False - if type_info.PtrCount > resolved.PtrCount: - resolved.PtrCount = type_info.PtrCount - return self._ctype_to_llvm(resolved) - elif isinstance(entry.OriginalType, str): - resolved = _CTypeInfo.FromTypeName(entry.OriginalType) - if resolved and resolved.BaseType: - resolved.IsTypedef = False - if type_info.PtrCount > resolved.PtrCount: - resolved.PtrCount = type_info.PtrCount - return self._ctype_to_llvm(resolved) - - return None - - def _base_ctype_to_llvm(self, BaseType, type_info=None): - from lib.includes import t as _t - from lib.includes.t import CTypeRegistry - - if BaseType is None: - return ir.VoidType() - - if isinstance(BaseType, (tuple, list)): - elem_types = [self._base_ctype_to_llvm(bt, type_info) for bt in BaseType] - return ir.LiteralStructType(elem_types) if elem_types else ir.IntType(32) - - if isinstance(BaseType, type) and issubclass(BaseType, _t.CType): - BaseType = BaseType() - - if isinstance(BaseType, _t.CVoid): - return ir.VoidType() - - if isinstance(BaseType, _t.CStruct): - struct_name = getattr(BaseType, 'name', '') or (type_info.Name if type_info else '') - if struct_name and struct_name in self.structs: - return self.structs[struct_name] - if struct_name: - return self._get_or_create_struct(struct_name) - return ir.LiteralStructType([]) - - if isinstance(BaseType, (_t.CEnum, _t.REnum)): - enum_name = type_info.Name if type_info else '' - if enum_name and enum_name in self.structs: - return self.structs[enum_name] - return ir.IntType(32) - - if isinstance(BaseType, _t.CUnion): - union_name = type_info.Name if type_info else '' - if union_name and union_name in self.structs: - return self.structs[union_name] - if union_name: - return self._get_or_create_struct(union_name) - return ir.IntType(32) - - if isinstance(BaseType, _t._CTypedef): - typedef_name = getattr(BaseType, 'value', '') or (type_info.Name if type_info else '') - if typedef_name and hasattr(self, 'SymbolTable') and self.SymbolTable: - from lib.core.Handles.HandlesBase import CTypeInfo as _CTypeInfo - entry = self.SymbolTable.lookup(typedef_name) - if entry and isinstance(entry, _CTypeInfo) and entry.BaseType: - if not isinstance(entry.BaseType, _t._CTypedef) or entry.PtrCount > 0: - return self._base_ctype_to_llvm(entry.BaseType, entry) - return ir.IntType(32) - - if isinstance(BaseType, _t.CDefine): - # Use 64-bit type if the define value exceeds 32-bit range - if type_info and isinstance(type_info.DefineValue, int): - if type_info.DefineValue < 0 or type_info.DefineValue > 0xFFFFFFFF: - return ir.IntType(64) - return ir.IntType(32) - - if isinstance(BaseType, _t.CPass): - return ir.VoidType() - - llvm_str = CTypeRegistry.CTypeToLLVM(type(BaseType)) - return self._llvm_str_to_ir(llvm_str) - - def _llvm_str_to_ir(self, llvm_str): - _map = { - 'void': ir.VoidType, 'i1': lambda: ir.IntType(1), - 'i8': lambda: ir.IntType(8), 'i16': lambda: ir.IntType(16), - 'i32': lambda: ir.IntType(32), 'i64': lambda: ir.IntType(64), - 'i128': lambda: ir.IntType(128), 'half': lambda: ir.IntType(16), - 'float': ir.FloatType, 'double': ir.DoubleType, - 'fp128': lambda: ir.IntType(128), 'i8*': lambda: ir.IntType(8).as_pointer(), - 'f8': lambda: ir.IntType(8), 'f16': lambda: ir.IntType(16), - 'f32': ir.FloatType, 'f64': ir.DoubleType, 'f128': lambda: ir.IntType(128), - } - factory = _map.get(llvm_str) - if factory: - return factory() if callable(factory) else factory - return ir.IntType(32) - - def _resolve_typedef(self, type_name: str) -> str: - if type_name in {'typedef', 'CType', 'CVolatile', 'CEnum', 'CUnion', 'CStruct', 'enum', 'REnum', 'renum'}: - return type_name - if type_name == 'Callable': - return 'Callable' - visited = set() - current = type_name - while current not in visited: - visited.add(current) - if hasattr(self, 'SymbolTable') and self.SymbolTable and self.SymbolTable.has(current): - Entry = self.SymbolTable[current] - if isinstance(Entry, dict) and Entry.get('type') == 'typedef': - OriginalType = Entry.get('OriginalType', '') - if OriginalType: - current = OriginalType - continue - elif Entry.IsTypedef: - if Entry.OriginalType: - if isinstance(Entry.OriginalType, _CTypeInfo): - if Entry.OriginalType.IsFuncPtr: - return 'Callable' - return Entry.OriginalType.ToString() if Entry.OriginalType.BaseType else current - elif isinstance(Entry.OriginalType, str): - current = Entry.OriginalType - continue - if Entry.BaseType: - from lib.includes import t as _t - if not isinstance(Entry.BaseType, (_t._CTypedef,)) or Entry.PtrCount > 0: - resolved = self._resolve_ctype_to_str(Entry) - if resolved and resolved != current: - current = resolved - continue - from lib.core.Handles.HandlesBase import BuiltinTypeMap - bm = BuiltinTypeMap.Get(current) - if bm: - base_cls = bm[0] - try: - instance = base_cls() - cname = getattr(instance, 'CName', '') - if cname: - current = cname + ' *' * bm[1] - continue - except Exception as _e: - if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": - import logging; logging.warning(f"异常被忽略: {_e}") - pass - from lib.core.Handles.HandlesBase import BuiltinTypeMap - bm = BuiltinTypeMap.Get(current) - if bm and bm[1] > 0: - base_cls = bm[0] - try: - instance = base_cls() - cname = getattr(instance, 'CName', '') - if cname: - current = cname + ' *' * bm[1] - continue - except Exception as _e: - if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": - import logging; logging.warning(f"异常被忽略: {_e}") - pass - break - return current - - def _resolve_ctype_to_str(self, type_info) -> str: - from lib.includes import t as _t - parts = [] - base = type_info.BaseType - if base is None or base is _t.CVoid or isinstance(base, _t.CVoid): - parts.append('void') - elif isinstance(base, _t._CTypedef) or base is _t._CTypedef: - return '' - elif isinstance(base, _t.CStruct) or base is _t.CStruct: - parts.append(f'struct {getattr(base, "name", "")}') - elif isinstance(base, _t.CEnum) or base is _t.CEnum: - parts.append(f'enum {getattr(base, "name", "")}') - else: - cname = getattr(base, 'CName', '') - if not cname and isinstance(base, type) and issubclass(base, _t.CType): - try: - inst = base() - cname = getattr(inst, 'CName', '') - except Exception as _e: - if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": - import logging; logging.warning(f"异常被忽略: {_e}") - pass - if cname: - parts.append(cname) - else: - return '' - if type_info.PtrCount > 0: - parts.append('*' * type_info.PtrCount) - return ' '.join(parts) - - def _type_str_to_llvm(self, type_str, IsPtr=False): - type_str = type_str.strip() - cache_key = (type_str, IsPtr) - cached = self._type_cache.get(cache_key) - if cached is not None: - return cached - result = self._type_str_to_llvm_impl(type_str, IsPtr) - if result is not None: - if isinstance(result, (ir.IntType, ir.FloatType, ir.DoubleType, ir.VoidType)): - self._type_cache[cache_key] = result - elif isinstance(result, ir.PointerType) and isinstance(result.pointee, (ir.IntType, ir.FloatType, ir.DoubleType, ir.VoidType)): - self._type_cache[cache_key] = result - elif isinstance(result, ir.ArrayType) and not isinstance(result.element, (ir.IdentifiedStructType, ir.LiteralStructType)): - self._type_cache[cache_key] = result - return result - - _CType2LLVM = _type_str_to_llvm - - def _type_str_to_llvm_impl(self, type_str, IsPtr=False): - array_dims = [] - dim_match = __import__('re').findall(r'\[(\d+)\]', type_str) - if dim_match: - array_dims = [int(d) for d in dim_match] - type_str = __import__('re').sub(r'\s*\[\d+\]', '', type_str).strip() - result = self._type_str_to_llvm_base(type_str, IsPtr) - for dim in reversed(array_dims): - result = ir.ArrayType(result, dim) - return result - - def _type_str_to_llvm_base(self, type_str, IsPtr=False): - ptr_depth = 0 - while type_str.endswith('*'): - ptr_depth += 1 - type_str = type_str[:-1].strip() - if ptr_depth > 0: - IsPtr = True - if type_str in {'typedef', 'CType', 'CVolatile', 'CEnum', 'CUnion', 'CStruct', 'enum', 'REnum', 'renum'}: - if IsPtr: - result = ir.IntType(8).as_pointer() - for _ in range(ptr_depth - 1): - result = ir.PointerType(result) - return result - return ir.IntType(32) - if type_str in {'const', 'volatile'}: - return ir.IntType(8) - if type_str == 'Callable': - return ir.IntType(8).as_pointer() - if type_str.startswith('const '): - inner_type = self._type_str_to_llvm(type_str[6:].strip(), IsPtr) - return inner_type - if type_str.startswith('volatile '): - inner_type = self._type_str_to_llvm(type_str[9:].strip(), IsPtr) - return inner_type - if type_str.startswith('const_'): - inner_type = self._type_str_to_llvm(type_str[6:], IsPtr) - return inner_type - if type_str.startswith('volatile_'): - inner_type = self._type_str_to_llvm(type_str[9:], IsPtr) - return inner_type - if type_str.startswith('static '): - return self._type_str_to_llvm(type_str[7:].strip(), IsPtr) - if type_str.startswith('extern '): - return self._type_str_to_llvm(type_str[7:].strip(), IsPtr) - if type_str.startswith('register '): - return self._type_str_to_llvm(type_str[9:].strip(), IsPtr) - if type_str.startswith('inline '): - return self._type_str_to_llvm(type_str[7:].strip(), IsPtr) - if type_str.startswith('export '): - return self._type_str_to_llvm(type_str[7:].strip(), IsPtr) - resolved = self._resolve_typedef(type_str) - if resolved != type_str: - if '*' in resolved: - IsPtr = False - return self._type_str_to_llvm(resolved, IsPtr) - if type_str.endswith('*'): - BaseType = type_str[:-1].strip() - base_llvm = self._basic_type_to_llvm(BaseType) - if base_llvm is not None and isinstance(base_llvm, ir.VoidType): - result = ir.IntType(8).as_pointer() - for _ in range(ptr_depth): - result = ir.PointerType(result) - return result - if base_llvm is not None and not isinstance(base_llvm, ir.VoidType): - if isinstance(base_llvm, ir.PointerType): - return base_llvm - return ir.PointerType(base_llvm) - if BaseType in self.structs: - return ir.PointerType(self.structs[BaseType]) - if BaseType.startswith('struct '): - stripped = BaseType[7:].strip() - if stripped in self.structs: - return ir.PointerType(self.structs[stripped]) - if '.' in BaseType: - LastPart = BaseType.split('.')[-1] - if LastPart in self.structs: - return ir.PointerType(self.structs[LastPart]) - placeholder = self._get_or_create_struct(LastPart) - return ir.PointerType(placeholder) - if base_llvm is not None and isinstance(base_llvm, ir.VoidType): - return ir.PointerType(ir.IntType(8)) - if type_str.startswith('{') and type_str.endswith('}'): - inner = type_str[1:-1].strip() - elem_strs = [] - depth = 0 - current = '' - for ch in inner: - if ch == ',' and depth == 0: - elem_strs.append(current.strip()) - current = '' - else: - if ch == '{': - depth += 1 - elif ch == '}': - depth -= 1 - current += ch - if current.strip(): - elem_strs.append(current.strip()) - elem_types = [] - for es in elem_strs: - et = self._type_str_to_llvm(es, '*' in es) - if isinstance(et, ir.VoidType): - et = ir.IntType(8).as_pointer() - elem_types.append(et) - if elem_types: - return ir.LiteralStructType(elem_types) - return ir.IntType(32) - if type_str in {'typedef', 'CType', 'CVolatile', 'CEnum', 'CUnion', 'CStruct', 'enum', 'REnum', 'renum'}: - return ir.IntType(32) - if type_str.startswith('%'): - stripped = type_str[1:] - if stripped in {'typedef', 'CType', 'CVolatile', 'CEnum', 'CUnion', 'CStruct', 'enum', 'REnum', 'renum'}: - return ir.IntType(32) if not IsPtr else ir.PointerType(ir.IntType(32)) - basic_stripped = self._basic_type_to_llvm(stripped) - if basic_stripped is not None: - if IsPtr and not isinstance(basic_stripped, ir.VoidType): - return ir.PointerType(basic_stripped) - return basic_stripped - if hasattr(self, 'SymbolTable') and self.SymbolTable and self.SymbolTable.has(type_str): - _Entry = self.SymbolTable[type_str] - if _Entry.IsTypedef: - resolved_str = self._resolve_typedef(type_str) - if resolved_str != type_str: - return self._type_str_to_llvm(resolved_str, IsPtr) - if _Entry.BaseType: - from lib.includes import t as _t - if not isinstance(_Entry.BaseType, (_t._CTypedef,)) or _Entry.PtrCount > 0: - resolved = self._resolve_ctype_to_str(_Entry) - if resolved: - return self._type_str_to_llvm(resolved, IsPtr) - if _Entry.IsRenum: - if type_str in self.structs: - return self.structs[type_str] - if _Entry.IsEnum: - return ir.IntType(32) if not IsPtr else ir.PointerType(ir.IntType(32)) - if _Entry.IsExceptionClass: - return ir.IntType(32) if not IsPtr else ir.PointerType(ir.IntType(32)) - if _Entry.BaseType: - from lib.includes import t as _t - if (isinstance(_Entry.BaseType, type) and issubclass(_Entry.BaseType, _t.CEnum)) or _Entry.BaseType is _t.CEnum: - return ir.IntType(32) if not IsPtr else ir.PointerType(ir.IntType(32)) - for ClassName in self.structs: - if type_str == ClassName: - if IsPtr: - return ir.PointerType(self.structs[ClassName]) - return self.structs[ClassName] - if '.' in type_str and not type_str.startswith('%'): - LastPart = type_str.split('.')[-1] - basic_last = self._basic_type_to_llvm(LastPart) - if basic_last is not None: - if IsPtr and not isinstance(basic_last, ir.VoidType): - return ir.PointerType(basic_last) - return basic_last - if hasattr(self, 'SymbolTable') and self.SymbolTable and self.SymbolTable.has(LastPart): - _Entry = self.SymbolTable[LastPart] - if _Entry.IsTypedef: - resolved_str = self._resolve_typedef(LastPart) - if resolved_str != LastPart: - return self._type_str_to_llvm(resolved_str, IsPtr) - if _Entry.BaseType: - from lib.includes import t as _t - if not isinstance(_Entry.BaseType, (_t._CTypedef,)) or _Entry.PtrCount > 0: - resolved = self._resolve_ctype_to_str(_Entry) - if resolved: - return self._type_str_to_llvm(resolved, IsPtr) - if _Entry.IsRenum: - if LastPart in self.structs: - return self.structs[LastPart] - if _Entry.IsEnum: - return ir.IntType(32) if not IsPtr else ir.PointerType(ir.IntType(32)) - if _Entry.IsExceptionClass: - return ir.IntType(32) if not IsPtr else ir.PointerType(ir.IntType(32)) - if _Entry.BaseType: - from lib.includes import t as _t - if (isinstance(_Entry.BaseType, type) and issubclass(_Entry.BaseType, _t.CEnum)) or _Entry.BaseType is _t.CEnum: - return ir.IntType(32) if not IsPtr else ir.PointerType(ir.IntType(32)) - if LastPart in self.structs: - if IsPtr: - return ir.PointerType(self.structs[LastPart]) - return self.structs[LastPart] - placeholder = self._get_or_create_struct(LastPart) - if IsPtr: - return ir.PointerType(placeholder) - return placeholder - if type_str.startswith('struct '): - stripped = type_str[7:].strip().replace(' *', '').replace('*', '') - if stripped in self.structs: - if IsPtr: - return ir.PointerType(self.structs[stripped]) - return self.structs[stripped] - basic_match = self._basic_type_to_llvm(stripped) - if basic_match is not None: - if IsPtr and not isinstance(basic_match, ir.VoidType): - return ir.PointerType(basic_match) - return basic_match - placeholder = self._get_or_create_struct(stripped) - if IsPtr: - return ir.PointerType(placeholder) - return placeholder - if type_str.startswith('%struct.'): - stripped = type_str[8:].strip().replace(' *', '').replace('*', '') - if stripped in self.structs: - if IsPtr: - return ir.PointerType(self.structs[stripped]) - return self.structs[stripped] - basic_match = self._basic_type_to_llvm(stripped) - if basic_match is not None: - if IsPtr and not isinstance(basic_match, ir.VoidType): - return ir.PointerType(basic_match) - return basic_match - placeholder = self._get_or_create_struct(stripped) - if IsPtr: - return ir.PointerType(placeholder) - return placeholder - if type_str.startswith('union '): - stripped = type_str[6:].strip() - basic_match = self._basic_type_to_llvm(stripped) - if basic_match is not None: - if IsPtr and not isinstance(basic_match, ir.VoidType): - return ir.PointerType(basic_match) - return basic_match - if type_str.endswith('*'): - pointee = self._type_str_to_llvm(type_str[:-1].strip()) - if isinstance(pointee, ir.VoidType): - return ir.PointerType(ir.IntType(8)) - return ir.PointerType(pointee) - result = self._basic_type_to_llvm(type_str) - if result is None: - result = ir.IntType(32) - if IsPtr: - if isinstance(result, ir.VoidType): - result = ir.PointerType(ir.IntType(8)) - elif isinstance(result, ir.PointerType): - pass - else: - result = ir.PointerType(result) - for _ in range(ptr_depth - 1): - result = ir.PointerType(result) - return result - - def _llvm_str_to_ir(self, llvm_str): - _LLVM_IR_TYPES = { - 'void': ir.VoidType(), 'i1': ir.IntType(1), 'i8': ir.IntType(8), - 'i16': ir.IntType(16), 'i32': ir.IntType(32), 'i64': ir.IntType(64), - 'i128': ir.IntType(128), 'float': ir.FloatType(), 'double': ir.DoubleType(), - 'half': ir.IntType(16), 'fp128': ir.IntType(128), - } - return _LLVM_IR_TYPES.get(llvm_str) - - def _basic_type_to_llvm(self, type_str): - _LLVM_IR_TYPES = { - 'void': ir.VoidType(), 'i1': ir.IntType(1), 'i8': ir.IntType(8), - 'i16': ir.IntType(16), 'i32': ir.IntType(32), 'i64': ir.IntType(64), - 'i128': ir.IntType(128), 'f32': ir.FloatType(), 'f64': ir.DoubleType(), - 'half': ir.IntType(16), 'fp128': ir.IntType(128), - } - if type_str in _LLVM_IR_TYPES: - return _LLVM_IR_TYPES[type_str] - from lib.includes.t import CTypeRegistry - resolved = CTypeRegistry.ResolveName(type_str) - if resolved is not None: - ctype_cls, ptr_level = resolved - llvm_str = CTypeRegistry.CTypeToLLVM(ctype_cls) - if llvm_str: - base = self._llvm_str_to_ir(llvm_str) - if base is not None: - for _ in range(ptr_level): - if isinstance(base, ir.VoidType): - base = ir.IntType(8).as_pointer() - else: - base = ir.PointerType(base) - return base - cnameres = CTypeRegistry.CNameToClass(type_str) - if cnameres is not None: - llvm_str = CTypeRegistry.CTypeToLLVM(cnameres) - if llvm_str: - return self._llvm_str_to_ir(llvm_str) - if type_str == '*': - return ir.IntType(8) - if type_str in ('const_', 'const'): - return ir.IntType(8) - return None - - def _is_type_unsigned(self, type_str): - s = type_str.strip() - if s.endswith('*'): - return True - if s.startswith('unsigned'): - return True - from lib.includes.t import CTypeRegistry - resolved = CTypeRegistry.ResolveName(s) - if resolved is not None: - ctype_cls, _ = resolved - try: - inst = ctype_cls() - if getattr(inst, 'IsSigned', None) is False: - return True - except Exception as _e: - from lib.core.VLogger import get_logger as _vlog - from lib.constants.config import mode as _config_mode - if _config_mode == "strict": - raise - _vlog().warning(f"判断类型符号性失败: {_e}", "Exception") - cnameres = CTypeRegistry.CNameToClass(s) - if cnameres is not None: - try: - inst = cnameres() - if getattr(inst, 'IsSigned', None) is False: - return True - except Exception as _e: - from lib.core.VLogger import get_logger as _vlog - from lib.constants.config import mode as _config_mode - if _config_mode == "strict": - raise - _vlog().warning(f"判断类型符号性失败: {_e}", "Exception") - return False - - def _record_var_signedness(self, name, type_str_or_bool): - if isinstance(type_str_or_bool, bool): - self.var_signedness[name] = type_str_or_bool - else: - self.var_signedness[name] = self._is_type_unsigned(type_str_or_bool) - - def _is_var_unsigned(self, name): - return self.var_signedness.get(name, False) - - def _check_node_unsigned(self, node): - if isinstance(node, ast.Name): - return self._is_var_unsigned(node.id) - if isinstance(node, ast.BinOp): - return self._check_node_unsigned(node.left) or self._check_node_unsigned(node.right) - if isinstance(node, ast.UnaryOp): - return self._check_node_unsigned(node.operand) - if isinstance(node, ast.Call): - return False - if isinstance(node, ast.Subscript): - return self._check_node_unsigned(node.value) - if isinstance(node, ast.Attribute): - return self._check_node_unsigned(node.value) - return False +from __future__ import annotations +from typing import Any +import ast +import re +import logging +import llvmlite.ir as ir +from lib.includes import t as _t +from lib.includes.t import CTypeRegistry +from lib.core.Handles.HandlesBase import CTypeInfo as _CTypeInfo, BuiltinTypeMap +from lib.constants.config import mode as _config_mode +from lib.core.VLogger import get_logger as _vlog +from lib.core.SymbolUtils import IsTModule + + +class TypeConvertMixin: + + def _ctype_to_llvm(self, type_info: _CTypeInfo | str | None) -> ir.Type: + if type_info is None: + return ir.IntType(32) + + if isinstance(type_info, str): + return self._type_str_to_llvm(type_info) + + if not isinstance(type_info, _CTypeInfo): + return ir.IntType(32) + + if type_info.IsFuncPtr: + return ir.IntType(8).as_pointer() + + if type_info.IsState and type_info.PtrCount == 0 and not type_info.IsTypedef: + if type_info.BaseType is None or (isinstance(type_info.BaseType, type) and issubclass(type_info.BaseType, _t.CVoid)) or isinstance(type_info.BaseType, _t.CVoid): + return ir.VoidType() + + if type_info.IsTypedef and type_info.Name: + resolved: ir.Type | None = self._resolve_typedef_ctype(type_info) + if resolved is not None: + return resolved + + BaseType: ir.Type = self._base_ctype_to_llvm(type_info.BaseType, type_info) + + result: ir.Type = BaseType + for _ in range(type_info.PtrCount): + if isinstance(result, ir.VoidType): + result = ir.IntType(8).as_pointer() + else: + result = ir.PointerType(result) + + for dim in reversed(type_info.ArrayDims): + try: + dim_val: int = int(dim) + if dim_val > 0: + result = ir.ArrayType(result, dim_val) + except (ValueError, TypeError): + pass + + return result + + def _resolve_typedef_ctype(self, type_info: _CTypeInfo) -> ir.Type | None: + name: str = type_info.Name + if not name or not hasattr(self, 'SymbolTable') or not self.SymbolTable: + return None + + entry: Any = self.SymbolTable.lookup(name) + if not entry or not isinstance(entry, _CTypeInfo): + return None + + if entry.BaseType and (not isinstance(entry.BaseType, _t._CTypedef) or entry.PtrCount > 0): + resolved: Any = entry.Copy() + resolved.IsTypedef = False + if type_info.PtrCount > resolved.PtrCount: + resolved.PtrCount = type_info.PtrCount + return self._ctype_to_llvm(resolved) + + if entry.OriginalType: + if isinstance(entry.OriginalType, _CTypeInfo): + resolved: Any = entry.OriginalType.Copy() + resolved.IsTypedef = False + if type_info.PtrCount > resolved.PtrCount: + resolved.PtrCount = type_info.PtrCount + return self._ctype_to_llvm(resolved) + elif isinstance(entry.OriginalType, str): + resolved: Any = _CTypeInfo.FromTypeName(entry.OriginalType) + if resolved and resolved.BaseType: + resolved.IsTypedef = False + if type_info.PtrCount > resolved.PtrCount: + resolved.PtrCount = type_info.PtrCount + return self._ctype_to_llvm(resolved) + + return None + + def _base_ctype_to_llvm(self, BaseType: Any, type_info: _CTypeInfo | None = None) -> ir.Type: + if BaseType is None: + return ir.VoidType() + + if isinstance(BaseType, (tuple, list)): + elem_types: list[ir.Type] = [self._base_ctype_to_llvm(bt, type_info) for bt in BaseType] + return ir.LiteralStructType(elem_types) if elem_types else ir.IntType(32) + + if isinstance(BaseType, type) and issubclass(BaseType, _t.CType): + BaseType = BaseType() + + if isinstance(BaseType, _t.CVoid): + return ir.VoidType() + + if isinstance(BaseType, _t.CStruct): + struct_name: str = getattr(BaseType, 'name', '') or (type_info.Name if type_info else '') + if struct_name and struct_name in self.structs: + return self.structs[struct_name] + if struct_name: + return self._get_or_create_struct(struct_name) + return ir.LiteralStructType([]) + + if isinstance(BaseType, (_t.CEnum, _t.REnum)): + enum_name: str = type_info.Name if type_info else '' + if enum_name and enum_name in self.structs: + return self.structs[enum_name] + return ir.IntType(32) + + if isinstance(BaseType, _t.CUnion): + union_name: str = type_info.Name if type_info else '' + if union_name and union_name in self.structs: + return self.structs[union_name] + if union_name: + return self._get_or_create_struct(union_name) + return ir.IntType(32) + + if isinstance(BaseType, _t._CTypedef): + typedef_name: str = getattr(BaseType, 'value', '') or (type_info.Name if type_info else '') + if typedef_name and hasattr(self, 'SymbolTable') and self.SymbolTable: + entry: Any = self.SymbolTable.lookup(typedef_name) + if entry and isinstance(entry, _CTypeInfo) and entry.BaseType: + if not isinstance(entry.BaseType, _t._CTypedef) or entry.PtrCount > 0: + return self._base_ctype_to_llvm(entry.BaseType, entry) + return ir.IntType(32) + + if isinstance(BaseType, _t.CDefine): + # Use 64-bit type if the define value exceeds 32-bit range + if type_info and isinstance(type_info.DefineValue, int): + if type_info.DefineValue < 0 or type_info.DefineValue > 0xFFFFFFFF: + return ir.IntType(64) + return ir.IntType(32) + + if isinstance(BaseType, _t.CPass): + return ir.VoidType() + + llvm_str: str = CTypeRegistry.CTypeToLLVM(type(BaseType)) + return self._llvm_str_to_ir(llvm_str) + + def _llvm_str_to_ir(self, llvm_str: str) -> ir.Type: + _map: dict[str, Any] = { + 'void': ir.VoidType, 'i1': lambda: ir.IntType(1), + 'i8': lambda: ir.IntType(8), 'i16': lambda: ir.IntType(16), + 'i32': lambda: ir.IntType(32), 'i64': lambda: ir.IntType(64), + 'i128': lambda: ir.IntType(128), 'half': lambda: ir.IntType(16), + 'float': ir.FloatType, 'double': ir.DoubleType, + 'fp128': lambda: ir.IntType(128), 'i8*': lambda: ir.IntType(8).as_pointer(), + 'f8': lambda: ir.IntType(8), 'f16': lambda: ir.IntType(16), + 'f32': ir.FloatType, 'f64': ir.DoubleType, 'f128': lambda: ir.IntType(128), + } + factory: Any = _map.get(llvm_str) + if factory: + return factory() if callable(factory) else factory + return ir.IntType(32) + + def _resolve_typedef(self, type_name: str) -> str: + if type_name in {'typedef', 'CType', 'CVolatile', 'CEnum', 'CUnion', 'CStruct', 'enum', 'REnum', 'renum', 'CPtr'}: + return type_name + if type_name == 'Callable': + return 'Callable' + visited: set[str] = set() + current: str = type_name + while current not in visited: + visited.add(current) + if hasattr(self, 'SymbolTable') and self.SymbolTable: + Entry: _CTypeInfo | None = self.SymbolTable.lookup(current) + if isinstance(Entry, dict) and Entry.get('type') == 'typedef': + OriginalType: str = Entry.get('OriginalType', '') + if OriginalType: + current = OriginalType + continue + elif Entry and Entry.IsTypedef: + if Entry.OriginalType: + if isinstance(Entry.OriginalType, _CTypeInfo): + if Entry.OriginalType.IsFuncPtr: + return 'Callable' + return Entry.OriginalType.ToString() if Entry.OriginalType.BaseType else current + elif isinstance(Entry.OriginalType, str): + current = Entry.OriginalType + continue + if Entry.BaseType: + if not isinstance(Entry.BaseType, (_t._CTypedef,)) or Entry.PtrCount > 0: + resolved: str = self._resolve_ctype_to_str(Entry) + if resolved and resolved != current: + current = resolved + continue + bm: Any = BuiltinTypeMap.Get(current) + if bm: + base_cls: Any = bm[0] + try: + instance: Any = base_cls() + cname: str = type(instance).__name__ + if cname: + current = cname + ' *' * bm[1] + continue + except Exception as _e: + if _config_mode == "strict": + logging.warning(f"异常被忽略: {_e}") + pass + bm: Any = BuiltinTypeMap.Get(current) + if bm and bm[1] > 0: + base_cls: Any = bm[0] + try: + instance: Any = base_cls() + cname: str = type(instance).__name__ + if cname: + current = cname + ' *' * bm[1] + continue + except Exception as _e: + if _config_mode == "strict": + logging.warning(f"异常被忽略: {_e}") + pass + break + return current + + def _resolve_ctype_to_str(self, type_info: _CTypeInfo) -> str: + parts: list[str] = [] + base: Any = type_info.BaseType + if base is None or base is _t.CVoid or isinstance(base, _t.CVoid): + parts.append('void') + elif isinstance(base, _t._CTypedef) or base is _t._CTypedef: + return '' + elif isinstance(base, _t.CStruct) or base is _t.CStruct: + parts.append(f'struct {getattr(base, "name", "")}') + elif isinstance(base, _t.CEnum) or base is _t.CEnum: + parts.append(f'enum {getattr(base, "name", "")}') + else: + cname: str = '' + if isinstance(base, type) and issubclass(base, _t.CType): + cname = base.__name__ + elif isinstance(base, _t.CType): + cname = type(base).__name__ + if cname: + parts.append(cname) + else: + return '' + if type_info.PtrCount > 0: + parts.append('*' * type_info.PtrCount) + return ' '.join(parts) + + def _type_str_to_llvm(self, type_str: str, IsPtr: bool = False) -> ir.Type: + type_str = type_str.strip() + cache_key: tuple[str, bool] = (type_str, IsPtr) + cached: ir.Type | None = self._type_cache.get(cache_key) + if cached is not None: + return cached + result: ir.Type = self._type_str_to_llvm_impl(type_str, IsPtr) + if result is not None: + if isinstance(result, (ir.IntType, ir.FloatType, ir.DoubleType, ir.VoidType)): + self._type_cache[cache_key] = result + elif isinstance(result, ir.PointerType) and isinstance(result.pointee, (ir.IntType, ir.FloatType, ir.DoubleType, ir.VoidType)): + self._type_cache[cache_key] = result + elif isinstance(result, ir.ArrayType) and not isinstance(result.element, (ir.IdentifiedStructType, ir.LiteralStructType)): + self._type_cache[cache_key] = result + return result + + _CType2LLVM = _type_str_to_llvm + + def _type_str_to_llvm_impl(self, type_str: str, IsPtr: bool = False) -> ir.Type: + array_dims: list[int] = [] + dim_match: list[str] = re.findall(r'\[(\d+)\]', type_str) + if dim_match: + array_dims = [int(d) for d in dim_match] + type_str = re.sub(r'\s*\[\d+\]', '', type_str).strip() + result: ir.Type = self._type_str_to_llvm_base(type_str, IsPtr) + for dim in reversed(array_dims): + result = ir.ArrayType(result, dim) + return result + + def _type_str_to_llvm_base(self, type_str: str, IsPtr: bool = False) -> ir.Type: + ptr_depth: int = 0 + while type_str.endswith('*'): + ptr_depth += 1 + type_str = type_str[:-1].strip() + if ptr_depth > 0: + IsPtr = True + if type_str in {'typedef', 'CType', 'CVolatile', 'CEnum', 'CUnion', 'CStruct', 'enum', 'REnum', 'renum'}: + result: ir.Type + if IsPtr: + result = ir.IntType(8).as_pointer() + for _ in range(ptr_depth - 1): + result = ir.PointerType(result) + return result + return ir.IntType(32) + if type_str in {'const', 'volatile'}: + return ir.IntType(8) + if type_str == 'Callable': + return ir.IntType(8).as_pointer() + if type_str.startswith('const '): + inner_type: ir.Type = self._type_str_to_llvm(type_str[6:].strip(), IsPtr) + return inner_type + if type_str.startswith('volatile '): + inner_type: ir.Type = self._type_str_to_llvm(type_str[9:].strip(), IsPtr) + return inner_type + if type_str.startswith('const_'): + inner_type: ir.Type = self._type_str_to_llvm(type_str[6:], IsPtr) + return inner_type + if type_str.startswith('volatile_'): + inner_type: ir.Type = self._type_str_to_llvm(type_str[9:], IsPtr) + return inner_type + if type_str.startswith('static '): + return self._type_str_to_llvm(type_str[7:].strip(), IsPtr) + if type_str.startswith('extern '): + return self._type_str_to_llvm(type_str[7:].strip(), IsPtr) + if type_str.startswith('register '): + return self._type_str_to_llvm(type_str[9:].strip(), IsPtr) + if type_str.startswith('inline '): + return self._type_str_to_llvm(type_str[7:].strip(), IsPtr) + if type_str.startswith('export '): + return self._type_str_to_llvm(type_str[7:].strip(), IsPtr) + if type_str.startswith('CStatic '): + return self._type_str_to_llvm(type_str[8:].strip(), IsPtr) + if type_str.startswith('CExtern '): + return self._type_str_to_llvm(type_str[8:].strip(), IsPtr) + if type_str.startswith('CRegister '): + return self._type_str_to_llvm(type_str[10:].strip(), IsPtr) + if type_str.startswith('CInline '): + return self._type_str_to_llvm(type_str[8:].strip(), IsPtr) + if type_str.startswith('CAuto '): + return self._type_str_to_llvm(type_str[6:].strip(), IsPtr) + resolved: str = self._resolve_typedef(type_str) + if resolved != type_str: + if '*' in resolved: + IsPtr = False + return self._type_str_to_llvm(resolved, IsPtr) + if type_str.endswith('*'): + BaseType: str = type_str[:-1].strip() + base_llvm: ir.Type | None = self._basic_type_to_llvm(BaseType) + if base_llvm is not None and isinstance(base_llvm, ir.VoidType): + result: ir.Type = ir.IntType(8).as_pointer() + for _ in range(ptr_depth): + result = ir.PointerType(result) + return result + if base_llvm is not None and not isinstance(base_llvm, ir.VoidType): + if isinstance(base_llvm, ir.PointerType): + return base_llvm + return ir.PointerType(base_llvm) + if BaseType in self.structs: + return ir.PointerType(self.structs[BaseType]) + if BaseType.startswith('struct '): + stripped: str = BaseType[7:].strip() + if stripped in self.structs: + return ir.PointerType(self.structs[stripped]) + if '.' in BaseType: + LastPart: str = BaseType.split('.')[-1] + if LastPart in self.structs: + return ir.PointerType(self.structs[LastPart]) + placeholder: ir.IdentifiedStructType = self._get_or_create_struct(LastPart) + return ir.PointerType(placeholder) + if base_llvm is not None and isinstance(base_llvm, ir.VoidType): + return ir.PointerType(ir.IntType(8)) + if type_str.startswith('{') and type_str.endswith('}'): + inner: str = type_str[1:-1].strip() + elem_strs: list[str] = [] + depth: int = 0 + current: str = '' + for ch in inner: + if ch == ',' and depth == 0: + elem_strs.append(current.strip()) + current = '' + else: + if ch == '{': + depth += 1 + elif ch == '}': + depth -= 1 + current += ch + if current.strip(): + elem_strs.append(current.strip()) + elem_types: list[ir.Type] = [] + for es in elem_strs: + et: ir.Type = self._type_str_to_llvm(es, '*' in es) + if isinstance(et, ir.VoidType): + et = ir.IntType(8).as_pointer() + elem_types.append(et) + if elem_types: + return ir.LiteralStructType(elem_types) + return ir.IntType(32) + if type_str in {'typedef', 'CType', 'CVolatile', 'CEnum', 'CUnion', 'CStruct', 'enum', 'REnum', 'renum'}: + return ir.IntType(32) + if type_str.startswith('%'): + stripped: str = type_str[1:] + if stripped in {'typedef', 'CType', 'CVolatile', 'CEnum', 'CUnion', 'CStruct', 'enum', 'REnum', 'renum'}: + return ir.IntType(32) if not IsPtr else ir.PointerType(ir.IntType(32)) + basic_stripped: ir.Type | None = self._basic_type_to_llvm(stripped) + if basic_stripped is not None: + if IsPtr and not isinstance(basic_stripped, ir.VoidType): + return ir.PointerType(basic_stripped) + return basic_stripped + if hasattr(self, 'SymbolTable') and self.SymbolTable: + _Entry: _CTypeInfo | None = self.SymbolTable.lookup(type_str) + if _Entry and _Entry.IsTypedef: + resolved_str: str = self._resolve_typedef(type_str) + if resolved_str != type_str: + return self._type_str_to_llvm(resolved_str, IsPtr) + if _Entry.BaseType: + if not isinstance(_Entry.BaseType, (_t._CTypedef,)) or _Entry.PtrCount > 0: + resolved: str = self._resolve_ctype_to_str(_Entry) + if resolved: + return self._type_str_to_llvm(resolved, IsPtr) + if _Entry and _Entry.IsRenum: + if type_str in self.structs: + return self.structs[type_str] + if _Entry and _Entry.IsEnum: + return ir.IntType(32) if not IsPtr else ir.PointerType(ir.IntType(32)) + if _Entry and _Entry.IsExceptionClass: + return ir.IntType(32) if not IsPtr else ir.PointerType(ir.IntType(32)) + if _Entry and _Entry.IsFunction: + return ir.PointerType(ir.IntType(8)) + if _Entry and _Entry.BaseType: + if (isinstance(_Entry.BaseType, type) and issubclass(_Entry.BaseType, _t.CEnum)) or _Entry.BaseType is _t.CEnum: + return ir.IntType(32) if not IsPtr else ir.PointerType(ir.IntType(32)) + for ClassName in self.structs: + if type_str == ClassName: + if IsPtr: + return ir.PointerType(self.structs[ClassName]) + return self.structs[ClassName] + if '.' in type_str and not type_str.startswith('%'): + LastPart: str = type_str.split('.')[-1] + basic_last: ir.Type | None = self._basic_type_to_llvm(LastPart) + if basic_last is not None: + if IsPtr and not isinstance(basic_last, ir.VoidType): + return ir.PointerType(basic_last) + return basic_last + if hasattr(self, 'SymbolTable') and self.SymbolTable: + _Entry: _CTypeInfo | None = self.SymbolTable.lookup(LastPart) + if _Entry and _Entry.IsTypedef: + resolved_str: str = self._resolve_typedef(LastPart) + if resolved_str != LastPart: + return self._type_str_to_llvm(resolved_str, IsPtr) + if _Entry.BaseType: + if not isinstance(_Entry.BaseType, (_t._CTypedef,)) or _Entry.PtrCount > 0: + resolved: str = self._resolve_ctype_to_str(_Entry) + if resolved: + return self._type_str_to_llvm(resolved, IsPtr) + if _Entry and _Entry.IsRenum: + if LastPart in self.structs: + return self.structs[LastPart] + if _Entry and _Entry.IsEnum: + return ir.IntType(32) if not IsPtr else ir.PointerType(ir.IntType(32)) + if _Entry and _Entry.IsExceptionClass: + return ir.IntType(32) if not IsPtr else ir.PointerType(ir.IntType(32)) + if _Entry and _Entry.IsFunction: + return ir.PointerType(ir.IntType(8)) + if _Entry and _Entry.BaseType: + if (isinstance(_Entry.BaseType, type) and issubclass(_Entry.BaseType, _t.CEnum)) or _Entry.BaseType is _t.CEnum: + return ir.IntType(32) if not IsPtr else ir.PointerType(ir.IntType(32)) + if LastPart in self.structs: + if IsPtr: + return ir.PointerType(self.structs[LastPart]) + return self.structs[LastPart] + placeholder: ir.IdentifiedStructType = self._get_or_create_struct(LastPart) + if IsPtr: + return ir.PointerType(placeholder) + return placeholder + if type_str.startswith('struct '): + stripped: str = type_str[7:].strip().replace(' *', '').replace('*', '') + if stripped in self.structs: + if IsPtr: + return ir.PointerType(self.structs[stripped]) + return self.structs[stripped] + basic_match: ir.Type | None = self._basic_type_to_llvm(stripped) + if basic_match is not None: + if IsPtr and not isinstance(basic_match, ir.VoidType): + return ir.PointerType(basic_match) + return basic_match + placeholder: ir.IdentifiedStructType = self._get_or_create_struct(stripped) + if IsPtr: + return ir.PointerType(placeholder) + return placeholder + if type_str.startswith('%struct.'): + stripped: str = type_str[8:].strip().replace(' *', '').replace('*', '') + if stripped in self.structs: + if IsPtr: + return ir.PointerType(self.structs[stripped]) + return self.structs[stripped] + basic_match: ir.Type | None = self._basic_type_to_llvm(stripped) + if basic_match is not None: + if IsPtr and not isinstance(basic_match, ir.VoidType): + return ir.PointerType(basic_match) + return basic_match + placeholder: ir.IdentifiedStructType = self._get_or_create_struct(stripped) + if IsPtr: + return ir.PointerType(placeholder) + return placeholder + if type_str.startswith('union '): + stripped: str = type_str[6:].strip() + basic_match: ir.Type | None = self._basic_type_to_llvm(stripped) + if basic_match is not None: + if IsPtr and not isinstance(basic_match, ir.VoidType): + return ir.PointerType(basic_match) + return basic_match + if type_str.endswith('*'): + pointee: ir.Type = self._type_str_to_llvm(type_str[:-1].strip()) + if isinstance(pointee, ir.VoidType): + return ir.PointerType(ir.IntType(8)) + return ir.PointerType(pointee) + result: ir.Type | None = self._basic_type_to_llvm(type_str) + if result is None: + result = ir.IntType(32) + if IsPtr: + if isinstance(result, ir.VoidType): + result = ir.PointerType(ir.IntType(8)) + elif isinstance(result, ir.PointerType): + pass + else: + result = ir.PointerType(result) + for _ in range(ptr_depth - 1): + result = ir.PointerType(result) + return result + + def _llvm_str_to_ir(self, llvm_str: str) -> ir.Type | None: + _LLVM_IR_TYPES: dict[str, ir.Type] = { + 'void': ir.VoidType(), 'i1': ir.IntType(1), 'i8': ir.IntType(8), + 'i16': ir.IntType(16), 'i32': ir.IntType(32), 'i64': ir.IntType(64), + 'i128': ir.IntType(128), 'float': ir.FloatType(), 'double': ir.DoubleType(), + 'half': ir.IntType(16), 'fp128': ir.IntType(128), + } + return _LLVM_IR_TYPES.get(llvm_str) + + def _basic_type_to_llvm(self, type_str: str) -> ir.Type | None: + _LLVM_IR_TYPES: dict[str, ir.Type] = { + 'void': ir.VoidType(), 'i1': ir.IntType(1), 'i8': ir.IntType(8), + 'i16': ir.IntType(16), 'i32': ir.IntType(32), 'i64': ir.IntType(64), + 'i128': ir.IntType(128), 'f32': ir.FloatType(), 'f64': ir.DoubleType(), + 'half': ir.IntType(16), 'fp128': ir.IntType(128), + } + if type_str in _LLVM_IR_TYPES: + return _LLVM_IR_TYPES[type_str] + resolved: Any = CTypeRegistry.ResolveName(type_str) + if resolved is not None: + ctype_cls: Any + ptr_level: int + ctype_cls, ptr_level = resolved + llvm_str: str = CTypeRegistry.CTypeToLLVM(ctype_cls) + if llvm_str: + # CTypeToLLVM 对 CPtr 等指针类型已返回含 * 的串(如 'i8*'), + # 此时 ptr_level 已内含在 llvm_str 中,直接解析即可 + if '*' in llvm_str: + return self._type_str_to_llvm(llvm_str) + base: ir.Type | None = self._llvm_str_to_ir(llvm_str) + if base is not None: + for _ in range(ptr_level): + if isinstance(base, ir.VoidType): + base = ir.IntType(8).as_pointer() + else: + base = ir.PointerType(base) + return base + if type_str == '*': + return ir.IntType(8) + if type_str in ('const_', 'const'): + return ir.IntType(8) + return None + + def _is_type_unsigned(self, type_str: str) -> bool: + s: str = type_str.strip() + if s.endswith('*'): + return True + if s.startswith('unsigned'): + return True + resolved: Any = CTypeRegistry.ResolveName(s) + if resolved is not None: + ctype_cls: Any + _: int + ctype_cls, _ = resolved + try: + inst: Any = ctype_cls() + if getattr(inst, 'IsSigned', None) is False: + return True + except Exception as _e: + if _config_mode == "strict": + raise + _vlog().warning(f"判断类型符号性失败: {_e}", "Exception") + return False + + def _record_var_signedness(self, name: str, type_str_or_bool: str | bool) -> None: + if isinstance(type_str_or_bool, bool): + self.var_signedness[name] = type_str_or_bool + else: + self.var_signedness[name] = self._is_type_unsigned(type_str_or_bool) + + def _is_var_unsigned(self, name: str) -> bool: + return self.var_signedness.get(name, False) + + def _check_node_unsigned(self, node: ast.AST) -> bool: + if isinstance(node, ast.Name): + return self._is_var_unsigned(node.id) + if isinstance(node, ast.BinOp): + return self._check_node_unsigned(node.left) or self._check_node_unsigned(node.right) + if isinstance(node, ast.UnaryOp): + return self._check_node_unsigned(node.operand) + if isinstance(node, ast.Call): + return self._check_call_unsigned(node) + if isinstance(node, ast.Subscript): + return self._check_node_unsigned(node.value) + if isinstance(node, ast.Attribute): + # 检查是否为结构体字段,并查询其符号性 + field_signed: bool | None = self._check_attribute_signedness(node) + if field_signed is not None: + return not field_signed # IsSigned=False 表示无符号 → 返回 True + return self._check_node_unsigned(node.value) + return False + + def _check_call_unsigned(self, node: ast.Call) -> bool: + """推断函数调用返回值的无符号性。 + + 修复:原代码对所有 Call 节点返回 False,导致函数调用返回值 + 直接参与 >>/% 等运算时丢失无符号性,退化成 ashr/srem。 + + 规则(用户确认): + - a = b 赋值时,若 a 无显式类型注解,则自动推导为 b 的类型(含符号性) + - 若 a 有显式有符号类型,b 无符号,则相当于将 b 强转为 a 的有符号类型 + - 此处仅推断 b(调用本身)的符号性,赋值时的强转由赋值逻辑处理 + """ + func_node: ast.AST = node.func + func_name: str = '' + + if isinstance(func_node, ast.Name): + # 直接调用: rdrand64() + func_name = func_node.id + elif isinstance(func_node, ast.Attribute): + # t.CUInt64T(x) 等类型转换调用 + if hasattr(func_node.value, 'id') and IsTModule(func_node.value.id, self.SymbolTable): + if self._is_type_unsigned(func_node.attr): + return True + # module.func() 形式的调用 + try: + func_name = f"{func_node.value.id}.{func_node.attr}" + except AttributeError: + return False + else: + return False + + if not func_name or not hasattr(self, 'SymbolTable') or not self.SymbolTable: + return False + + try: + sym_info: Any = self.SymbolTable.lookup(func_name) + except Exception: + return False + + if sym_info and isinstance(sym_info, _CTypeInfo): + if sym_info.IsFunction or sym_info.IsFuncPtr: + ret_info: Any = sym_info.FuncPtrReturn + if ret_info and isinstance(ret_info, _CTypeInfo): + # 指针类型视为无符号 + if ret_info.PtrCount > 0: + return True + # 检查返回类型的 IsUInt 属性(IsSigned is False) + if ret_info.IsUInt: + return True + elif sym_info.IsTypedef: + # 修复:typedef 强转调用(如 ULONGLONG(0x11))需要解析底层类型的无符号性 + # IsUInt 对组合类型(CType | CType 产生的 list)会失败,需多策略回退 + if sym_info.IsUInt: + return True + # 策略1:直接检查 BaseType(可能是组合类型,如 ULONGLONG = CUnsignedLong | CLong) + bt: Any = sym_info.BaseType + if isinstance(bt, (tuple, list)): + for elem in bt: + if isinstance(elem, _t.CType) and getattr(elem, 'IsSigned', None) is False: + return True + elif isinstance(bt, _t.CType) and getattr(bt, 'IsSigned', None) is False: + return True + # 策略2:通过 OriginalType 解析 + if sym_info.OriginalType: + ot: Any = sym_info.OriginalType + if isinstance(ot, str): + if self._is_type_unsigned(ot): + return True + elif isinstance(ot, _CTypeInfo): + if ot.IsUInt: + return True + elif isinstance(ot, (tuple, list)): + for elem in ot: + if isinstance(elem, _t.CType) and getattr(elem, 'IsSigned', None) is False: + return True + # 策略3:通过 _resolve_typedef 解析为字符串后判断 + resolved_str: str = self._resolve_typedef(func_name) + if resolved_str and self._is_type_unsigned(resolved_str): + return True + return False + + def _check_attribute_signedness(self, node: ast.Attribute) -> bool | None: + """检查 Attribute 节点是否引用具有已知符号性的结构体字段。 + + Returns: + True: 字段是有符号类型 + False: 字段是无符号类型 + None: 无法确定(非结构体字段或符号性未知) + """ + if not isinstance(node.value, ast.Name): + return None + var_name: str = node.value.id + field_name: str = node.attr + class_name: str | None = self._resolve_class_for_var(var_name) + if not class_name: + return None + signed_dict: dict[str, bool] = self.class_member_signeds.get(class_name, {}) + if field_name in signed_dict: + return signed_dict[field_name] + return None \ No newline at end of file diff --git a/lib/core/LLVMCG/VaArg.py b/lib/core/LLVMCG/VaArg.py index b3d5370..3bb03d9 100644 --- a/lib/core/LLVMCG/VaArg.py +++ b/lib/core/LLVMCG/VaArg.py @@ -1,94 +1,94 @@ -from __future__ import annotations -import sys -import llvmlite.ir as ir -from lib.core.LLVMCG.BaseGen import VaArgInstruction - - -class VaArgMixin: - - def _get_va_start_intrinsic(self): - if 'llvm.va_start' in self.functions: - return self.functions['llvm.va_start'] - ftype = ir.FunctionType(ir.VoidType(), [ir.IntType(8).as_pointer()]) - func = ir.Function(self.module, ftype, name='llvm.va_start') - self.functions['llvm.va_start'] = func - return func - - def _get_va_end_intrinsic(self): - if 'llvm.va_end' in self.functions: - return self.functions['llvm.va_end'] - ftype = ir.FunctionType(ir.VoidType(), [ir.IntType(8).as_pointer()]) - func = ir.Function(self.module, ftype, name='llvm.va_end') - self.functions['llvm.va_end'] = func - return func - - def emit_va_start(self, va_list_ptr): - if not self.builder: - return None - func = self._get_va_start_intrinsic() - i8ptr_type = ir.IntType(8).as_pointer() - if va_list_ptr.type == i8ptr_type: - self.builder.call(func, [va_list_ptr]) - else: - ptr = self.builder.bitcast(va_list_ptr, i8ptr_type, name="va_list_i8ptr") - self.builder.call(func, [ptr]) - return None - - def _emit_stack_align(self, alignment=16): - if not self.builder: - return None - void = ir.VoidType() - asm_type = ir.FunctionType(void, []) - mask = -alignment - asm_str = f"andq ${mask}, %rsp" - asm_func = ir.InlineAsm(asm_type, asm_str, "~{dirflag},~{fpsr},~{flags},~{rsp}", side_effect=True) - self.builder.call(asm_func, [], name="align_stack") - return None - - def emit_va_end(self, va_list_ptr): - if not self.builder: - return None - func = self._get_va_end_intrinsic() - i8ptr_type = ir.IntType(8).as_pointer() - if va_list_ptr.type == i8ptr_type: - self.builder.call(func, [va_list_ptr]) - else: - ptr = self.builder.bitcast(va_list_ptr, i8ptr_type, name="va_list_i8ptr") - self.builder.call(func, [ptr]) - return None - - def emit_va_arg(self, va_list_ptr, arg_type): - if not self.builder: - return self._ZeroConst(arg_type) - if not hasattr(self, '_va_arg_counter'): - self._va_arg_counter = 0 - self._va_arg_counter += 1 - import sys - is_x86_64 = sys.platform in ('win32', 'win64', 'windows', 'linux', 'linux2', 'darwin') - if is_x86_64: - if isinstance(arg_type, ir.PointerType): - va_arg_type = ir.IntType(64) - elif isinstance(arg_type, (ir.FloatType, ir.DoubleType)): - va_arg_type = ir.DoubleType() - elif isinstance(arg_type, ir.IntType) and arg_type.width < 64: - va_arg_type = ir.IntType(64) - else: - va_arg_type = arg_type - instr = VaArgInstruction(self.builder.block, va_arg_type, 'va_arg', (va_list_ptr,), name=f'va_arg_raw_{self._va_arg_counter}') - self.builder._insert(instr) - if va_arg_type != arg_type: - if isinstance(arg_type, ir.PointerType): - result = self.builder.inttoptr(instr, arg_type, name=f'va_arg_ptr_{self._va_arg_counter}') - elif isinstance(arg_type, ir.FloatType): - result = self.builder.fptrunc(instr, arg_type, name=f'va_arg_fptrunc_{self._va_arg_counter}') - else: - result = self.builder.trunc(instr, arg_type, name=f'va_arg_trunc_{self._va_arg_counter}') - else: - result = instr - return result - else: - if isinstance(arg_type, ir.IntType) and arg_type.width < 64: - arg_type = ir.IntType(64) - instr = VaArgInstruction(self.builder.block, arg_type, 'va_arg', (va_list_ptr,), name=f'va_arg_raw_{self._va_arg_counter}') - self.builder._insert(instr) - return instr +from __future__ import annotations +import llvmlite.ir as ir +from lib.core.LLVMCG.BaseGen import VaArgInstruction + + +class VaArgMixin: + + def _get_va_start_intrinsic(self) -> ir.Function: + if 'llvm.va_start' in self.functions: + return self.functions['llvm.va_start'] + ftype: ir.FunctionType = ir.FunctionType(ir.VoidType(), [ir.IntType(8).as_pointer()]) + func: ir.Function = ir.Function(self.module, ftype, name='llvm.va_start') + self.functions['llvm.va_start'] = func + return func + + def _get_va_end_intrinsic(self) -> ir.Function: + if 'llvm.va_end' in self.functions: + return self.functions['llvm.va_end'] + ftype: ir.FunctionType = ir.FunctionType(ir.VoidType(), [ir.IntType(8).as_pointer()]) + func: ir.Function = ir.Function(self.module, ftype, name='llvm.va_end') + self.functions['llvm.va_end'] = func + return func + + def emit_va_start(self, va_list_ptr: ir.Value) -> None: + if not self.builder: + return None + func: ir.Function = self._get_va_start_intrinsic() + i8ptr_type: ir.PointerType = ir.IntType(8).as_pointer() + if va_list_ptr.type == i8ptr_type: + self.builder.call(func, [va_list_ptr]) + else: + ptr: ir.Value = self.builder.bitcast(va_list_ptr, i8ptr_type, name="va_list_i8ptr") + self.builder.call(func, [ptr]) + return None + + def _emit_stack_align(self, alignment: int = 16) -> None: + if not self.builder: + return None + void: ir.VoidType = ir.VoidType() + asm_type: ir.FunctionType = ir.FunctionType(void, []) + mask: int = -alignment + asm_str: str = f"andq ${mask}, %rsp" + asm_func: ir.InlineAsm = ir.InlineAsm(asm_type, asm_str, "~{dirflag},~{fpsr},~{flags},~{rsp}", side_effect=True) + self.builder.call(asm_func, [], name="align_stack") + return None + + def emit_va_end(self, va_list_ptr: ir.Value) -> None: + if not self.builder: + return None + func: ir.Function = self._get_va_end_intrinsic() + i8ptr_type: ir.PointerType = ir.IntType(8).as_pointer() + if va_list_ptr.type == i8ptr_type: + self.builder.call(func, [va_list_ptr]) + else: + ptr: ir.Value = self.builder.bitcast(va_list_ptr, i8ptr_type, name="va_list_i8ptr") + self.builder.call(func, [ptr]) + return None + + def emit_va_arg(self, va_list_ptr: ir.Value, arg_type: ir.Type) -> ir.Value: + if not self.builder: + return self._ZeroConst(arg_type) + if not hasattr(self, '_va_arg_counter'): + self._va_arg_counter: int = 0 + self._va_arg_counter += 1 + is_x86_64: bool = self._platform_info['is_x86_64'] + if is_x86_64: + va_arg_type: ir.Type + if isinstance(arg_type, ir.PointerType): + va_arg_type = ir.IntType(64) + elif isinstance(arg_type, (ir.FloatType, ir.DoubleType)): + va_arg_type = ir.DoubleType() + elif isinstance(arg_type, ir.IntType) and arg_type.width < 64: + va_arg_type = ir.IntType(64) + else: + va_arg_type = arg_type + instr: ir.Instruction = VaArgInstruction(self.builder.block, va_arg_type, 'va_arg', (va_list_ptr,), name=f'va_arg_raw_{self._va_arg_counter}') + self.builder._insert(instr) + result: ir.Value + if va_arg_type != arg_type: + if isinstance(arg_type, ir.PointerType): + result = self.builder.inttoptr(instr, arg_type, name=f'va_arg_ptr_{self._va_arg_counter}') + elif isinstance(arg_type, ir.FloatType): + result = self.builder.fptrunc(instr, arg_type, name=f'va_arg_fptrunc_{self._va_arg_counter}') + else: + result = self.builder.trunc(instr, arg_type, name=f'va_arg_trunc_{self._va_arg_counter}') + else: + result = instr + return result + else: + if isinstance(arg_type, ir.IntType) and arg_type.width < 64: + arg_type = ir.IntType(64) + instr: ir.Instruction = VaArgInstruction(self.builder.block, arg_type, 'va_arg', (va_list_ptr,), name=f'va_arg_raw_{self._va_arg_counter}') + self.builder._insert(instr) + return instr \ No newline at end of file diff --git a/lib/core/LLVMTypeMapper.py b/lib/core/LLVMTypeMapper.py index cc05779..4a75e6d 100644 --- a/lib/core/LLVMTypeMapper.py +++ b/lib/core/LLVMTypeMapper.py @@ -17,7 +17,9 @@ from typing import TYPE_CHECKING if TYPE_CHECKING: from lib.core.SymbolTable import SymbolTable -from lib.core.Handles.HandlesBase import CTypeInfo, CTypeHelper +from lib.core.Handles.HandlesBase import CTypeInfo, CTypeHelper, BuiltinTypeMap +from lib.core.SymbolUtils import IsTModule, IsListAnnotation +from lib.includes.t import CTypeRegistry class LLVMTypeMapper: @@ -30,7 +32,7 @@ class LLVMTypeMapper: # 公共 API # ================================================================== - def get_llvm_type_str(self, node) -> str: + def get_llvm_type_str(self, node: ast.AST | None) -> str: """将 AST 注解节点转换为 LLVM IR 类型字符串""" if node is None: self._symtab.diagnostics.warn('', 0, "类型注解为 None,回退到 i32") @@ -52,13 +54,13 @@ class LLVMTypeMapper: self._symtab.diagnostics.warn('', 0, f"无法解析类型节点 {type(node).__name__},回退到 i32") return 'i32' - def get_func_ret_type_str(self, returns_node) -> str: + def get_func_ret_type_str(self, returns_node: ast.AST | None) -> str: """提取函数返回类型的 LLVM 字符串""" if returns_node is None: return 'i32' if isinstance(returns_node, ast.BinOp) and isinstance(returns_node.op, ast.BitOr): - left_str = self.get_llvm_type_str(returns_node.left) - right_str = self.get_llvm_type_str(returns_node.right) + left_str: str = self.get_llvm_type_str(returns_node.left) + right_str: str = self.get_llvm_type_str(returns_node.right) if right_str and right_str.endswith('*'): return right_str if left_str and left_str.endswith('*'): @@ -68,16 +70,16 @@ class LLVMTypeMapper: if right_str and right_str not in ('i32', 'void', 'i64'): return right_str return left_str - result = self.get_llvm_type_str(returns_node) + result: str = self.get_llvm_type_str(returns_node) return result if result else 'i32' - def get_func_param_type_str(self, annotation_node) -> str: + def get_func_param_type_str(self, annotation_node: ast.AST | None) -> str: """提取函数参数类型的 LLVM 字符串""" if annotation_node is None: return 'i8*' if isinstance(annotation_node, ast.BinOp) and isinstance(annotation_node.op, ast.BitOr): - left_str = self.get_llvm_type_str(annotation_node.left) - right_str = self.get_llvm_type_str(annotation_node.right) + left_str: str = self.get_llvm_type_str(annotation_node.left) + right_str: str = self.get_llvm_type_str(annotation_node.right) if right_str and right_str.endswith('*'): return right_str if left_str and left_str.endswith('*'): @@ -89,35 +91,38 @@ class LLVMTypeMapper: if left_str and left_str.endswith('*'): return left_str return right_str if right_str else left_str - result = self.get_llvm_type_str(annotation_node) + result: str = self.get_llvm_type_str(annotation_node) return result if result else 'i8*' - def resolve_typedef_value_type(self, node) -> str: + def resolve_typedef_value_type(self, node: ast.AST | None) -> str: """解析 typedef 值表达式的 C 类型字符串""" if node is None: return '' if isinstance(node, ast.Name): if node.id in self._symtab: - Entry = self._symtab[node.id] + Entry: CTypeInfo = self._symtab[node.id] if Entry.IsTypedef and Entry.OriginalType: return Entry.OriginalType return '' if isinstance(node, ast.Attribute): - if isinstance(node.value, ast.Name) and node.value.id == 't': - CName = CTypeHelper.GetCName(node.attr) - if CName and CName == '*': + if isinstance(node.value, ast.Name) and IsTModule(node.value.id): + # 直接判断属性名是否为 CPtr(消除对 CName=='*' 的依赖) + if node.attr == 'CPtr': + return 'ptr' + CName: str | None = CTypeHelper.GetCName(node.attr) + if CName == 'CPtr': return 'ptr' if CName: return CName return '' if isinstance(node, ast.BinOp) and isinstance(node.op, ast.BitOr): - left_str = self.resolve_typedef_value_type(node.left) - right_str = self.resolve_typedef_value_type(node.right) + left_str: str = self.resolve_typedef_value_type(node.left) + right_str: str = self.resolve_typedef_value_type(node.right) if right_str == 'ptr' or (right_str and right_str.endswith('*')): - base = left_str if left_str and left_str != 'ptr' else '' + base: str = left_str if left_str and left_str != 'ptr' else '' return base + ' *' if base else 'void *' if left_str == 'ptr' or (left_str and left_str.endswith('*')): - base = right_str if right_str and right_str != 'ptr' else '' + base: str = right_str if right_str and right_str != 'ptr' else '' return base + ' *' if base else 'void *' if right_str and right_str not in ('ptr', 'void', 'i32', 'i64'): return right_str @@ -132,7 +137,7 @@ class LLVMTypeMapper: def _resolve_name(self, node: ast.Name) -> str: """解析 ast.Name 节点""" - id_map = { + id_map: dict[str, str] = { 'str': 'i8*', 'int': 'i32', 'bool': 'i8', 'float': 'double', 'None': 'void', 'UINT8PTR': 'i8*', 'INT8PTR': 'i8*', 'BYTEPTR': 'i8*', @@ -142,9 +147,21 @@ class LLVMTypeMapper: } if node.id in id_map: return id_map[node.id] + # 通过 BuiltinTypeMap 解析 VOIDPTR、INTPTR 等指针别名 + builtin_entry: tuple[type, int] | None = BuiltinTypeMap.Get(node.id) + if builtin_entry: + TypeClass: type + base_ptr: int + TypeClass, base_ptr = builtin_entry + base_llvm: str = CTypeRegistry.CTypeToLLVM(TypeClass) + if base_ptr > 0: + if base_llvm == 'void': + return 'i8*' + return base_llvm + '*' * base_ptr + return base_llvm if base_llvm else 'i32' # 查找 SymbolTable 中的 typedef if node.id in self._symtab: - entry = self._symtab[node.id] + entry: CTypeInfo = self._symtab[node.id] if entry and entry.IsTypedef and entry.OriginalType: if isinstance(entry.OriginalType, CTypeInfo) and entry.OriginalType.IsFuncPtr: return 'i8*' @@ -157,9 +174,8 @@ class LLVMTypeMapper: def _resolve_attribute(self, node: ast.Attribute) -> str: """解析 ast.Attribute 节点""" - attr_name = node.attr if hasattr(node, 'attr') else '' - from lib.includes.t import CTypeRegistry - llvm_str = CTypeRegistry.NameToLLVM(attr_name) + attr_name: str = node.attr if hasattr(node, 'attr') else '' + llvm_str: str | None = CTypeRegistry.NameToLLVM(attr_name) if llvm_str is not None: return llvm_str if attr_name in ('CState', 'CDefine', 'CTypedef', 'CExtern', 'CStatic', 'CConst', 'State'): @@ -178,17 +194,19 @@ class LLVMTypeMapper: def _resolve_subscript(self, node: ast.Subscript) -> str: """解析 ast.Subscript 节点""" if isinstance(node.value, ast.Name) and node.value.id == 'tuple': - slice_node = node.slice - elem_types = [] + slice_node: ast.AST = node.slice + elem_types: list[str] = [] if isinstance(slice_node, ast.Tuple): + elt: ast.AST for elt in slice_node.elts: elem_types.append(self.get_llvm_type_str(elt)) else: elem_types.append(self.get_llvm_type_str(slice_node)) if elem_types: return '{ ' + ', '.join(elem_types) + ' }' - if isinstance(node.value, ast.Name) and node.value.id == 'list': - slice_node = node.slice + if IsListAnnotation(node): + slice_node: ast.AST = node.slice + elem_type: str if isinstance(slice_node, ast.Tuple) and len(slice_node.elts) >= 1: elem_type = self.get_llvm_type_str(slice_node.elts[0]) else: @@ -199,8 +217,8 @@ class LLVMTypeMapper: def _resolve_bitor(self, node: ast.BinOp) -> str: """解析 ast.BinOp(BitOr) 节点""" - left = self.get_llvm_type_str(node.left) - right = self.get_llvm_type_str(node.right) + left: str = self.get_llvm_type_str(node.left) + right: str = self.get_llvm_type_str(node.right) if right and right.endswith('*'): return right if left and left.endswith('*'): @@ -214,7 +232,7 @@ class LLVMTypeMapper: def _resolve_call(self, node: ast.Call) -> str: """解析 ast.Call 节点""" if isinstance(node.func, ast.Attribute): - if hasattr(node.func.value, 'id') and node.func.value.id == 't': + if hasattr(node.func.value, 'id') and IsTModule(node.func.value.id): return self.get_llvm_type_str(ast.Attribute(value=ast.Name(id='t'), attr=node.func.attr)) self._symtab.diagnostics.warn('', 0, "无法解析 Call 类型,回退到 i32") return 'i32' diff --git a/lib/core/LlvmCodeGenerator.py b/lib/core/LlvmCodeGenerator.py index 78fbd1c..ec5d6aa 100644 --- a/lib/core/LlvmCodeGenerator.py +++ b/lib/core/LlvmCodeGenerator.py @@ -9,6 +9,7 @@ # - ExprGen.py: 表达式生成(常量、二元运算、返回) # - FuncGen.py: 函数处理(参数调整、成员偏移) # - VaArg.py: 变长参数处理 +from __future__ import annotations from lib.core.LLVMCG.BaseGen import BaseGenMixin, VaArgInstruction from lib.core.LLVMCG.TypeConvert import TypeConvertMixin @@ -43,4 +44,4 @@ class LlvmCodeGenerator( # 向后兼容:重新导出常量和辅助类 -__all__ = ['LlvmCodeGenerator', 'VaArgInstruction'] +__all__: list[str] = ['LlvmCodeGenerator', 'VaArgInstruction'] diff --git a/lib/core/SymbolData.py b/lib/core/SymbolData.py index 21aa109..c422de0 100644 --- a/lib/core/SymbolData.py +++ b/lib/core/SymbolData.py @@ -1,7 +1,11 @@ """符号表处理的数据结构:四阶段管线中传递的中间数据""" from __future__ import annotations from dataclasses import dataclass, field -from typing import Any, Dict, List, Optional, Tuple +from typing import Dict, List, Optional, Tuple, TYPE_CHECKING +import ast + +if TYPE_CHECKING: + from lib.core.Handles.HandlesBase import CTypeInfo @dataclass @@ -10,7 +14,7 @@ class ClassSymbolData: name: str type_kind: str # 'struct', 'union', 'enum', 'exception' lineno: int - members: Dict[str, Any] + members: Dict[str, CTypeInfo] is_cpython_object: bool = False is_packed: bool = False enum_members: List[Tuple[str, int, int]] = field(default_factory=list) # (name, value, lineno) @@ -22,14 +26,14 @@ class TypedefSymbolData: name: str lineno: int # 原始注解数据(由 Extractor 设置,Resolver 使用) - annotation: Any = None - value: Any = None + annotation: ast.expr | None = None + value: ast.expr | int | str | float | None = None has_cdefine: bool = False has_postdef: bool = False has_ctypedef: bool = False # 解析结果(由 Resolver 设置,Inserter 使用) original_type_kind: Optional[str] = None - original_class: Any = None + original_class: type | None = None members: Optional[Dict] = None @@ -39,13 +43,15 @@ class FuncSymbolData: name: str lineno: int # 原始数据(由 Extractor 设置) - returns_node: Any = None + returns_node: ast.expr | None = None params: List = field(default_factory=list) # [(name, annotation_node), ...] is_variadic: bool = False is_inline: bool = False # 解析结果(由 Resolver 设置) - ret_type: Any = None + ret_type: str | None = None param_types: List = field(default_factory=list) # [str, ...] + # 解析结果(CTypeInfo,保留符号性,由 Resolver 设置) + ret_ctype: Optional[CTypeInfo] = None @dataclass @@ -54,9 +60,9 @@ class DefineSymbolData: name: str lineno: int # 原始数据(由 Extractor 设置) - value_node: Any = None + value_node: ast.expr | None = None # 解析结果(由 Resolver 设置) - value: Any = None + value: int | str | float | None = None @dataclass @@ -64,7 +70,7 @@ class AnonymousTypeData: """匿名类型数据""" name: str is_union: bool - members: Dict[str, Any] + members: Dict[str, CTypeInfo] lineno: int diff --git a/lib/core/SymbolExtractor.py b/lib/core/SymbolExtractor.py index 288f9d7..d9f1f04 100644 --- a/lib/core/SymbolExtractor.py +++ b/lib/core/SymbolExtractor.py @@ -10,36 +10,36 @@ from lib.core.SymbolData import ( FuncSymbolData, DefineSymbolData, AnonymousTypeData ) from lib.core.Handles.HandlesBase import CTypeInfo +from lib.core.SymbolUtils import AnnotationContainsTType, CheckAnnotationHasCInline, IsTModule from lib.includes import t -from lib.core.SymbolUtils import AnnotationContainsTType, CheckAnnotationHasCInline class ASTSymbolExtractor: """从 Python 源文件的 AST 中提取所有符号信息""" - def __init__(self, symbol_table: SymbolTable): - self._symtab = symbol_table + def __init__(self, symbol_table: SymbolTable) -> None: + self._symtab: SymbolTable = symbol_table def extract(self, file_path: str) -> ModuleSymbols: """提取文件中的所有符号信息""" with open(file_path, 'r', encoding='utf-8') as f: - code = f.read() - tree = ast.parse(code) + code: str = f.read() + tree: ast.Module = ast.parse(code) - result = ModuleSymbols(file_path=file_path) + result: ModuleSymbols = ModuleSymbols(file_path=file_path) # 第一步:收集所有类的成员和匿名类型 - class_members = {} + class_members: dict[str, dict[str, CTypeInfo]] = {} for node in tree.body: if isinstance(node, ast.ClassDef): - members = {} + members: dict[str, CTypeInfo] = {} self._collect_members(node, members, result.anonymous_types) class_members[node.name] = members # 第二步:从每个顶层节点提取符号信息 for node in tree.body: if isinstance(node, ast.ClassDef): - members_info = class_members.get(node.name, {}) + members_info: dict[str, CTypeInfo] = class_members.get(node.name, {}) result.classes.append(self._extract_class(node, members_info)) elif isinstance(node, ast.AnnAssign) and isinstance(node.target, ast.Name): self._extract_ann_assign(node, result) @@ -52,46 +52,59 @@ class ASTSymbolExtractor: # 成员收集(递归处理嵌套匿名类) # ------------------------------------------------------------------ - def _collect_members(self, class_node, members, anonymous_types, prefix=''): + def _collect_members(self, class_node: ast.ClassDef, members: dict[str, CTypeInfo], anonymous_types: dict[str, AnonymousTypeData], prefix: str = '') -> None: """递归收集类成员,包括嵌套匿名类型""" for item in class_node.body: if isinstance(item, ast.AnnAssign) and isinstance(item.target, ast.Name): - member_name = item.target.id - full_name = f'{prefix}{member_name}' if prefix else member_name - member_type = CTypeInfo.FromNode(item.annotation, self._symtab) + member_name: str = item.target.id + full_name: str = f'{prefix}{member_name}' if prefix else member_name + member_type: CTypeInfo | None = CTypeInfo.FromNode(item.annotation, self._symtab) if member_type is None: member_type = CTypeInfo() member_type.BaseType = t.CInt() - is_ptr = member_type.IsPtr + is_ptr: bool = member_type.IsPtr if isinstance(item.annotation, ast.BinOp): - annotation_str = ast.dump(item.annotation) + annotation_str: str = ast.dump(item.annotation) if 'CPtr' in annotation_str: is_ptr = True members[full_name] = member_type.Copy() elif isinstance(item, ast.ClassDef): - is_anonymous = any( + is_anonymous: bool = any( any(AnnotationContainsTType(base, 'Anonymous') for base in item.bases) ) if item.bases else False if is_anonymous: - is_union = any( + is_union: bool = any( any(AnnotationContainsTType(base, 'CUnion') for base in item.bases) ) + # 也检查装饰器形式 @t.CUnion + if not is_union and hasattr(item, 'decorator_list') and item.decorator_list: + for deco in item.decorator_list: + if isinstance(deco, ast.Attribute) and hasattr(deco.value, 'id') and IsTModule(deco.value.id, self._symtab) and deco.attr == 'CUnion': + is_union = True + break + elif isinstance(deco, ast.Name): + cls2: type | None = getattr(t, deco.id, None) + if cls2 is None and hasattr(self._symtab, '_t_type_symbols'): + cls2 = self._symtab._t_type_symbols.get(deco.id) + if cls2 is not None and isinstance(cls2, type) and issubclass(cls2, t.CUnion): + is_union = True + break - nested_name = f'{prefix}{item.name}' if prefix else item.name + nested_name: str = f'{prefix}{item.name}' if prefix else item.name members[nested_name] = CTypeInfo() members[nested_name].BaseType = f'union {item.name}' if is_union else f'struct {item.name}' members[nested_name].PtrCount = 0 members[nested_name].ArrayDims = [] - new_prefix = f'{prefix}{item.name}.' if prefix else f'{item.name}.' + new_prefix: str = f'{prefix}{item.name}.' if prefix else f'{item.name}.' self._collect_members(item, members, anonymous_types, new_prefix) - anonymous_members = {} + anonymous_members: dict[str, CTypeInfo] = {} for full_name, member_info in members.items(): if full_name.startswith(f"{nested_name}."): - member_name = full_name[len(nested_name) + 1:] + member_name: str = full_name[len(nested_name) + 1:] anonymous_members[member_name] = member_info if item.name not in anonymous_types: @@ -106,28 +119,47 @@ class ASTSymbolExtractor: # 类符号提取 # ------------------------------------------------------------------ - def _extract_class(self, node, members_info) -> ClassSymbolData: + def _extract_class(self, node: ast.ClassDef, members_info: dict[str, CTypeInfo]) -> ClassSymbolData: """从 ClassDef 节点提取类符号数据""" - type_kind = 'struct' - is_cpython_object = False - is_packed = False + type_kind: str = 'struct' + is_cpython_object: bool = False + is_packed: bool = False # 检查装饰器 if hasattr(node, 'decorator_list') and node.decorator_list: for decorator in node.decorator_list: if isinstance(decorator, ast.Attribute): if (hasattr(decorator.value, 'id') and - decorator.value.id == 't' and - decorator.attr == 'Object'): - is_cpython_object = True - break + IsTModule(decorator.value.id, self._symtab)): + if decorator.attr == 'Object': + is_cpython_object = True + elif decorator.attr == 'CUnion': + type_kind = 'union' + elif decorator.attr in ('CEnum', 'REnum'): + type_kind = 'enum' + elif decorator.attr == 'CStruct': + type_kind = 'struct' + elif isinstance(decorator, ast.Name): + # from t import CStruct / CUnion / CEnum / REnum + cls: type | None = getattr(t, decorator.id, None) + if cls is None and hasattr(self._symtab, '_t_type_symbols'): + cls = self._symtab._t_type_symbols.get(decorator.id) + if cls is not None and isinstance(cls, type) and issubclass(cls, t.CType): + if issubclass(cls, t.CUnion): + type_kind = 'union' + elif issubclass(cls, (t.CEnum, t.REnum)): + type_kind = 'enum' + elif issubclass(cls, t.CStruct): + type_kind = 'struct' + elif decorator.id == 'Object': + is_cpython_object = True elif isinstance(decorator, ast.Call): if isinstance(decorator.func, ast.Attribute): if hasattr(decorator.func.value, 'id') and decorator.func.value.id == 'c' and decorator.func.attr == 'Attribute': for arg in decorator.args: if isinstance(arg, ast.Attribute): if isinstance(arg.value, ast.Attribute): - if hasattr(arg.value.value, 'id') and arg.value.value.id == 't' and arg.value.attr == 'attr' and arg.attr == 'packed': + if hasattr(arg.value.value, 'id') and IsTModule(arg.value.value.id, self._symtab) and arg.value.attr == 'attr' and arg.attr == 'packed': is_packed = True # 检查基类 @@ -149,19 +181,19 @@ class ASTSymbolExtractor: type_kind = 'exception' break elif isinstance(base, ast.Name): - base_entry = self._symtab.get(base.id) + base_entry: CTypeInfo | None = self._symtab.get(base.id) if base_entry and base_entry.IsExceptionClass: type_kind = 'exception' break # 提取枚举成员 - enum_members = [] + enum_members: list[tuple[str, int, int]] = [] if type_kind == 'enum': - next_enum_value = 0 + next_enum_value: int = 0 for item in node.body: if isinstance(item, ast.Assign): if len(item.targets) == 1 and isinstance(item.targets[0], ast.Name): - member_name = item.targets[0].id + member_name: str = item.targets[0].id if isinstance(item.value, ast.Constant) and isinstance(item.value.value, int): next_enum_value = item.value.value + 1 else: @@ -169,7 +201,7 @@ class ASTSymbolExtractor: enum_members.append((member_name, next_enum_value - 1, item.lineno)) elif isinstance(item, ast.AnnAssign): if isinstance(item.target, ast.Name): - member_name = item.target.id + member_name: str = item.target.id if item.value: if isinstance(item.value, ast.Constant) and isinstance(item.value.value, int): next_enum_value = item.value.value + 1 @@ -193,12 +225,12 @@ class ASTSymbolExtractor: # AnnAssign 提取(typedef / define) # ------------------------------------------------------------------ - def _extract_ann_assign(self, node, result: ModuleSymbols): + def _extract_ann_assign(self, node: ast.AnnAssign, result: ModuleSymbols) -> None: """从 AnnAssign 节点提取 typedef 或 define 数据""" - var_name = node.target.id - has_cdefine = AnnotationContainsTType(node.annotation, 'CDefine') if node.annotation else False - has_postdef = AnnotationContainsTType(node.annotation, 'Postdefinition') if node.annotation else False - has_ctypedef = AnnotationContainsTType(node.annotation, 'CTypedef') if node.annotation else False + var_name: str = node.target.id + has_cdefine: bool = AnnotationContainsTType(node.annotation, 'CDefine') if node.annotation else False + has_postdef: bool = AnnotationContainsTType(node.annotation, 'Postdefinition') if node.annotation else False + has_ctypedef: bool = AnnotationContainsTType(node.annotation, 'CTypedef') if node.annotation else False if has_cdefine: result.defines.append(DefineSymbolData( @@ -221,11 +253,11 @@ class ASTSymbolExtractor: # 函数提取 # ------------------------------------------------------------------ - def _extract_function(self, node) -> FuncSymbolData: + def _extract_function(self, node: ast.FunctionDef) -> FuncSymbolData: """从 FunctionDef 节点提取函数符号数据""" - params = [(arg.arg, arg.annotation) for arg in node.args.args] - is_variadic = node.args.vararg is not None - is_inline = CheckAnnotationHasCInline(node.returns) + params: list[tuple[str, ast.AST | None]] = [(arg.arg, arg.annotation) for arg in node.args.args] + is_variadic: bool = node.args.vararg is not None + is_inline: bool = CheckAnnotationHasCInline(node.returns) return FuncSymbolData( name=node.name, diff --git a/lib/core/SymbolInserter.py b/lib/core/SymbolInserter.py index c1a1453..617eb16 100644 --- a/lib/core/SymbolInserter.py +++ b/lib/core/SymbolInserter.py @@ -1,6 +1,6 @@ """Pass 3: SymbolInserter — 将解析后的符号插入 SymbolTable(主命名空间)""" from __future__ import annotations -from typing import TYPE_CHECKING, List +from typing import TYPE_CHECKING if TYPE_CHECKING: from lib.core.SymbolTable import SymbolTable @@ -10,13 +10,20 @@ from lib.core.SymbolData import ModuleSymbols class SymbolInserter: """将解析后的符号插入 SymbolTable 的主命名空间(无前缀)""" - def __init__(self, symbol_table: SymbolTable): - self._symtab = symbol_table + def __init__(self, symbol_table: SymbolTable) -> None: + self._symtab: SymbolTable = symbol_table + self._namespace: str | None = None - def insert(self, module_symbols: ModuleSymbols) -> List[str]: + def set_namespace(self, namespace: str) -> None: + """设置当前模块的命名空间""" + self._namespace = namespace + self._symtab.register_namespace(namespace) + + def insert(self, module_symbols: ModuleSymbols) -> list[str]: """插入所有符号到主命名空间,返回已加载的符号名列表""" - loaded = [] - file_path = module_symbols.file_path + loaded: list[str] = [] + file_path: str = module_symbols.file_path + ns: dict[str, object] = self._symtab._namespaces.get(self._namespace, {}) if self._namespace else {} # 插入类符号 for cls in module_symbols.classes: @@ -25,13 +32,15 @@ class SymbolInserter: cls.members, cls.is_cpython_object, cls.is_packed ) loaded.append(cls.name) + if self._namespace: + ns[cls.name] = self._symtab._symbols[cls.name] # 插入枚举成员(短名 + 类名.成员名) if cls.type_kind == 'enum': for member_name, _member_value, member_lineno in cls.enum_members: self._symtab._InsertEnumMemberSymbol(member_name, cls.name, member_lineno, file_path) loaded.append(member_name) - class_member_name = f"{cls.name}.{member_name}" + class_member_name: str = f"{cls.name}.{member_name}" self._symtab._InsertEnumMemberSymbol(class_member_name, cls.name, member_lineno, file_path) loaded.append(class_member_name) @@ -42,14 +51,20 @@ class SymbolInserter: td.lineno, file_path, td.members ) loaded.append(td.name) + if self._namespace: + ns[td.name] = self._symtab._symbols[td.name] # 插入函数符号 for func in module_symbols.functions: + # 优先使用 CTypeInfo(保留符号性),回退到 LLVM 类型字符串 + ret_type = func.ret_ctype if func.ret_ctype else func.ret_type self._symtab._InsertFuncSymbol( - func.name, func.ret_type, func.param_types, + func.name, ret_type, func.param_types, func.lineno, file_path, func.is_variadic, func.is_inline ) loaded.append(func.name) + if self._namespace: + ns[func.name] = self._symtab._symbols[func.name] # 插入 define 符号 for define in module_symbols.defines: @@ -57,6 +72,8 @@ class SymbolInserter: define.name, define.value, define.lineno, file_path ) loaded.append(define.name) + if self._namespace: + ns[define.name] = self._symtab._symbols[define.name] # 插入匿名类型符号(短名) for anon_name, anon_data in module_symbols.anonymous_types.items(): diff --git a/lib/core/SymbolNode.py b/lib/core/SymbolNode.py index 3ef6a7e..f1aa0ef 100644 --- a/lib/core/SymbolNode.py +++ b/lib/core/SymbolNode.py @@ -1,8 +1,7 @@ from __future__ import annotations -from typing import Any, Dict, Optional, TYPE_CHECKING -if TYPE_CHECKING: - from lib.core.Handles.HandlesBase import CTypeInfo +from typing import Any, Dict, Optional +from lib.core.Handles.HandlesBase import CTypeInfo from lib.includes import t @@ -13,7 +12,6 @@ class SymbolNode: """ def __init__(self, name: str, NodeType: str, lineno: int = 0, file: str = '', parent: SymbolNode | None = None): - from lib.core.Handles.HandlesBase import CTypeInfo self.name: str = name self.type: str = NodeType self.lineno: int = lineno @@ -30,10 +28,10 @@ class SymbolNode: return getattr(self.attributes, key) return self.attributes._extra.get(key, default) - def set(self, key: str, value: Any): + def set(self, key: str, value: Any) -> None: """设置属性值""" if hasattr(self.attributes, key): - attr = getattr(type(self.attributes), key, None) + attr: Any = getattr(type(self.attributes), key, None) if isinstance(attr, property) and attr.fset is None: return setattr(self.attributes, key, value) @@ -62,8 +60,8 @@ class SymbolNode: def find(self, path: str, separator: str = '.') -> Optional[SymbolNode]: """根据路径查找节点,如 'test.ClassA'""" - parts = path.split(separator) - current = self + parts: list[str] = path.split(separator) + current: SymbolNode = self for part in parts: if current.HasChild(part): @@ -75,13 +73,13 @@ class SymbolNode: def ToDict(self) -> Dict[str, Any]: """转换为字典格式""" - result = { + result: dict[str, Any] = { 'type': self.type, 'lineno': self.lineno, 'file': self.file, } # 序列化 CTypeInfo 属性 - attrs = self.attributes + attrs: CTypeInfo = self.attributes if attrs.BaseType: result['BaseType'] = str(attrs.BaseType) if attrs.PtrCount: @@ -130,7 +128,6 @@ class SymbolNode: @classmethod def CreateMember(cls, name: str, TypeName: str | None = None, TypeInfo: 'CTypeInfo | None' = None, IsPtr: bool = False, dims: list[int] | None = None, lineno: int = 0, file: str = '') -> SymbolNode: """创建成员节点(工厂函数)""" - from lib.core.Handles.HandlesBase import CTypeInfo node = cls(name=name, NodeType='member', lineno=lineno, file=file) node.attributes = CTypeInfo() node.attributes.Name = name @@ -151,8 +148,7 @@ class SymbolNode: @classmethod def CreateClass(cls, name: str, TypeKind: type, members: dict | None = None, lineno: int = 0, file: str = '', IsCpythonObject: bool = False, IsPacked: bool = False) -> SymbolNode: """创建类节点(工厂函数)""" - from lib.core.Handles.HandlesBase import CTypeInfo - node = cls(name=name, NodeType=TypeKind, lineno=lineno, file=file) + node: SymbolNode = cls(name=name, NodeType=TypeKind, lineno=lineno, file=file) node.attributes = CTypeInfo() node.attributes.Name = name node.attributes.Lineno = lineno @@ -163,12 +159,12 @@ class SymbolNode: if isinstance(MemberInfo, CTypeInfo): node.attributes.Members[MemberName] = MemberInfo elif isinstance(MemberInfo, dict): - CTypeMember = CTypeInfo() - type_str = MemberInfo.get('type', 'int') - IsPtr = MemberInfo.get('IsPtr', False) + CTypeMember: CTypeInfo = CTypeInfo() + type_str: str = MemberInfo.get('type', 'int') + IsPtr: bool = MemberInfo.get('IsPtr', False) if isinstance(type_str, str): try: - resolved = CTypeInfo.FromTypeName(type_str) + resolved: CTypeInfo | None = CTypeInfo.FromTypeName(type_str) if resolved and resolved.BaseType: CTypeMember = resolved else: @@ -193,9 +189,8 @@ class SymbolNode: return node @classmethod - def CreateTypedef(cls, name: str, OriginalType, members: dict | None = None, lineno: int = 0, file: str = '') -> SymbolNode: - from lib.core.Handles.HandlesBase import CTypeInfo - node = cls(name=name, NodeType='typedef', lineno=lineno, file=file) + def CreateTypedef(cls, name: str, OriginalType: CTypeInfo | str | None, members: dict | None = None, lineno: int = 0, file: str = '') -> SymbolNode: + node: SymbolNode = cls(name=name, NodeType='typedef', lineno=lineno, file=file) node.attributes = CTypeInfo() node.attributes.Name = name node.attributes.Lineno = lineno @@ -211,9 +206,8 @@ class SymbolNode: @classmethod def CreateAnonymous(cls, name: str, IsUnion: bool, members: dict, lineno: int = 0, file: str = '') -> SymbolNode: """创建匿名类型节点(工厂函数)""" - from lib.core.Handles.HandlesBase import CTypeInfo - NodeType = t.CUnion if IsUnion else t.CStruct - node = cls(name=name, NodeType=NodeType, lineno=lineno, file=file) + NodeType: type = t.CUnion if IsUnion else t.CStruct + node: SymbolNode = cls(name=name, NodeType=NodeType, lineno=lineno, file=file) node.attributes = CTypeInfo() node.attributes.Name = name node.attributes.Lineno = lineno diff --git a/lib/core/SymbolReexporter.py b/lib/core/SymbolReexporter.py index 5226c08..ae021ff 100644 --- a/lib/core/SymbolReexporter.py +++ b/lib/core/SymbolReexporter.py @@ -1,6 +1,6 @@ """Pass 4: PackageReexporter — 将符号重新导出到命名空间前缀下""" from __future__ import annotations -from typing import TYPE_CHECKING, List +from typing import TYPE_CHECKING if TYPE_CHECKING: from lib.core.SymbolTable import SymbolTable @@ -10,64 +10,79 @@ from lib.core.SymbolData import ModuleSymbols class PackageReexporter: """将已解析的符号重新导出到命名空间前缀下(如 mpool.MPool)""" - def __init__(self, symbol_table: SymbolTable): - self._symtab = symbol_table + def __init__(self, symbol_table: SymbolTable) -> None: + self._symtab: SymbolTable = symbol_table + self._namespace: str | None = None - def reexport(self, module_symbols: ModuleSymbols, prefixes: List[str], lineno: int = 0) -> List[str]: + def set_namespace(self, namespace: str) -> None: + """设置当前模块的命名空间""" + self._namespace = namespace + + def reexport(self, module_symbols: ModuleSymbols, prefixes: list[str], lineno: int = 0) -> list[str]: """将符号重新导出到所有命名空间前缀下,返回新增的符号名列表""" - loaded = [] - file_path = module_symbols.file_path - primary_prefix = prefixes[0] if prefixes else None + loaded: list[str] = [] + file_path: str = module_symbols.file_path + ns: dict[str, object] = self._symtab._namespaces.get(self._namespace, {}) if self._namespace else {} for prefix in prefixes: # 插入类符号(前缀.类名) for cls in module_symbols.classes: - full_name = f"{prefix}.{cls.name}" + full_name: str = f"{prefix}.{cls.name}" self._symtab._InsertClassSymbol( full_name, cls.type_kind, cls.lineno, file_path, cls.members, cls.is_cpython_object, cls.is_packed ) loaded.append(full_name) + if self._namespace: + ns[full_name] = self._symtab._symbols[full_name] # 插入枚举成员(前缀.成员名) if cls.type_kind == 'enum': for member_name, _member_value, member_lineno in cls.enum_members: - full_member_name = f"{prefix}.{member_name}" + full_member_name: str = f"{prefix}.{member_name}" self._symtab._InsertEnumMemberSymbol(full_member_name, cls.name, member_lineno, file_path) loaded.append(full_member_name) # 插入 typedef 符号(前缀.名称) for td in module_symbols.typedefs: - full_name = f"{prefix}.{td.name}" + full_name: str = f"{prefix}.{td.name}" self._symtab._InsertTypedefSymbol( full_name, td.original_type_kind, td.original_class, td.lineno, file_path, td.members ) loaded.append(full_name) + if self._namespace: + ns[full_name] = self._symtab._symbols[full_name] # 插入函数符号(前缀.名称) for func in module_symbols.functions: - full_name = f"{prefix}.{func.name}" + full_name: str = f"{prefix}.{func.name}" + # 优先使用 CTypeInfo(保留符号性),回退到 LLVM 类型字符串 + ret_type = func.ret_ctype if func.ret_ctype else func.ret_type self._symtab._InsertFuncSymbol( - full_name, func.ret_type, func.param_types, + full_name, ret_type, func.param_types, func.lineno, file_path, func.is_variadic, func.is_inline ) loaded.append(full_name) + if self._namespace: + ns[full_name] = self._symtab._symbols[full_name] # 插入 define 符号(前缀.名称) for define in module_symbols.defines: - full_name = f"{prefix}.{define.name}" + full_name: str = f"{prefix}.{define.name}" self._symtab._InsertDefineSymbol( full_name, define.value, define.lineno, file_path ) loaded.append(full_name) + if self._namespace: + ns[full_name] = self._symtab._symbols[full_name] # 插入模块别名 self._symtab._InsertModuleSymbol(prefix, lineno, file_path) # 插入匿名类型符号(前缀.名称) for anon_name, anon_data in module_symbols.anonymous_types.items(): - full_type_name = f"{prefix}.{anon_name}" + full_type_name: str = f"{prefix}.{anon_name}" self._symtab._InsertAnonymousSymbol( full_type_name, anon_data.is_union, anon_data.members, anon_data.lineno, file_path diff --git a/lib/core/SymbolTable.py b/lib/core/SymbolTable.py index 48ecfde..b24054c 100644 --- a/lib/core/SymbolTable.py +++ b/lib/core/SymbolTable.py @@ -1,11 +1,22 @@ from __future__ import annotations -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Any, Dict, Iterator if TYPE_CHECKING: from lib.core.translator import Translator + +import ast +import traceback + from lib.core.Handles.HandlesBase import CTypeInfo, CTypeHelper from lib.includes import t -from typing import Any, Dict, Iterator -import ast +from lib.core.VLogger import get_logger as _vlog +from lib.core.DiagnosticCollector import DiagnosticCollector +from lib.core.LLVMTypeMapper import LLVMTypeMapper +from lib.core.SymbolExtractor import ASTSymbolExtractor +from lib.core.SymbolTypeResolver import TypeResolver +from lib.core.SymbolInserter import SymbolInserter +from lib.core.SymbolReexporter import PackageReexporter +from lib.core.ConstEvaluator import ConstEvaluator +from lib.core.SymbolData import ModuleSymbols # 从 SymbolUtils 重导出,保持向后兼容 from lib.core.SymbolUtils import IsTModuleType as _IsTModuleType @@ -14,30 +25,35 @@ from lib.core.SymbolUtils import CheckAnnotationHasCInline as _CheckAnnotationHa class SymbolTable: - def __init__(self, translator: "Translator"): - self.translator = translator - self._symbols: Dict[str, CTypeInfo] = {} - from lib.core.DiagnosticCollector import DiagnosticCollector - self.diagnostics = DiagnosticCollector() - from lib.core.LLVMTypeMapper import LLVMTypeMapper - self._type_mapper = LLVMTypeMapper(self) - self.import_aliases: Dict[str, str] = {} + def __init__(self, translator: Translator) -> None: + self.translator: Translator = translator + self._symbols: dict[str, CTypeInfo] = {} + self._namespaces: dict[str, dict[str, CTypeInfo]] = {} # 模块名 -> 符号字典 + self._namespace_imports: dict[str, set[str]] = {} # 模块名 -> 已导入的模块名集合 + self._t_type_symbols: dict[str, type] = {} # 别名 -> t.CType 子类 (from t import CEnum as en) + self.diagnostics: DiagnosticCollector = DiagnosticCollector() + self._type_mapper: LLVMTypeMapper = LLVMTypeMapper(self) + self.import_aliases: dict[str, str] = {} # 别名 -> 模块路径 - def clear(self): + def clear(self) -> None: self._symbols.clear() + self._namespaces.clear() + self._namespace_imports.clear() + self._t_type_symbols.clear() + self.import_aliases.clear() - def get(self, name: str, default=None) -> CTypeInfo: + def get(self, name: str, default: CTypeInfo | None = None) -> CTypeInfo | None: return self._symbols.get(name, default) - def set(self, name: str, value: Any): + def set(self, name: str, value: CTypeInfo | dict[str, Any]) -> None: if isinstance(value, CTypeInfo): self._symbols[name] = value else: # 兼容旧代码传入 dict 的情况 - info = self._CTypeInfoFromDict(name, value) + info: CTypeInfo = self._CTypeInfoFromDict(name, value) self._symbols[name] = info - def update(self, symbols: Dict[str, Any]): + def update(self, symbols: dict[str, CTypeInfo | dict[str, Any]]) -> None: for name, value in symbols.items(): self.set(name, value) @@ -50,7 +66,7 @@ class SymbolTable: def items(self) -> Iterator[tuple[str, CTypeInfo]]: return iter(self._symbols.items()) - def pop(self, name: str, *args) -> CTypeInfo: + def pop(self, name: str, *args: Any) -> CTypeInfo: return self._symbols.pop(name, *args) def __getitem__(self, name: str) -> CTypeInfo: @@ -58,10 +74,10 @@ class SymbolTable: return self._symbols[name] raise KeyError(name) - def __setitem__(self, name: str, value: Any): + def __setitem__(self, name: str, value: CTypeInfo | dict[str, Any]) -> None: self.set(name, value) - def __delitem__(self, name: str): + def __delitem__(self, name: str) -> None: del self._symbols[name] def __contains__(self, name: str) -> bool: @@ -78,8 +94,73 @@ class SymbolTable: # ================================================================== def lookup(self, name: str) -> CTypeInfo | None: - """查找符号,不存在返回 None(替代 `SymbolTable.get(name)`)""" - return self._symbols.get(name) + """查找符号,支持别名解析和 dotted name + + 解析顺序: + 1. 直接匹配 _symbols + 2. 如果包含 '.',解析第一个段为别名后查找剩余路径 + 3. 查 _t_type_symbols(t/c 类型别名,返回模拟 CTypeInfo) + """ + if name in self._symbols: + return self._symbols[name] + + if '.' not in name: + return self._lookup_t_type(name) + + # dotted name: 尝试解析第一个段为别名 + parts: list[str] = name.split('.', 1) + first: str = parts[0] + rest: str = parts[1] + + # 1) 别名解析:import X as Y → Y.Symbol → X.Symbol + resolved: str | None = self.import_aliases.get(first) + if resolved: + alias_name: str = f"{resolved}.{rest}" + if alias_name in self._symbols: + return self._symbols[alias_name] + + # 2) 纯路径查找:module.ClassName + # (已在 line 100 检查过,此处为兜底,保留注释说明路径查找语义) + + return None + + def _lookup_t_type(self, name: str) -> CTypeInfo | None: + """在 _t_type_symbols 中查找 t/c 类型别名,返回模拟 CTypeInfo""" + cls: type | None = self._t_type_symbols.get(name) + if cls is None: + return None + info: CTypeInfo = CTypeInfo() + info.Name = name + info.BaseType = cls() + if issubclass(cls, (t.CEnum, t.REnum)): + info.IsEnum = True + elif issubclass(cls, t.CUnion): + info.IsUnion = True + elif issubclass(cls, t.CStruct): + info.IsStruct = True + return info + + def lookup_in_namespace(self, name: str, namespace: str) -> CTypeInfo | None: + """在指定模块命名空间中查找符号""" + ns: dict[str, CTypeInfo] | None = self._namespaces.get(namespace) + if ns: + return ns.get(name) + return None + + def register_namespace(self, module_name: str) -> None: + """注册一个模块命名空间""" + if module_name not in self._namespaces: + self._namespaces[module_name] = {} + + def register_namespace_import(self, importer: str, imported: str) -> None: + """记录模块导入关系""" + if importer not in self._namespace_imports: + self._namespace_imports[importer] = set() + self._namespace_imports[importer].add(imported) + + def get_namespace_symbols(self, module_name: str) -> dict[str, CTypeInfo]: + """获取模块的命名空间符号表""" + return self._namespaces.get(module_name, {}) def has(self, name: str) -> bool: """检查符号是否存在(替代 `name in SymbolTable`)""" @@ -87,70 +168,70 @@ class SymbolTable: def lookup_struct(self, name: str) -> CTypeInfo | None: """查找结构体符号,非结构体返回 None""" - entry = self._symbols.get(name) + entry: CTypeInfo | None = self._symbols.get(name) if entry and (entry.IsStruct or entry.IsCpythonObject): return entry return None def lookup_enum(self, name: str) -> CTypeInfo | None: """查找枚举符号,非枚举返回 None""" - entry = self._symbols.get(name) + entry: CTypeInfo | None = self._symbols.get(name) if entry and entry.IsEnum: return entry return None def lookup_typedef(self, name: str) -> CTypeInfo | None: """查找 typedef 符号,非 typedef 返回 None""" - entry = self._symbols.get(name) + entry: CTypeInfo | None = self._symbols.get(name) if entry and entry.IsTypedef: return entry return None def lookup_function(self, name: str) -> CTypeInfo | None: """查找函数符号,非函数返回 None""" - entry = self._symbols.get(name) + entry: CTypeInfo | None = self._symbols.get(name) if entry and (entry.IsFunction or entry.IsFuncPtr): return entry return None def lookup_define(self, name: str) -> CTypeInfo | None: """查找常量定义符号,非 define 返回 None""" - entry = self._symbols.get(name) + entry: CTypeInfo | None = self._symbols.get(name) if entry and entry.IsDefine: return entry return None def is_struct(self, name: str) -> bool: """检查名称是否为结构体""" - entry = self._symbols.get(name) + entry: CTypeInfo | None = self._symbols.get(name) return entry is not None and (entry.IsStruct or entry.IsCpythonObject) def is_enum(self, name: str) -> bool: """检查名称是否为枚举""" - entry = self._symbols.get(name) + entry: CTypeInfo | None = self._symbols.get(name) return entry is not None and entry.IsEnum def is_typedef(self, name: str) -> bool: """检查名称是否为 typedef""" - entry = self._symbols.get(name) + entry: CTypeInfo | None = self._symbols.get(name) return entry is not None and entry.IsTypedef def is_function(self, name: str) -> bool: """检查名称是否为函数""" - entry = self._symbols.get(name) + entry: CTypeInfo | None = self._symbols.get(name) return entry is not None and (entry.IsFunction or entry.IsFuncPtr) def is_variable(self, name: str) -> bool: """检查名称是否为变量""" - entry = self._symbols.get(name) + entry: CTypeInfo | None = self._symbols.get(name) return entry is not None and entry.IsVariable def is_define(self, name: str) -> bool: """检查名称是否为常量定义""" - entry = self._symbols.get(name) + entry: CTypeInfo | None = self._symbols.get(name) return entry is not None and entry.IsDefine - def insert(self, name: str, info: CTypeInfo): + def insert(self, name: str, info: CTypeInfo) -> None: """插入符号(替代 `SymbolTable[name] = info`)""" self._symbols[name] = info @@ -160,19 +241,25 @@ class SymbolTable: def find_by_suffix(self, suffix: str) -> list[tuple[str, CTypeInfo]]: """按名称后缀模糊查找符号(替代遍历 + endswith 匹配)""" - results = [] + results: list[tuple[str, CTypeInfo]] = [] for name, info in self._symbols.items(): if name.endswith(suffix): results.append((name, info)) return results - def ToDict(self) -> Dict[str, Any]: - """序列化为字典格式""" - result = {} + def ToDict(self) -> dict[str, Any]: + """序列化为字典格式,BaseType 使用可重建的 dict 格式 + + 返回的 dict 包含: + - 符号条目:{name: {attrs}}(与旧格式兼容) + - '__namespaces__': {namespace: [symbol_names]} 命名空间索引 + - '__import_aliases__': {alias: module_path} 导入别名 + """ + result: dict[str, Any] = {} for name, info in self._symbols.items(): - entry = {'name': name} + entry: dict[str, Any] = {'name': name} if info.BaseType: - entry['BaseType'] = str(info.BaseType) + entry['BaseType'] = self._SerializeBaseType(info.BaseType) if info.PtrCount: entry['PtrCount'] = info.PtrCount if info.IsTypedef: @@ -197,27 +284,99 @@ class SymbolTable: entry['file'] = info.file if info.Members: entry['members'] = info.Members - extra = info._sm._extra + extra: dict[str, Any] = info._sm._extra if extra: entry.update(extra) result[name] = entry + + # 序列化命名空间信息 + if self._namespaces: + result['__namespaces__'] = { + ns: list(symbols.keys()) for ns, symbols in self._namespaces.items() + } + if self.import_aliases: + result['__import_aliases__'] = dict(self.import_aliases) + if self._t_type_symbols: + result['__t_type_symbols__'] = { + name: cls.__name__ for name, cls in self._t_type_symbols.items() + } + return result + + @staticmethod + def _SerializeBaseType(base_type: t.CType | tuple | list | str | None) -> dict | str: + """将 BaseType 序列化为可重建的格式""" + if isinstance(base_type, t.CType): + return {'class': type(base_type).__name__} + if isinstance(base_type, (tuple, list)): + return {'classes': [type(b).__name__ for b in base_type if isinstance(b, t.CType)]} + return str(base_type) + + @staticmethod + def _DeserializeBaseType(data: Any) -> Any: + """从序列化格式恢复 BaseType""" + if isinstance(data, dict): + if 'class' in data: + cls: type | None = getattr(t, data['class'], None) + if cls and isinstance(cls, type) and issubclass(cls, t.CType): + return cls() + elif 'classes' in data: + types: list[t.CType] = [] + for cname in data['classes']: + cls: type | None = getattr(t, cname, None) + if cls and isinstance(cls, type) and issubclass(cls, t.CType): + types.append(cls()) + if types: + return tuple(types) + elif isinstance(data, str): + cls: type | None = getattr(t, data, None) + if cls and isinstance(cls, type) and issubclass(cls, t.CType): + return cls() + return None - def FromDict(self, symbols: Dict[str, Any]): - """从字典格式反序列化""" + def FromDict(self, symbols: dict[str, Any]) -> None: + """从字典格式反序列化(兼容带/不带命名空间信息的两种格式)""" self._symbols.clear() + self._namespaces.clear() + self.import_aliases.clear() + self._t_type_symbols.clear() + + _SPECIAL_KEYS: frozenset[str] = frozenset({'__namespaces__', '__import_aliases__', '__t_type_symbols__'}) + for name, attrs in symbols.items(): + if name in _SPECIAL_KEYS: + continue if isinstance(attrs, dict): - info = self._CTypeInfoFromDict(name, attrs) + info: CTypeInfo = self._CTypeInfoFromDict(name, attrs) self._symbols[name] = info elif isinstance(attrs, CTypeInfo): self._symbols[name] = attrs + + # 恢复命名空间信息 + ns_data: dict[str, list[str]] | None = symbols.get('__namespaces__') + if ns_data: + for ns, sym_names in ns_data.items(): + self._namespaces[ns] = {} + for sym_name in sym_names: + if sym_name in self._symbols: + self._namespaces[ns][sym_name] = self._symbols[sym_name] + aliases_data: dict[str, str] | None = symbols.get('__import_aliases__') + if aliases_data: + self.import_aliases.update(aliases_data) + + # 恢复 t 类型别名 + t_type_data: dict[str, str] | None = symbols.get('__t_type_symbols__') + if t_type_data: + for name, cls_name in t_type_data.items(): + cls: type | None = getattr(t, cls_name, None) + if cls and isinstance(cls, type) and issubclass(cls, t.CType): + self._t_type_symbols[name] = cls - def _CTypeInfoFromDict(self, name: str, attrs: dict) -> CTypeInfo: + def _CTypeInfoFromDict(self, name: str, attrs: dict[str, Any]) -> CTypeInfo: """从旧 dict 格式创建 CTypeInfo(兼容旧代码)""" - info = CTypeInfo() + info: CTypeInfo = CTypeInfo() info.Name = name - node_type = attrs.get('type', '') + node_type: str = attrs.get('type', '') if node_type == 'struct' or attrs.get('IsStruct'): info.IsStruct = True @@ -260,13 +419,17 @@ class SymbolTable: info.EnumName = attrs['EnumName'] if 'DefineValue' in attrs: info.DefineValue = attrs['DefineValue'] + if 'BaseType' in attrs: + info.BaseType = self._DeserializeBaseType(attrs['BaseType']) + if 'name' in attrs and attrs['name'] != name: + info.Name = attrs['name'] # 其他属性存入 _extra - skip_keys = {'type', 'PtrCount', 'OriginalType', 'lineno', 'file', + skip_keys: frozenset[str] = frozenset({'type', 'name', 'PtrCount', 'OriginalType', 'lineno', 'file', 'members', 'IsPtr', 'dims', 'IsCpythonObject', 'IsAnonymous', - 'IsPacked', 'EnumName', 'DefineValue', + 'IsPacked', 'EnumName', 'DefineValue', 'BaseType', 'IsStruct', 'IsEnum', 'IsUnion', 'IsTypedef', - 'IsFunction', 'IsVariable', 'IsDefine', 'IsEnumMember'} + 'IsFunction', 'IsVariable', 'IsDefine', 'IsEnumMember'}) for key, value in attrs.items(): if key not in skip_keys: info.set(key, value) @@ -281,34 +444,33 @@ class SymbolTable: return self._LoadSymbolsFromFile(FullModulePath, asname, lineno) def _LoadSymbolsFromFile(self, FilePath: str, namespace_prefix: str | list[str], lineno: int = 0) -> list[str]: - from lib.core.SymbolExtractor import ASTSymbolExtractor - from lib.core.SymbolTypeResolver import TypeResolver - from lib.core.SymbolInserter import SymbolInserter - from lib.core.SymbolReexporter import PackageReexporter - try: + # 提取模块名作为命名空间 + module_name: str = namespace_prefix[0] if isinstance(namespace_prefix, list) else namespace_prefix + # Pass 1: 从 AST 提取原始符号信息 - extractor = ASTSymbolExtractor(self) - module_symbols = extractor.extract(FilePath) + extractor: ASTSymbolExtractor = ASTSymbolExtractor(self) + module_symbols: ModuleSymbols = extractor.extract(FilePath) # Pass 2: 解析类型信息(typedef、函数签名、define 值) - resolver = TypeResolver(self) + resolver: TypeResolver = TypeResolver(self) resolver.resolve(module_symbols) # Pass 3: 插入符号到主命名空间(无前缀) - inserter = SymbolInserter(self) - loaded = inserter.insert(module_symbols) + inserter: SymbolInserter = SymbolInserter(self) + inserter.set_namespace(module_name) + loaded: list[str] = inserter.insert(module_symbols) # Pass 4: 重新导出到命名空间前缀下 - prefixes = [namespace_prefix] if isinstance(namespace_prefix, str) else namespace_prefix - reexporter = PackageReexporter(self) + prefixes: list[str] = [namespace_prefix] if isinstance(namespace_prefix, str) else namespace_prefix + reexporter: PackageReexporter = PackageReexporter(self) + reexporter.set_namespace(module_name) loaded.extend(reexporter.reexport(module_symbols, prefixes, lineno)) return loaded except Exception as e: - import traceback - print(traceback.format_exc()) + _vlog().error(traceback.format_exc()) self.diagnostics.error(FilePath, lineno, f"加载模块失败: {e}") return [] @@ -316,28 +478,28 @@ class SymbolTable: # 类型解析辅助方法(委托到 LLVMTypeMapper) # ================================================================== - def _GetLLVMTypeStr(self, node): + def _GetLLVMTypeStr(self, node: ast.AST) -> str: return self._type_mapper.get_llvm_type_str(node) - def _GetFuncRetTypeStr(self, returns_node): + def _GetFuncRetTypeStr(self, returns_node: ast.AST | None) -> str: return self._type_mapper.get_func_ret_type_str(returns_node) @staticmethod - def _CheckAnnotationHasCInline(annotation_node) -> bool: + def _CheckAnnotationHasCInline(annotation_node: ast.AST | None) -> bool: return _CheckAnnotationHasCInline(annotation_node) - def _GetFuncParamTypeStr(self, annotation_node): + def _GetFuncParamTypeStr(self, annotation_node: ast.AST) -> str: return self._type_mapper.get_func_param_type_str(annotation_node) - def _ResolveTypedefValueType(self, node): + def _ResolveTypedefValueType(self, node: ast.AST) -> str: return self._type_mapper.resolve_typedef_value_type(node) # ================================================================== # 符号插入方法(供 SymbolInserter / PackageReexporter 调用) # ================================================================== - def _InsertClassSymbol(self, FullName: str, TypeKind: str, lineno: int, FilePath: str, members: dict, IsCpythonObject: bool, IsPacked: bool = False): - info = CTypeInfo() + def _InsertClassSymbol(self, FullName: str, TypeKind: str, lineno: int, FilePath: str, members: dict[str, CTypeInfo], IsCpythonObject: bool, IsPacked: bool = False) -> None: + info: CTypeInfo = CTypeInfo() info.Lineno = lineno info.file = FilePath info.Members = members if members else {} @@ -359,17 +521,18 @@ class SymbolTable: self._symbols[FullName] = info - def _InsertEnumMemberSymbol(self, FullName: str, EnumName: str, lineno: int, FilePath: str): - info = CTypeInfo() + def _InsertEnumMemberSymbol(self, FullName: str, EnumName: str, lineno: int, FilePath: str) -> None: + info: CTypeInfo = CTypeInfo() info.IsEnumMember = True info.EnumName = EnumName info.Lineno = lineno info.file = FilePath self._symbols[FullName] = info - def _InsertTypedefSymbol(self, FullName: str, OriginalType_kind: str | None, OriginalClass, lineno: int, FilePath: str, members: dict | None = None): - info = CTypeInfo() + def _InsertTypedefSymbol(self, FullName: str, OriginalType_kind: str | None, OriginalClass: CTypeInfo | str | None, lineno: int, FilePath: str, members: dict[str, CTypeInfo] | None = None) -> None: + info: CTypeInfo = CTypeInfo() info.IsTypedef = True + info.Name = FullName info.Lineno = lineno info.file = FilePath if members: @@ -378,7 +541,7 @@ class SymbolTable: if isinstance(OriginalClass, CTypeInfo): info.OriginalType = OriginalClass elif OriginalType_kind == 'typedef' and OriginalClass and isinstance(OriginalClass, str) and ('*' in OriginalClass): - OriginalType = OriginalClass + OriginalType: str = OriginalClass if OriginalType == 'CVoid *': OriginalType = 'void *' info.OriginalType = OriginalType @@ -393,15 +556,15 @@ class SymbolTable: self._symbols[FullName] = info - def _InsertModuleSymbol(self, name: str, lineno: int, FilePath: str): - info = CTypeInfo() + def _InsertModuleSymbol(self, name: str, lineno: int, FilePath: str) -> None: + info: CTypeInfo = CTypeInfo() info.IsModuleAlias = True info.Lineno = lineno info.file = FilePath self._symbols[name] = info - def _InsertFuncSymbol(self, FullName: str, RetType, ParamTypes: list, lineno: int, FilePath: str, IsVariadic: bool = False, IsInline: bool = False): - info = CTypeInfo() + def _InsertFuncSymbol(self, FullName: str, RetType: str | CTypeInfo | None, ParamTypes: list[str], lineno: int, FilePath: str, IsVariadic: bool = False, IsInline: bool = False) -> None: + info: CTypeInfo = CTypeInfo() info.IsFunction = True if isinstance(RetType, str): info.FuncPtrReturn = CTypeInfo.FromTypeName(RetType) if RetType else CTypeInfo.VoidTypeInfo() @@ -418,21 +581,20 @@ class SymbolTable: info.file = FilePath self._symbols[FullName] = info - def _InsertDefineSymbol(self, FullName: str, DefineValue, lineno: int, FilePath: str): - info = CTypeInfo() + def _InsertDefineSymbol(self, FullName: str, DefineValue: int | str | float | bool | None, lineno: int, FilePath: str) -> None: + info: CTypeInfo = CTypeInfo() info.IsDefine = True info.DefineValue = DefineValue info.Lineno = lineno info.file = FilePath self._symbols[FullName] = info - def _eval_const_expr(self, node): + def _eval_const_expr(self, node: ast.AST) -> int | float | str | None: """计算常量表达式的值(委托到 ConstEvaluator)""" - from lib.core.ConstEvaluator import ConstEvaluator return ConstEvaluator.eval_with_symtab(node, self) - def _InsertAnonymousSymbol(self, FullName: str, IsUnion: bool, members: dict, lineno: int, FilePath: str): - info = CTypeInfo() + def _InsertAnonymousSymbol(self, FullName: str, IsUnion: bool, members: dict[str, CTypeInfo], lineno: int, FilePath: str) -> None: + info: CTypeInfo = CTypeInfo() if IsUnion: info.IsUnion = True else: diff --git a/lib/core/SymbolTypeResolver.py b/lib/core/SymbolTypeResolver.py index c671e88..2edc844 100644 --- a/lib/core/SymbolTypeResolver.py +++ b/lib/core/SymbolTypeResolver.py @@ -9,6 +9,8 @@ from lib.core.SymbolData import ( ModuleSymbols, TypedefSymbolData, FuncSymbolData, DefineSymbolData ) from lib.core.Handles.HandlesBase import CTypeInfo, CTypeHelper +from lib.core.LLVMTypeMapper import LLVMTypeMapper +from lib.core.SymbolUtils import IsTModule from lib.includes import t @@ -17,23 +19,25 @@ class TypeResolver: def __init__(self, symbol_table: SymbolTable): self._symtab = symbol_table - from lib.core.LLVMTypeMapper import LLVMTypeMapper self._type_mapper = LLVMTypeMapper(symbol_table) def resolve(self, module_symbols: ModuleSymbols) -> ModuleSymbols: """解析所有类型信息,就地更新 ModuleSymbols""" # 构建 class_members 查找表(typedef Postdefinition 需要) - class_members = {cls.name: cls.members for cls in module_symbols.classes} + class_members: dict[str, dict[str, CTypeInfo]] = {cls.name: cls.members for cls in module_symbols.classes} # 解析 typedef + td: TypedefSymbolData for td in module_symbols.typedefs: self._resolve_typedef(td, class_members) # 解析函数签名 + func: FuncSymbolData for func in module_symbols.functions: self._resolve_function(func) # 解析 define 值 + define: DefineSymbolData for define in module_symbols.defines: self._resolve_define(define) @@ -43,9 +47,9 @@ class TypeResolver: # Typedef 解析 # ------------------------------------------------------------------ - def _resolve_typedef(self, td: TypedefSymbolData, class_members: dict): + def _resolve_typedef(self, td: TypedefSymbolData, class_members: dict[str, dict[str, CTypeInfo]]): """解析单个 typedef 的类型信息""" - is_postdef_with_typedef = td.has_postdef and td.has_ctypedef + is_postdef_with_typedef: bool = td.has_postdef and td.has_ctypedef if is_postdef_with_typedef: self._resolve_postdef_typedef(td, class_members) @@ -56,14 +60,14 @@ class TypeResolver: td.original_type_kind = None td.original_class = None - def _resolve_postdef_typedef(self, td: TypedefSymbolData, class_members: dict): + def _resolve_postdef_typedef(self, td: TypedefSymbolData, class_members: dict[str, dict[str, CTypeInfo]]): """解析 Postdefinition + CTypedef 组合注解""" - original_class = self._find_postdef_arg(td.annotation) + original_class: str | None = self._find_postdef_arg(td.annotation) if original_class and original_class in class_members: - members_info = class_members[original_class] - original_type_kind = 'struct' + members_info: dict[str, CTypeInfo] = class_members[original_class] + original_type_kind: str = 'struct' if original_class in self._symtab: - orig_type_info = self._symtab[original_class] + orig_type_info: CTypeInfo = self._symtab[original_class] if orig_type_info.type_cls in (t.CStruct, t.CEnum, t.CUnion): if orig_type_info.type_cls is t.CStruct: original_type_kind = 'struct' @@ -80,22 +84,22 @@ class TypeResolver: def _resolve_ctypedef_typedef(self, td: TypedefSymbolData): """解析 CTypedef 注解""" - base_type_name = self._find_base_type(td.annotation) - _TYPE_QUALIFIERS = {'CTypedef', 'CConst', 'CVolatile', 'CInline', 'CStatic', 'CExtern', 'CDefine', 'CPostdefinition'} + base_type_name: str | None = self._find_base_type(td.annotation) + _TYPE_QUALIFIERS: frozenset[str] = frozenset({'CTypedef', 'CConst', 'CVolatile', 'CInline', 'CStatic', 'CExtern', 'CDefine', 'CPostdefinition'}) if base_type_name == 'Callable': - original_type = CTypeInfo() + original_type: CTypeInfo = CTypeInfo() original_type.IsFuncPtr = True original_type.FuncPtrReturn = CTypeInfo.VoidTypeInfo() original_type.FuncPtrParams = [] td.original_type_kind = 'typedef' td.original_class = original_type elif base_type_name and base_type_name not in _TYPE_QUALIFIERS: - cname = CTypeHelper.GetCName(base_type_name) - if cname and cname != base_type_name: + cname: str | None = CTypeHelper.GetCName(base_type_name) + if cname: td.original_class = cname else: - td.original_class = base_type_name[1:] if base_type_name.startswith('C') else base_type_name + td.original_class = base_type_name td.original_type_kind = 'typedef' else: # 尝试从值表达式解析 @@ -108,24 +112,25 @@ class TypeResolver: td.original_class = None return - value_base_type = self._find_base_type(td.value) - _PTR_MODIFIERS = {'CPtr', 'CArrayPtr', 'CConst', 'CVolatile', 'CInline', 'CStatic', 'CExtern'} + value_base_type: str | None = self._find_base_type(td.value) + _PTR_MODIFIERS: frozenset[str] = frozenset({'CPtr', 'CArrayPtr', 'CConst', 'CVolatile', 'CInline', 'CStatic', 'CExtern'}) if value_base_type and value_base_type not in _PTR_MODIFIERS: - cname = CTypeHelper.GetCName(value_base_type) - if cname and cname != value_base_type: + cname: str | None = CTypeHelper.GetCName(value_base_type) + if cname: td.original_class = cname else: - td.original_class = value_base_type[1:] if value_base_type.startswith('C') else value_base_type + td.original_class = value_base_type td.original_type_kind = 'typedef' return if isinstance(td.value, ast.BinOp) and isinstance(td.value.op, ast.BitOr): - left_type = self._type_mapper.resolve_typedef_value_type(td.value.left) - right_type = self._type_mapper.resolve_typedef_value_type(td.value.right) - is_ptr_type = right_type == 'ptr' or left_type == 'ptr' + left_type: str = self._type_mapper.resolve_typedef_value_type(td.value.left) + right_type: str = self._type_mapper.resolve_typedef_value_type(td.value.right) + is_ptr_type: bool = right_type == 'ptr' or left_type == 'ptr' if is_ptr_type: - base_name = left_type if left_type != 'ptr' else (right_type if right_type != 'ptr' else '') + base_name: str = left_type if left_type != 'ptr' else (right_type if right_type != 'ptr' else '') + original_type: str if base_name: original_type = base_name + ' *' else: @@ -141,9 +146,9 @@ class TypeResolver: return if isinstance(td.value, ast.Name): - ref_name = td.value.id + ref_name: str = td.value.id if ref_name in self._symtab: - ref_info = self._symtab[ref_name] + ref_info: CTypeInfo = self._symtab[ref_name] if ref_info and ref_info.IsTypedef and ref_info.OriginalType: td.original_class = ref_info.OriginalType td.original_type_kind = 'typedef' @@ -159,7 +164,15 @@ class TypeResolver: def _resolve_function(self, func: FuncSymbolData): """解析函数的返回类型和参数类型""" func.ret_type = self._type_mapper.get_func_ret_type_str(func.returns_node) + # 同时解析为 CTypeInfo,保留符号性(LLVM 类型字符串 'i64' 不区分有无符号) + if func.returns_node is not None: + try: + func.ret_ctype = CTypeInfo.FromNode(func.returns_node, self._symtab) + except Exception: + func.ret_ctype = None func.param_types = [] + _arg_name: str + annotation: ast.expr | None for _arg_name, annotation in func.params: if annotation: func.param_types.append(self._type_mapper.get_func_param_type_str(annotation)) @@ -180,28 +193,34 @@ class TypeResolver: # ------------------------------------------------------------------ @staticmethod - def _find_base_type(node): + def _find_base_type(node: ast.AST | None) -> str | None: """从注解 AST 节点中查找基础类型名称""" if isinstance(node, ast.Attribute): - if hasattr(node.value, 'id') and node.value.id == 't': + if hasattr(node.value, 'id') and IsTModule(node.value.id): if node.attr == 'CPtr': return 'ptr' return node.attr elif isinstance(node, ast.Subscript): - if isinstance(node.value, ast.Attribute) and isinstance(node.value.value, ast.Name) and node.value.value.id == 't' and node.value.attr == 'Callable': + if isinstance(node.value, ast.Attribute) and isinstance(node.value.value, ast.Name) and IsTModule(node.value.value.id) and node.value.attr == 'Callable': return 'Callable' elif isinstance(node, ast.BinOp) and isinstance(node.op, ast.BitOr): - left_result = TypeResolver._find_base_type(node.left) + left_result: str | None = TypeResolver._find_base_type(node.left) if left_result == 'ptr': - right_result = TypeResolver._find_base_type(node.right) + right_result: str | None = TypeResolver._find_base_type(node.right) return (right_result if right_result and right_result != 'ptr' else 'void') + ' *' if left_result == 'Callable': return 'Callable' - right_result = TypeResolver._find_base_type(node.right) + right_result: str | None = TypeResolver._find_base_type(node.right) if right_result == 'ptr': return (left_result if left_result and left_result != 'ptr' else 'void') + ' *' if right_result == 'Callable': return 'Callable' + # 类型拼接语义:CLong | CLong → CLongLong, CUnsignedLong | CLong → CUnsignedLongLong + long_types: frozenset[str] = frozenset({'CLong', 'CUnsignedLong'}) + if left_result in long_types and right_result in long_types: + if left_result == 'CUnsignedLong' or right_result == 'CUnsignedLong': + return 'CUnsignedLongLong' + return 'CLongLong' if left_result: return left_result if right_result: @@ -209,18 +228,18 @@ class TypeResolver: return None @staticmethod - def _find_postdef_arg(node): + def _find_postdef_arg(node: ast.AST | None) -> str | None: """从注解 AST 节点中查找 Postdefinition 参数""" if isinstance(node, ast.Call): if isinstance(node.func, ast.Attribute): - if hasattr(node.func.value, 'id') and node.func.value.id == 't' and node.func.attr == 'Postdefinition': + if hasattr(node.func.value, 'id') and IsTModule(node.func.value.id) and node.func.attr == 'Postdefinition': if node.args and isinstance(node.args[0], ast.Name): return node.args[0].id elif isinstance(node, ast.BinOp) and isinstance(node.op, ast.BitOr): - left_result = TypeResolver._find_postdef_arg(node.left) + left_result: str | None = TypeResolver._find_postdef_arg(node.left) if left_result: return left_result - right_result = TypeResolver._find_postdef_arg(node.right) + right_result: str | None = TypeResolver._find_postdef_arg(node.right) if right_result: return right_result return None diff --git a/lib/core/SymbolUtils.py b/lib/core/SymbolUtils.py index 5f14a09..8895f5b 100644 --- a/lib/core/SymbolUtils.py +++ b/lib/core/SymbolUtils.py @@ -3,26 +3,51 @@ from __future__ import annotations import ast from lib.includes import t +_T_MODULE_NAMES: frozenset[str] = frozenset({'t', t.__name__}) + + +def IsTModule(module_id: str, symtable: object | None = None) -> bool: + """检查模块标识符是否指向 t 类型模块(支持别名如 import t as tt)""" + if module_id in _T_MODULE_NAMES: + return True + if symtable is not None and hasattr(symtable, 'import_aliases'): + resolved: str = symtable.import_aliases.get(module_id, module_id) + if resolved in _T_MODULE_NAMES: + return True + return False + + +def IsTModulePath(module_path: str) -> bool: + """检查模块路径是否指向 t 类型模块""" + if module_path in _T_MODULE_NAMES: + return True + if module_path: + t_name: str + for t_name in _T_MODULE_NAMES: + if module_path == t_name or module_path.startswith(t_name + '.'): + return True + return False + def IsTModuleType(TypeName: str) -> bool: """检测类型名称是否是 t 模块中的类型(CType 或其他特殊类型)""" if TypeName in ('t', 'State', 'Bit', 'Anonymous', 'Postdefinition'): return True - TypeClass = getattr(t, TypeName, None) + TypeClass: type | None = getattr(t, TypeName, None) if TypeClass and isinstance(TypeClass, type): if issubclass(TypeClass, t.CType): return True - FallbackClass = getattr(t, f'_{TypeName}', None) + FallbackClass: type | None = getattr(t, f'_{TypeName}', None) if FallbackClass and isinstance(FallbackClass, type): if issubclass(FallbackClass, t.CType): return True return False -def AnnotationContainsTType(node, TypeName: str) -> bool: +def AnnotationContainsTType(node: ast.AST, TypeName: str) -> bool: """检测 AST 节点中是否包含指定名称的 t 模块类型""" if isinstance(node, ast.Attribute): - if (hasattr(node.value, 'id') and node.value.id == 't' and + if (hasattr(node.value, 'id') and IsTModule(node.value.id) and node.attr == TypeName): return True elif isinstance(node, ast.BinOp): @@ -41,12 +66,70 @@ def AnnotationContainsTType(node, TypeName: str) -> bool: return False -def CheckAnnotationHasCInline(annotation_node) -> bool: +def IsListAnnotation(annotation: ast.expr) -> bool: + """检查注解是否为 t.CArray[...] 类型(栈上固定数组)""" + if not isinstance(annotation, ast.Subscript): + return False + value = annotation.value + # t.CArray[...] + if (isinstance(value, ast.Attribute) + and isinstance(value.value, ast.Name) + and value.value.id == 't' + and value.attr == 'CArray'): + return True + return False + + +def ExtractListFromBinOp(annotation: ast.expr) -> ast.Subscript | None: + """从 BinOp(BitOr) 注解中提取 list[...] 部分,如 list[i32] | t.CPtr""" + if isinstance(annotation, ast.BinOp) and isinstance(annotation.op, ast.BitOr): + for side in (annotation.left, annotation.right): + if IsListAnnotation(side): + return side + return None + + +class ListAnnotationParseResult: + """list[...] 注解解析结果。 + + is_pointer=True 表示单参数 list[type] → 指针模式; + is_pointer=False 表示 Tuple(2) 模式 list[type, count]。 + """ + __slots__ = ('elem_type_node', 'count_node', 'is_pointer') + + def __init__(self, elem_type_node: ast.expr, count_node: ast.expr | None, is_pointer: bool) -> None: + self.elem_type_node: ast.expr = elem_type_node + self.count_node: ast.expr | None = count_node + self.is_pointer: bool = is_pointer + + +def ParseListAnnotation(annotation: ast.expr) -> ListAnnotationParseResult | None: + """解析 list[...] 注解,统一处理 list[type, count] / list[type] / BinOp(BitOr) 形式。 + + 自动处理 BinOp(BitOr) 包裹(如 list[i32, N] | t.CPtr)。 + 返回 None 表示不是 list 注解。 + """ + list_node: ast.expr = annotation + if isinstance(annotation, ast.BinOp) and isinstance(annotation.op, ast.BitOr): + extracted: ast.Subscript | None = ExtractListFromBinOp(annotation) + if extracted is None: + return None + list_node = extracted + if not IsListAnnotation(list_node): + return None + slice_node: ast.AST = list_node.slice + if isinstance(slice_node, ast.Tuple) and len(slice_node.elts) == 2: + return ListAnnotationParseResult(slice_node.elts[0], slice_node.elts[1], is_pointer=False) + # 单参数 list[type] → 指针模式 + return ListAnnotationParseResult(slice_node, None, is_pointer=True) + + +def CheckAnnotationHasCInline(annotation_node: ast.AST | None) -> bool: """检测注解节点中是否包含 CInline""" if annotation_node is None: return False if isinstance(annotation_node, ast.Attribute): - if hasattr(annotation_node.value, 'id') and annotation_node.value.id == 't' and annotation_node.attr == 'CInline': + if hasattr(annotation_node.value, 'id') and IsTModule(annotation_node.value.id) and annotation_node.attr == 'CInline': return True if isinstance(annotation_node, ast.Name): if annotation_node.id == 'CInline': @@ -54,3 +137,50 @@ def CheckAnnotationHasCInline(annotation_node) -> bool: if isinstance(annotation_node, ast.BinOp) and isinstance(annotation_node.op, ast.BitOr): return CheckAnnotationHasCInline(annotation_node.left) or CheckAnnotationHasCInline(annotation_node.right) return False + + +def ExtractTypeNameFromBinOp(annotation: ast.expr) -> str | None: + """从 BinOp(BitOr) 注解左侧提取类型名(如 TypeA | TypeB → TypeA)。 + + 返回 Name.id 或 Attribute.attr,非 BinOp 返回 None。 + """ + if isinstance(annotation, ast.BinOp) and isinstance(annotation.op, ast.BitOr): + left: ast.expr = annotation.left + if isinstance(left, ast.Name): + return left.id + if isinstance(left, ast.Attribute): + return left.attr + return None + + +def FindStructNameInAnnotation(node: ast.AST, struct_names: dict | set) -> str | None: + """递归在注解中查找结构体名(支持 BinOp(BitOr) 递归)。 + + 检查 Name.id、Constant.str、Attribute.attr 是否在 struct_names 中。 + """ + if isinstance(node, ast.Name) and node.id in struct_names: + return node.id + if isinstance(node, ast.Constant) and isinstance(node.value, str) and node.value in struct_names: + return node.value + if isinstance(node, ast.Attribute) and node.attr in struct_names: + return node.attr + if isinstance(node, ast.BinOp) and isinstance(node.op, ast.BitOr): + result: str | None = FindStructNameInAnnotation(node.left, struct_names) + if result: + return result + return FindStructNameInAnnotation(node.right, struct_names) + return None + + +def AnnotationContainsName(annotation: ast.AST, name: str) -> bool: + """检查注解中是否包含指定名称(支持 BinOp(BitOr) 递归)。 + + 同时检查 Attribute.attr 和 Name.id,比 ast.dump 字符串匹配更精确。 + """ + if isinstance(annotation, ast.Attribute): + return annotation.attr == name + if isinstance(annotation, ast.Name): + return annotation.id == name + if isinstance(annotation, ast.BinOp) and isinstance(annotation.op, ast.BitOr): + return AnnotationContainsName(annotation.left, name) or AnnotationContainsName(annotation.right, name) + return False diff --git a/lib/core/Translator/AnnotationLoader.py b/lib/core/Translator/AnnotationLoader.py index 7e5595b..d406213 100644 --- a/lib/core/Translator/AnnotationLoader.py +++ b/lib/core/Translator/AnnotationLoader.py @@ -3,9 +3,16 @@ from __future__ import annotations import ast import sys import os +import importlib +import types +from typing import Any from lib.core.Handles.HandlesBase import CTypeInfo +from lib.core.SymbolUtils import IsTModule from lib.includes import t +from lib.includes.t import CType, CEnum +from lib.constants.config import mode as _config_mode +from lib.core.VLogger import get_logger as _vlog class AnnotationLoaderMixin: @@ -14,7 +21,7 @@ class AnnotationLoaderMixin: 提供注解模块/文件的加载与符号表注册能力。 """ - def _LoadAnnotationModule(self, ModuleName: str, library_name: str = None, parse_method: str = 'auto'): + def _LoadAnnotationModule(self, ModuleName: str, library_name: str | None = None, parse_method: str = 'auto') -> int: """加载注解模块并将 CType 子类注册为 typedef 支持两种模式: @@ -29,25 +36,20 @@ class AnnotationLoaderMixin: - 'file': 强制使用 AST 模式(文件路径) - 'module': 强制使用 importlib 模式(模块名) """ - import importlib - import sys - import os - - CurrentDir = os.path.dirname(os.path.abspath(__file__)) - ProjectRoot = os.path.dirname(os.path.dirname(os.path.dirname(CurrentDir))) + CurrentDir: str = os.path.dirname(os.path.abspath(__file__)) + ProjectRoot: str = os.path.dirname(os.path.dirname(os.path.dirname(CurrentDir))) if ProjectRoot not in sys.path: sys.path.insert(0, ProjectRoot) - def register_to_symboltable(module, lib_name: str = None, source_file: str = None): + def register_to_symboltable(module: types.ModuleType, lib_name: str | None = None, source_file: str | None = None) -> int: """将模块中的 CType 子类和 CEnum 类注册到符号表""" - from lib.includes.t import CType, CEnum - count = 0 + count: int = 0 for AttrName in dir(module): - attr = getattr(module, AttrName) + attr: type = getattr(module, AttrName) # 优先检查是否是 CEnum 子类(枚举) if isinstance(attr, type) and issubclass(attr, CEnum) and attr is not CEnum: # 注册枚举类型 - EnumNode = CTypeInfo() + EnumNode: CTypeInfo = CTypeInfo() EnumNode.Name = AttrName EnumNode.BaseType = t.CEnum() EnumNode.IsEnum = True @@ -57,8 +59,8 @@ class AnnotationLoaderMixin: EnumNode.file = source_file self.SymbolTable.insert(AttrName, EnumNode) if lib_name: - FullName = f'{lib_name}.{AttrName}' - full_EnumNode = CTypeInfo() + FullName: str = f'{lib_name}.{AttrName}' + full_EnumNode: CTypeInfo = CTypeInfo() full_EnumNode.Name = FullName full_EnumNode.IsEnum = True full_EnumNode.set('enum_class', attr) @@ -69,9 +71,9 @@ class AnnotationLoaderMixin: # 枚举成员也需要注册 for MemberName in dir(attr): if not MemberName.startswith('_'): - member = getattr(attr, MemberName, None) + member: int = getattr(attr, MemberName, None) if isinstance(member, int): - MemberNode = CTypeInfo() + MemberNode: CTypeInfo = CTypeInfo() MemberNode.Name = MemberName MemberNode.BaseType = t.CEnum(AttrName) MemberNode.value = member @@ -90,23 +92,23 @@ class AnnotationLoaderMixin: # 继承 CType 的类是类型别名(typedef),不是结构体 # 使用手动指定的库名称作为前缀 if lib_name: - FullName = f'{lib_name}.{AttrName}' + FullName: str = f'{lib_name}.{AttrName}' else: FullName = AttrName # 同时注册带前缀和不带前缀的名称(都是 typedef 别名) - TypedefNode = CTypeInfo() + TypedefNode: CTypeInfo = CTypeInfo() TypedefNode.Name = AttrName TypedefNode.IsTypedef = True - TypedefNode.OriginalType = attr().CName + TypedefNode.OriginalType = attr.__name__ TypedefNode.set('source', 'annotation_module') TypedefNode.library_name = lib_name TypedefNode.file = source_file self.SymbolTable.insert(AttrName, TypedefNode) if lib_name and FullName != AttrName: - FullTypedef_node = CTypeInfo() + FullTypedef_node: CTypeInfo = CTypeInfo() FullTypedef_node.Name = FullName FullTypedef_node.IsTypedef = True - FullTypedef_node.OriginalType = attr().CName + FullTypedef_node.OriginalType = attr.__name__ FullTypedef_node.set('source', 'annotation_module') FullTypedef_node.library_name = lib_name FullTypedef_node.file = source_file @@ -114,29 +116,29 @@ class AnnotationLoaderMixin: count += 1 # 检查是否是下划线前缀的 CType 子类(如 _CTypedef -> CTypedef) elif AttrName.startswith('_') and len(AttrName) > 1: - PublicName = AttrName[1:] - PublicAttr = getattr(module, PublicName, None) + PublicName: str = AttrName[1:] + PublicAttr: type | None = getattr(module, PublicName, None) if PublicAttr is not None and not isinstance(attr, type): continue if isinstance(attr, type) and issubclass(attr, CType) and attr is not CType: if not self.SymbolTable.has(PublicName): if lib_name: - FullName = f'{lib_name}.{PublicName}' + FullName: str = f'{lib_name}.{PublicName}' else: FullName = PublicName - TypedefNode = CTypeInfo() + TypedefNode: CTypeInfo = CTypeInfo() TypedefNode.Name = PublicName TypedefNode.IsTypedef = True - TypedefNode.OriginalType = attr().CName + TypedefNode.OriginalType = attr.__name__ TypedefNode.set('source', 'annotation_module') TypedefNode.library_name = lib_name TypedefNode.file = source_file self.SymbolTable.insert(PublicName, TypedefNode) if lib_name and FullName != PublicName: - FullTypedef_node = CTypeInfo() + FullTypedef_node: CTypeInfo = CTypeInfo() FullTypedef_node.Name = FullName FullTypedef_node.IsTypedef = True - FullTypedef_node.OriginalType = attr().CName + FullTypedef_node.OriginalType = attr.__name__ FullTypedef_node.set('source', 'annotation_module') FullTypedef_node.library_name = lib_name FullTypedef_node.file = source_file @@ -145,7 +147,7 @@ class AnnotationLoaderMixin: return count # 确定解析方法 - use_file_mode = False + use_file_mode: bool = False if parse_method == 'file': use_file_mode = True elif parse_method == 'module': @@ -154,7 +156,7 @@ class AnnotationLoaderMixin: use_file_mode = os.path.isfile(ModuleName) # 确定库名称 - lib_name = library_name + lib_name: str | None = library_name if lib_name is None: if use_file_mode: # 从文件路径推断库名称 @@ -168,8 +170,8 @@ class AnnotationLoaderMixin: # AST 模式:使用 AST 解析文件,不执行代码 try: # 临时保存当前的 EmbeddedAssignments 和 TypedefAssignments - saved_embedded = self.EmbeddedAssignments.copy() - saved_typedef = self.TypedefAssignments.copy() + saved_embedded: dict = self.EmbeddedAssignments.copy() + saved_typedef: dict = self.TypedefAssignments.copy() # 清空 PD 收集(注解文件不应该收集 PD 语句) self.EmbeddedAssignments = {} @@ -185,12 +187,12 @@ class AnnotationLoaderMixin: self.TypedefAssignments = saved_typedef # 从文件名推断类型前缀(如 test_t -> test_t.xxx) - TypePrefix = lib_name - count = 0 + TypePrefix: str = lib_name + count: int = 0 # 检查符号表中新增的类型(注解文件解析后的所有 struct 类型) # 需要检查这些类型是否继承自 CType,如果是则是 typedef 别名 - new_types = [] + new_types: list[str] = [] for TypeName, TypeInfo in self.SymbolTable.items(): if TypeInfo.IsStruct: new_types.append(TypeName) @@ -198,18 +200,18 @@ class AnnotationLoaderMixin: # 再次遍历 AST,检测继承自 CType 的类 try: with open(ModuleName, 'r', encoding='utf-8') as f: - ann_content = f.read() - ann_tree = ast.parse(ann_content) + ann_content: str = f.read() + ann_tree: ast.Module = ast.parse(ann_content) for node in ann_tree.body: if isinstance(node, ast.ClassDef): - ClassName = node.name + ClassName: str = node.name # 检查是否有基类 for base in node.bases: if isinstance(base, ast.Name) and base.id == 'CType': # 这个类继承自 CType,是 typedef 别名 # 更新符号表中的类型为 typedef if self.SymbolTable.has(ClassName): - TypedefNode = CTypeInfo() + TypedefNode: CTypeInfo = CTypeInfo() TypedefNode.Name = ClassName TypedefNode.IsTypedef = True TypedefNode.OriginalType = self.SymbolTable[ClassName].get('OriginalType', f'struct {ClassName}') @@ -217,17 +219,15 @@ class AnnotationLoaderMixin: TypedefNode.set('is_ctype_subclass', True) self.SymbolTable.insert(ClassName, TypedefNode) except Exception as _e: - from lib.core.VLogger import get_logger as _vlog - from lib.constants.config import mode as _ConfigMode - if _ConfigMode == "strict": + if _config_mode == "strict": raise _vlog().warning(f"解析注解文件类型定义失败: {_e}", "Exception") # 为所有新增的类型添加库前缀和 source 标记 for TypeName in new_types: # 添加带前缀的类型名 - FullName = f'{TypePrefix}.{TypeName}' - TypeInfo = self.SymbolTable[TypeName].copy() + FullName: str = f'{TypePrefix}.{TypeName}' + TypeInfo: CTypeInfo | dict[str, Any] = self.SymbolTable[TypeName].copy() TypeInfo['source'] = 'annotation_module' TypeInfo['original_name'] = TypeName self.SymbolTable.insert(FullName, TypeInfo) @@ -235,23 +235,23 @@ class AnnotationLoaderMixin: # 再次遍历 AST,查找注解文件中的 typedef 语句(AnnAssign with t.CTypedef) # 注意:必须在类定义处理完之后再处理 typedef - typedef_annots = [] + typedef_annots: list[tuple[str, str]] = [] # 查找 CEnum 成员变量(AnnAssign with t.CEnum | t.State 或 t.CEnum) - cEnumMembers = [] + cEnumMembers: list[tuple[str, int | None]] = [] try: with open(ModuleName, 'r', encoding='utf-8') as f: - ann_content = f.read() - ann_tree = ast.parse(ann_content) + ann_content: str = f.read() + ann_tree: ast.Module = ast.parse(ann_content) for node in ann_tree.body: # 检测 xxx: t.CEnum 形式的枚举成员变量 if isinstance(node, ast.AnnAssign): if isinstance(node.target, ast.Name) and node.annotation: - TargetName = node.target.id + TargetName: str = node.target.id # 检查注解是否是 BinOp (Union) 或直接是 Attribute - IsCenum = False + IsCenum: bool = False if isinstance(node.annotation, ast.BinOp): # 检查是否包含 CEnum - annot_str = ast.dump(node.annotation) + annot_str: str = ast.dump(node.annotation) if 'CEnum' in annot_str: IsCenum = True elif isinstance(node.annotation, ast.Attribute): @@ -262,21 +262,19 @@ class AnnotationLoaderMixin: if IsCenum: # 检查值是否是 Constant (枚举成员值) if node.value and isinstance(node.value, ast.Constant): - value = node.value.value + value: int | str | float | None = node.value.value else: value = None cEnumMembers.append((TargetName, value)) except Exception as _e: - from lib.core.VLogger import get_logger as _vlog - from lib.constants.config import mode as _ConfigMode - if _ConfigMode == "strict": + if _config_mode == "strict": raise _vlog().warning(f"解析 CEnum 成员变量失败: {_e}", "Exception") # 处理 CEnum 成员变量 for TargetName, value in cEnumMembers: # 注册枚举成员 - MemberNode = CTypeInfo() + MemberNode: CTypeInfo = CTypeInfo() MemberNode.Name = TargetName MemberNode.BaseType = t.CEnum(TypePrefix) MemberNode.value = value @@ -289,40 +287,38 @@ class AnnotationLoaderMixin: try: with open(ModuleName, 'r', encoding='utf-8') as f: - ann_content = f.read() - ann_tree = ast.parse(ann_content) + ann_content: str = f.read() + ann_tree: ast.Module = ast.parse(ann_content) for node in ann_tree.body: # 检测 xxx: t.CTypedef = xxx 形式的 typedef 语句 if isinstance(node, ast.AnnAssign): if isinstance(node.target, ast.Name) and node.annotation and node.value: - TargetName = node.target.id + TargetName: str = node.target.id # 检查注解是否是 t.CTypedef if isinstance(node.annotation, ast.Attribute): if isinstance(node.annotation.value, ast.Name): - if node.annotation.value.id == 't' and node.annotation.attr == 'CTypedef': + if IsTModule(node.annotation.value.id) and node.annotation.attr == 'CTypedef': # 检查值是否是 Name if isinstance(node.value, ast.Name): - original_name = node.value.id + original_name: str = node.value.id typedef_annots.append((TargetName, original_name)) except Exception as _e: - from lib.core.VLogger import get_logger as _vlog - from lib.constants.config import mode as _ConfigMode - if _ConfigMode == "strict": + if _config_mode == "strict": raise _vlog().warning(f"解析 typedef 语句失败: {_e}", "Exception") # 处理 typedef 注解 for TargetName, original_name in typedef_annots: # 检查原始类型是否在符号表中(带前缀或不带前缀) - orig_with_prefix = f'{TypePrefix}.{original_name}' + orig_with_prefix: str = f'{TypePrefix}.{original_name}' if self.SymbolTable.has(orig_with_prefix): # 添加带前缀的 typedef 别名 - FullTypedef_name = f'{TypePrefix}.{TargetName}' - TypedefNode = CTypeInfo() + FullTypedef_name: str = f'{TypePrefix}.{TargetName}' + TypedefNode: CTypeInfo = CTypeInfo() TypedefNode.Name = FullTypedef_name TypedefNode.IsTypedef = True - orig_entry = self.SymbolTable.lookup(orig_with_prefix) - orig_type_str = f'struct {original_name}' + orig_entry: CTypeInfo | dict[str, Any] = self.SymbolTable.lookup(orig_with_prefix) + orig_type_str: str = f'struct {original_name}' if isinstance(orig_entry, dict): if orig_entry.get('type') == 'typedef': orig_type_str = orig_entry.get('OriginalType', f'struct {original_name}') @@ -349,8 +345,8 @@ class AnnotationLoaderMixin: else: # importlib 模式:导入模块 try: - module = importlib.import_module(ModuleName) - count = register_to_symboltable(module, lib_name, None) + module: types.ModuleType = importlib.import_module(ModuleName) + count: int = register_to_symboltable(module, lib_name, None) self.AnnotationModules.add(lib_name) return count except ImportError: @@ -360,7 +356,7 @@ class AnnotationLoaderMixin: self.LogWarning(f"加载注解模块失败: {ModuleName}, 错误: {e}") return 0 - def _LoadAnnotationFiles(self, FilePaths: list): + def _LoadAnnotationFiles(self, FilePaths: list[str | tuple]) -> None: """加载多个注解文件并注册到符号表 Args: @@ -371,15 +367,20 @@ class AnnotationLoaderMixin: for item in FilePaths: if isinstance(item, tuple): if len(item) >= 3: + path: str + library_name: str + parse_method: str path, library_name, parse_method = item[:3] - count = self._loadAnnotationModule(path, library_name, parse_method) + count: int = self._LoadAnnotationModule(path, library_name, parse_method) elif len(item) == 2: + path: str + library_name: str path, library_name = item - count = self._loadAnnotationModule(path, library_name, 'auto') + count: int = self._LoadAnnotationModule(path, library_name, 'auto') else: - count = self._loadAnnotationModule(item) + count: int = self._LoadAnnotationModule(item) else: - count = self._loadAnnotationModule(item) + count: int = self._LoadAnnotationModule(item) # 别名,保持向后兼容 LoadAnnotationFiles = _LoadAnnotationFiles diff --git a/lib/core/Translator/BaseTranslator.py b/lib/core/Translator/BaseTranslator.py index 8d38afa..ff7c50f 100644 --- a/lib/core/Translator/BaseTranslator.py +++ b/lib/core/Translator/BaseTranslator.py @@ -1,11 +1,15 @@ from __future__ import annotations -from typing import Dict +import ast +from typing import Any, Callable, Dict, TYPE_CHECKING import sys import os from lib.core.Exportable import Exportable +if TYPE_CHECKING: + import llvmlite.ir as ir + sys.path.append(os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(__file__)))), 'lib', 'includes')) from lib.includes import c from lib.includes import t @@ -27,10 +31,11 @@ from lib.core.Handles.HandlesBase import CTypeInfo from lib.core.SymbolTable import SymbolTable from lib.core.SymbolNode import SymbolNode from lib.constants.config import mode as _ConfigMode +from lib.core.VLogger import get_logger as _vlog from lib.core.LlvmCodeGenerator import LlvmCodeGenerator -def _StrictLog(logger, msg): +def _StrictLog(logger: Callable[[str], None], msg: str) -> None: """在 strict 模式下记录异常日志""" if _ConfigMode == "strict": logger(msg) @@ -42,11 +47,11 @@ class BaseTranslatorMixin: 提供 __init__、日志、调试输出与表达式处理等基础能力。 """ - def __init__(self): + def __init__(self) -> None: self.VarScopes: list[Dict[str, SymbolNode]] = [{}] # 跟踪变量作用域,第一个是全局作用域 self.FunctionReturnTypes: Dict[str, CTypeInfo] = {} # 记录函数名和其返回类型 - self.CurrentCReturnTypes: list[CTypeInfo] = None # 当前函数的 CReturn 类型列表 - self._CurrentCpythonObjectClass: str = None # 当前正在处理的 CPython 对象类名 + self.CurrentCReturnTypes: list[CTypeInfo] | None = None # 当前函数的 CReturn 类型列表 + self._CurrentCpythonObjectClass: str | None = None # 当前正在处理的 CPython 对象类名 self.FunctionDefCache: dict = {} # 函数定义缓存 self.OriginalLines: list[str] = [] # 原始代码行 self.Content: str = '' @@ -54,20 +59,20 @@ class BaseTranslatorMixin: self.IsHeader: bool = False # 是否生成头文件(仅处理定义、宏、导入等,忽略函数体) self.AnnotationModules: set[str] = set() # 注解模块集合,用于识别类型定义模块 self.Warnings: list[str] = [] # 警告日志 - self._ErrorStack = [] # 错误栈,按顺序收集错误位置 - self.Errors = [] # 错误日志 - self.SliceCount = 0 # 切片计数 - self.SliceInfos = [] # 切片信息列表 - self.SliceLevel = 3 # 切片优化级别 - self.GeneratedTypes = set() # 在当前代码中生成的类型(struct/typedef) - self.EmbeddedAssignments = {} # {ClassName: [var1, var2, ...]} 嵌入的实例化变量 - self.TypedefAssignments = {} # {ClassName: [(var1, IsPtr), ...]} 嵌入的 typedef/指针变量 - self.ChainAssignmentArrays = [] # 链式赋值数组形式 [(ClassName, VarName, ArraySize_node), ...] - self.tree = None # 保存解析后的 AST 树 - self.LibraryPaths = ['.'] # 库搜索路径列表,默认包含当前目录 - self.InClass = False # 是否正在处理 class 定义 - self._UserTypeModules = {} - self._source_module_sig_files = {} + self._ErrorStack: list[tuple[str, str, str]] = [] # 错误栈,按顺序收集错误位置 + self.Errors: list[dict[str, str | None]] = [] # 错误日志 + self.SliceCount: int = 0 # 切片计数 + self.SliceInfos: list = [] # 切片信息列表 + self.SliceLevel: int = 3 # 切片优化级别 + self.GeneratedTypes: set[str] = set() # 在当前代码中生成的类型(struct/typedef) + self.EmbeddedAssignments: dict[str, list] = {} # {ClassName: [var1, var2, ...]} 嵌入的实例化变量 + self.TypedefAssignments: dict[str, list] = {} # {ClassName: [(var1, IsPtr), ...]} 嵌入的 typedef/指针变量 + self.ChainAssignmentArrays: list = [] # 链式赋值数组形式 [(ClassName, VarName, ArraySize_node), ...] + self.tree: ast.AST | None = None # 保存解析后的 AST 树 + self.LibraryPaths: list[str] = ['.'] # 库搜索路径列表,默认包含当前目录 + self.InClass: bool = False # 是否正在处理 class 定义 + self._UserTypeModules: dict = {} + self._source_module_sig_files: dict = {} self._global_function_default_args: dict = {} self.exception_registry: dict = {} self.exception_parents: dict = {} @@ -107,7 +112,7 @@ class BaseTranslatorMixin: self.RaiseHandler = RaiseHandle(self) self.MatchHandler = MatchHandle(self) - def LogWarning(self, message: str, LineNum: int = None): + def LogWarning(self, message: str, LineNum: int | None = None) -> None: """记录警告 Args: @@ -119,36 +124,36 @@ class BaseTranslatorMixin: warning += f" (line {LineNum})" self.Warnings.append(warning) - def LogError(self, message: str, LineNum: int = None): + def LogError(self, message: str, LineNum: int | None = None) -> None: """记录错误 Args: message: 错误消息 LineNum: 行号 """ - print(f"[ERROR] {message}") - entry = {'message': message, 'line': LineNum} + _vlog().error(message) + entry: dict[str, str | int | None] = {'message': message, 'line': LineNum} self.Errors.append(entry) # 检查 config 中是否有 debug 文件 - DebugFile = None + DebugFile: str | None = None if hasattr(self, 'config') and self.config: DebugFile = getattr(self.config, 'debug', None) if DebugFile: with open(DebugFile, 'a', encoding='utf-8') as f: - LineInfo = f' line {LineNum}' if LineNum else '' + LineInfo: str = f' line {LineNum}' if LineNum else '' f.write(f'[ERROR]{LineInfo}: {message}\n') - def SetDebugFile(self, FilePath): + def SetDebugFile(self, FilePath: str) -> None: """设置调试输出文件""" self.DebugFile = FilePath - def DebugPrint(self, *args, **kwargs): + def DebugPrint(self, *args: Any, **kwargs: Any) -> None: """输出调试信息到文件""" if self.DebugFile: with open(self.DebugFile, 'a', encoding='utf-8') as f: print(*args, file=f, **kwargs) - def HandleExpr(self, Node, UseSingleQuote=False, VarType=None): + def HandleExpr(self, Node: ast.AST, UseSingleQuote: bool = False, VarType: ir.Type | None = None) -> Any: return self.ExprHandler.HandleExpr(Node, UseSingleQuote, VarType) diff --git a/lib/core/Translator/ConstEval.py b/lib/core/Translator/ConstEval.py index 0cad71e..034d398 100644 --- a/lib/core/Translator/ConstEval.py +++ b/lib/core/Translator/ConstEval.py @@ -1,8 +1,14 @@ from __future__ import annotations import ast +from typing import Any, TYPE_CHECKING import llvmlite.ir as ir +from lib.core.ConstEvaluator import ConstEvaluator + +if TYPE_CHECKING: + from lib.core.LlvmCodeGenerator import LlvmCodeGenerator + class ConstEvalMixin: """常量表达式求值 Mixin @@ -10,17 +16,27 @@ class ConstEvalMixin: 提供数组初始化常量构建与常量表达式求值能力。 """ - def _BuildArrayInitConstants(self, value_node, ElemType, elem_type_node, ArrayCount, Gen): - from lib.core.Handles.HandlesAssign import AssignHandle - _zv = AssignHandle._zero_value(ElemType) - _fallback = _zv if _zv is not None else ir.Constant(ElemType, ir.Undefined) + @staticmethod + def _bswap_constant_value(val: int, width: int) -> int: + """编译期字节序交换""" + if width == 16: + return ((val & 0xFF) << 8) | ((val >> 8) & 0xFF) + elif width == 32: + return ((val & 0xFF) << 24) | ((val & 0xFF00) << 8) | ((val >> 8) & 0xFF00) | ((val >> 24) & 0xFF) + elif width == 64: + return ((val & 0xFF) << 56) | ((val & 0xFF00) << 40) | ((val & 0xFF0000) << 24) | ((val & 0xFF000000) << 8) | ((val >> 8) & 0xFF000000) | ((val >> 24) & 0xFF0000) | ((val >> 40) & 0xFF00) | ((val >> 56) & 0xFF) + return val + + def _BuildArrayInitConstants(self, value_node: ast.AST, ElemType: ir.Type, elem_type_node: ast.AST, ArrayCount: int, Gen: LlvmCodeGenerator, byte_order: str = '') -> list[ir.Constant] | None: + _zv: ir.Constant | None = Gen._zero_value_for_type(ElemType) + _fallback: ir.Constant = _zv if _zv is not None else ir.Constant(ElemType, ir.Undefined) if not isinstance(value_node, (ast.List, ast.Set)): return None if isinstance(ElemType, ir.ArrayType): - constants = [] + constants: list[ir.Constant] = [] for elt in value_node.elts: if isinstance(elt, (ast.List, ast.Set)): - inner_consts = self._BuildMultiDimArrayInitConstants(elt, ElemType, Gen) + inner_consts: list[ir.Constant] | None = self._BuildMultiDimArrayInitConstants(elt, ElemType, Gen) if inner_consts: try: constants.append(ir.Constant(ElemType, inner_consts)) @@ -33,25 +49,33 @@ class ConstEvalMixin: while len(constants) < ArrayCount: constants.append(_fallback) return constants[:ArrayCount] - StructName = None + StructName: str | None = None if isinstance(elem_type_node, ast.Name) and elem_type_node.id in Gen.structs: StructName = elem_type_node.id constants = [] for elt in value_node.elts: if StructName and isinstance(elt, ast.Call) and isinstance(elt.func, ast.Name) and elt.func.id == StructName: - const = self.ClassHandler._BuildStructConstant(elt, StructName, Gen) + const: ir.Constant | None = self.ClassHandler._BuildStructConstant(elt, StructName, Gen) if const: constants.append(const) else: constants.append(_fallback) elif isinstance(elt, ast.Constant): - const = self.ClassHandler._BuildScalarConstant(elt, ElemType) - if const: - constants.append(const) + # 字符串常量:根据引号类型决定 i8 或 i8* + if isinstance(elt.value, str): + const: ir.Constant | None = self._BuildStringLiteralConstant(elt, ElemType, Gen) + if const: + constants.append(const) + else: + constants.append(_fallback) else: - constants.append(_fallback) + const = self._BuildScalarConstantUnified(elt, ElemType, Gen) + if const: + constants.append(const) + else: + constants.append(_fallback) elif isinstance(elt, ast.UnaryOp): - const = self.ClassHandler._BuildScalarConstant(elt, ElemType) + const = self._BuildScalarConstantUnified(elt, ElemType, Gen) if const: constants.append(const) else: @@ -73,7 +97,7 @@ class ConstEvalMixin: else: constants.append(_fallback) else: - const_val = self._try_eval_const_call(elt, Gen) + const_val: int | float | str | None = self._try_eval_const_call(elt, Gen) if const_val is not None: try: constants.append(ir.Constant(ElemType, const_val)) @@ -83,24 +107,155 @@ class ConstEvalMixin: constants.append(_fallback) while len(constants) < ArrayCount: constants.append(_fallback) + if byte_order == 'big' and isinstance(ElemType, ir.IntType) and ElemType.width in (16, 32, 64): + swapped: list[ir.Constant] = [] + for c in constants: + if isinstance(c, ir.Constant) and isinstance(c.type, ir.IntType) and isinstance(c.constant, int): + swapped_val: int = self._bswap_constant_value(int(c.constant), ElemType.width) + swapped.append(ir.Constant(ElemType, swapped_val)) + else: + swapped.append(c) + constants = swapped return constants[:ArrayCount] - def _try_eval_const_call(self, node, Gen): - import ast + def _BuildStringLiteralConstant(self, node: ast.Constant, target_type: ir.Type, Gen: LlvmCodeGenerator) -> ir.Constant | None: + """根据引号类型决定字符串常量的类型: + + - 单引号单字符 → i8 (char 值) + - 双引号/单引号多字符/三重引号 → i8* (C 字符串指针) + - 空字符串 → 0 (None),传入 ptr 目标自动隐式转换 + """ + if not isinstance(node.value, str): + return None + s: str = node.value + # 空字符串 → 0 (None) + if len(s) == 0: + try: + return ir.Constant(target_type, 0) + except Exception: + return None + # 获取源代码以判断引号类型 + quote_char: str | None = None + is_triple: bool = False + col_offset: int = getattr(node, 'col_offset', 0) + node_lineno: int = getattr(node, 'lineno', 0) + # AST 的 lineno 可能不准确(常量节点可能指向下一行), + # 因此在 lineno 和 lineno-1 两行中查找引号 + for try_lineno in (node_lineno, node_lineno - 1): + source_line: str | None = Gen._get_source_line(try_lineno) + if source_line and col_offset < len(source_line): + ch: str = source_line[col_offset] + if ch in ("'", '"'): + quote_char = ch + if col_offset + 2 < len(source_line) and source_line[col_offset:col_offset + 3] in ("'''", '"""'): + is_triple = True + break + # 判断是否为 char (i8):单引号、非三重、单字符 + is_char: bool = (not is_triple) and (quote_char == "'") and (len(s) == 1) + if is_char: + # 单引号单字符 → i8 + if isinstance(target_type, ir.IntType): + try: + return ir.Constant(target_type, ord(s)) + except Exception: + return None + # 目标类型不是整数 → 类型不匹配 + return None + else: + # 双引号/多字符/三重 → i8* (C 字符串) + if isinstance(target_type, ir.PointerType): + str_val: str = s + '\x00' + str_bytes: bytes = str_val.encode('utf-8') + arr_type: ir.ArrayType = ir.ArrayType(ir.IntType(8), len(str_bytes)) + gv_name: str = f"str_const_{id(node)}" + gv: ir.GlobalVariable = ir.GlobalVariable(Gen.module, arr_type, name=gv_name) + gv.initializer = ir.Constant(arr_type, bytearray(str_bytes)) + gv.linkage = 'internal' + return ir.Constant(target_type, gv.get_reference()) + # 目标类型不是指针 → 类型不匹配 + return None + + def _BuildScalarConstantUnified(self, node: ast.AST, target_type: ir.Type, Gen: LlvmCodeGenerator) -> ir.Constant | None: + """统一的标量常量构建方法。 + + 合并原 HandlesClassDef._BuildScalarConstant 与 HandlesImports._BuildScalarConstant 的特性: + - 支持 bool/int/float/str/ast.UnaryOp(USub)/ast.Name(True/False) + - 字符串处理委托给 _BuildStringLiteralConstant + - 显式拒绝 BaseStructType + - 全部 try/except 保护 + """ + # 显式拒绝结构体类型 + if isinstance(target_type, ir.BaseStructType): + return None + # 处理常量节点 + if isinstance(node, ast.Constant): + # bool 必须在 int 之前判断(bool 是 int 的子类) + if isinstance(node.value, bool): + try: + return ir.Constant(target_type, 1 if node.value else 0) + except Exception: + return None + elif isinstance(node.value, int): + try: + return ir.Constant(target_type, node.value) + except Exception: + return None + elif isinstance(node.value, float): + try: + return ir.Constant(target_type, node.value) + except Exception: + return None + elif isinstance(node.value, str): + # 字符串处理委托给 _BuildStringLiteralConstant + const: ir.Constant | None = self._BuildStringLiteralConstant(node, target_type, Gen) + if const is not None: + return const + # 回退:直接创建字符串全局变量(i8*) + try: + return Gen._create_string_global(node.value) + except Exception: + return None + # 处理一元负号 + elif isinstance(node, ast.UnaryOp) and isinstance(node.op, ast.USub): + if isinstance(node.operand, ast.Constant) and isinstance(node.operand.value, int): + try: + return ir.Constant(target_type, -node.operand.value) + except Exception: + return None + # 处理 True/False 名称节点 + elif isinstance(node, ast.Name): + if node.id == 'True': + try: + return ir.Constant(target_type, 1) + except Exception: + return None + elif node.id == 'False': + try: + if isinstance(target_type, ir.PointerType): + return ir.Constant(target_type, None) + return ir.Constant(target_type, 0) + except Exception: + return None + return None + + def _try_eval_const_call(self, node: ast.AST, Gen: LlvmCodeGenerator) -> int | None: if isinstance(node, ast.Call): - func_name = None + func_name: str | None = None if isinstance(node.func, ast.Name): func_name = node.func.id elif isinstance(node.func, ast.Attribute): func_name = node.func.attr if func_name: - arg_vals = [] + arg_vals: list[int | float | str | None] = [] for arg in node.args: - v = self._try_eval_const_expr(arg, Gen) + v: int | float | str | None = self._try_eval_const_expr(arg, Gen) if v is None: return None arg_vals.append(v) if func_name == 'COLOR_RGB' and len(arg_vals) == 3: + r: int | float | str | None + g: int | float | str | None + b: int | float | str | None r, g, b = arg_vals return (255 << 24) | (int(b) << 16) | (int(g) << 8) | int(r) if func_name in Gen._DefineConstants: @@ -111,22 +266,20 @@ class ConstEvalMixin: return None return self._try_eval_const_expr(node, Gen) - def _try_eval_const_expr(self, node, Gen): - from lib.core.ConstEvaluator import ConstEvaluator + def _try_eval_const_expr(self, node: ast.AST, Gen: LlvmCodeGenerator) -> int | float | str | None: return ConstEvaluator.eval_with_symtab(node, self.SymbolTable) - def _BuildMultiDimArrayInitConstants(self, value_node, ArrayType, Gen): - from lib.core.Handles.HandlesAssign import AssignHandle - inner_type = ArrayType.element - count = ArrayType.count - elts = list(value_node.elts) if hasattr(value_node, 'elts') else [] - _zv = AssignHandle._zero_value(inner_type) - _fallback = _zv if _zv is not None else ir.Constant(inner_type, ir.Undefined) - constants = [] + def _BuildMultiDimArrayInitConstants(self, value_node: ast.AST, ArrayType: ir.ArrayType, Gen: LlvmCodeGenerator) -> list[ir.Constant] | None: + inner_type: ir.Type = ArrayType.element + count: int = ArrayType.count + elts: list[ast.AST] = list(value_node.elts) if hasattr(value_node, 'elts') else [] + _zv: ir.Constant | None = Gen._zero_value_for_type(inner_type) + _fallback: ir.Constant = _zv if _zv is not None else ir.Constant(inner_type, ir.Undefined) + constants: list[ir.Constant] = [] for elt in elts: if isinstance(inner_type, ir.ArrayType): if isinstance(elt, (ast.List, ast.Set)): - inner_consts = self._BuildMultiDimArrayInitConstants(elt, inner_type, Gen) + inner_consts: list[ir.Constant] | None = self._BuildMultiDimArrayInitConstants(elt, inner_type, Gen) if inner_consts: constants.append(ir.Constant(inner_type, inner_consts)) else: @@ -134,13 +287,13 @@ class ConstEvalMixin: else: constants.append(_fallback) elif isinstance(elt, ast.Constant): - const = self.ClassHandler._BuildScalarConstant(elt, inner_type) + const: ir.Constant | None = self._BuildScalarConstantUnified(elt, inner_type, Gen) if const: constants.append(const) else: constants.append(_fallback) elif isinstance(elt, ast.UnaryOp): - const = self.ClassHandler._BuildScalarConstant(elt, inner_type) + const = self._BuildScalarConstantUnified(elt, inner_type, Gen) if const: constants.append(const) else: diff --git a/lib/core/Translator/LlvmGenerator.py b/lib/core/Translator/LlvmGenerator.py index f3e18d2..14b8a2f 100644 --- a/lib/core/Translator/LlvmGenerator.py +++ b/lib/core/Translator/LlvmGenerator.py @@ -3,13 +3,18 @@ from __future__ import annotations import ast import os import re +from typing import Any import llvmlite.ir as ir from lib.core.LlvmCodeGenerator import LlvmCodeGenerator from lib.core.Handles.HandlesBase import CTypeInfo +from lib.core.Handles.HandlesBase import CTypeInfo as _CTypeInfo, CTypeHelper from lib.includes import t from lib.constants.config import mode as _config_mode +from lib.core.VLogger import get_logger as _vlog +from lib.core.DecoratorPass import run as _run_decorator_pass from lib.core.Translator.BaseTranslator import _StrictLog +from lib.core.SymbolUtils import IsTModule, AnnotationContainsName class LlvmGeneratorMixin: @@ -18,8 +23,25 @@ class LlvmGeneratorMixin: 提供 LLVM IR 直接生成、模块级 LLVM IR 处理与 C 代码生成入口能力。 """ - def GenerateLlvmDirect(self, Tree): - Gen = self.LlvmGen + def GenerateLlvmDirect(self, Tree: ast.Module) -> str: + Gen: LlvmCodeGenerator = self.LlvmGen + + # === 新增:轻量 AST 遍历,收集类图信息,解决前向引用 === + Gen._class_graph: dict[str, dict[str, bool | list[str]]] = {} + for Node in ast.iter_child_nodes(Tree): + if isinstance(Node, ast.ClassDef): + bases: list[str] = [] + for base in Node.bases: + if hasattr(base, 'id'): + bases.append(base.id) + elif hasattr(base, 'attr'): + bases.append(base.attr) + has_methods: bool = any(isinstance(item, ast.FunctionDef) for item in Node.body) + Gen._class_graph[Node.name] = { + 'bases': bases, + 'has_methods': has_methods, + } + # === 结束新增 === # 预扫描:为所有 -> str 注解的函数注册正确的返回类型 i8* # 这样在类方法中调用这些函数时,前向声明会使用正确的类型 @@ -29,7 +51,7 @@ class LlvmGeneratorMixin: Gen.known_return_types[Node.name] = ir.PointerType(ir.IntType(8)) # 首先收集所有 CDefine 常量,确保类定义中可以引用 - def _extract_call_const_val(node): + def _extract_call_const_val(node: ast.AST) -> int | str | float | None: if isinstance(node, ast.Call): if isinstance(node.func, ast.Attribute): if getattr(node.func.value, 'id', None) == 't': @@ -42,48 +64,44 @@ class LlvmGeneratorMixin: for Node in ast.iter_child_nodes(Tree): if isinstance(Node, ast.AnnAssign) and isinstance(Node.target, ast.Name) and Node.value: - TypeInfo = self.TypeMergeHandler.GetCTypeInfo(Node.annotation) - if TypeInfo and TypeInfo.BaseType and hasattr(TypeInfo.BaseType, 'CName') and TypeInfo.BaseType.CName == '#define': - val = None + TypeInfo: CTypeInfo | None = self.TypeMergeHandler.GetCTypeInfo(Node.annotation) + if TypeInfo and TypeInfo.BaseType and ((isinstance(TypeInfo.BaseType, type) and issubclass(TypeInfo.BaseType, t.CDefine)) or isinstance(TypeInfo.BaseType, t.CDefine)): + val: int | str | float | None = None if isinstance(Node.value, ast.Constant): val = Node.value.value else: val = _extract_call_const_val(Node.value) if val is not None: if not hasattr(Gen, '_define_constants'): - Gen._define_constants = {} + Gen._define_constants: dict[str, int | str | float | bool] = {} Gen._define_constants[Node.target.id] = val - from lib.core.Handles.HandlesBase import CTypeInfo as _CTypeInfo - sym_info = _CTypeInfo() + sym_info: _CTypeInfo = _CTypeInfo() sym_info.IsDefine = True sym_info.DefineValue = val self.SymbolTable.insert(Node.target.id, sym_info) elif isinstance(Node, ast.Assign): for target in Node.targets: if isinstance(target, ast.Name): - TypeInfo = None + TypeInfo: CTypeInfo | None = None if Node.type_comment: try: - tc_ast = ast.parse(Node.type_comment, mode='eval') + tc_ast: ast.Expression = ast.parse(Node.type_comment, mode='eval') TypeInfo = self.TypeMergeHandler.GetCTypeInfo(tc_ast.body) except Exception as _e: - from lib.core.VLogger import get_logger as _vlog - from lib.constants.config import mode as _config_mode if _config_mode == "strict": raise _vlog().warning(f"解析类型注释失败: {_e}", "Exception") - if TypeInfo and TypeInfo.BaseType and hasattr(TypeInfo.BaseType, 'CName') and TypeInfo.BaseType.CName == '#define': - val = None + if TypeInfo and TypeInfo.BaseType and ((isinstance(TypeInfo.BaseType, type) and issubclass(TypeInfo.BaseType, t.CDefine)) or isinstance(TypeInfo.BaseType, t.CDefine)): + val: int | str | float | None = None if isinstance(Node.value, ast.Constant): val = Node.value.value else: val = _extract_call_const_val(Node.value) if val is not None: if not hasattr(Gen, '_define_constants'): - Gen._define_constants = {} + Gen._define_constants: dict[str, int | str | float | bool] = {} Gen._define_constants[target.id] = val - from lib.core.Handles.HandlesBase import CTypeInfo as _CTypeInfo - sym_info = _CTypeInfo() + sym_info: _CTypeInfo = _CTypeInfo() sym_info.IsDefine = True sym_info.DefineValue = val self.SymbolTable.insert(target.id, sym_info) @@ -92,7 +110,7 @@ class LlvmGeneratorMixin: # 这样类方法编译时遇到未声明的函数可以按需前向声明 for Node in ast.iter_child_nodes(Tree): if isinstance(Node, ast.FunctionDef): - FuncName = Node.name + FuncName: str = Node.name if FuncName not in self.FunctionDefCache: self.FunctionDefCache[FuncName] = Node @@ -105,17 +123,17 @@ class LlvmGeneratorMixin: elif isinstance(Node, ast.ImportFrom): self.ImportHandler._EmitImportFromDeclarationsLlvm(Node, Gen) except Exception as e: - lineno = getattr(Node, 'lineno', 0) - source_line = Gen._get_source_line(lineno) - src_file = getattr(Gen, '_current_source_file', '') - src_path = src_file if src_file else 'unknown' - line_info = "源代码 (%s, line %d)" % (src_path, lineno) + lineno: int = getattr(Node, 'lineno', 0) + source_line: str | None = Gen._get_source_line(lineno) + src_file: str = getattr(Gen, '_current_source_file', '') + src_path: str = src_file if src_file else 'unknown' + line_info: str = "源代码 (%s, line %d)" % (src_path, lineno) if source_line: line_info += ":\n %d | %s" % (lineno, source_line) self._ErrorStack.append((type(e).__name__, str(e), line_info)) # 预创建全局变量(带初始化器),确保类方法编译时能引用全局数组等 - Gen._current_tree = Tree + Gen._current_tree: ast.Module = Tree for Node in ast.iter_child_nodes(Tree): if isinstance(Node, ast.AnnAssign): self.AssignHandler._EmitGlobalAnnAssignLlvm(Node, Gen) @@ -155,42 +173,41 @@ class LlvmGeneratorMixin: elif isinstance(Node, ast.Expr): self._HandleModuleLevelExprLlvm(Node, Gen) except Exception as e: - lineno = getattr(Node, 'lineno', 0) - source_line = Gen._get_source_line(lineno) - src_file = getattr(Gen, '_current_source_file', '') - src_path = src_file if src_file else 'unknown' - line_info = "源代码 (%s, line %d)" % (src_path, lineno) + lineno: int = getattr(Node, 'lineno', 0) + source_line: str | None = Gen._get_source_line(lineno) + src_file: str = getattr(Gen, '_current_source_file', '') + src_path: str = src_file if src_file else 'unknown' + line_info: str = "源代码 (%s, line %d)" % (src_path, lineno) if source_line: line_info += ":\n %d | %s" % (lineno, source_line) self._ErrorStack.append((type(e).__name__, str(e), line_info)) raise Gen._set_Vtable_initializers() # 执行 DecoratorPass:为带自定义装饰器的函数生成 wrapper - from lib.core.DecoratorPass import run as _run_decorator_pass _run_decorator_pass(Gen) - ir_code = Gen.finalize() + ir_code: str = Gen.finalize() return ir_code - def _HandleModuleLevelExprLlvm(self, Node, Gen): + def _HandleModuleLevelExprLlvm(self, Node: ast.Expr, Gen: LlvmCodeGenerator) -> None: if not isinstance(Node.value, ast.Call): return - call = Node.value + call: ast.Call = Node.value if not isinstance(call.func, ast.Attribute): return if not isinstance(call.func.value, ast.Name) or call.func.value.id != 'c': return - func_name = call.func.attr + func_name: str = call.func.attr if func_name == 'LLVMIR': self._HandleModuleLevelLLVMIR(call, Gen) - def _HandleModuleLevelLLVMIR(self, Node, Gen): + def _HandleModuleLevelLLVMIR(self, Node: ast.Call, Gen: LlvmCodeGenerator) -> None: if not Node.args: return - first_arg = Node.args[0] + first_arg: ast.expr = Node.args[0] if isinstance(first_arg, ast.Constant) and isinstance(first_arg.value, str): - ir_text = first_arg.value + ir_text: str = first_arg.value elif isinstance(first_arg, ast.JoinedStr): - parts = [] + parts: list[str] = [] for value in first_arg.values: if isinstance(value, ast.Constant) and isinstance(value.value, str): parts.append(value.value) @@ -201,79 +218,78 @@ class LlvmGeneratorMixin: return self._InsertModuleLevelLLVMIR(Gen, ir_text) - def _InsertModuleLevelLLVMIR(self, Gen, ir_text): - import re + def _InsertModuleLevelLLVMIR(self, Gen: LlvmCodeGenerator, ir_text: str) -> None: for line in ir_text.strip().split('\n'): line = line.strip() if not line: continue - module_flags_match = re.match(r'!llvm\.module\.flags\s*=\s*!\{(!\d+)\}', line) + module_flags_match: re.Match[str] | None = re.match(r'!llvm\.module\.flags\s*=\s*!\{(!\d+)\}', line) if module_flags_match: - ref = module_flags_match.group(1) + ref: str = module_flags_match.group(1) if not hasattr(Gen, '_pending_module_flags'): - Gen._pending_module_flags = [] - Gen._pending_module_flags_refs = ref + Gen._pending_module_flags: list = [] + Gen._pending_module_flags_refs: str = ref continue - metadata_match = re.match(r'(!\d+)\s*=\s*!\{(.+)\}', line) + metadata_match: re.Match[str] | None = re.match(r'(!\d+)\s*=\s*!\{(.+)\}', line) if metadata_match: - md_id = metadata_match.group(1) - md_body = metadata_match.group(2) - fields = [] + md_id: str = metadata_match.group(1) + md_body: str = metadata_match.group(2) + fields: list[ir.Constant | ir.MetaDataString | str] = [] for field_str in re.split(r',\s*', md_body): field_str = field_str.strip() if not field_str: continue - int_m = re.match(r'^i32\s+(\d+)$', field_str) + int_m: re.Match[str] | None = re.match(r'^i32\s+(\d+)$', field_str) if int_m: fields.append(ir.Constant(ir.IntType(32), int(int_m.group(1)))) continue - str_m = re.match(r'^"([^"]*)"$', field_str) + str_m: re.Match[str] | None = re.match(r'^"([^"]*)"$', field_str) if str_m: fields.append(ir.MetaDataString(Gen.module, str_m.group(1))) continue - mdstr_m = re.match(r'^!"([^"]*)"$', field_str) + mdstr_m: re.Match[str] | None = re.match(r'^!"([^"]*)"$', field_str) if mdstr_m: fields.append(ir.MetaDataString(Gen.module, mdstr_m.group(1))) continue - int_m2 = re.match(r'^(\d+)$', field_str) + int_m2: re.Match[str] | None = re.match(r'^(\d+)$', field_str) if int_m2: fields.append(ir.Constant(ir.IntType(32), int(int_m2.group(1)))) continue - ref_m = re.match(r'^(!\d+)$', field_str) + ref_m: re.Match[str] | None = re.match(r'^(!\d+)$', field_str) if ref_m: fields.append(ref_m.group(1)) continue if fields: if not hasattr(Gen, '_pending_metadata'): - Gen._pending_metadata = [] + Gen._pending_metadata: list[tuple[str, list]] = [] Gen._pending_metadata.append((md_id, fields)) continue self._FlushModuleMetadata(Gen) - def _FlushModuleMetadata(self, Gen): + def _FlushModuleMetadata(self, Gen: LlvmCodeGenerator) -> None: if not hasattr(Gen, '_pending_metadata') or not Gen._pending_metadata: return - md_map = {} + md_map: dict[str, ir.MetaDataString] = {} for md_id, fields in Gen._pending_metadata: - resolved = [] + resolved: list[ir.Constant | ir.MetaDataString] = [] for f in fields: if isinstance(f, str) and f.startswith('!'): - ref = md_map.get(f) + ref: ir.MetaDataString | None = md_map.get(f) if ref: resolved.append(ref) else: resolved.append(f) - md_value = Gen.module.add_metadata(resolved) + md_value: ir.MetaDataString = Gen.module.add_metadata(resolved) md_map[md_id] = md_value if hasattr(Gen, '_pending_module_flags_refs'): - ref = Gen._pending_module_flags_refs - md_node = md_map.get(ref) + ref: str = Gen._pending_module_flags_refs + md_node: ir.MetaDataString | None = md_map.get(ref) if md_node: Gen.module.add_named_metadata('llvm.module.flags', md_node) Gen._pending_metadata = [] Gen._pending_module_flags_refs = None - def GenerateCCode(self, Tree, target='llvm'): + def GenerateCCode(self, Tree: ast.Module, target: str = 'llvm') -> str: """生成代码 Args: @@ -283,23 +299,23 @@ class LlvmGeneratorMixin: Returns: 生成的代码字符串 """ - self._generated_vars = set() + self._generated_vars: set[str] = set() self.VarScopes = [{}] # 全局作用域 # 预扫描 import 语句,注册别名,确保类型解析时能正确解析模块别名 if not getattr(self, '_ImportedModules', None): - self._ImportedModules = set() + self._ImportedModules: set[str] = set() for Node in ast.iter_child_nodes(Tree): if isinstance(Node, ast.Import): for alias in Node.names: - name = alias.name + name: str = alias.name if name in ('c', 't'): continue self._ImportedModules.add(name) if alias.asname: self.SymbolTable.import_aliases[alias.asname] = name elif isinstance(Node, ast.ImportFrom): - module_name = Node.module + module_name: str | None = Node.module if module_name and module_name not in ('c', 't'): self._ImportedModules.add(module_name) for alias in Node.names: @@ -308,10 +324,10 @@ class LlvmGeneratorMixin: for Node in ast.iter_child_nodes(Tree): if isinstance(Node, ast.ClassDef): - ClassName = Node.name + ClassName: str = Node.name # 检查是否是特殊类型(枚举或联合体) - IsSpecialType = False + IsSpecialType: bool = False if Node.bases: for base in Node.bases: if hasattr(base, 'attr'): @@ -327,13 +343,13 @@ class LlvmGeneratorMixin: if IsSpecialType: continue - members = {} - IsTypedef = False - TypedefName = None + members: dict[str, CTypeInfo] = {} + IsTypedef: bool = False + TypedefName: str | None = None if hasattr(Node, 'annotation') and Node.annotation: try: - AnnotationStr = ast.dump(Node.annotation) + AnnotationStr: str = ast.dump(Node.annotation) if 'CTypedef' in AnnotationStr: IsTypedef = True if isinstance(Node.annotation, ast.Call): @@ -341,8 +357,6 @@ class LlvmGeneratorMixin: if isinstance(Node.annotation.args[0], ast.Constant): TypedefName = Node.annotation.args[0].value except Exception as _e: - from lib.core.VLogger import get_logger as _vlog - from lib.constants.config import mode as _config_mode if _config_mode == "strict": raise _vlog().warning(f"解析 typedef 注解失败: {_e}", "Exception") @@ -355,7 +369,7 @@ class LlvmGeneratorMixin: if isinstance(item.value, ast.Dict): for key, value in zip(item.value.keys, item.value.values): if isinstance(key, ast.Constant) and key.value == '__type__': - value_str = ast.dump(value) + value_str: str = ast.dump(value) if 'CTypedef' in value_str: IsTypedef = True if isinstance(value, ast.Call): @@ -364,8 +378,8 @@ class LlvmGeneratorMixin: TypedefName = value.args[0].value if IsTypedef: - TypedefKey = TypedefName if TypedefName else ClassName - TypedefNode = CTypeInfo() + TypedefKey: str = TypedefName if TypedefName else ClassName + TypedefNode: CTypeInfo = CTypeInfo() TypedefNode.Name = TypedefKey TypedefNode.IsTypedef = True TypedefNode.OriginalType = f'struct {ClassName}' @@ -375,80 +389,79 @@ class LlvmGeneratorMixin: for item in Node.body: if isinstance(item, ast.AnnAssign) and isinstance(item.target, ast.Name): - VarName = item.target.id + VarName: str = item.target.id try: - TypeInfo = self.TypeMergeHandler.GetCTypeInfo(item.annotation) + TypeInfo: CTypeInfo | None = self.TypeMergeHandler.GetCTypeInfo(item.annotation) if TypeInfo is None: TypeInfo = CTypeInfo() TypeInfo.BaseType = t.CInt() - IsPtr = TypeInfo.IsPtr + IsPtr: bool = TypeInfo.IsPtr if not IsPtr: if isinstance(item.annotation, ast.BinOp) and isinstance(item.annotation.op, ast.BitOr): - LeftStr = ast.dump(item.annotation.left) - RightStr = ast.dump(item.annotation.right) - if 'CPtr' in LeftStr or 'CPtr' in RightStr: + if AnnotationContainsName(item.annotation, 'CPtr'): IsPtr = True - dims = [] + dims: list[int] = [] if hasattr(item.annotation, 'slice') and isinstance(item.annotation.slice, ast.Constant): if isinstance(item.annotation.value, ast.Name): - if item.annotation.value.id == 't': + if IsTModule(item.annotation.value.id, self.SymbolTable): if hasattr(item.annotation, 'slice'): try: dims.append(int(item.annotation.slice.value)) except Exception as _e: - if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": + if _config_mode == "strict": self.LogWarning(f"异常被忽略: {_e}") - MemberInfo = TypeInfo.Copy() + MemberInfo: CTypeInfo = TypeInfo.Copy() if dims: MemberInfo.ArrayDims = [str(d) for d in dims] members[VarName] = MemberInfo except Exception as _e: - if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": + if _config_mode == "strict": self.LogWarning(f"异常被忽略: {_e}") if not IsTypedef: - StructNode = CTypeInfo() + StructNode: CTypeInfo = CTypeInfo() StructNode.Name = ClassName StructNode.IsStruct = True StructNode.Members = members or {} StructNode.file = '' - if self.SymbolTable.has(ClassName): - existing = self.SymbolTable[ClassName] + existing: CTypeInfo | None = self.SymbolTable.lookup(ClassName) + if existing: if hasattr(existing, 'IsCpythonObject') and existing.IsCpythonObject: StructNode.IsCpythonObject = True self.SymbolTable.insert(ClassName, StructNode) elif isinstance(Node, ast.FunctionDef): - FuncName = Node.name - FuncNode = CTypeInfo() - FuncNode.Name = FuncName - FuncNode.IsFunction = True - FuncNode.file = '' - self.SymbolTable.insert(FuncName, FuncNode) + FuncName: str = Node.name + if not self.SymbolTable.has(FuncName): + FuncNode: CTypeInfo = CTypeInfo() + FuncNode.Name = FuncName + FuncNode.IsFunction = True + FuncNode.file = '' + self.SymbolTable.insert(FuncName, FuncNode) elif isinstance(Node, ast.AnnAssign): if isinstance(Node.target, ast.Name): - VarName = Node.target.id + VarName: str = Node.target.id - VarType = 'unknown' - IsPtr = False - IsTypedef_assignment = False + VarType: str = 'unknown' + IsPtr: bool = False + IsTypedef_assignment: bool = False if Node.annotation: try: - AnnotationStr = ast.dump(Node.annotation) + AnnotationStr: str = ast.dump(Node.annotation) if 'CTypedef' in AnnotationStr: IsTypedef_assignment = True except Exception as _e: - if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": + if _config_mode == "strict": self.LogWarning(f"异常被忽略: {_e}") if IsTypedef_assignment and Node.value: if isinstance(Node.value, ast.Name): - OriginalType = Node.value.id + OriginalType: str = Node.value.id if OriginalType in self.GeneratedTypes: - if self.SymbolTable.has(OriginalType): - OriginalInfo = self.SymbolTable[OriginalType] + OriginalInfo: CTypeInfo | None = self.SymbolTable.lookup(OriginalType) + if OriginalInfo: if isinstance(OriginalInfo, dict): - actual_type = OriginalInfo.get('type', 'struct') + actual_type: str = OriginalInfo.get('type', 'struct') elif isinstance(OriginalInfo, CTypeInfo): if OriginalInfo.IsEnum: actual_type = 'enum' @@ -461,7 +474,7 @@ class LlvmGeneratorMixin: else: actual_type = 'struct' if actual_type == 'enum': - TypedefNode = CTypeInfo() + TypedefNode: CTypeInfo = CTypeInfo() TypedefNode.Name = VarName TypedefNode.IsTypedef = True TypedefNode.OriginalType = f'enum {OriginalType}' @@ -491,10 +504,10 @@ class LlvmGeneratorMixin: self.GeneratedTypes.add(VarName) continue else: - if self.SymbolTable.has(OriginalType): - OriginalInfo = self.SymbolTable[OriginalType] + OriginalInfo: CTypeInfo | None = self.SymbolTable.lookup(OriginalType) + if OriginalInfo: if isinstance(OriginalInfo, dict): - actual_type = OriginalInfo.get('type', 'struct') + actual_type: str = OriginalInfo.get('type', 'struct') elif isinstance(OriginalInfo, CTypeInfo): if OriginalInfo.IsEnum: actual_type = 'enum' @@ -507,7 +520,7 @@ class LlvmGeneratorMixin: else: actual_type = 'struct' if actual_type == 'typedef': - TypedefNode = CTypeInfo() + TypedefNode: CTypeInfo = CTypeInfo() TypedefNode.Name = VarName TypedefNode.IsTypedef = True if isinstance(OriginalInfo, dict): @@ -548,10 +561,9 @@ class LlvmGeneratorMixin: OriginalInfo['skip_generation'] = True continue elif isinstance(Node.value, ast.Attribute): - from lib.core.Handles.HandlesBase import CTypeHelper - CName = CTypeHelper.GetCName(Node.value.attr) + CName: str | None = CTypeHelper.GetCName(Node.value.attr) if CName: - TypedefNode = CTypeInfo() + TypedefNode: CTypeInfo = CTypeInfo() TypedefNode.Name = VarName TypedefNode.IsTypedef = True TypedefNode.OriginalType = CName @@ -562,19 +574,19 @@ class LlvmGeneratorMixin: if Node.annotation: try: - TypeInfo = self.TypeMergeHandler.GetCTypeInfo(Node.annotation) + TypeInfo: CTypeInfo | None = self.TypeMergeHandler.GetCTypeInfo(Node.annotation) IsPtr = TypeInfo.IsPtr if TypeInfo else False except Exception as _e: - if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": + if _config_mode == "strict": self.LogWarning(f"异常被忽略: {_e}") - var_node = CTypeInfo() + var_node: CTypeInfo = CTypeInfo() var_node.Name = VarName var_node.IsVariable = True var_node.PtrCount = 1 if IsPtr else 0 var_node.file = '' self.SymbolTable.insert(VarName, var_node) - self.LlvmGen = LlvmCodeGenerator( + self.LlvmGen: LlvmCodeGenerator = LlvmCodeGenerator( triple=getattr(self, 'triple', None), datalayout=getattr(self, 'datalayout', None), ) diff --git a/lib/core/Translator/PythonParser.py b/lib/core/Translator/PythonParser.py index 5341732..53bc5ab 100644 --- a/lib/core/Translator/PythonParser.py +++ b/lib/core/Translator/PythonParser.py @@ -8,8 +8,10 @@ import struct from lib.utils.helpers import DetectFileType from lib.core.Handles.HandlesBase import CTypeInfo +from lib.core.SymbolUtils import IsTModule, AnnotationContainsName from lib.includes import t from lib.constants.config import mode as _ConfigMode +from lib.core.VLogger import get_logger as _vlog from lib.core.Translator.BaseTranslator import _StrictLog @@ -19,13 +21,13 @@ class PythonParserMixin: 提供辅助文件解析、symbin 文件加载与 Python 源文件解析能力。 """ - def ParseHelperFiles(self, HelperFiles, encoding='utf-8'): + def ParseHelperFiles(self, HelperFiles: list[str], encoding: str = 'utf-8') -> None: """解析辅助文件,提取符号信息 支持 .py, .c, .h 和 .symbin 文件 """ for FilePath in HelperFiles: - ext = DetectFileType(FilePath) + ext: str = DetectFileType(FilePath) if ext == '.py': self.ParsePythonFile(FilePath, encoding, UpdateCurrentFile=False) elif ext == '.c': @@ -33,7 +35,7 @@ class PythonParserMixin: elif FilePath.endswith('.symbin'): self.LoadSymbinFile(FilePath) - def LoadSymbinFile(self, FilePath): + def LoadSymbinFile(self, FilePath: str) -> None: """从.symbin文件加载符号表 Args: @@ -41,32 +43,27 @@ class PythonParserMixin: """ try: with open(FilePath, 'rb') as f: - data = f.read() + data: bytes = f.read() # 导入序列化函数(避免循环导入) - import sys - import os - import json - import struct - # 解析二进制格式 if len(data) < 4: - print(f"Warning: Invalid symbin file (too short): {FilePath}") + _vlog().warning(f"无效的 symbin 文件 (太短): {FilePath}") return # 解析4字节长度头(小端序) - length = struct.unpack(' None: """解析Python文件,提取类、函数、变量信息 Args: @@ -76,41 +73,41 @@ class PythonParserMixin: """ try: with open(FilePath, 'r', encoding=encoding) as f: - content = f.read() + content: str = f.read() # 保存当前处理的文件路径(仅在主文件处理时更新) if UpdateCurrentFile: self.CurrentFile = FilePath # 解析Python代码为AST - tree = ast.parse(content) + tree: ast.Module = ast.parse(content) # 保存 AST 树供后续使用 self.tree = tree # 第一遍:检测特殊赋值语句,收集跟在 class 后面的 # 遍历 tree.body,找到所有 ClassDef,然后收集紧随其后的赋值语句 - i = 0 + i: int = 0 while i < len(tree.body): - node = tree.body[i] + node: ast.stmt = tree.body[i] # 检测 ClassDef if isinstance(node, ast.ClassDef): - ClassName = node.name + ClassName: str = node.name # 使用类名_行号作为唯一 key - ClassKey = f"{ClassName}_{node.lineno}" + ClassKey: str = f"{ClassName}_{node.lineno}" # 检查后面的语句,收集特殊赋值 - j = i + 1 + j: int = i + 1 while j < len(tree.body): - NextNode = tree.body[j] + NextNode: ast.stmt = tree.body[j] if isinstance(NextNode, ast.Assign): # 检测 xxx = xxx 或 xxx = yyy if len(NextNode.targets) == 1 and isinstance(NextNode.targets[0], ast.Name): - TargetName = NextNode.targets[0].id + TargetName: str = NextNode.targets[0].id if isinstance(NextNode.value, ast.Name): - ValueName = NextNode.value.id + ValueName: str = NextNode.value.id if ValueName == ClassName: # 这是 class 的实例化 if ClassKey not in self.EmbeddedAssignments: @@ -121,23 +118,23 @@ class PythonParserMixin: elif isinstance(NextNode, ast.AnnAssign): # 检测 xxx: t.Postdefinition(yyy) 或 xxx: t.CTypedef = xxx 或 xxx: t.CPtr = xxx if isinstance(NextNode.target, ast.Name): - TargetName = NextNode.target.id + TargetName: str = NextNode.target.id # 先处理新格式:t.Postdefinition(...) - annotation = NextNode.annotation - original_AnnotationStr = ast.dump(NextNode.annotation) - PostdefNode = None + annotation: ast.expr | None = NextNode.annotation + original_AnnotationStr: str = ast.dump(NextNode.annotation) + PostdefNode: ast.Call | None = None # 递归搜索整个注解树,找到 t.Postdefinition(...) 调用 - def find_PostdefNode(node): + def find_PostdefNode(node: ast.AST) -> ast.Call | None: if isinstance(node, ast.Call): if isinstance(node.func, ast.Attribute): - if hasattr(node.func.value, 'id') and node.func.value.id == 't' and node.func.attr == 'Postdefinition': + if hasattr(node.func.value, 'id') and IsTModule(node.func.value.id, self.SymbolTable) and node.func.attr == 'Postdefinition': return node elif isinstance(node, ast.BinOp) and isinstance(node.op, ast.BitOr): - LeftResult = find_PostdefNode(node.left) + LeftResult: ast.Call | None = find_PostdefNode(node.left) if LeftResult: return LeftResult - RightResult = find_PostdefNode(node.right) + RightResult: ast.Call | None = find_PostdefNode(node.right) if RightResult: return RightResult return None @@ -148,25 +145,25 @@ class PythonParserMixin: if (isinstance(PostdefNode.func, ast.Attribute) and hasattr(PostdefNode.func, 'value') and hasattr(PostdefNode.func.value, 'id') and - PostdefNode.func.value.id == 't' and + IsTModule(PostdefNode.func.value.id, self.SymbolTable) and PostdefNode.func.attr == 'Postdefinition' and PostdefNode.args): # 检查第一个参数是否是当前类名 - arg = PostdefNode.args[0] + arg: ast.expr = PostdefNode.args[0] if isinstance(arg, ast.Name) and arg.id == ClassName: # 检查是否包含 CTypedef 或 CPtr - HasCtypedef = False - IsPtr = False + HasCtypedef: bool = False + IsPtr: bool = False if 'CTypedef' in original_AnnotationStr: HasCtypedef = True if 'CPtr' in original_AnnotationStr: IsPtr = True # 解析维度列表(第二个参数) - dimensions = [] + dimensions: list[ast.expr] = [] if len(PostdefNode.args) > 1: # 第二个参数应该是一个列表 - dim_arg = PostdefNode.args[1] + dim_arg: ast.expr = PostdefNode.args[1] if isinstance(dim_arg, ast.List): for DimExpr in dim_arg.elts: dimensions.append(DimExpr) @@ -174,9 +171,9 @@ class PythonParserMixin: # 如果没有从 Postdefinition 参数中获取维度,尝试从类型注解中的 Subscript 获取 # 例如:memory_block_t[MAX_ORDER + 1] | t.CPtr if not dimensions: - def extract_subscript_dims(node): + def extract_subscript_dims(node: ast.AST) -> list[ast.expr]: """递归提取 Subscript 节点的维度""" - dims = [] + dims: list[ast.expr] = [] if isinstance(node, ast.Subscript): # 提取当前维度 if isinstance(node.slice, ast.Constant): @@ -193,13 +190,13 @@ class PythonParserMixin: return dims # 从注解中提取维度 - subscript_dims = extract_subscript_dims(annotation) + subscript_dims: list[ast.expr] = extract_subscript_dims(annotation) if subscript_dims: # 反转维度顺序(从内到外) dimensions = list(reversed(subscript_dims)) # 获取赋值值 - value = None + value: ast.expr | None = None if hasattr(NextNode, 'value') and NextNode.value is not None: value = NextNode.value @@ -241,11 +238,11 @@ class PythonParserMixin: # 而应该生成独立的 typedef 语句,所以不添加到 TypedefAssignments elif NextNode.annotation and isinstance(NextNode.annotation, ast.Attribute): if isinstance(NextNode.annotation.value, ast.Name): - annot_id = NextNode.annotation.value.id - annot_attr = NextNode.annotation.attr + annot_id: str = NextNode.annotation.value.id + annot_attr: str = NextNode.annotation.attr if annot_id == 't' and NextNode.value: if isinstance(NextNode.value, ast.Name): - ValueName = NextNode.value.id + ValueName: str = NextNode.value.id if ValueName == ClassName: # 检查是 CTypedef 还是 CPtr if annot_attr == t.CPtr.__name__: @@ -267,15 +264,15 @@ class PythonParserMixin: # 提取类定义(作为结构体) for node in ast.walk(tree): if isinstance(node, ast.ClassDef): - ClassName = node.name + ClassName: str = node.name # 先把类名加入 GeneratedTypes,这样 GetTypeName 可以正确识别 self.GeneratedTypes.add(ClassName) # 检测是否是 CEnum - IsCenum = False + IsCenum: bool = False for base in node.bases: if isinstance(base, ast.Attribute): - BaseStr = ast.dump(base) + BaseStr: str = ast.dump(base) if 'CEnum' in BaseStr or 'REnum' in BaseStr: IsCenum = True break @@ -285,19 +282,19 @@ class PythonParserMixin: break # 检测是否有 @t.Object 装饰器或继承自 t.Object - IsCpythonObject = False + IsCpythonObject: bool = False if hasattr(node, 'decorator_list') and node.decorator_list: for decorator in node.decorator_list: if isinstance(decorator, ast.Attribute): if (hasattr(decorator.value, 'id') and - decorator.value.id == 't' and + IsTModule(decorator.value.id, self.SymbolTable) and decorator.attr == 'Object'): IsCpythonObject = True break elif isinstance(decorator, ast.Call): if isinstance(decorator.func, ast.Attribute): if (hasattr(decorator.func.value, 'id') and - decorator.func.value.id == 't' and + IsTModule(decorator.func.value.id, self.SymbolTable) and decorator.func.attr == 'Object'): IsCpythonObject = True break @@ -313,7 +310,7 @@ class PythonParserMixin: for base in node.bases: if isinstance(base, ast.Attribute): if (hasattr(base.value, 'id') and - base.value.id == 't' and + IsTModule(base.value.id, self.SymbolTable) and base.attr == 'Object'): IsCpythonObject = True break @@ -324,7 +321,7 @@ class PythonParserMixin: if IsCenum: # 注册为 enum 类型 - EnumNode = CTypeInfo() + EnumNode: CTypeInfo = CTypeInfo() EnumNode.Name = ClassName EnumNode.IsEnum = True EnumNode.set('file', '') @@ -333,8 +330,8 @@ class PythonParserMixin: # 注册 enum 成员 for item in node.body: if isinstance(item, ast.AnnAssign) and isinstance(item.target, ast.Name): - MemberName = item.target.id - MemberNode = CTypeInfo() + MemberName: str = item.target.id + MemberNode: CTypeInfo = CTypeInfo() MemberNode.Name = MemberName MemberNode.BaseType = t.CEnum(ClassName) MemberNode.value = None @@ -348,49 +345,43 @@ class PythonParserMixin: continue # 检测是否是 Anonymous - IsAnonymous = False + IsAnonymous: bool = False # 提取结构体成员信息 - members = {} + members: dict[str, CTypeInfo] = {} for item in node.body: if isinstance(item, ast.AnnAssign) and isinstance(item.target, ast.Name): - VarName = item.target.id + VarName: str = item.target.id try: - TypeInfo = self.TypeMergeHandler.GetCTypeInfo(item.annotation) + TypeInfo: CTypeInfo | None = self.TypeMergeHandler.GetCTypeInfo(item.annotation) if TypeInfo is None: TypeInfo = CTypeInfo() TypeInfo.BaseType = t.CInt() - IsPtr = TypeInfo.IsPtr + IsPtr: bool = TypeInfo.IsPtr if not IsPtr: if isinstance(item.annotation, ast.BinOp) and isinstance(item.annotation.op, ast.BitOr): - LeftStr = ast.dump(item.annotation.left) - RightStr = ast.dump(item.annotation.right) - if 'CPtr' in LeftStr or 'CPtr' in RightStr: + if AnnotationContainsName(item.annotation, 'CPtr'): IsPtr = True - dims = [] + dims: list[int] = [] if hasattr(item.annotation, 'slice') and isinstance(item.annotation.slice, ast.Constant): if isinstance(item.annotation.value, ast.Name): - if item.annotation.value.id == 't': + if IsTModule(item.annotation.value.id, self.SymbolTable): if hasattr(item.annotation, 'slice'): try: dims.append(int(item.annotation.slice.value)) except Exception as _e: - from lib.core.VLogger import get_logger as _vlog - from lib.constants.config import mode as _ConfigMode if _ConfigMode == "strict": raise _vlog().warning(f"解析数组维度失败: {_e}", "Exception") - MemberInfo = TypeInfo.Copy() + MemberInfo: CTypeInfo = TypeInfo.Copy() if dims: MemberInfo.ArrayDims = [str(d) for d in dims] members[VarName] = MemberInfo except Exception as _e: - from lib.core.VLogger import get_logger as _vlog - from lib.constants.config import mode as _ConfigMode if _ConfigMode == "strict": raise _vlog().warning(f"解析结构体成员失败: {_e}", "Exception") - StructNode = CTypeInfo() + StructNode: CTypeInfo = CTypeInfo() StructNode.Name = ClassName StructNode.IsStruct = True StructNode.Members = members or {} @@ -399,26 +390,27 @@ class PythonParserMixin: StructNode.set('IsCpythonObject', IsCpythonObject) self.SymbolTable.insert(ClassName, StructNode) elif isinstance(node, ast.FunctionDef): - FuncName = node.name - FuncNode = CTypeInfo() - FuncNode.Name = FuncName - FuncNode.IsFunction = True - FuncNode.set('file', '') - self.SymbolTable.insert(FuncName, FuncNode) + FuncName: str = node.name + if not self.SymbolTable.has(FuncName): + FuncNode: CTypeInfo = CTypeInfo() + FuncNode.Name = FuncName + FuncNode.IsFunction = True + FuncNode.set('file', '') + self.SymbolTable.insert(FuncName, FuncNode) elif isinstance(node, ast.AnnAssign): if isinstance(node.target, ast.Name): - VarName = node.target.id + VarName: str = node.target.id # 检查是否是 t.CTypedef 格式,如果是则跳过(由 HandleClassDef 处理) - is_ctypedef = False + is_ctypedef: bool = False if node.annotation: if isinstance(node.annotation, ast.Attribute): if isinstance(node.annotation.value, ast.Name): - if node.annotation.value.id == 't' and node.annotation.attr == 'CTypedef': + if IsTModule(node.annotation.value.id, self.SymbolTable) and node.annotation.attr == 'CTypedef': is_ctypedef = True elif isinstance(node.annotation, ast.BinOp) and isinstance(node.annotation.op, ast.BitOr): - def _has_ctype(ann): + def _has_ctype(ann: ast.AST) -> bool: if isinstance(ann, ast.Attribute): - return hasattr(ann.value, 'id') and ann.value.id == 't' and ann.attr == 'CTypedef' + return hasattr(ann.value, 'id') and IsTModule(ann.value.id) and ann.attr == 'CTypedef' if isinstance(ann, ast.BinOp) and isinstance(ann.op, ast.BitOr): return _has_ctype(ann.left) or _has_ctype(ann.right) if isinstance(ann, ast.Subscript): @@ -427,25 +419,23 @@ class PythonParserMixin: if _has_ctype(node.annotation): is_ctypedef = True if not is_ctypedef: - IsPtr = False + IsPtr: bool = False if node.annotation: try: - TypeInfo = self.TypeMergeHandler.GetCTypeInfo(node.annotation) + TypeInfo: CTypeInfo | None = self.TypeMergeHandler.GetCTypeInfo(node.annotation) IsPtr = TypeInfo.IsPtr if TypeInfo else False except Exception as _e: - from lib.core.VLogger import get_logger as _vlog - from lib.constants.config import mode as _ConfigMode if _ConfigMode == "strict": raise _vlog().warning(f"获取类型信息失败(ParsePythonFile): {_e}", "Exception") - var_node = CTypeInfo() + var_node: CTypeInfo = CTypeInfo() var_node.Name = VarName var_node.IsVariable = True var_node.set('IsPtr', IsPtr) var_node.set('file', '') self.SymbolTable.insert(VarName, var_node) except Exception as e: - print(f'Warning: Failed to parse Python file {FilePath}: {e}') + _vlog().warning(f'解析 Python 文件失败 {FilePath}: {e}') # ParseCFile 已移除 - .h/.c 文件的旧正则解析路径不再使用 # 类型解析现在直接通过 CTypeInfo 对象进行,不经过中间字符串格式 diff --git a/lib/core/TypeAnnotationResolver.py b/lib/core/TypeAnnotationResolver.py index b2e51ca..614914c 100644 --- a/lib/core/TypeAnnotationResolver.py +++ b/lib/core/TypeAnnotationResolver.py @@ -1,6 +1,16 @@ from __future__ import annotations import ast +import warnings +from typing import TYPE_CHECKING + from lib.core.Handles.HandlesBase import CTypeInfo, BuiltinTypeMap, CTypeHelper +from lib.core.ConstEvaluator import ConstEvaluator +from lib.core.SymbolUtils import IsTModule, IsTModulePath, IsListAnnotation +from lib.includes import t +from lib.constants.config import mode as _config_mode + +if TYPE_CHECKING: + from lib.core.SymbolTable import SymbolTable class TypeAnnotationResolver: @@ -10,48 +20,51 @@ class TypeAnnotationResolver: def from_type_name(TypeName: str) -> CTypeInfo: """从简单类型名构造 CTypeInfo(不经过 FromStr 字符串解析)""" # Handle pointer types like 'CUInt32T *', 'void *', etc. - ptr_count = 0 - base_name = TypeName + ptr_count: int = 0 + base_name: str = TypeName while base_name.endswith(' *') or base_name.endswith('*'): ptr_count += 1 base_name = base_name.rstrip(' *').rstrip() - entry = BuiltinTypeMap.Get(base_name) + entry: tuple[type, int] | None = BuiltinTypeMap.Get(base_name) if entry: + TypeClass: type + base_ptr: int TypeClass, base_ptr = entry - info = CTypeInfo() + info: CTypeInfo = CTypeInfo() info.BaseType = TypeClass info.PtrCount = base_ptr + ptr_count return info # Handle LLVM primitive type names (e.g., 'i64', 'double' from generic type inference) - llvm_map = CTypeInfo._get_llvm_primitive_map() - llvm_entry = llvm_map.get(base_name) + llvm_map: dict = CTypeInfo._get_llvm_primitive_map() + llvm_entry: tuple[type, int] | None = llvm_map.get(base_name) if llvm_entry: + TypeClass: type + base_ptr: int TypeClass, base_ptr = llvm_entry - info = CTypeInfo() + info: CTypeInfo = CTypeInfo() info.BaseType = TypeClass info.PtrCount = base_ptr + ptr_count return info # Fallback with pointer count - info = CTypeInfo.CreateFromTypeName(TypeName) + info: CTypeInfo = CTypeInfo.CreateFromTypeName(TypeName) if ptr_count > 0: info.PtrCount = ptr_count return info @staticmethod - def try_eval_const_expr(node, SymbolTable): - from lib.core.ConstEvaluator import ConstEvaluator + def try_eval_const_expr(node: ast.AST, SymbolTable: SymbolTable) -> int | float | str | None: return ConstEvaluator.eval_with_symtab(node, SymbolTable) @staticmethod - def from_node(Node: ast.AST, SymbolTable: dict) -> CTypeInfo: + def from_node(Node: ast.AST, SymbolTable: dict | SymbolTable) -> CTypeInfo: """从 AST 节点解析 CTypeInfo Args: Node: AST 节点(如 ast.Name, ast.Attribute 等) SymbolTable: 符号表字典 """ - if isinstance(Node, (ast.Constant, ast.Str)): + if isinstance(Node, ast.Constant): return TypeAnnotationResolver._from_node_constant(Node, SymbolTable) if isinstance(Node, ast.Name): return TypeAnnotationResolver._from_node_name(Node, SymbolTable) @@ -66,8 +79,9 @@ class TypeAnnotationResolver: return CTypeInfo() @staticmethod - def _from_node_constant(Node: ast.AST, SymbolTable: dict) -> CTypeInfo: - """处理 ast.Constant / ast.Str 节点""" + def _from_node_constant(Node: ast.AST, SymbolTable: dict | SymbolTable) -> CTypeInfo: + """处理 ast.Constant 节点""" + TypeName: str if isinstance(Node, ast.Constant): TypeName = Node.value else: @@ -75,35 +89,42 @@ class TypeAnnotationResolver: return TypeAnnotationResolver.from_type_name(TypeName) @staticmethod - def _from_node_name(Node: ast.Name, SymbolTable: dict) -> CTypeInfo: + def _from_node_name(Node: ast.Name, SymbolTable: dict | SymbolTable) -> CTypeInfo: """处理 ast.Name 节点""" - from lib.includes import t - - TypeName = Node.id - TypeObj = CTypeHelper.GetTModuleCType(TypeName) + TypeName: str = Node.id + TypeObj: type | None = CTypeHelper.GetTModuleCType(TypeName) if TypeObj is None: TypeObj = getattr(t, TypeName, None) if isinstance(TypeObj, type) and issubclass(TypeObj, t.CType) and TypeObj is not t.CType: if TypeObj == t.CPtr: - Result = CTypeInfo() + Result: CTypeInfo = CTypeInfo() Result.PtrCount = 1 Result.BaseType = t.CVoid() return Result if TypeObj == t.State: - Result = CTypeInfo() + Result: CTypeInfo = CTypeInfo() Result.IsState = True Result.BaseType = t.CVoid() return Result - Inst = TypeObj() - Result = CTypeInfo() + Inst: t.CType = TypeObj() + Result: CTypeInfo = CTypeInfo() Result.BaseType = TypeObj - if hasattr(Inst, 'CName') and Inst.CName: - Result.Name = Inst.CName + Result.Name = type(Inst).__name__ if hasattr(Inst, 'IsSigned'): Result.IsSigned = Inst.IsSigned return Result + # 检查 BuiltinTypeMap(覆盖 VOIDPTR, BYTEPTR 等指针别名) + builtin_entry: tuple[type, int] | None = BuiltinTypeMap.Get(TypeName) + if builtin_entry: + TypeClass: type + base_ptr: int + TypeClass, base_ptr = builtin_entry + Result: CTypeInfo = CTypeInfo() + Result.BaseType = TypeClass + Result.PtrCount = base_ptr + return Result if TypeName in SymbolTable: - Entry = SymbolTable[TypeName] + Entry: CTypeInfo | dict = SymbolTable[TypeName] if Entry: if isinstance(Entry, CTypeInfo): if Entry.IsTypedef: @@ -192,6 +213,13 @@ class TypeAnnotationResolver: Result.IsTypedef = True Result.Name = TypeName return Result + # 检查 t 类型别名(from t import CInt as myint) + if hasattr(SymbolTable, '_t_type_symbols'): + t_cls = SymbolTable._t_type_symbols.get(TypeName) + if t_cls is not None: + Result = CTypeInfo() + Result.BaseType = t_cls + return Result # 特殊处理 str 类型,它应该是 char*(指针) if TypeName in ('str', 'bytes'): Result = CTypeInfo() @@ -203,32 +231,31 @@ class TypeAnnotationResolver: return TypeAnnotationResolver.from_type_name(TypeName) @staticmethod - def _from_node_call(Node: ast.Call, SymbolTable: dict) -> CTypeInfo: + def _from_node_call(Node: ast.Call, SymbolTable: dict | SymbolTable) -> CTypeInfo: """处理 ast.Call 节点""" - from lib.includes import t - if isinstance(Node.func, ast.Name) and Node.func.id == 'callable': - Result = CTypeInfo() + Result: CTypeInfo = CTypeInfo() Result.IsFuncPtr = True Result.FuncPtrReturn = CTypeInfo.VoidTypeInfo() Result.FuncPtrParams = [] try: if len(Node.args) > 0: - RetInfo = TypeAnnotationResolver.from_node(Node.args[0], SymbolTable) + RetInfo: CTypeInfo = TypeAnnotationResolver.from_node(Node.args[0], SymbolTable) if RetInfo: Result.FuncPtrReturn = RetInfo + kw: ast.keyword for kw in Node.keywords: - ParamInfo = TypeAnnotationResolver.from_node(kw.value, SymbolTable) + ParamInfo: CTypeInfo = TypeAnnotationResolver.from_node(kw.value, SymbolTable) if ParamInfo: Result.FuncPtrParams.append((kw.arg or '', ParamInfo)) except Exception as _e: - if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": - import warnings; warnings.warn(f"异常被忽略: {_e}") + if _config_mode == "strict": + warnings.warn(f"异常被忽略: {_e}") return Result if isinstance(Node.func, ast.Attribute): - if isinstance(Node.func.value, ast.Name) and Node.func.value.id == 't': + if isinstance(Node.func.value, ast.Name) and IsTModule(Node.func.value.id, SymbolTable): if Node.func.attr == 'Bit' and len(Node.args) > 0: - Result = CTypeInfo() + Result: CTypeInfo = CTypeInfo() Result.BaseType = t.CInt() Result.IsBitField = True if isinstance(Node.args[0], ast.Constant) and isinstance(Node.args[0].value, int): @@ -239,18 +266,16 @@ class TypeAnnotationResolver: return CTypeInfo() @staticmethod - def _from_node_binop(Node: ast.BinOp, SymbolTable: dict) -> CTypeInfo: + def _from_node_binop(Node: ast.BinOp, SymbolTable: dict | SymbolTable) -> CTypeInfo: """处理 ast.BinOp (BitOr) 节点""" - from lib.includes import t - - LeftInfo = TypeAnnotationResolver.from_node(Node.left, SymbolTable) - RightInfo = TypeAnnotationResolver.from_node(Node.right, SymbolTable) + LeftInfo: CTypeInfo = TypeAnnotationResolver.from_node(Node.left, SymbolTable) + RightInfo: CTypeInfo = TypeAnnotationResolver.from_node(Node.right, SymbolTable) if LeftInfo.IsState or RightInfo.IsState: - Result = CTypeInfo() + Result: CTypeInfo = CTypeInfo() Result.IsState = True - NonStateInfo = LeftInfo if not LeftInfo.IsState else RightInfo - StateInfo = LeftInfo if LeftInfo.IsState else RightInfo + NonStateInfo: CTypeInfo = LeftInfo if not LeftInfo.IsState else RightInfo + StateInfo: CTypeInfo = LeftInfo if LeftInfo.IsState else RightInfo if NonStateInfo.BaseType and (not isinstance(NonStateInfo.BaseType, (t._CTypedef,)) or NonStateInfo.PtrCount > 0): Result.BaseType = NonStateInfo.BaseType elif NonStateInfo.IsTypedef and NonStateInfo.Name: @@ -389,15 +414,19 @@ class TypeAnnotationResolver: return Result # 处理字节序类型 (t.BigEndian, t.LittleEndian) - if LeftInfo.ByteOrder: + # 合并两侧:保留非字节序侧的实际类型(如 CUInt64T),取字节序侧的 ByteOrder + if LeftInfo.ByteOrder or RightInfo.ByteOrder: Result = CTypeInfo() - Result.BaseType = LeftInfo.BaseType if LeftInfo.BaseType else t.CInt() - Result.ByteOrder = LeftInfo.ByteOrder - return Result - if RightInfo.ByteOrder: - Result = CTypeInfo() - Result.BaseType = RightInfo.BaseType if RightInfo.BaseType else t.CInt() - Result.ByteOrder = RightInfo.ByteOrder + ByteOrderSide: CTypeInfo = LeftInfo if LeftInfo.ByteOrder else RightInfo + OtherSide: CTypeInfo = RightInfo if LeftInfo.ByteOrder else LeftInfo + if OtherSide.BaseType and (not isinstance(OtherSide.BaseType, (t._CTypedef,)) or OtherSide.PtrCount > 0): + Result.BaseType = OtherSide.BaseType + elif ByteOrderSide.BaseType and (not isinstance(ByteOrderSide.BaseType, (t._CTypedef,)) or ByteOrderSide.PtrCount > 0): + Result.BaseType = ByteOrderSide.BaseType + else: + Result.BaseType = t.CInt() + Result.ByteOrder = LeftInfo.ByteOrder or RightInfo.ByteOrder + Result.PtrCount = max(LeftInfo.PtrCount, RightInfo.PtrCount) return Result if LeftInfo.IsFuncPtr or RightInfo.IsFuncPtr: @@ -436,14 +465,12 @@ class TypeAnnotationResolver: return CTypeInfo() @staticmethod - def _from_node_subscript(Node: ast.Subscript, SymbolTable: dict) -> CTypeInfo: + def _from_node_subscript(Node: ast.Subscript, SymbolTable: dict | SymbolTable) -> CTypeInfo: """处理 ast.Subscript 节点""" - from lib.includes import t - - base = Node.value + base: ast.AST = Node.value if isinstance(base, ast.Attribute): - if isinstance(base.value, ast.Name) and base.value.id == 't' and base.attr == 'Bit': - Result = CTypeInfo() + if isinstance(base.value, ast.Name) and IsTModule(base.value.id, SymbolTable) and base.attr == 'Bit': + Result: CTypeInfo = CTypeInfo() Result.BaseType = t.CInt() Result.IsBitField = True if isinstance(Node.slice, ast.Constant) and isinstance(Node.slice.value, int): @@ -451,22 +478,22 @@ class TypeAnnotationResolver: else: Result.BitWidth = 1 return Result - if isinstance(base, ast.Name) and base.id == 'list': - slice_node = Node.slice - elts = [] + if IsListAnnotation(Node): + slice_node: ast.AST = Node.slice + elts: list[ast.AST] = [] if isinstance(slice_node, ast.Tuple): elts = slice_node.elts elif isinstance(slice_node, (ast.Attribute, ast.Name, ast.Subscript)): elts = [slice_node] if elts: - ElemInfo = TypeAnnotationResolver.from_node(elts[0], SymbolTable) + ElemInfo: CTypeInfo = TypeAnnotationResolver.from_node(elts[0], SymbolTable) if ElemInfo and ElemInfo.BaseType: - Result = CTypeInfo() + Result: CTypeInfo = CTypeInfo() Result.BaseType = ElemInfo.BaseType Result.PtrCount = ElemInfo.PtrCount Result.ArrayDims = list(ElemInfo.ArrayDims) if len(elts) >= 2: - count_val = TypeAnnotationResolver.try_eval_const_expr(elts[1], SymbolTable) + count_val: int | None = TypeAnnotationResolver.try_eval_const_expr(elts[1], SymbolTable) if count_val is not None and isinstance(count_val, int) and count_val > 0: Result.ArrayDims.insert(0, str(count_val)) else: @@ -475,34 +502,34 @@ class TypeAnnotationResolver: Result.PtrCount = max(Result.PtrCount, 1) return Result if isinstance(base, ast.Attribute): - parts = [] - current = base + parts: list[str] = [] + current: ast.AST = base while isinstance(current, ast.Attribute): parts.insert(0, current.attr) current = current.value if isinstance(current, ast.Name): parts.insert(0, current.id) - if parts and parts[0] == 't' and parts[-1] == t.CPtr.__name__: - Result = CTypeInfo() + if parts and IsTModule(parts[0], SymbolTable) and parts[-1] == t.CPtr.__name__: + Result: CTypeInfo = CTypeInfo() Result.BaseType = t.CVoid() Result.PtrCount = 1 - slice_node = Node.slice + slice_node: ast.AST = Node.slice if isinstance(slice_node, ast.Subscript): - InnerInfo = TypeAnnotationResolver.from_node(slice_node, SymbolTable) + InnerInfo: CTypeInfo = TypeAnnotationResolver.from_node(slice_node, SymbolTable) if InnerInfo: if InnerInfo.PtrCount > 0: Result.PtrCount += InnerInfo.PtrCount if InnerInfo.BaseType and not isinstance(InnerInfo.BaseType, t.CVoid): Result.BaseType = InnerInfo.BaseType elif isinstance(slice_node, ast.Attribute): - SliceInfo = TypeAnnotationResolver.from_node(slice_node, SymbolTable) + SliceInfo: CTypeInfo = TypeAnnotationResolver.from_node(slice_node, SymbolTable) if SliceInfo: if SliceInfo.IsPtr: Result.PtrCount += SliceInfo.PtrCount elif SliceInfo.BaseType and not isinstance(SliceInfo.BaseType, t.CVoid): Result.BaseType = SliceInfo.BaseType elif isinstance(slice_node, ast.Name): - SliceType = getattr(t, slice_node.id, None) + SliceType: type | None = getattr(t, slice_node.id, None) if SliceType == t.CPtr: Result.PtrCount += 1 else: @@ -510,7 +537,7 @@ class TypeAnnotationResolver: if SliceInfo and SliceInfo.BaseType and not isinstance(SliceInfo.BaseType, t.CVoid): Result.BaseType = SliceInfo.BaseType return Result - if parts and parts[0] == 't' and parts[-1] == 'Callable': + if parts and IsTModule(parts[0], SymbolTable) and parts[-1] == 'Callable': Result = CTypeInfo() Result.IsFuncPtr = True slice_node = Node.slice @@ -532,12 +559,10 @@ class TypeAnnotationResolver: return CTypeInfo() @staticmethod - def _from_node_attribute(Node: ast.Attribute, SymbolTable: dict) -> CTypeInfo: + def _from_node_attribute(Node: ast.Attribute, SymbolTable: dict | SymbolTable) -> CTypeInfo: """处理 ast.Attribute 节点""" - from lib.includes import t - - ModuleParts = [] - Current = Node + ModuleParts: list[str] = [] + Current: ast.AST = Node while isinstance(Current, ast.Attribute): ModuleParts.insert(0, Current.attr) Current = Current.value @@ -545,6 +570,8 @@ class TypeAnnotationResolver: if isinstance(Current, ast.Name): ModuleParts.insert(0, Current.id) + TypeName: str + ModulePath: str | None if len(ModuleParts) >= 2: TypeName = ModuleParts[-1] ModulePath = '.'.join(ModuleParts[:-1]) @@ -556,62 +583,66 @@ class TypeAnnotationResolver: # 解析 import 别名: 如 import vpsdk.window as window -> window -> vpsdk.window if ModulePath: - resolved = False - import_aliases = SymbolTable.import_aliases + resolved: bool = False + import_aliases: dict = SymbolTable.import_aliases if ModulePath in import_aliases: ModulePath = import_aliases[ModulePath] resolved = True if not resolved and ModulePath in SymbolTable: - entry = SymbolTable[ModulePath] + entry: CTypeInfo = SymbolTable[ModulePath] if isinstance(entry, CTypeInfo) and entry.IsModuleAlias: resolved_name = entry.ResolvedModule if resolved_name: ModulePath = resolved_name - if ModulePath == 't' or (ModulePath and ModulePath.startswith('t.')): - TypeClass = CTypeHelper.GetTModuleCType(TypeName) + if ModulePath and IsTModulePath(ModulePath): + TypeClass: type | None = CTypeHelper.GetTModuleCType(TypeName) if TypeClass is None: TypeClass = getattr(t, TypeName, None) if TypeClass is not None and TypeClass.HasPosition(t.CType.POINTER): - Info = CTypeInfo() + Info: CTypeInfo = CTypeInfo() Info.PtrCount = 1 if TypeClass == t.CArrayPtr: Info.IsArrayPtr = True Info.BaseType = t.CVoid return Info if TypeClass is not None and TypeClass.IsStorageClass(): - Info = CTypeInfo() + Info: CTypeInfo = CTypeInfo() Info.Storage = TypeClass() if TypeClass == t.State: Info.IsState = True Info.BaseType = t.CVoid() return Info if TypeClass is not None and TypeClass.IsTypeQualifier(): - Info = CTypeInfo() + Info: CTypeInfo = CTypeInfo() if TypeClass == t.CConst: Info.DataConst = True elif TypeClass == t.CVolatile: Info.DataVolatile = True return Info + if TypeClass is not None and TypeClass in (t.BigEndian, t.LittleEndian): + Result: CTypeInfo = CTypeInfo() + Result.BaseType = t.CInt() + Result.ByteOrder = 'big' if TypeClass == t.BigEndian else 'little' + return Result if (TypeClass is not None and isinstance(TypeClass, type) and issubclass(TypeClass, t.CType) and TypeClass is not t.CType and TypeClass.HasPosition(t.CType.BASE)): if TypeClass == t.State: - Result = CTypeInfo() + Result: CTypeInfo = CTypeInfo() Result.IsState = True Result.BaseType = t.CVoid() return Result - Inst = TypeClass() - Result = CTypeInfo() + Inst: t.CType = TypeClass() + Result: CTypeInfo = CTypeInfo() Result.BaseType = TypeClass - if hasattr(Inst, 'CName') and Inst.CName: - Result.Name = Inst.CName + Result.Name = type(Inst).__name__ if hasattr(Inst, 'IsSigned'): Result.IsSigned = Inst.IsSigned return Result - CNAME = CTypeHelper.GetCName(TypeName) + CNAME: str | None = CTypeHelper.GetCName(TypeName) if CNAME: return TypeAnnotationResolver.from_type_name(CNAME) @@ -627,29 +658,29 @@ class TypeAnnotationResolver: Result.ByteOrder = 'little' return Result - FullName = f"{ModulePath}.{TypeName}" if ModulePath else TypeName + FullName: str = f"{ModulePath}.{TypeName}" if ModulePath else TypeName if TypeName in SymbolTable: - Entry = SymbolTable[TypeName] + Entry: CTypeInfo = SymbolTable[TypeName] if Entry and Entry.IsTypedef: - Resolved = Entry.Copy() + Resolved: CTypeInfo = Entry.Copy() if Resolved.BaseType is None: Resolved.BaseType = t._CTypedef(TypeName) return Resolved if Entry and Entry.IsEnum: - Result = CTypeInfo() + Result: CTypeInfo = CTypeInfo() Result.BaseType = t.CInt() Result.IsEnum = True Result.Name = TypeName return Result if Entry and Entry.IsExceptionClass: - Result = CTypeInfo() + Result: CTypeInfo = CTypeInfo() Result.BaseType = t.CInt() Result.IsExceptionClass = True Result.Name = TypeName return Result if Entry: - Result = Entry.Copy() + Result: CTypeInfo = Entry.Copy() if Result.BaseType is None and (Result.IsStruct or Result.IsCpythonObject or Result.Name): Result.BaseType = t.CStruct(name=TypeName) Result.IsStruct = True @@ -657,24 +688,24 @@ class TypeAnnotationResolver: return CTypeInfo() if FullName in SymbolTable: - Info = SymbolTable[FullName] + Info: CTypeInfo = SymbolTable[FullName] if Info and Info.IsTypedef: - OriginalType = Info.get('OriginalType', '') + OriginalType: str = Info.get('OriginalType', '') if OriginalType and 'typedef' in OriginalType: - parts = OriginalType.split() + parts: list[str] = OriginalType.split() if len(parts) >= 2: - BaseType_name = parts[1] + BaseType_name: str = parts[1] if not BaseType_name.startswith('C'): BaseType_name = 'C' + BaseType_name - CNAME = CTypeHelper.GetCName(BaseType_name) + CNAME: str | None = CTypeHelper.GetCName(BaseType_name) if CNAME: return TypeAnnotationResolver.from_type_name(CNAME) - Result = CTypeInfo() + Result: CTypeInfo = CTypeInfo() Result.BaseType = t._CTypedef(TypeName) Result.IsTypedef = True return Result if Info: - Result = Info.Copy() + Result: CTypeInfo = Info.Copy() if Result.BaseType is None and (Result.IsStruct or Result.IsCpythonObject or Result.Name): Result.BaseType = t.CStruct(name=TypeName) Result.IsStruct = True @@ -684,11 +715,11 @@ class TypeAnnotationResolver: return CTypeInfo() @staticmethod - def _handle_array_subscript(Node, SymbolTable): + def _handle_array_subscript(Node: ast.AST, SymbolTable: dict | SymbolTable) -> CTypeInfo | None: if not isinstance(Node, ast.Subscript): return None - dims = [] - current = Node + dims: list[str] = [] + current: ast.AST = Node while isinstance(current, ast.Subscript): if isinstance(current.slice, ast.Constant) and isinstance(current.slice.value, int): dims.insert(0, str(current.slice.value)) @@ -697,7 +728,7 @@ class TypeAnnotationResolver: else: return None current = current.value - base_info = TypeAnnotationResolver.from_node(current, SymbolTable) + base_info: CTypeInfo = TypeAnnotationResolver.from_node(current, SymbolTable) if base_info and base_info.BaseType: base_info.ArrayDims = dims return base_info diff --git a/lib/core/TypeSpec.py b/lib/core/TypeSpec.py index 64e85fc..24e4f0d 100644 --- a/lib/core/TypeSpec.py +++ b/lib/core/TypeSpec.py @@ -19,7 +19,8 @@ from typing import TYPE_CHECKING, List, Dict, Tuple, Any, Optional if TYPE_CHECKING: from lib.core.Handles.HandlesBase import CTypeInfo - from lib.includes import t + +from lib.includes import t class SymbolKind(enum.Enum): @@ -134,37 +135,35 @@ class TypeSpec: ) def __init__(self): - self._base_type: Any = None # t.CType 实例或 tuple + self._base_type: t.CType | tuple | None = None # t.CType 实例或 tuple self.ptr_count: int = 0 self.var_const: bool = False self.var_volatile: bool = False self.data_const: bool = False self.data_volatile: bool = False self.array_dims: List[str] = [] - self.storage: Any = None # t.CType (CStatic/CExtern/CExport 等) + self.storage: t.CType | None = None # t.CType (CStatic/CExtern/CExport 等) self.is_func_ptr: bool = False - self.func_ptr_params: List[Tuple[str, Any]] = [] # (参数名, CTypeInfo) + self.func_ptr_params: List[Tuple[str, CTypeInfo]] = [] # (参数名, CTypeInfo) self.func_param_names: List[str] = [] - self.func_ptr_return: Any = None # CTypeInfo + self.func_ptr_return: CTypeInfo | None = None # CTypeInfo self.is_variadic: bool = False self.is_bitfield: bool = False self.bit_width: int = 0 self.byte_order: str = "" # "big", "little", or "" self.is_array_ptr: bool = False - self.array_ptr: Any = None # CTypeInfo + self.array_ptr: CTypeInfo | None = None # CTypeInfo self.is_state: bool = False - self.original_type: Any = None # CTypeInfo | str | None (typedef 原始类型) + self.original_type: CTypeInfo | str | None = None # CTypeInfo | str | None (typedef 原始类型) self.is_signed: Optional[bool] = None # None = 未设置, True/False = 有符号/无符号 @property - def base_type(self) -> Any: + def base_type(self) -> t.CType | tuple | None: return self._base_type @base_type.setter - def base_type(self, value: Any): + def base_type(self, value: t.CType | tuple | None): """设置 BaseType,与 CTypeInfo.BaseType setter 逻辑一致(不含 kind 副作用)""" - from lib.includes import t - if value is None: self._base_type = None return @@ -187,7 +186,7 @@ class TypeSpec: def copy(self) -> TypeSpec: """深拷贝""" - new = TypeSpec() + new: TypeSpec = TypeSpec() new._base_type = self._base_type new.ptr_count = self.ptr_count new.var_const = self.var_const @@ -244,12 +243,12 @@ class SymbolMeta: self.lineno: int = 0 self.file: str = "" self.module_name: str = "" - self.members: Dict[str, Any] = {} # 成员名 -> CTypeInfo + self.members: Dict[str, CTypeInfo] = {} # 成员名 -> CTypeInfo self.is_cpython_object: bool = False self.is_packed: bool = False - self.define_value: Any = None + self.define_value: int | str | float | bool | None = None self.enum_name: str = "" # 枚举成员所属的枚举类名 - self.enum_value: Any = None # 枚举成员的值 + self.enum_value: int | None = None # 枚举成员的值 self.is_inline: bool = False self.inline_body: list | None = None self.inline_params: list | None = None @@ -287,7 +286,7 @@ class SymbolMeta: def copy(self) -> SymbolMeta: """深拷贝""" - new = SymbolMeta() + new: SymbolMeta = SymbolMeta() new.name = self.name new.lineno = self.lineno new.file = self.file diff --git a/lib/core/VLogger.py b/lib/core/VLogger.py index 865c99a..242e474 100644 --- a/lib/core/VLogger.py +++ b/lib/core/VLogger.py @@ -2,11 +2,13 @@ TransPyC 彩色日志系统 支持终端颜色输出和日志文件转储 """ +from __future__ import annotations import sys import os from datetime import datetime -from typing import Optional +from typing import Any, Callable, Optional +from lib.constants.config import mode as _ConfigMode # ANSI 颜色代码 class Colors: @@ -45,7 +47,7 @@ class Colors: GRAY = '\033[90m' # 检查是否支持颜色 -def supports_color(): +def supports_color() -> bool: if not hasattr(sys.stdout, 'isatty'): return False if not sys.stdout.isatty(): @@ -109,28 +111,28 @@ class Logger: self.file_handler.write(f"[{timestamp}] {level} {clean_msg}\n") self.file_handler.flush() - def set_phase(self, phase: str, total: int = 0): + def set_phase(self, phase: str, total: int = 0) -> None: self.current_phase = phase self.total_items = total self.current_item = 0 self.progress(phase, 0, total) - def progress(self, message: str = "", current: int = 0, total: int = 0): + def progress(self, message: str = "", current: int = 0, total: int = 0) -> None: if total > 0: self.total_items = total if current > 0: self.current_item = current if self.total_items > 0: - percent = (self.current_item / self.total_items) * 100 - bar_length = 30 - filled = int(bar_length * self.current_item / self.total_items) - bar = '█' * filled + '░' * (bar_length - filled) - status = f"[{self._colorize(bar, Colors.BLUE)}] {self.current_item}/{self.total_items} ({percent:.1f}%)" + percent: float = (self.current_item / self.total_items) * 100 + bar_length: int = 30 + filled: int = int(bar_length * self.current_item / self.total_items) + bar: str = '█' * filled + '░' * (bar_length - filled) + status: str = f"[{self._colorize(bar, Colors.BLUE)}] {self.current_item}/{self.total_items} ({percent:.1f}%)" else: status = "" - msg = f"{self._colorize('▶', Colors.BRIGHT_CYAN)} {self.current_phase}" + msg: str = f"{self._colorize('▶', Colors.BRIGHT_CYAN)} {self.current_phase}" if status: msg += f" {status}" if message: @@ -140,67 +142,67 @@ class Logger: sys.stdout.write('\r' + msg) sys.stdout.flush() - def debug(self, message: str, category: str = ""): + def debug(self, message: str, category: str = "") -> None: if self.level > LogLevel.DEBUG: return - prefix = self._colorize("DEBUG", Colors.GRAY) + prefix: str = self._colorize("DEBUG", Colors.GRAY) if category: prefix += f"[{self._colorize(category, Colors.CYAN)}]" - msg = f"{self._colorize('├', Colors.GRAY)} {prefix}: {message}" + msg: str = f"{self._colorize('├', Colors.GRAY)} {prefix}: {message}" self._write(msg, "DEBUG") - def info(self, message: str, category: str = ""): - prefix = self._colorize("INFO", Colors.GREEN) + def info(self, message: str, category: str = "") -> None: + prefix: str = self._colorize("INFO", Colors.GREEN) if category: prefix += f"[{self._colorize(category, Colors.CYAN)}]" - msg = f"{self._colorize('├', Colors.GREEN)} {prefix}: {message}" + msg: str = f"{self._colorize('├', Colors.GREEN)} {prefix}: {message}" self._write(msg, "INFO") - def warning(self, message: str, category: str = ""): - prefix = self._colorize("WARN", Colors.BRIGHT_YELLOW) + def warning(self, message: str, category: str = "", exc_info: Exception | None = None) -> None: + prefix: str = self._colorize("WARN", Colors.BRIGHT_YELLOW) if category: prefix += f"[{self._colorize(category, Colors.CYAN)}]" - - msg = f"{self._colorize('├', Colors.YELLOW)} {prefix}: {message}" + + msg: str = f"{self._colorize('├', Colors.YELLOW)} {prefix}: {message}" self._write(msg, "WARNING") - def error(self, message: str, category: str = "", exception: Optional[Exception] = None): - prefix = self._colorize("ERROR", Colors.BRIGHT_RED) + def error(self, message: str, category: str = "", exception: Optional[Exception] = None) -> None: + prefix: str = self._colorize("ERROR", Colors.BRIGHT_RED) if category: prefix += f"[{self._colorize(category, Colors.CYAN)}]" - msg = f"{self._colorize('├', Colors.RED)} {prefix}: {message}" + msg: str = f"{self._colorize('├', Colors.RED)} {prefix}: {message}" if exception: msg += f"\n{self._colorize('│', Colors.RED)} Exception: {type(exception).__name__}: {exception}" self._write(msg, "ERROR") - def critical(self, message: str, category: str = ""): - prefix = self._colorize("CRITICAL", Colors.BG_RED + Colors.WHITE + Colors.BOLD) + def critical(self, message: str, category: str = "") -> None: + prefix: str = self._colorize("CRITICAL", Colors.BG_RED + Colors.WHITE + Colors.BOLD) if category: prefix += f"[{self._colorize(category, Colors.CYAN)}]" - msg = f"{self._colorize('╠', Colors.RED)} {prefix}: {message}" + msg: str = f"{self._colorize('╠', Colors.RED)} {prefix}: {message}" self._write(msg, "CRITICAL") - def success(self, message: str, category: str = ""): - prefix = self._colorize("SUCCESS", Colors.BRIGHT_GREEN) + def success(self, message: str, category: str = "") -> None: + prefix: str = self._colorize("SUCCESS", Colors.BRIGHT_GREEN) if category: prefix += f"[{self._colorize(category, Colors.CYAN)}]" - msg = f"{self._colorize('├', Colors.GREEN)} {prefix}: {message}" + msg: str = f"{self._colorize('├', Colors.GREEN)} {prefix}: {message}" self._write(msg, "SUCCESS") - def compile_error(self, message: str, file: str = "", line: int = 0, code: str = ""): + def compile_error(self, message: str, file: str = "", line: int = 0, code: str = "") -> None: """编译错误格式化输出""" - header = self._colorize("编译错误", Colors.BG_RED + Colors.WHITE + Colors.BOLD) + header: str = self._colorize("编译错误", Colors.BG_RED + Colors.WHITE + Colors.BOLD) - msg = f"\n{self._colorize('╔', Colors.RED)}{header}{self._colorize('╗', Colors.RED)}\n" + msg: str = f"\n{self._colorize('╔', Colors.RED)}{header}{self._colorize('╗', Colors.RED)}\n" if file and line > 0: - location = f"{self._colorize(file, Colors.CYAN)}:{self._colorize(str(line), Colors.YELLOW)}" + location: str = f"{self._colorize(file, Colors.CYAN)}:{self._colorize(str(line), Colors.YELLOW)}" msg += f"{self._colorize('║', Colors.RED)} 位置:{location}\n" if code: @@ -211,14 +213,14 @@ class Logger: self._write(msg, "ERROR") - def compile_warning(self, message: str, file: str = "", line: int = 0, code: str = ""): + def compile_warning(self, message: str, file: str = "", line: int = 0, code: str = "") -> None: """编译警告格式化输出""" - header = self._colorize("警告", Colors.BG_YELLOW + Colors.BLACK) + header: str = self._colorize("警告", Colors.BG_YELLOW + Colors.BLACK) - msg = f"\n{self._colorize('╔', Colors.YELLOW)}{header}{self._colorize('╗', Colors.YELLOW)}\n" + msg: str = f"\n{self._colorize('╔', Colors.YELLOW)}{header}{self._colorize('╗', Colors.YELLOW)}\n" if file and line > 0: - location = f"{self._colorize(file, Colors.CYAN)}:{self._colorize(str(line), Colors.YELLOW)}" + location: str = f"{self._colorize(file, Colors.CYAN)}:{self._colorize(str(line), Colors.YELLOW)}" msg += f"{self._colorize('║', Colors.YELLOW)} 位置:{location}\n" if code: @@ -229,21 +231,21 @@ class Logger: self._write(msg, "WARNING") - def summary(self, stats: dict): + def summary(self, stats: dict[str, int | str]) -> None: """输出编译摘要""" - header = self._colorize("编译摘要", Colors.BG_BLUE + Colors.WHITE + Colors.BOLD) + header: str = self._colorize("编译摘要", Colors.BG_BLUE + Colors.WHITE + Colors.BOLD) - msg = f"\n{self._colorize('╔', Colors.BLUE)}{header}{self._colorize('╗', Colors.BLUE)}\n" + msg: str = f"\n{self._colorize('╔', Colors.BLUE)}{header}{self._colorize('╗', Colors.BLUE)}\n" for key, value in stats.items(): - color = Colors.GREEN if value > 0 else Colors.WHITE + color: str = Colors.GREEN if value > 0 else Colors.WHITE msg += f"{self._colorize('║', Colors.BLUE)} {key}: {self._colorize(str(value), color)}\n" msg += f"{self._colorize('╚', Colors.BLUE)}{self._colorize('═' * 50, Colors.BLUE)}{self._colorize('╝', Colors.BLUE)}" self._write(msg, "SUMMARY") - def close(self): + def close(self) -> None: if self.file_handler: self.file_handler.close() self.info(f"日志已保存到:{self.log_file}") @@ -258,46 +260,46 @@ def get_logger(name: str = "TransPyC", log_file: Optional[str] = None, _global_logger = Logger(name, log_file, level, use_colors) return _global_logger -def set_logger(logger: Logger): +def set_logger(logger: Logger) -> None: global _global_logger _global_logger = logger # 便捷函数 -def debug(msg, category=""): +def debug(msg: str, category: str = "") -> None: get_logger().debug(msg, category) -def info(msg, category=""): +def info(msg: str, category: str = "") -> None: get_logger().info(msg, category) -def warning(msg, category=""): +def warning(msg: str, category: str = "") -> None: get_logger().warning(msg, category) -def error(msg, category="", exception=None): +def error(msg: str, category: str = "", exception: Exception | None = None) -> None: get_logger().error(msg, category, exception) -def critical(msg, category=""): +def critical(msg: str, category: str = "") -> None: get_logger().critical(msg, category) -def success(msg, category=""): +def success(msg: str, category: str = "") -> None: get_logger().success(msg, category) -def compile_error(msg, file="", line=0, code=""): +def compile_error(msg: str, file: str = "", line: int = 0, code: str = "") -> None: get_logger().compile_error(msg, file, line, code) -def compile_warning(msg, file="", line=0, code=""): +def compile_warning(msg: str, file: str = "", line: int = 0, code: str = "") -> None: get_logger().compile_warning(msg, file, line, code) -def set_phase(phase, total=0): +def set_phase(phase: str, total: int = 0) -> None: get_logger().set_phase(phase, total) -def progress(message="", current=0, total=0): +def progress(message: str = "", current: int = 0, total: int = 0) -> None: get_logger().progress(message, current, total) -def summary(stats): +def summary(stats: dict[str, int | str]) -> None: get_logger().summary(stats) -def safe_call(func, *args, context: str = "", **kwargs): +def safe_call(func: Callable[..., Any], *args: Any, context: str = "", **kwargs: Any) -> Any: """安全调用函数,在异常时根据模式处理。 - strict 模式:重新抛出异常 @@ -314,7 +316,6 @@ def safe_call(func, *args, context: str = "", **kwargs): try: return func(*args, **kwargs) except Exception as e: - from lib.constants.config import mode as _ConfigMode msg = f"{context}: {type(e).__name__}: {e}" if context else f"{type(e).__name__}: {e}" if _ConfigMode == "strict": raise diff --git a/lib/core/stub_generator.py b/lib/core/stub_generator.py index 20d92fa..5b60618 100644 --- a/lib/core/stub_generator.py +++ b/lib/core/stub_generator.py @@ -5,54 +5,83 @@ C/H 文件到 Python 存根文件生成器 将 C 头文件 (.h) 或 C 源文件 (.c) 转换为 Python 存根文件 (.pyi) 生成的 Python 代码使用 TransPyC 语法,包含类型注解 """ +from __future__ import annotations import os import re -from typing import List, Dict, Optional +import sys +from typing import Any +from lib.core.VLogger import get_logger as _vlog class CTypeMapper: + # 硬编码 C 类型名 → Python 类型映射表 + # 这是 stub 生成器(C 头文件 → Python stub)专用的固定映射, + # 不再依赖运行时 CTypeRegistry._cname_to_class(该映射已删除)。 + _CNAME_TO_PY: dict[str, str] = { + # 基本类型 + 'char': 't.CChar', 'int': 't.CInt', 'short': 't.CShort', + 'long': 't.CLong', 'long long': 't.CLongLong', + 'float': 't.CFloat', 'double': 't.CDouble', 'void': 't.CVoid', + # unsigned / signed 变体 + 'unsigned': 't.CUnsigned', 'unsigned char': 't.CUnsignedChar', + 'unsigned int': 't.CUnsignedInt', 'unsigned short': 't.CUnsignedShort', + 'unsigned long': 't.CUnsignedLong', + 'unsigned long long': 't.CUnsignedLongLong', + 'signed char': 't.CSignedChar', + # bool / size_t + 'bool': 't.CBool', '_Bool': 't.CBool', 'size_t': 't.CSizeT', + 'ssize_t': 't.CLong', + # stdint 固定宽度类型 + 'int8_t': 't.CInt8T', 'int16_t': 't.CInt16T', + 'int32_t': 't.CInt32T', 'int64_t': 't.CInt64T', + 'uint8_t': 't.CUInt8T', 'uint16_t': 't.CUInt16T', + 'uint32_t': 't.CUInt32T', 'uint64_t': 't.CUInt64T', + 'intptr_t': 't.CIntPtrT', 'uintptr_t': 't.CUIntPtrT', + 'ptrdiff_t': 't.CPtrDiffT', + # 宽字符 / 字符类型 + 'wchar_t': 't.CWCharT', 'char8_t': 't.CChar8T', + 'char16_t': 't.CChar16T', 'char32_t': 't.CChar32T', + # 浮点特化类型 + 'float8_t': 't.CFloat8T', 'float16_t': 't.CFloat16T', + 'float32_t': 't.CFloat32T', 'float64_t': 't.CFloat64T', + 'float128_t': 't.CFloat128T', + # signed 速记 + 'signed': 't.CInt', 'signed int': 't.CInt', + 'signed short': 't.CShort', 'signed long': 't.CLong', + } + @classmethod def _ResolveCNameToPyType(cls, c_type: str) -> str: - from lib.includes.t import CTypeRegistry - ctype_cls = CTypeRegistry.CNameToClass(c_type) - if ctype_cls is not None: - name = ctype_cls.__name__ - return f't.{name}' - resolved = CTypeRegistry.ResolveName(c_type) - if resolved is not None: - ctype_cls, _ = resolved - name = ctype_cls.__name__ - return f't.{name}' - _SPECIAL = { - 'signed': 't.CInt', 'unsigned': 't.CUnsigned', - 'signed char': 't.CChar', 'signed short': 't.CShort', - 'signed int': 't.CInt', 'signed long': 't.CLong', - '_Bool': 't.CBool', 'ssize_t': 't.CLong', - } - if c_type in _SPECIAL: - return _SPECIAL[c_type] + """将 C 类型名解析为 Python 类型字符串(如 'int' → 't.CInt') + + 使用硬编码映射表,不再依赖 CTypeRegistry._cname_to_class。 + 未识别的类型原样返回(用于 struct/union/enum/typedef 用户自定义名)。 + """ + py: str | None = cls._CNAME_TO_PY.get(c_type) + if py is not None: + return py return c_type @classmethod def MapType(cls, c_type: str, IsPtr: bool = False, IsArray: bool = False) -> str: c_type = c_type.strip() - IsConst = 'const ' in c_type + IsConst: bool = 'const ' in c_type c_type = c_type.replace('const ', '').replace('const', '').strip() - IsVolatile = 'volatile ' in c_type + IsVolatile: bool = 'volatile ' in c_type c_type = c_type.replace('volatile ', '').replace('volatile', '').strip() - IsStatic = 'static ' in c_type + IsStatic: bool = 'static ' in c_type c_type = c_type.replace('static ', '').replace('static', '').strip() - IsExtern = 'extern ' in c_type + IsExtern: bool = 'extern ' in c_type c_type = c_type.replace('extern ', '').replace('extern', '').strip() - IsRegister = 'register ' in c_type + IsRegister: bool = 'register ' in c_type c_type = c_type.replace('register ', '').replace('register', '').strip() - IsInline = 'inline ' in c_type + IsInline: bool = 'inline ' in c_type c_type = c_type.replace('inline ', '').replace('inline', '').strip() - PtrSuffix = '' + PtrSuffix: str = '' if IsPtr or c_type.endswith('*'): PtrSuffix = ' | t.CPtr' c_type = c_type.rstrip('*').strip() @@ -64,9 +93,9 @@ class CTypeMapper: elif c_type.startswith('enum '): c_type = c_type[5:].strip() - PyType = cls._ResolveCNameToPyType(c_type) + PyType: str = cls._ResolveCNameToPyType(c_type) - result = PyType + PtrSuffix + result: str = PyType + PtrSuffix if IsArray: result += ' | t.CArrayPtr' @@ -75,8 +104,8 @@ class CTypeMapper: def _find_matching_brace(text: str, start: int) -> int: - depth = 0 - i = start + depth: int = 0 + i: int = start while i < len(text): if text[i] == '{': depth += 1 @@ -85,7 +114,7 @@ def _find_matching_brace(text: str, start: int) -> int: if depth == 0: return i elif text[i] == '"' or text[i] == "'": - quote = text[i] + quote: str = text[i] i += 1 while i < len(text) and text[i] != quote: if text[i] == '\\': @@ -105,8 +134,8 @@ def _find_matching_brace(text: str, start: int) -> int: def _strip_comments(content: str) -> str: - result = [] - i = 0 + result: list[str] = [] + i: int = 0 while i < len(content): if content[i] == '/' and i + 1 < len(content) and content[i + 1] == '/': while i < len(content) and content[i] != '\n': @@ -117,7 +146,7 @@ def _strip_comments(content: str) -> str: i += 1 i += 2 elif content[i] == '"' or content[i] == "'": - quote = content[i] + quote: str = content[i] result.append(content[i]) i += 1 while i < len(content) and content[i] != quote: @@ -136,10 +165,10 @@ def _strip_comments(content: str) -> str: def _strip_preprocessor_guards(content: str) -> str: - lines = content.split('\n') - filtered = [] + lines: list[str] = content.split('\n') + filtered: list[str] = [] for line in lines: - stripped = line.strip() + stripped: str = line.strip() if stripped.startswith('#ifndef') and '_H' in stripped.upper(): continue if stripped.startswith('#define') and '_H' in stripped.upper(): @@ -153,22 +182,22 @@ def _strip_preprocessor_guards(content: str) -> str: class CHeaderParser: """C 头文件解析器""" - def __init__(self): - self.defines: List[Dict] = [] - self.structs: Dict[str, Dict] = {} - self.enums: Dict[str, Dict] = {} - self.typedefs: Dict[str, str] = [] - self.functions: Dict[str, Dict] = {} - self.variables: Dict[str, Dict] = {} - self.unions: Dict[str, Dict] = {} - self.func_ptr_typedefs: Dict[str, Dict] = {} - self._typedef_struct_map: Dict[str, str] = {} - self._typedef_enum_map: Dict[str, str] = {} - self._typedef_union_map: Dict[str, str] = {} + def __init__(self) -> None: + self.defines: list[dict[str, str | None]] = [] + self.structs: dict[str, dict[str, Any]] = {} + self.enums: dict[str, dict[str, Any]] = {} + self.typedefs: list[dict[str, str]] = [] + self.functions: dict[str, dict[str, Any]] = {} + self.variables: dict[str, dict[str, Any]] = {} + self.unions: dict[str, dict[str, Any]] = {} + self.func_ptr_typedefs: dict[str, dict[str, Any]] = {} + self._typedef_struct_map: dict[str, str] = {} + self._typedef_enum_map: dict[str, str] = {} + self._typedef_union_map: dict[str, str] = {} def ParseFile(self, FilePath: str) -> None: with open(FilePath, 'r', encoding='utf-8') as f: - content = f.read() + content: str = f.read() self.ParseContent(content) def ParseContent(self, content: str) -> None: @@ -183,17 +212,17 @@ class CHeaderParser: self._ParseStandaloneStructs(content) self._ParseStandaloneEnums(content) self._ParseStandaloneUnions(content) - stripped = self._StripBodies(content) + stripped: str = self._StripBodies(content) self._ParseFunctions(stripped) self._ParseVariables(stripped) def _StripBodies(self, content: str) -> str: - result = content + result: str = content while True: - pos = result.find('{') + pos: int = result.find('{') if pos < 0: break - end = _find_matching_brace(result, pos) + end: int = _find_matching_brace(result, pos) if end < 0: break result = result[:pos] + result[end + 1:] @@ -201,8 +230,8 @@ class CHeaderParser: def _ParseDefines(self, content: str) -> None: for match in re.finditer(r'#define\s+(\w+)(?:\s+(.+?))?\s*$', content, re.MULTILINE): - Name = match.group(1) - Value = match.group(2) + Name: str = match.group(1) + Value: str | None = match.group(2) if Name.startswith('_') and Name.endswith('_'): continue if Name.startswith('__'): @@ -213,20 +242,20 @@ class CHeaderParser: }) def _ParseTypedefStructs(self, content: str) -> None: - pattern = r'typedef\s+struct\s*(\w*)\s*\{' + pattern: str = r'typedef\s+struct\s*(\w*)\s*\{' for match in re.finditer(pattern, content): - brace_start = content.index('{', match.start()) - brace_end = _find_matching_brace(content, brace_start) + brace_start: int = content.index('{', match.start()) + brace_end: int = _find_matching_brace(content, brace_start) if brace_end < 0: continue - body = content[brace_start + 1:brace_end] - rest = content[brace_end + 1:].lstrip() - AliasMatch = re.match(r'(\w+)\s*;', rest) + body: str = content[brace_start + 1:brace_end] + rest: str = content[brace_end + 1:].lstrip() + AliasMatch: re.Match[str] | None = re.match(r'(\w+)\s*;', rest) if not AliasMatch: continue - AliasName = AliasMatch.group(1) - TagName = match.group(1) if match.group(1) else None - members = self._ParseStructMembers(body) + AliasName: str = AliasMatch.group(1) + TagName: str | None = match.group(1) if match.group(1) else None + members: list[dict[str, Any]] = self._ParseStructMembers(body) self.structs[AliasName] = { 'name': AliasName, 'tag': TagName, @@ -236,20 +265,20 @@ class CHeaderParser: self._typedef_struct_map[TagName] = AliasName def _ParseTypedefEnums(self, content: str) -> None: - pattern = r'typedef\s+enum\s*(\w*)\s*\{' + pattern: str = r'typedef\s+enum\s*(\w*)\s*\{' for match in re.finditer(pattern, content): - brace_start = content.index('{', match.start()) - brace_end = _find_matching_brace(content, brace_start) + brace_start: int = content.index('{', match.start()) + brace_end: int = _find_matching_brace(content, brace_start) if brace_end < 0: continue - body = content[brace_start + 1:brace_end] - rest = content[brace_end + 1:].lstrip() - AliasMatch = re.match(r'(\w+)\s*;', rest) + body: str = content[brace_start + 1:brace_end] + rest: str = content[brace_end + 1:].lstrip() + AliasMatch: re.Match[str] | None = re.match(r'(\w+)\s*;', rest) if not AliasMatch: continue - AliasName = AliasMatch.group(1) - TagName = match.group(1) if match.group(1) else None - values = self._ParseEnumValues(body) + AliasName: str = AliasMatch.group(1) + TagName: str | None = match.group(1) if match.group(1) else None + values: list[dict[str, str | None]] = self._ParseEnumValues(body) self.enums[AliasName] = { 'name': AliasName, 'tag': TagName, @@ -259,20 +288,20 @@ class CHeaderParser: self._typedef_enum_map[TagName] = AliasName def _ParseTypedefUnions(self, content: str) -> None: - pattern = r'typedef\s+union\s*(\w*)\s*\{' + pattern: str = r'typedef\s+union\s*(\w*)\s*\{' for match in re.finditer(pattern, content): - brace_start = content.index('{', match.start()) - brace_end = _find_matching_brace(content, brace_start) + brace_start: int = content.index('{', match.start()) + brace_end: int = _find_matching_brace(content, brace_start) if brace_end < 0: continue - body = content[brace_start + 1:brace_end] - rest = content[brace_end + 1:].lstrip() - AliasMatch = re.match(r'(\w+)\s*;', rest) + body: str = content[brace_start + 1:brace_end] + rest: str = content[brace_end + 1:].lstrip() + AliasMatch: re.Match[str] | None = re.match(r'(\w+)\s*;', rest) if not AliasMatch: continue - AliasName = AliasMatch.group(1) - TagName = match.group(1) if match.group(1) else None - members = self._ParseStructMembers(body) + AliasName: str = AliasMatch.group(1) + TagName: str | None = match.group(1) if match.group(1) else None + members: list[dict[str, Any]] = self._ParseStructMembers(body) self.unions[AliasName] = { 'name': AliasName, 'tag': TagName, @@ -282,12 +311,12 @@ class CHeaderParser: self._typedef_union_map[TagName] = AliasName def _ParseFuncPtrTypedefs(self, content: str) -> None: - pattern = r'typedef\s+([\w\s\*]+?)\s*\(\s*\*\s*(\w+)\s*\)\s*\(([^)]*)\)\s*;' + pattern: str = r'typedef\s+([\w\s\*]+?)\s*\(\s*\*\s*(\w+)\s*\)\s*\(([^)]*)\)\s*;' for match in re.finditer(pattern, content): - ReturnType = match.group(1).strip() - Name = match.group(2) - ParamsStr = match.group(3).strip() - params = self._ParseFuncParams(ParamsStr) + ReturnType: str = match.group(1).strip() + Name: str = match.group(2) + ParamsStr: str = match.group(3).strip() + params: list[dict[str, Any]] = self._ParseFuncParams(ParamsStr) self.func_ptr_typedefs[Name] = { 'name': Name, 'return_type': ReturnType, @@ -295,11 +324,11 @@ class CHeaderParser: } def _ParseSimpleTypedefs(self, content: str) -> None: - stripped = self._StripBodies(content) - pattern = r'typedef\s+([\w\s\*]+?)\s+(\w+)\s*;' + stripped: str = self._StripBodies(content) + pattern: str = r'typedef\s+([\w\s\*]+?)\s+(\w+)\s*;' for match in re.finditer(pattern, stripped): - BaseType = match.group(1).strip() - AliasName = match.group(2) + BaseType: str = match.group(1).strip() + AliasName: str = match.group(2) if AliasName in self.structs: continue if AliasName in self.enums: @@ -313,19 +342,19 @@ class CHeaderParser: self.typedefs.append({'name': AliasName, 'base': BaseType}) def _ParseStandaloneStructs(self, content: str) -> None: - pattern = r'(? None: - pattern = r'(? None: - pattern = r'(? None: - pattern = r'(?:(?:static|extern|inline)\s+)*([\w][\w\s\*]*?)\b(\w+)\s*\(([^)]*)\)\s*;' + pattern: str = r'(?:(?:static|extern|inline)\s+)*([\w][\w\s\*]*?)\b(\w+)\s*\(([^)]*)\)\s*;' for match in re.finditer(pattern, content): - ReturnType = match.group(1).strip() - FuncName = match.group(2) - ParamsStr = match.group(3).strip() + ReturnType: str = match.group(1).strip() + FuncName: str = match.group(2) + ParamsStr: str = match.group(3).strip() if FuncName in self.structs or FuncName in self.enums or FuncName in self.unions: continue if FuncName in self.func_ptr_typedefs: @@ -390,7 +419,7 @@ class CHeaderParser: continue if not re.match(r'^[A-Za-z_]', FuncName): continue - params = self._ParseFuncParams(ParamsStr) + params: list[dict[str, Any]] = self._ParseFuncParams(ParamsStr) self.functions[FuncName] = { 'name': FuncName, 'return_type': ReturnType, @@ -398,11 +427,11 @@ class CHeaderParser: } def _ParseVariables(self, content: str) -> None: - pattern = r'(?:(?:static|extern|volatile|const)\s+)*([\w][\w\s\*]*?)\s+(\w+)\s*(?:\[(\d*)\])?\s*;' + pattern: str = r'(?:(?:static|extern|volatile|const)\s+)*([\w][\w\s\*]*?)\s+(\w+)\s*(?:\[(\d*)\])?\s*;' for match in re.finditer(pattern, content): - TypeStr = match.group(1).strip() - VarName = match.group(2) - ArraySize = match.group(3) + TypeStr: str = match.group(1).strip() + VarName: str = match.group(2) + ArraySize: str | None = match.group(3) if VarName in self.functions or VarName in self.structs or VarName in self.enums: continue if VarName in self.unions or VarName in self.func_ptr_typedefs: @@ -417,8 +446,8 @@ class CHeaderParser: continue if not re.match(r'^[A-Za-z_]', VarName): continue - IsPtr = '*' in TypeStr - IsArray = ArraySize is not None + IsPtr: bool = '*' in TypeStr + IsArray: bool = ArraySize is not None self.variables[VarName] = { 'name': VarName, 'type': TypeStr, @@ -427,17 +456,17 @@ class CHeaderParser: 'array_size': int(ArraySize) if ArraySize and ArraySize.isdigit() else None, } - def _ParseStructMembers(self, body: str) -> List[Dict]: - members = [] + def _ParseStructMembers(self, body: str) -> list[dict[str, Any]]: + members: list[dict[str, Any]] = [] for line in body.split(';'): line = line.strip() if not line: continue - arr_match = re.match(r'([\w\s\*]+?)\s+(\w+)\s*\[(\d*)\]', line) + arr_match: re.Match[str] | None = re.match(r'([\w\s\*]+?)\s+(\w+)\s*\[(\d*)\]', line) if arr_match: - MemberType = arr_match.group(1).strip() - MemberName = arr_match.group(2) - ArraySize = arr_match.group(3) + MemberType: str = arr_match.group(1).strip() + MemberName: str = arr_match.group(2) + ArraySize: str = arr_match.group(3) members.append({ 'name': MemberName, 'type': MemberType, @@ -445,36 +474,36 @@ class CHeaderParser: 'array_size': int(ArraySize) if ArraySize and ArraySize.isdigit() else None, }) continue - ptr_match = re.match(r'([\w\s\*]+?)\s*\*\s*(\w+)', line) + ptr_match: re.Match[str] | None = re.match(r'([\w\s\*]+?)\s*\*\s*(\w+)', line) if ptr_match: - MemberType = ptr_match.group(1).strip() + ' *' - MemberName = ptr_match.group(2) + MemberType: str = ptr_match.group(1).strip() + ' *' + MemberName: str = ptr_match.group(2) members.append({ 'name': MemberName, 'type': MemberType, 'IsPtr': True, }) continue - simple_match = re.match(r'([\w\s]+?)\s+(\w+)', line) + simple_match: re.Match[str] | None = re.match(r'([\w\s]+?)\s+(\w+)', line) if simple_match: - MemberType = simple_match.group(1).strip() - MemberName = simple_match.group(2) + MemberType: str = simple_match.group(1).strip() + MemberName: str = simple_match.group(2) members.append({ 'name': MemberName, 'type': MemberType, }) return members - def _ParseEnumValues(self, body: str) -> List[Dict]: - values = [] + def _ParseEnumValues(self, body: str) -> list[dict[str, str | None]]: + values: list[dict[str, str | None]] = [] for item in body.split(','): item = item.strip() if not item: continue - eq_pos = item.find('=') + eq_pos: int = item.find('=') if eq_pos >= 0: - Name = item[:eq_pos].strip() - Value = item[eq_pos + 1:].strip() + Name: str = item[:eq_pos].strip() + Value: str | None = item[eq_pos + 1:].strip() else: Name = item.strip() Value = None @@ -482,46 +511,46 @@ class CHeaderParser: values.append({'name': Name, 'value': Value}) return values - def _ParseFuncParams(self, params_str: str) -> List[Dict]: - params = [] + def _ParseFuncParams(self, params_str: str) -> list[dict[str, Any]]: + params: list[dict[str, Any]] = [] if not params_str or params_str.strip() == 'void' or params_str.strip() == '': return params for param in params_str.split(','): param = param.strip() if not param: continue - func_ptr_match = re.match(r'([\w\s\*]+?)\s*\(\s*\*\s*(\w*)\s*\)\s*\([^)]*\)', param) + func_ptr_match: re.Match[str] | None = re.match(r'([\w\s\*]+?)\s*\(\s*\*\s*(\w*)\s*\)\s*\([^)]*\)', param) if func_ptr_match: - RetType = func_ptr_match.group(1).strip() - ParamName = func_ptr_match.group(2) or 'callback' + RetType: str = func_ptr_match.group(1).strip() + ParamName: str = func_ptr_match.group(2) or 'callback' params.append({ 'name': ParamName, 'type': RetType + ' (*)', 'is_func_ptr': True, }) continue - arr_match = re.match(r'([\w\s\*]+?)\s+(\w+)\s*\[\d*\]', param) + arr_match: re.Match[str] | None = re.match(r'([\w\s\*]+?)\s+(\w+)\s*\[\d*\]', param) if arr_match: - ParamType = arr_match.group(1).strip() - ParamName = arr_match.group(2) + ParamType: str = arr_match.group(1).strip() + ParamName: str = arr_match.group(2) params.append({ 'name': ParamName, 'type': ParamType, 'is_array': True, }) continue - tokens = param.split() + tokens: list[str] = param.split() if len(tokens) >= 2: - LastToken = tokens[-1] - PtrCount = 0 + LastToken: str = tokens[-1] + PtrCount: int = 0 while LastToken.startswith('*'): PtrCount += 1 LastToken = LastToken[1:] - TypeTokens = tokens[:-1] + TypeTokens: list[str] = tokens[:-1] for _ in range(PtrCount): TypeTokens.append('*') - ParamName = LastToken - ParamType = ' '.join(TypeTokens) + ParamName: str = LastToken + ParamType: str = ' '.join(TypeTokens) if not ParamName: ParamName = 'arg' ParamType = param @@ -540,11 +569,11 @@ class CHeaderParser: class PythonStubGenerator: """Python 存根文件生成器""" - def __init__(self, parser: CHeaderParser): - self.parser = parser - self.OutputLines: List[str] = [] + def __init__(self, parser: CHeaderParser) -> None: + self.parser: CHeaderParser = parser + self.OutputLines: list[str] = [] - def generate(self, ModuleName: Optional[str] = None) -> str: + def generate(self, ModuleName: str | None = None) -> str: self.OutputLines = [] self._AddHeader(ModuleName) self._GenerateImports() @@ -558,7 +587,7 @@ class PythonStubGenerator: self._GenerateFunctions() return '\n'.join(self.OutputLines) - def _AddHeader(self, ModuleName: Optional[str] = None) -> None: + def _AddHeader(self, ModuleName: str | None = None) -> None: self.OutputLines.append('"""') self.OutputLines.append('Auto-generated Python stub file from C header') if ModuleName: @@ -575,8 +604,8 @@ class PythonStubGenerator: if not self.parser.defines: return for define in self.parser.defines: - Name = define['name'] - Value = define['value'] + Name: str = define['name'] + Value: str | None = define['value'] if Value is not None: self.OutputLines.append(f'{Name}: t.CDefine = {Value}') else: @@ -587,11 +616,11 @@ class PythonStubGenerator: if not self.parser.func_ptr_typedefs: return for Name, Info in self.parser.func_ptr_typedefs.items(): - RetType = CTypeMapper.MapType(Info['return_type']) - ParamTypes = [] + RetType: str = CTypeMapper.MapType(Info['return_type']) + ParamTypes: list[str] = [] for p in Info['params']: ParamTypes.append(CTypeMapper.MapType(p['type'])) - ParamStr = ', '.join(ParamTypes) if ParamTypes else '' + ParamStr: str = ', '.join(ParamTypes) if ParamTypes else '' self.OutputLines.append(f'{Name}: t.CTypedef = t.Callable[[{ParamStr}], {RetType}]') self.OutputLines.append('') @@ -599,9 +628,9 @@ class PythonStubGenerator: if not self.parser.typedefs: return for td in self.parser.typedefs: - AliasName = td['name'] - BaseType = td['base'] - PyType = CTypeMapper.MapType(BaseType) + AliasName: str = td['name'] + BaseType: str = td['base'] + PyType: str = CTypeMapper.MapType(BaseType) self.OutputLines.append(f'{AliasName}: t.CTypedef | {PyType}') self.OutputLines.append('') @@ -613,11 +642,11 @@ class PythonStubGenerator: self.OutputLines.append(f'class {StructName}(t.CStruct):') if StructInfo['members']: for member in StructInfo['members']: - MemberName = member['name'] - IsPtr = member.get('IsPtr', False) - IsArray = member.get('is_array', False) - ArraySize = member.get('array_size') - PyType = CTypeMapper.MapType(member['type'], IsPtr=IsPtr) + MemberName: str = member['name'] + IsPtr: bool = member.get('IsPtr', False) + IsArray: bool = member.get('is_array', False) + ArraySize: int | None = member.get('array_size') + PyType: str = CTypeMapper.MapType(member['type'], IsPtr=IsPtr) if IsArray and ArraySize is not None: self.OutputLines.append(f' {MemberName}: list[{PyType}, {ArraySize}]') elif IsArray: @@ -636,7 +665,7 @@ class PythonStubGenerator: self.OutputLines.append(f'class {UnionName}(t.CUnion):') if UnionInfo['members']: for member in UnionInfo['members']: - PyType = CTypeMapper.MapType(member['type'], IsPtr=member.get('IsPtr', False)) + PyType: str = CTypeMapper.MapType(member['type'], IsPtr=member.get('IsPtr', False)) self.OutputLines.append(f' {member["name"]}: {PyType}') else: self.OutputLines.append(' pass') @@ -662,7 +691,7 @@ class PythonStubGenerator: if not self.parser.variables: return for VarName, VarInfo in self.parser.variables.items(): - PyType = CTypeMapper.MapType(VarInfo['type'], IsPtr=VarInfo['IsPtr'], IsArray=VarInfo['is_array']) + PyType: str = CTypeMapper.MapType(VarInfo['type'], IsPtr=VarInfo['IsPtr'], IsArray=VarInfo['is_array']) self.OutputLines.append(f'{VarName}: {PyType}') self.OutputLines.append('') @@ -670,42 +699,41 @@ class PythonStubGenerator: if not self.parser.functions: return for FuncName, FuncInfo in self.parser.functions.items(): - params = [] + params: list[str] = [] for param in FuncInfo['params']: if param.get('is_func_ptr'): - PyType = CTypeMapper.MapType(param['type']) + PyType: str = CTypeMapper.MapType(param['type']) elif param.get('is_array'): - PyType = CTypeMapper.MapType(param['type'], IsPtr=True) + PyType: str = CTypeMapper.MapType(param['type'], IsPtr=True) else: - PyType = CTypeMapper.MapType(param['type']) + PyType: str = CTypeMapper.MapType(param['type']) params.append(f'{param["name"]}: {PyType}') - ParamStr = ', '.join(params) if params else '' - ReturnType = CTypeMapper.MapType(FuncInfo['return_type']) + ParamStr: str = ', '.join(params) if params else '' + ReturnType: str = CTypeMapper.MapType(FuncInfo['return_type']) self.OutputLines.append(f'def {FuncName}({ParamStr}) -> {ReturnType}: pass') self.OutputLines.append('') -def GenerateStubFromC(InputFile: str, OutputFile: Optional[str] = None) -> str: - parser = CHeaderParser() +def GenerateStubFromC(InputFile: str, OutputFile: str | None = None) -> str: + parser: CHeaderParser = CHeaderParser() parser.ParseFile(InputFile) - generator = PythonStubGenerator(parser) - ModuleName = os.path.splitext(os.path.basename(InputFile))[0] - content = generator.generate(ModuleName) + generator: PythonStubGenerator = PythonStubGenerator(parser) + ModuleName: str = os.path.splitext(os.path.basename(InputFile))[0] + content: str = generator.generate(ModuleName) if OutputFile: with open(OutputFile, 'w', encoding='utf-8') as f: f.write(content) - print(f"Generated: {OutputFile}") + _vlog().success(f"生成: {OutputFile}") return content if __name__ == '__main__': - import sys if len(sys.argv) >= 3: GenerateStubFromC(sys.argv[1], sys.argv[2]) elif len(sys.argv) == 2: - print(GenerateStubFromC(sys.argv[1])) + _vlog().info(GenerateStubFromC(sys.argv[1])) else: - test_code = ''' + test_code: str = ''' struct memory_block { uint64_t size; uint8_t state; @@ -727,7 +755,7 @@ void *malloc(size_t size); void free(void *ptr); void *memcpy(void *dest, const void *src, size_t n); ''' - parser = CHeaderParser() + parser: CHeaderParser = CHeaderParser() parser.ParseContent(test_code) - generator = PythonStubGenerator(parser) - print(generator.generate("test_header")) + generator: PythonStubGenerator = PythonStubGenerator(parser) + _vlog().info(generator.generate("test_header")) diff --git a/lib/core/translator.py b/lib/core/translator.py index 65dda2b..219684d 100644 --- a/lib/core/translator.py +++ b/lib/core/translator.py @@ -7,6 +7,7 @@ # - PythonParser.py: Python 文件解析 # - LlvmGenerator.py: LLVM IR 生成 # - ConstEval.py: 常量表达式求值 +from __future__ import annotations from lib.core.Translator.BaseTranslator import BaseTranslatorMixin, _StrictLog from lib.core.Translator.AnnotationLoader import AnnotationLoaderMixin @@ -30,4 +31,4 @@ class Translator( pass -__all__ = ['Translator', '_StrictLog'] +__all__: list[str] = ['Translator', '_StrictLog'] diff --git a/lib/includes/c.py b/lib/includes/c.py index e6fcc8c..72036eb 100644 --- a/lib/includes/c.py +++ b/lib/includes/c.py @@ -1,37 +1,41 @@ # C语法定义模块 +from __future__ import annotations import ast import sys import os +import logging +from typing import Any, Optional sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..')) from . import t +from lib.constants.config import mode as _config_mode -def _to_str(node): +def _to_str(node: Any) -> str: if node is None: return '' if isinstance(node, str): return node if isinstance(node, list): return ' && '.join([_to_str(n) for n in node]) - NodeType = type(node).__name__ + NodeType: str = type(node).__name__ if NodeType == 'Constant': return node.value elif NodeType == 'ID': return node.name elif NodeType == 'BinaryOp': - left = _to_str(node.left) - right = _to_str(node.right) + left: str = _to_str(node.left) + right: str = _to_str(node.right) return f'{left} {node.op} {right}' elif NodeType == 'UnaryOp': - expr = _to_str(node.expr) + expr: str = _to_str(node.expr) return f'{node.op}{expr}' else: return repr(node) class Asm: @staticmethod - def _parse_asm_descr(expr): + def _parse_asm_descr(expr: ast.AST) -> str: """递归解析AST节点,确保获取t.ASM_DESCR的实际值,支持|组合 处理场景: 1. t.ASM_DESCR.XXX → 取属性值 @@ -40,8 +44,8 @@ class Asm: """ # 场景1:位或组合(XXX | YYY) if isinstance(expr, ast.BinOp): - left_val = Asm._parse_asm_descr(expr.left) - right_val = Asm._parse_asm_descr(expr.right) + left_val: str = Asm._parse_asm_descr(expr.left) + right_val: str = Asm._parse_asm_descr(expr.right) return left_val + right_val # 场景2:t.ASM_DESCR.XXX 多层属性访问 @@ -53,13 +57,13 @@ class Asm: expr.value.value.id == 't' and expr.value.attr == 'ASM_DESCR'): # 取 t.ASM_DESCR.XXX 的实际值 - AttrName = expr.attr + AttrName: str = expr.attr if hasattr(t.ASM_DESCR, AttrName): return getattr(t.ASM_DESCR, AttrName, "") # 兼容 t.XXX 简化写法(如果有的话) elif isinstance(expr.value, ast.Name) and expr.value.id == 't': - AttrName = expr.attr + AttrName: str = expr.attr if hasattr(t.ASM_DESCR, AttrName): return getattr(t.ASM_DESCR, AttrName, "") @@ -71,39 +75,39 @@ class Asm: return "" @staticmethod - def _extract_val_expr(translator, expr_node): + def _extract_val_expr(translator: Any, expr_node: ast.AST) -> str: """从AST表达式节点提取值表达式的字符串形式""" - val_ExprNode = translator.HandleExpr(expr_node)[0] + val_ExprNode: Any = translator.HandleExpr(expr_node)[0] if isinstance(val_ExprNode, str): return val_ExprNode try: return str(val_ExprNode) except Exception as _e: - if __import__('lib.constants.config', fromlist=['mode']).mode == "strict": - import logging; logging.warning(f"异常被忽略: {_e}") + if _config_mode == "strict": + logging.warning(f"异常被忽略: {_e}") return '' @staticmethod - def _parse_asm_template(translator, args): + def _parse_asm_template(translator: Any, args: list[ast.AST]) -> tuple[str, list[tuple[str, str]], list[tuple[str, str]], int]: """解析f-string或常量模板字符串,返回(asm_code, output_ops, input_ops, operand_seq)""" - output_ops = [] - input_ops = [] - operand_seq = 0 - asm_code = "" - first_arg = args[0] + output_ops: list[tuple[str, str]] = [] + input_ops: list[tuple[str, str]] = [] + operand_seq: int = 0 + asm_code: str = "" + first_arg: ast.AST = args[0] if isinstance(first_arg, ast.JoinedStr): - asm_parts = [] + asm_parts: list[str] = [] for part in first_arg.values: if isinstance(part, ast.Constant): asm_parts.append(part.value) elif isinstance(part, ast.FormattedValue): - expr = part.value + expr: ast.AST = part.value if isinstance(expr, ast.Call) and isinstance(expr.func, ast.Attribute) and expr.func.value.id == 'c': # 解析内联的AsmInp/AsmOut - call_node = expr - val_expr = Asm._extract_val_expr(translator, call_node.args[0]) if len(call_node.args)>=1 else "" - constraint = Asm._parse_asm_descr(call_node.args[1]) if len(call_node.args)>=2 else "" + call_node: ast.Call = expr + val_expr: str = Asm._extract_val_expr(translator, call_node.args[0]) if len(call_node.args)>=1 else "" + constraint: str = Asm._parse_asm_descr(call_node.args[1]) if len(call_node.args)>=2 else "" if call_node.func.attr == 'AsmOut': output_ops.append((val_expr, constraint)) @@ -122,15 +126,15 @@ class Asm: return asm_code, output_ops, input_ops, operand_seq @staticmethod - def _parse_asm_operands(translator, args, keywords, output_ops, input_ops, operand_seq): + def _parse_asm_operands(translator: Any, args: list[ast.AST], keywords: list[ast.keyword], output_ops: list[tuple[str, str]], input_ops: list[tuple[str, str]], operand_seq: int) -> tuple[list[tuple[str, str]], list[tuple[str, str]], int]: """解析位置参数和关键字参数中的输出/输入操作数""" - def parse_operand(arg): + def parse_operand(arg: ast.AST) -> Optional[tuple[str, str, str]]: """解析 AsmInp/AsmOut 参数""" if isinstance(arg, ast.Call) and isinstance(arg.func, ast.Attribute) and arg.func.value.id == 'c': - call_node = arg - val_expr = Asm._extract_val_expr(translator, call_node.args[0]) if len(call_node.args)>=1 else "" - constraint = Asm._parse_asm_descr(call_node.args[1]) if len(call_node.args)>=2 else "" + call_node: ast.Call = arg + val_expr: str = Asm._extract_val_expr(translator, call_node.args[0]) if len(call_node.args)>=1 else "" + constraint: str = Asm._parse_asm_descr(call_node.args[1]) if len(call_node.args)>=2 else "" if call_node.func.attr == 'AsmOut': return ('out', val_expr, constraint) @@ -140,7 +144,7 @@ class Asm: # 处理位置参数中的操作数 for arg in args[1:]: - result = parse_operand(arg) + result: Optional[tuple[str, str, str]] = parse_operand(arg) if result: direction, val_expr, constraint = result if direction == 'out': @@ -172,8 +176,8 @@ class Asm: if isinstance(elt, ast.Tuple): # 处理列表中的 (value, constraint) 元组格式 if len(elt.elts) >= 2: - val_expr = Asm._extract_val_expr(translator, elt.elts[0]) if len(elt.elts) >= 1 else "" - constraint = Asm._parse_asm_descr(elt.elts[1]) + val_expr: str = Asm._extract_val_expr(translator, elt.elts[0]) if len(elt.elts) >= 1 else "" + constraint: str = Asm._parse_asm_descr(elt.elts[1]) input_ops.append((val_expr, constraint)) operand_seq += 1 else: @@ -189,24 +193,24 @@ class Asm: elif isinstance(kw.value, ast.Tuple): # 处理 (value, constraint) 元组格式 if len(kw.value.elts) >= 2: - val_expr = Asm._extract_val_expr(translator, kw.value.elts[0]) if len(kw.value.elts) >= 1 else "" - constraint = Asm._parse_asm_descr(kw.value.elts[1]) + val_expr: str = Asm._extract_val_expr(translator, kw.value.elts[0]) if len(kw.value.elts) >= 1 else "" + constraint: str = Asm._parse_asm_descr(kw.value.elts[1]) input_ops.append((val_expr, constraint)) operand_seq += 1 return output_ops, input_ops, operand_seq @staticmethod - def _parse_asm_clobbers(args, keywords): + def _parse_asm_clobbers(args: list[ast.AST], keywords: list[ast.keyword]) -> list[str]: """解析位置参数和关键字参数中的破坏列表""" - clobbers = [] + clobbers: list[str] = [] # 处理位置参数中的破坏列表 for arg in args[1:]: if isinstance(arg, ast.List): # 解析破坏列表(支持|组合) for elt in arg.elts: - clobber_val = Asm._parse_asm_descr(elt) + clobber_val: str = Asm._parse_asm_descr(elt) if clobber_val: clobbers.append(clobber_val) @@ -216,29 +220,29 @@ class Asm: # 处理 op 关键字参数 (clobber,破坏列表) if isinstance(kw.value, ast.List): for elt in kw.value.elts: - clobber_val = Asm._parse_asm_descr(elt) + clobber_val: str = Asm._parse_asm_descr(elt) if clobber_val: clobbers.append(clobber_val) elif kw.arg == 'clobber': # 处理 clobber 关键字参数 if isinstance(kw.value, ast.List): for elt in kw.value.elts: - clobber_val = Asm._parse_asm_descr(elt) + clobber_val: str = Asm._parse_asm_descr(elt) if clobber_val: clobbers.append(clobber_val) return clobbers @staticmethod - def _generate_asm_code(asm_code, output_ops, input_ops, clobbers, asm_format): + def _generate_asm_code(asm_code: str, output_ops: list[tuple[str, str]], input_ops: list[tuple[str, str]], clobbers: list[str], asm_format: str) -> list[str]: """格式化汇编代码并生成最终的__asm__代码字符串""" # 格式化汇编代码 - asm_lines = [line.strip() for line in asm_code.split('\n') if line.strip()] - formatted_asm = '\n '.join([f'"{line}\\n"' for line in asm_lines]) + asm_lines: list[str] = [line.strip() for line in asm_code.split('\n') if line.strip()] + formatted_asm: str = '\n '.join([f'"{line}\\n"' for line in asm_lines]) # 拼接约束字符串 # 输出约束:如果约束已包含 = 或 +,直接使用;否则添加 = - def format_constraint(constraint, is_output=True): + def format_constraint(constraint: str, is_output: bool = True) -> str: if not constraint: return "" # 如果约束已包含修饰符,直接返回 @@ -247,12 +251,12 @@ class Asm: # 否则添加适当的修饰符 return ('=' if is_output else '') + constraint - out_const = ', '.join([f'"{format_constraint(c, True)}"({v})' for v, c in output_ops]) if output_ops else "" - in_const = ', '.join([f'"{format_constraint(c, False)}"({v})' for v, c in input_ops]) if input_ops else "" - clobber_const = ', '.join([f'"{x}"' for x in clobbers]) if clobbers else "" + out_const: str = ', '.join([f'"{format_constraint(c, True)}"({v})' for v, c in output_ops]) if output_ops else "" + in_const: str = ', '.join([f'"{format_constraint(c, False)}"({v})' for v, c in input_ops]) if input_ops else "" + clobber_const: str = ', '.join([f'"{x}"' for x in clobbers]) if clobbers else "" # 构建约束部分:确保冒号格式正确 - constraint_parts = [] + constraint_parts: list[str] = [] # 输出约束 if output_ops: constraint_parts.append(f': {out_const}') @@ -269,12 +273,12 @@ class Asm: if clobbers: constraint_parts.append(f': {clobber_const}') - constraint_str = ' '.join(constraint_parts) + constraint_str: str = ' '.join(constraint_parts) # 生成最终代码 if asm_format == 'ARM': # ARM 使用 .arch 指令和不同的内联汇编语法 - final_asm = f'__asm__ __volatile__ (\n {formatted_asm} {constraint_str});' + final_asm: str = f'__asm__ __volatile__ (\n {formatted_asm} {constraint_str});' elif asm_format == 'AT&T': # AT&T 语法不需要额外标记,GCC 默认就是 AT&T final_asm = f'__asm__ __volatile__ (\n {formatted_asm} {constraint_str});' @@ -284,11 +288,15 @@ class Asm: return [final_asm] @staticmethod - def HandleCall(translator, args, keywords): + def HandleCall(translator: Any, args: list[ast.AST], keywords: list[ast.keyword]) -> list[str]: if not args: return ['__asm__ volatile ("nop");'] # 解析模板 + asm_code: str + output_ops: list[tuple[str, str]] + input_ops: list[tuple[str, str]] + operand_seq: int asm_code, output_ops, input_ops, operand_seq = Asm._parse_asm_template(translator, args) # 解析操作数 @@ -296,10 +304,10 @@ class Asm: translator, args, keywords, output_ops, input_ops, operand_seq) # 解析破坏列表 - clobbers = Asm._parse_asm_clobbers(args, keywords) + clobbers: list[str] = Asm._parse_asm_clobbers(args, keywords) # 解析汇编格式 - asm_format = 'Intel' + asm_format: str = 'Intel' for kw in keywords: if kw.arg == 'format': if isinstance(kw.value, ast.Constant) and isinstance(kw.value.value, str): @@ -309,19 +317,19 @@ class Asm: return Asm._generate_asm_code(asm_code, output_ops, input_ops, clobbers, asm_format) class AsmInp: - def __init__(self, value, constraint): - self.value = value - self.constraint = constraint + def __init__(self, value: Any, constraint: Any) -> None: + self.value: Any = value + self.constraint: Any = constraint @staticmethod - def HandleCall(translator, args, keywords): + def HandleCall(translator: Any, args: Any, keywords: Any) -> list[Any]: return [] class AsmOut: - def __init__(self, value, constraint): - self.value = value - self.constraint = constraint + def __init__(self, value: Any, constraint: Any) -> None: + self.value: Any = value + self.constraint: Any = constraint @staticmethod - def HandleCall(translator, args, keywords): + def HandleCall(translator: Any, args: Any, keywords: Any) -> list[Any]: return [] class NoBreak: @@ -334,29 +342,29 @@ class Break: class Load: """解引用a写入b,等价于 *b = *a,无拷贝副作用""" - def __init__(self, src, dst): - self.src = src - self.dst = dst + def __init__(self, src: Any, dst: Any) -> None: + self.src: Any = src + self.dst: Any = dst @staticmethod - def HandleCall(translator, args, keywords): + def HandleCall(translator: Any, args: Any, keywords: Any) -> list[str]: if len(args) >= 2: - src = translator.HandleExpr(args[0])[0] - dst = translator.HandleExpr(args[1])[0] + src: Any = translator.HandleExpr(args[0])[0] + dst: Any = translator.HandleExpr(args[1])[0] return [f'*({dst}) = *({src})'] return [] class Addr: """取地址""" - def __init__(self, addr): - self.addr = addr + def __init__(self, addr: Any) -> None: + self.addr: Any = addr @staticmethod - def HandleCall(translator, args, keywords): + def HandleCall(translator: Any, args: Any, keywords: Any) -> list[str]: """处理 c.Addr() 调用""" if args: - expr = translator.HandleExpr(args[0])[0] + expr: Any = translator.HandleExpr(args[0])[0] if isinstance(expr, str): return [f'&{expr}'] return [f'&{_to_str(expr)}'] @@ -365,14 +373,14 @@ class Addr: class Deref: """解引用""" - def __init__(self, ptr): - self.ptr = ptr + def __init__(self, ptr: Any) -> None: + self.ptr: Any = ptr @staticmethod - def HandleCall(translator, args, keywords): + def HandleCall(translator: Any, args: Any, keywords: Any) -> list[str]: """处理 c.Deref() 调用""" if args: - expr = translator.HandleExpr(args[0])[0] + expr: Any = translator.HandleExpr(args[0])[0] if hasattr(expr, 'op') and expr.op == '*': return [expr] return [f'*({_to_str(expr)})'] @@ -381,32 +389,32 @@ class Deref: class DerefAs: """解引用写入,等价于 *ptr = value""" - def __init__(self, ptr, value): - self.ptr = ptr - self.value = value + def __init__(self, ptr: Any, value: Any) -> None: + self.ptr: Any = ptr + self.value: Any = value @staticmethod - def HandleCall(translator, args, keywords): + def HandleCall(translator: Any, args: Any, keywords: Any) -> list[str]: """处理 c.DerefAs() 调用""" if len(args) >= 2: - ptr = translator.HandleExpr(args[0])[0] - val = translator.HandleExpr(args[1])[0] + ptr: Any = translator.HandleExpr(args[0])[0] + val: Any = translator.HandleExpr(args[1])[0] return [f'*({_to_str(ptr)}) = {_to_str(val)}'] return [] class Set: """设置值""" - def __init__(self, key, value): - self.key = key - self.value = value + def __init__(self, key: Any, value: Any) -> None: + self.key: Any = key + self.value: Any = value @staticmethod - def HandleCall(translator, args, keywords): + def HandleCall(translator: Any, args: Any, keywords: Any) -> list[str]: """处理 c.Set() 调用""" if len(args) >= 2: - target = translator.HandleExpr(args[0])[0] - value = translator.HandleExpr(args[1])[0] + target: Any = translator.HandleExpr(args[0])[0] + value: Any = translator.HandleExpr(args[1])[0] return [f'{_to_str(target)} = {_to_str(value)}'] return [] @@ -424,10 +432,10 @@ class CReturn: 3. return 语句使用 insert_value 构建结构体 4. 调用处使用 extract_value 提取各字段 """ - def __init__(self, *ReturnTypes): - self.ReturnTypes = ReturnTypes + def __init__(self, *ReturnTypes: Any) -> None: + self.ReturnTypes: tuple[Any, ...] = ReturnTypes - def __call__(self, func): + def __call__(self, func: Any) -> Any: """装饰器调用""" # 将返回类型信息附加到函数上 func._CreturnTypes = self.ReturnTypes @@ -436,20 +444,20 @@ class CReturn: class CDefine: """#define 宏定义""" - def __init__(self, name, value): - self.name = name - self.value = value + def __init__(self, name: Any, value: Any) -> None: + self.name: Any = name + self.value: Any = value @staticmethod - def HandleCall(translator, args, keywords): + def HandleCall(translator: Any, args: Any, keywords: Any) -> list[str]: """处理 c.CDefine() 调用""" if len(args) >= 1: if isinstance(args[0], ast.Constant): - name = args[0].value + name: Any = args[0].value else: name = 'MACRO' if len(args) >= 2: - value = translator.HandleExpr(args[1])[0] + value: Any = translator.HandleExpr(args[1])[0] return ['#define ' + str(name) + ' ' + _to_str(value)] return ['#define ' + str(name)] return [] @@ -457,65 +465,61 @@ class CDefine: class CIfndef: """#ifndef 条件编译""" - def __init__(self, condition): - self.condition = condition + def __init__(self, condition: Any) -> None: + self.condition: Any = condition @staticmethod - def HandleCall(translator, args, keywords): + def HandleCall(translator: Any, args: Any, keywords: Any) -> list[str]: """处理 c.CIfndef() 调用""" if args: - condition = translator.HandleExpr(args[0])[0] + condition: Any = translator.HandleExpr(args[0])[0] return ['#ifndef ' + _to_str(condition)] return ['#if 0'] class CIfdef: """#ifdef 条件编译""" - def __init__(self, condition): - self.condition = condition + def __init__(self, condition: Any) -> None: + self.condition: Any = condition @staticmethod - def HandleCall(translator, args, keywords): + def HandleCall(translator: Any, args: Any, keywords: Any) -> list[str]: """处理 c.CIfdef() 调用""" if args: - condition = translator.HandleExpr(args[0])[0] + condition: Any = translator.HandleExpr(args[0])[0] return ['#ifdef ' + _to_str(condition)] return ['#if 0'] class CError: """#error 错误信息""" - def __init__(self, condition): - self.condition = condition + def __init__(self, condition: Any) -> None: + self.condition: Any = condition @staticmethod - def HandleCall(translator, args, keywords): + def HandleCall(translator: Any, args: Any, keywords: Any) -> list[str]: """处理 c.CError() 调用""" if args: # 如果是字符串常量,保留引号 if isinstance(args[0], ast.Constant) and isinstance(args[0].value, str): return ['#error "' + args[0].value + '"'] - elif isinstance(args[0], ast.Str): - return ['#error "' + args[0].s + '"'] else: - condition = translator.HandleExpr(args[0])[0] + condition: Any = translator.HandleExpr(args[0])[0] return ['#error ' + _to_str(condition)] return ['#error "Error: Condition is not met."'] class TokenPast: """## 连接符""" - def __init__(self, left, right): - self.left = left - self.right = right + def __init__(self, left: Any, right: Any) -> None: + self.left: Any = left + self.right: Any = right @staticmethod - def HandleCall(translator, args, keywords): + def HandleCall(translator: Any, args: Any, keywords: Any) -> list[Any]: """处理 c.TokenPast() 调用""" if len(args) >= 2: # 处理左操作数 - 去掉引号 if isinstance(args[0], ast.Constant): - left = str(args[0].value) - elif isinstance(args[0], ast.Str): - left = str(args[0].s) + left: str = str(args[0].value) elif isinstance(args[0], ast.Name): left = args[0].id else: @@ -523,21 +527,19 @@ class TokenPast: # 处理右操作数 - 去掉引号 if isinstance(args[1], ast.Constant): - right = str(args[1].value) - elif isinstance(args[1], ast.Str): - right = str(args[1].s) + right: str = str(args[1].value) elif isinstance(args[1], ast.Name): right = args[1].id else: right = _to_str(translator.HandleExpr(args[1])[0]) # 返回字符串,但用特殊标记包装,让 _AstNodeToStr 能正确处理 - result = left + ' ## ' + right + result: str = left + ' ## ' + right # 使用一个特殊的类来包装结果,让 _AstNodeToStr 直接返回其值 class TokenPastResult: - def __init__(self, value): - self.value = value - def __str__(self): + def __init__(self, value: str) -> None: + self.value: str = value + def __str__(self) -> str: return self.value return [TokenPastResult(result)] return [''] @@ -545,67 +547,66 @@ class TokenPast: class CIf: """#if 条件编译""" - def __init__(self, condition): - self.condition = condition + def __init__(self, condition: Any) -> None: + self.condition: Any = condition @staticmethod - def HandleCall(translator, args, keywords): + def HandleCall(translator: Any, args: Any, keywords: Any) -> list[str]: """处理 c.CIf() 调用""" if args: - condition = translator.HandleExpr(args[0])[0] + condition: Any = translator.HandleExpr(args[0])[0] return ['#if ' + _to_str(condition)] return ['#if 0'] class CElif: """#elif 条件编译""" - def __init__(self, condition): - self.condition = condition + def __init__(self, condition: Any) -> None: + self.condition: Any = condition @staticmethod - def HandleCall(translator, args, keywords): + def HandleCall(translator: Any, args: Any, keywords: Any) -> list[str]: """处理 c.CElif() 调用""" if args: - condition = translator.HandleExpr(args[0])[0] + condition: Any = translator.HandleExpr(args[0])[0] return ['#elif ' + _to_str(condition)] return ['#else'] class CElse: """#else 条件编译""" - def __init__(self): + def __init__(self) -> None: pass @staticmethod - def HandleCall(translator, args, keywords): + def HandleCall(translator: Any, args: Any, keywords: Any) -> list[str]: """处理 c.CElse() 调用""" return ['#else'] class CEndif: """#endif 条件编译""" - def __init__(self): + def __init__(self) -> None: pass @staticmethod - def HandleCall(translator, args, keywords): + def HandleCall(translator: Any, args: Any, keywords: Any) -> list[str]: """处理 c.CEndif() 调用""" return ['#endif'] class CUndef: """#undef 取消宏定义""" - def __init__(self, name): - self.name = name + def __init__(self, name: Any) -> None: + self.name: Any = name @staticmethod - def HandleCall(translator, args, keywords): + def HandleCall(translator: Any, args: Any, keywords: Any) -> list[str]: """处理 c.CUndef(name) 调用""" - import ast if args: - arg = args[0] + arg: Any = args[0] if isinstance(arg, str): - name = arg + name: str = arg elif isinstance(arg, ast.Name): name = arg.id elif isinstance(arg, ast.Constant): @@ -625,12 +626,12 @@ class LLVMIR: c.LInp(expr) - 输入操作数,翻译后替换为对应的 LLVM 临时变量名 c.LOut(expr) - 输出操作数,翻译后替换为对应的 LLVM 临时变量名 """ - def __init__(self, ir_template, ret_type=None): - self.ir_template = ir_template - self.ret_type = ret_type + def __init__(self, ir_template: Any, ret_type: Any = None) -> None: + self.ir_template: Any = ir_template + self.ret_type: Any = ret_type @staticmethod - def HandleCall(translator, args, keywords): + def HandleCall(translator: Any, args: Any, keywords: Any) -> list[str]: return ['/* LLVMIR */'] @@ -640,11 +641,11 @@ class LInp: 用法: c.LInp(expr) - 标记 expr 为输入操作数 在 c.LLVMIR 的 f-string 中使用,翻译后替换为 %N 形式的操作数引用 """ - def __init__(self, value): - self.value = value + def __init__(self, value: Any) -> None: + self.value: Any = value @staticmethod - def HandleCall(translator, args, keywords): + def HandleCall(translator: Any, args: Any, keywords: Any) -> list[Any]: return [] @@ -654,11 +655,11 @@ class LOut: 用法: c.LOut(expr) - 标记 expr 为输出操作数 在 c.LLVMIR 的 f-string 中使用,翻译后替换为 %N 形式的操作数引用 """ - def __init__(self, value): - self.value = value + def __init__(self, value: Any) -> None: + self.value: Any = value @staticmethod - def HandleCall(translator, args, keywords): + def HandleCall(translator: Any, args: Any, keywords: Any) -> list[Any]: return [] @@ -668,20 +669,18 @@ class CPragma: 用于生成 C 语言的 #pragma 指令。 例如:c.CPragma("GCC diagnostic push") 生成 #pragma GCC diagnostic push """ - def __init__(self, directive): - self.directive = directive + def __init__(self, directive: Any) -> None: + self.directive: Any = directive @staticmethod - def HandleCall(translator, args, keywords): + def HandleCall(translator: Any, args: Any, keywords: Any) -> list[str]: """处理 c.CPragma() 调用""" if args: - arg = args[0] + arg: Any = args[0] if isinstance(arg, ast.Constant): - directive = arg.value - elif isinstance(arg, ast.Str): - directive = arg.s + directive: Any = arg.value else: - expr = translator.HandleExpr(arg)[0] + expr: Any = translator.HandleExpr(arg)[0] directive = _to_str(expr) return [f'#pragma {directive}'] return ['#pragma'] @@ -716,10 +715,10 @@ Library_C = { class Attribute: """函数/变量属性装饰器""" - def __init__(self, *attrs): - self.attrs = attrs + def __init__(self, *attrs: Any) -> None: + self.attrs: tuple[Any, ...] = attrs - def __call__(self, func): + def __call__(self, func: Any) -> Any: # 将属性附加到函数上 func._c_attributes = self.attrs return func diff --git a/lib/includes/t.py b/lib/includes/t.py index 09400d5..dcb7134 100644 --- a/lib/includes/t.py +++ b/lib/includes/t.py @@ -1,17 +1,26 @@ # 类型定义模块 +from __future__ import annotations import re +import sys import types -from typing import TypeVar, Generic, TypeAlias +from typing import Any, Callable, ClassVar, Optional, TypeVar, Generic, TypeAlias + +from lib.constants.config import mode as _ConfigMode +from lib.core.VLogger import get_logger as _vlog # ============================================================================= # 类型映射常量 # ============================================================================= -# 类型映射常量(由 _build_type_maps() 在模块末尾自动生成) -_BASIC_TYPES_MAP = {} -_T_TYPE_PATTERNS = [] +# 标记基类注册表(由 @_marker_base 装饰器自动注册,或手动添加) +_MARKER_BASES: set[str] = set() + +def _marker_base(cls: type) -> type: + """将类名注册为标记基类,供 HandlesClassDef 检测使用""" + _MARKER_BASES.add(cls.__name__) + return cls # 平台相关类型的默认 Size(可由 configure_platform 修改) _LONG_SIZE = 64 @@ -22,7 +31,7 @@ _INTPTR_T_SIZE = 64 _UINTPTR_T_SIZE = 64 _PTRDIFF_T_SIZE = 64 -def configure_platform(triple=None): +def configure_platform(triple: Optional[str] = None) -> None: """根据目标三元组配置平台相关类型的大小 Args: @@ -32,9 +41,9 @@ def configure_platform(triple=None): global _SIZE_T_SIZE, _INTPTR_T_SIZE, _UINTPTR_T_SIZE, _PTRDIFF_T_SIZE if not triple: return - triple_lower = triple.lower() - is_windows = any(k in triple_lower for k in ('windows', 'win32', 'mingw', 'msvc', 'cygwin')) - is_32bit = any(k in triple_lower for k in ('i386', 'i686')) + triple_lower: str = triple.lower() + is_windows: bool = any(k in triple_lower for k in ('windows', 'win32', 'mingw', 'msvc', 'cygwin')) + is_32bit: bool = any(k in triple_lower for k in ('i386', 'i686')) if is_windows: _LONG_SIZE = 32 # Windows LLP64: long = 32 位 _UNSIGNED_LONG_SIZE = 32 @@ -45,24 +54,6 @@ def configure_platform(triple=None): _UINTPTR_T_SIZE = 32 _PTRDIFF_T_SIZE = 32 -def _build_type_maps(): - global _BASIC_TYPES_MAP, _T_TYPE_PATTERNS - for _name in dir(): - _obj = eval(_name) - if isinstance(_obj, type) and issubclass(_obj, CType) and _obj is not CType: - try: - _inst = _obj() - _cname = getattr(_inst, 'CName', '') - if _cname and _obj.IsBasicType(): - _BASIC_TYPES_MAP[_cname] = _cname - _T_TYPE_PATTERNS.append((_name, _cname)) - except Exception as _e: - from lib.core.VLogger import get_logger as _vlog - from lib.constants.config import mode as _ConfigMode - if _ConfigMode == "strict": - raise - _vlog().warning(f"构建类型映射时实例化 CType 子类失败: {_e}", "Exception") - # ============================================================================= # CType 基类 @@ -71,33 +62,31 @@ def _build_type_maps(): class CType: """C 类型基类""" - PREFIX = 'prefix' - BASE = 'base' - POINTER = 'ptr' - ARRAY = 'array' - NAMED = 'named' - STORAGE_CLASS = 'storage_class' - TYPE_QUALIFIER = 'type_qualifier' + PREFIX: ClassVar[str] = 'prefix' + BASE: ClassVar[str] = 'base' + POINTER: ClassVar[str] = 'ptr' + ARRAY: ClassVar[str] = 'array' + NAMED: ClassVar[str] = 'named' + STORAGE_CLASS: ClassVar[str] = 'storage_class' + TYPE_QUALIFIER: ClassVar[str] = 'type_qualifier' - position = frozenset({BASE}) # 类属性,支持联合类型如 BASE | SPECIAL + position: ClassVar[frozenset[str]] = frozenset({BASE}) # 类属性,支持联合类型如 BASE | SPECIAL - def __init__(self, value=None, *types): - self.value = value - self.types = types - self.Name = '' - self.IsBasicType = False - self.IsPointer = False - self.IsSigned = None - self.Size = None - if not hasattr(self, 'CName'): - self.CName = '' + def __init__(self, value: Any = None, *types: Any) -> None: + self.value: Any = value + self.types: tuple[Any, ...] = types + self.Name: str = '' + self.IsBasicType: bool = False + self.IsPointer: bool = False + self.IsSigned: Optional[bool] = None + self.Size: Optional[int] = None - def GetPositions(self) -> frozenset: + def GetPositions(self) -> frozenset[str]: """获取 position 的 frozenset 形式""" return self.position @classmethod - def HasPosition(cls, pos) -> bool: + def HasPosition(cls, pos: str) -> bool: """检查是否包含指定的位置""" return pos in cls.position @@ -126,25 +115,21 @@ class CType: """检查是否是前缀类型""" return cls.PREFIX in cls.position - def rfind(self, s): + def rfind(self, s: str) -> None: """注解""" pass - def get_position(self): + def get_position(self) -> frozenset[str]: """获取类型在声明中的位置""" return self.position - def GetCName(self): - """获取 C 类型名称""" - return self.CName - - def __merge__(self, types): + def __merge__(self, types: Any) -> Any: return types - def __or__(self, other): + def __or__(self, other: Any) -> list[Any]: return [self, other] - def __set_default__(self, **kwargs): + def __set_default__(self, **kwargs: Any) -> CTypeDefault: """设置默认值/初始值,用于 static/global 变量的初始化 Args: @@ -155,55 +140,7 @@ class CType: """ return CTypeDefault(self, **kwargs) - @classmethod - def FromAnnotation(cls, AnnotationStr, TypeName=''): - """从类型注解字符串解析类型信息 - - Args: - AnnotationStr: 类型注解的字符串表示(ast.dump结果) - TypeName: 类型名称(可选) - - Returns: - CType 实例 - """ - ctype = cls() - - # 检查是否是基本类型 - if TypeName in _BASIC_TYPES_MAP: - ctype.IsBasicType = True - ctype.Name = _BASIC_TYPES_MAP[TypeName] - else: - for pattern, c_name in _T_TYPE_PATTERNS: - if pattern in AnnotationStr: - ctype.IsBasicType = True - ctype.Name = c_name - break - - # 检查是否包含指针 - if 'CPtr' in AnnotationStr: - ctype.IsPointer = True - - return ctype - - @classmethod - def FromTypeName(cls, TypeName): - """从类型名称创建 CType - - Args: - TypeName: 类型名称 - - Returns: - CType 实例 - """ - ctype = cls() - - if TypeName in _BASIC_TYPES_MAP: - ctype.IsBasicType = True - ctype.Name = _BASIC_TYPES_MAP[TypeName] - - return ctype - - def GetFullType(self, VarName='', ArraySizeStr=''): + def GetFullType(self, VarName: str = '', ArraySizeStr: str = '') -> str: """获取完整的类型声明字符串 Args: @@ -213,184 +150,180 @@ class CType: Returns: 完整的类型声明字符串 """ - ptr_str = '*' if self.IsPointer else '' + ptr_str: str = '*' if self.IsPointer else '' if VarName: return f'{self.Name}{ptr_str} {VarName}{ArraySizeStr}' return f'{self.Name}{ptr_str}' - def __repr__(self): - ptr_str = '*' if self.IsPointer else '' + def __repr__(self) -> str: + ptr_str: str = '*' if self.IsPointer else '' return f'CType({self.Name}{ptr_str}, IsBasicType={self.IsBasicType})' class CChar(CType): - def __init__(self, value=None): - self.CName = 'char' + def __init__(self, value: Any = None) -> None: super().__init__(value) - self.IsSigned = True - self.Size = 8 + self.IsSigned: bool = True + self.Size: int = 8 class CInt(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'int' + position: ClassVar[frozenset[str]] = frozenset({CType.BASE}) + def __init__(self, value: Any = None) -> None: super().__init__(value) - self.IsSigned = True - self.Size = 32 + self.IsSigned: bool = True + self.Size: int = 32 class CShort(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'short' + position: ClassVar[frozenset[str]] = frozenset({CType.BASE}) + def __init__(self, value: Any = None) -> None: super().__init__(value) - self.IsSigned = True - self.Size = 16 + self.IsSigned: bool = True + self.Size: int = 16 class CLong(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'long' + position: ClassVar[frozenset[str]] = frozenset({CType.BASE}) + def __init__(self, value: Any = None) -> None: super().__init__(value) - self.IsSigned = True - self.Size = _LONG_SIZE + self.IsSigned: bool = True + self.Size: int = _LONG_SIZE + +class CLongLong(CType): + position: ClassVar[frozenset[str]] = frozenset({CType.BASE}) + def __init__(self, value: Any = None) -> None: + super().__init__(value) + self.IsSigned: bool = True + self.Size: int = 64 class CFloat(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'float' + position: ClassVar[frozenset[str]] = frozenset({CType.BASE}) + def __init__(self, value: Any = None) -> None: super().__init__(value) - self.IsSigned = None - self.Size = 32 + self.IsSigned: Optional[bool] = None + self.Size: int = 32 class CDouble(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'double' + position: ClassVar[frozenset[str]] = frozenset({CType.BASE}) + def __init__(self, value: Any = None) -> None: super().__init__(value) - self.IsSigned = None - self.Size = 64 + self.IsSigned: Optional[bool] = None + self.Size: int = 64 class CFloat8T(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'float8_t' + position: ClassVar[frozenset[str]] = frozenset({CType.BASE}) + def __init__(self, value: Any = None) -> None: super().__init__(value) - self.IsSigned = None - self.Size = 8 + self.IsSigned: Optional[bool] = None + self.Size: int = 8 class CFloat16T(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'float16_t' + position: ClassVar[frozenset[str]] = frozenset({CType.BASE}) + def __init__(self, value: Any = None) -> None: super().__init__(value) - self.IsSigned = None - self.Size = 16 + self.IsSigned: Optional[bool] = None + self.Size: int = 16 class CFloat32T(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'float32_t' + position: ClassVar[frozenset[str]] = frozenset({CType.BASE}) + def __init__(self, value: Any = None) -> None: super().__init__(value) - self.IsSigned = None - self.Size = 32 + self.IsSigned: Optional[bool] = None + self.Size: int = 32 class CFloat64T(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'float64_t' + position: ClassVar[frozenset[str]] = frozenset({CType.BASE}) + def __init__(self, value: Any = None) -> None: super().__init__(value) - self.IsSigned = None - self.Size = 64 + self.IsSigned: Optional[bool] = None + self.Size: int = 64 class CFloat128T(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'float128_t' + position: ClassVar[frozenset[str]] = frozenset({CType.BASE}) + def __init__(self, value: Any = None) -> None: super().__init__(value) - self.IsSigned = None - self.Size = 128 + self.IsSigned: Optional[bool] = None + self.Size: int = 128 class CVoid(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'void' + position: ClassVar[frozenset[str]] = frozenset({CType.BASE}) + def __init__(self, value: Any = None) -> None: super().__init__(value) - self.IsSigned = None - self.Size = 0 + self.IsSigned: Optional[bool] = None + self.Size: int = 0 class CUnsigned(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'unsigned' + position: ClassVar[frozenset[str]] = frozenset({CType.BASE}) + def __init__(self, value: Any = None) -> None: super().__init__(value) - self.IsSigned = False - self.Size = 32 + self.IsSigned: bool = False + self.Size: int = 32 class CUnsignedChar(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'unsigned char' + position: ClassVar[frozenset[str]] = frozenset({CType.BASE}) + def __init__(self, value: Any = None) -> None: super().__init__(value) - self.IsSigned = False - self.Size = 8 + self.IsSigned: bool = False + self.Size: int = 8 class CUnsignedInt(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'unsigned int' + position: ClassVar[frozenset[str]] = frozenset({CType.BASE}) + def __init__(self, value: Any = None) -> None: super().__init__(value) - self.IsSigned = False - self.Size = 32 + self.IsSigned: bool = False + self.Size: int = 32 class CUnsignedShort(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'unsigned short' + position: ClassVar[frozenset[str]] = frozenset({CType.BASE}) + def __init__(self, value: Any = None) -> None: super().__init__(value) - self.IsSigned = False - self.Size = 16 + self.IsSigned: bool = False + self.Size: int = 16 class CUnsignedLong(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'unsigned long' + position: ClassVar[frozenset[str]] = frozenset({CType.BASE}) + def __init__(self, value: Any = None) -> None: super().__init__(value) - self.IsSigned = False - self.Size = _UNSIGNED_LONG_SIZE + self.IsSigned: bool = False + self.Size: int = _UNSIGNED_LONG_SIZE + +class CUnsignedLongLong(CType): + position: ClassVar[frozenset[str]] = frozenset({CType.BASE}) + def __init__(self, value: Any = None) -> None: + super().__init__(value) + self.IsSigned: bool = False + self.Size: int = 64 class CSignedChar(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'signed char' + position: ClassVar[frozenset[str]] = frozenset({CType.BASE}) + def __init__(self, value: Any = None) -> None: super().__init__(value) - self.IsSigned = True - self.Size = 8 + self.IsSigned: bool = True + self.Size: int = 8 +@_marker_base class CStruct(CType): - position = frozenset({CType.BASE, CType.NAMED}) - def __init__(self, value=None, name=None): - self.name = name - self.CName = f'struct {name}' if name else 'struct' + position: ClassVar[frozenset[str]] = frozenset({CType.BASE, CType.NAMED}) + def __init__(self, value: Any = None, name: Optional[str] = None) -> None: + self.name: Optional[str] = name super().__init__(value) +@_marker_base class CUnion(CType): - position = frozenset({CType.BASE, CType.NAMED}) - def __init__(self, value=None): - self.CName = 'union' + position: ClassVar[frozenset[str]] = frozenset({CType.BASE, CType.NAMED}) + def __init__(self, value: Any = None) -> None: super().__init__(value) +@_marker_base class CEnum(CType): - position = frozenset({CType.BASE, CType.NAMED}) - def __init__(self, value=None): - self.CName = 'enum' + position: ClassVar[frozenset[str]] = frozenset({CType.BASE, CType.NAMED}) + def __init__(self, value: Any = None) -> None: super().__init__(value) Enum = CEnum +@_marker_base class REnum(CType): - position = frozenset({CType.BASE, CType.NAMED}) + position: ClassVar[frozenset[str]] = frozenset({CType.BASE, CType.NAMED}) tag: int = 0 # 无用,只是个标记 - def __init__(self, value=None): - self.CName = 'renum' + def __init__(self, value: Any = None) -> None: super().__init__(value) ''' @@ -398,229 +331,228 @@ class Object(CType): """Python 对象类型,用于支持类方法外联函数""" position = frozenset({CType.BASE, CType.NAMED}) def __init__(self, value=None): - self.CName = 'struct' super().__init__(value) def __call__(self, cls): return cls ''' -def Object(): +def Object() -> None: pass -def CVTable(): +def CVTable() -> None: pass -CTypedef = TypeAlias +def TLS() -> None: + """标记函数为 TLS 初始化函数,首次调用时执行,后续调用跳过。 + 编译器自动生成全局标志变量和一次性执行检查代码。 + """ + pass + +# Object 和 CVTable 是普通函数,Exception 是 Python 内建类型,Enum 是 CEnum 的别名 +# 这些名称无法通过 @_marker_base 装饰器自动注册,需手动添加到 _MARKER_BASES +# TLS 是函数装饰器标记,由编译器在函数处理阶段识别 +_MARKER_BASES.update({'Object', 'CVTable', 'Exception', 'Enum'}) + +CTypedef: TypeAlias = TypeAlias class _CTypedef(CType): - position = frozenset({CType.PREFIX, CType.NAMED}) - def __init__(self, value=None): - self.CName = 'typedef' + position: ClassVar[frozenset[str]] = frozenset({CType.PREFIX, CType.NAMED}) + def __init__(self, value: Any = None) -> None: super().__init__(value) class CAuto(CType): - position = frozenset({CType.PREFIX}) - def __init__(self, value=None): - self.CName = 'auto' + position: ClassVar[frozenset[str]] = frozenset({CType.PREFIX}) + def __init__(self, value: Any = None) -> None: super().__init__(value) class CRegister(CType): - position = frozenset({CType.PREFIX, CType.STORAGE_CLASS}) - def __init__(self, value=None): - self.CName = 'register' + position: ClassVar[frozenset[str]] = frozenset({CType.PREFIX, CType.STORAGE_CLASS}) + def __init__(self, value: Any = None) -> None: super().__init__(value) class CStatic(CType): - position = frozenset({CType.PREFIX, CType.STORAGE_CLASS}) - def __init__(self, value=None): - self.CName = 'static' + position: ClassVar[frozenset[str]] = frozenset({CType.PREFIX, CType.STORAGE_CLASS}) + def __init__(self, value: Any = None) -> None: super().__init__(value) class CExtern(CType): - position = frozenset({CType.PREFIX, CType.STORAGE_CLASS}) - def __init__(self, value=None): - self.CName = 'extern' + position: ClassVar[frozenset[str]] = frozenset({CType.PREFIX, CType.STORAGE_CLASS}) + def __init__(self, value: Any = None) -> None: super().__init__(value) class CConst(CType): - position = frozenset({CType.PREFIX, CType.TYPE_QUALIFIER}) - def __init__(self, value=None): - self.CName = 'const' + position: ClassVar[frozenset[str]] = frozenset({CType.PREFIX, CType.TYPE_QUALIFIER}) + def __init__(self, value: Any = None) -> None: super().__init__(value) class CInline(CType): - position = frozenset({CType.PREFIX, CType.STORAGE_CLASS}) - def __init__(self, value=None): - self.CName = 'inline' + position: ClassVar[frozenset[str]] = frozenset({CType.PREFIX, CType.STORAGE_CLASS}) + def __init__(self, value: Any = None) -> None: super().__init__(value) class CExport(CType): - position = frozenset({CType.PREFIX, CType.STORAGE_CLASS}) - def __init__(self, value=None): - self.CName = 'export' + position: ClassVar[frozenset[str]] = frozenset({CType.PREFIX, CType.STORAGE_CLASS}) + def __init__(self, value: Any = None) -> None: super().__init__(value) class CVolatile(CType): - position = frozenset({CType.PREFIX, CType.TYPE_QUALIFIER}) - def __init__(self, value=None): - self.CName = 'volatile' + position: ClassVar[frozenset[str]] = frozenset({CType.PREFIX, CType.TYPE_QUALIFIER}) + def __init__(self, value: Any = None) -> None: super().__init__(value) class CSizeT(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'size_t' + position: ClassVar[frozenset[str]] = frozenset({CType.BASE}) + def __init__(self, value: Any = None) -> None: super().__init__(value) - self.IsSigned = False - self.Size = _SIZE_T_SIZE + self.IsSigned: bool = False + self.Size: int = _SIZE_T_SIZE class CInt8T(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'int8_t' + position: ClassVar[frozenset[str]] = frozenset({CType.BASE}) + def __init__(self, value: Any = None) -> None: super().__init__(value) - self.IsSigned = True - self.Size = 8 + self.IsSigned: bool = True + self.Size: int = 8 class CInt16T(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'int16_t' + position: ClassVar[frozenset[str]] = frozenset({CType.BASE}) + def __init__(self, value: Any = None) -> None: super().__init__(value) - self.IsSigned = True - self.Size = 16 + self.IsSigned: bool = True + self.Size: int = 16 class CInt32T(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'int32_t' + position: ClassVar[frozenset[str]] = frozenset({CType.BASE}) + def __init__(self, value: Any = None) -> None: super().__init__(value) - self.IsSigned = True - self.Size = 32 + self.IsSigned: bool = True + self.Size: int = 32 class CInt64T(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'int64_t' + position: ClassVar[frozenset[str]] = frozenset({CType.BASE}) + def __init__(self, value: Any = None) -> None: super().__init__(value) - self.IsSigned = True - self.Size = 64 + self.IsSigned: bool = True + self.Size: int = 64 class CUInt8T(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'uint8_t' + position: ClassVar[frozenset[str]] = frozenset({CType.BASE}) + def __init__(self, value: Any = None) -> None: super().__init__(value) - self.IsSigned = False - self.Size = 8 + self.IsSigned: bool = False + self.Size: int = 8 class CUInt16T(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'uint16_t' + position: ClassVar[frozenset[str]] = frozenset({CType.BASE}) + def __init__(self, value: Any = None) -> None: super().__init__(value) - self.IsSigned = False - self.Size = 16 + self.IsSigned: bool = False + self.Size: int = 16 class CUInt32T(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'uint32_t' + position: ClassVar[frozenset[str]] = frozenset({CType.BASE}) + def __init__(self, value: Any = None) -> None: super().__init__(value) - self.IsSigned = False - self.Size = 32 + self.IsSigned: bool = False + self.Size: int = 32 class CUInt64T(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'uint64_t' + position: ClassVar[frozenset[str]] = frozenset({CType.BASE}) + def __init__(self, value: Any = None) -> None: super().__init__(value) - self.IsSigned = False - self.Size = 64 + self.IsSigned: bool = False + self.Size: int = 64 class CIntPtrT(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'intptr_t' + position: ClassVar[frozenset[str]] = frozenset({CType.BASE}) + def __init__(self, value: Any = None) -> None: super().__init__(value) - self.IsSigned = True - self.Size = _INTPTR_T_SIZE + self.IsSigned: bool = True + self.Size: int = _INTPTR_T_SIZE class CUIntPtrT(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'uintptr_t' + position: ClassVar[frozenset[str]] = frozenset({CType.BASE}) + def __init__(self, value: Any = None) -> None: super().__init__(value) - self.IsSigned = False - self.Size = _UINTPTR_T_SIZE + self.IsSigned: bool = False + self.Size: int = _UINTPTR_T_SIZE class CPtrDiffT(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'ptrdiff_t' + position: ClassVar[frozenset[str]] = frozenset({CType.BASE}) + def __init__(self, value: Any = None) -> None: super().__init__(value) - self.IsSigned = True - self.Size = _PTRDIFF_T_SIZE + self.IsSigned: bool = True + self.Size: int = _PTRDIFF_T_SIZE class CWCharT(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'wchar_t' + position: ClassVar[frozenset[str]] = frozenset({CType.BASE}) + def __init__(self, value: Any = None) -> None: super().__init__(value) - self.IsSigned = True - self.Size = _WCHAR_T_SIZE + self.IsSigned: bool = True + self.Size: int = _WCHAR_T_SIZE class CChar8T(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'char8_t' + position: ClassVar[frozenset[str]] = frozenset({CType.BASE}) + def __init__(self, value: Any = None) -> None: super().__init__(value) - self.IsSigned = False - self.Size = 8 + self.IsSigned: bool = False + self.Size: int = 8 class CChar16T(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'char16_t' + position: ClassVar[frozenset[str]] = frozenset({CType.BASE}) + def __init__(self, value: Any = None) -> None: super().__init__(value) - self.IsSigned = False - self.Size = 16 + self.IsSigned: bool = False + self.Size: int = 16 class CChar32T(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'char32_t' + position: ClassVar[frozenset[str]] = frozenset({CType.BASE}) + def __init__(self, value: Any = None) -> None: super().__init__(value) - self.IsSigned = False - self.Size = 32 + self.IsSigned: bool = False + self.Size: int = 32 class CBool(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = 'bool' + position: ClassVar[frozenset[str]] = frozenset({CType.BASE}) + def __init__(self, value: Any = None) -> None: super().__init__(value) - self.IsSigned = False - self.Size = 8 + self.IsSigned: bool = False + self.Size: int = 8 class CComplex(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = '_Complex' + position: ClassVar[frozenset[str]] = frozenset({CType.BASE}) + def __init__(self, value: Any = None) -> None: super().__init__(value) class CImaginary(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = '_Imaginary' + position: ClassVar[frozenset[str]] = frozenset({CType.BASE}) + def __init__(self, value: Any = None) -> None: super().__init__(value) T = TypeVar("T") Callable = Generic[T] class CPtr(CType, Generic[T]): - position = frozenset({CType.POINTER}) - def __init__(self, value=None): - self.CName = '*' + position: ClassVar[frozenset[str]] = frozenset({CType.POINTER}) + def __init__(self, value: Any = None) -> None: + super().__init__(value) + +class CNeedPtr(CPtr): + """函数签名注解:自动取地址(仅对非指针值)。 + 用作参数类型时,编译器在调用处自动将非指针值取地址为指针。 + 若参数已经是指针,则不做操作。""" + position: ClassVar[frozenset[str]] = frozenset({CType.POINTER}) + auto_addr_mode: ClassVar[str] = 'need' + def __init__(self, value: Any = None) -> None: + super().__init__(value) + +class CAutoPtr(CPtr): + """函数签名注解:无条件取地址。 + 用作参数类型时,编译器在调用处无条件将值取地址为指针, + 即使值本身已经是指针也会再取一层地址。""" + position: ClassVar[frozenset[str]] = frozenset({CType.POINTER}) + auto_addr_mode: ClassVar[str] = 'always' + def __init__(self, value: Any = None) -> None: super().__init__(value) class CTypeDefault(CType): @@ -628,49 +560,56 @@ class CTypeDefault(CType): 当使用 t.CStatic.__set_default__(open=mouse_open, ...) 时创建 """ - def __init__(self, BaseType, **kwargs): + def __init__(self, BaseType: Any, **kwargs: Any) -> None: super().__init__() - self.BaseType = BaseType - self.defaults = kwargs - self.CName = BaseType.CName if hasattr(BaseType, 'CName') else '' - self.position = BaseType.position if hasattr(BaseType, 'position') else CType.BASE + self.BaseType: Any = BaseType + self.defaults: dict[str, Any] = kwargs + self.position: frozenset[str] = BaseType.position if hasattr(BaseType, 'position') else CType.BASE - def __repr__(self): + def __repr__(self) -> str: return f'CTypeDefault({self.BaseType}, {self.defaults})' class CArrayPtr(CType): - position = frozenset({CType.POINTER}) - def __init__(self, value=None): - self.CName = '(*)' # 特殊标记表示数组指针 + position: ClassVar[frozenset[str]] = frozenset({CType.POINTER}) + def __init__(self, value: Any = None) -> None: super().__init__(value) +class CArray(CType): + """栈上固定数组类型注解。 + 用法: names: t.CArray[VOIDPTR, 32] # void*[32] + data: t.CArray[t.CInt, 64] # int[64] + 第一个参数为元素类型,第二个参数为数组大小(整数或常量名)。""" + position: ClassVar[frozenset[str]] = frozenset({CType.ARRAY}) + def __init__(self, value: Any = None) -> None: + super().__init__(value) + def __class_getitem__(cls, item: Any) -> type: + return cls + class CDefine(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = '#define' + position: ClassVar[frozenset[str]] = frozenset({CType.BASE}) + def __init__(self, value: Any = None) -> None: super().__init__(value) class CPass(CType): - position = frozenset({CType.BASE}) - def __init__(self, value=None): - self.CName = '' + position: ClassVar[frozenset[str]] = frozenset({CType.BASE}) + def __init__(self, value: Any = None) -> None: super().__init__(value) class State(CType): """状态标记,用于仅声明不定义,等价于 CExport | CExtern""" - position = frozenset({CType.PREFIX, CType.STORAGE_CLASS}) + position: ClassVar[frozenset[str]] = frozenset({CType.PREFIX, CType.STORAGE_CLASS}) @staticmethod - def HandleCall(translator, args, keywords): + def HandleCall(translator: Any, args: Any, keywords: Any) -> list[str]: """处理 t.State() 调用""" return ['t.State'] class Postdefinition: - def __init__(self, c): + def __init__(self, c: Any) -> None: pass class Bit: - def __init__(self, i): + def __init__(self, i: Any) -> None: pass class BigEndian(CType): @@ -683,9 +622,9 @@ class BigEndian(CType): class MyStruct: a: t.CInt | t.BigEndian # 大端序存储的整数 """ - IsSigned = True - Size = 32 - Align = 32 + IsSigned: ClassVar[bool] = True + Size: ClassVar[int] = 32 + Align: ClassVar[int] = 32 class LittleEndian(CType): """小端序(Little-Endian)字节序标记类 @@ -697,9 +636,9 @@ class LittleEndian(CType): class MyStruct: b: t.CInt | t.LittleEndian # 小端序存储的整数 """ - IsSigned = True - Size = 32 - Align = 32 + IsSigned: ClassVar[bool] = True + Size: ClassVar[int] = 32 + Align: ClassVar[int] = 32 class ASM_DESCR: """内嵌 ASM 破坏描述符类 @@ -872,186 +811,186 @@ class ASM_DESCR: # 定义 ASM_LIST,包含所有可能的汇编约束字符 -ASM_LIST = ASM_DESCR.ALL +ASM_LIST: list[str] = ASM_DESCR.ALL class attr: """C 语言 __attribute__ 属性操作类型""" @staticmethod - def noreturn(): + def noreturn() -> str: return "noreturn" @staticmethod - def format(printf, arg1, arg2): + def format(printf: Any, arg1: Any, arg2: Any) -> str: return f"format({printf}, {arg1}, {arg2})" @staticmethod - def section(name): + def section(name: str) -> str: return f'section("{name}")' @staticmethod - def aligned(bytes): + def aligned(bytes: int) -> str: return f"aligned({bytes})" @staticmethod - def packed(): + def packed() -> str: return "packed" @staticmethod - def unused(): + def unused() -> str: return "unused" @staticmethod - def used(): + def used() -> str: return "used" @staticmethod - def weak(): + def weak() -> str: return "weak" @staticmethod - def alias(name): + def alias(name: str) -> str: return f'alias("{name}")' @staticmethod - def visibility(type): + def visibility(type: str) -> str: return f'visibility("{type}")' @staticmethod - def constructor(): + def constructor() -> str: return "constructor" @staticmethod - def destructor(): + def destructor() -> str: return "destructor" @staticmethod - def always_inline(): + def always_inline() -> str: return "always_inline" @staticmethod - def noinline(): + def noinline() -> str: return "noinline" @staticmethod - def pure(): + def pure() -> str: return "pure" @staticmethod - def const(): + def const() -> str: return "const" @staticmethod - def malloc(): + def malloc() -> str: return "malloc" @staticmethod - def alloc_size(n): + def alloc_size(n: int) -> str: return f"alloc_size({n})" @staticmethod - def warn_unused_result(): + def warn_unused_result() -> str: return "warn_unused_result" @staticmethod - def deprecated(msg=None): + def deprecated(msg: Optional[str] = None) -> str: if msg: return f'deprecated("{msg}")' return "deprecated" @staticmethod - def fallthrough(): + def fallthrough() -> str: return "fallthrough" @staticmethod - def likely(): + def likely() -> str: return "likely" @staticmethod - def unlikely(): + def unlikely() -> str: return "unlikely" @staticmethod - def hot(): + def hot() -> str: return "hot" @staticmethod - def cold(): + def cold() -> str: return "cold" @staticmethod - def interrupt(): + def interrupt() -> str: return "interrupt" @staticmethod - def naked(): + def naked() -> str: return "naked" @staticmethod - def sentinel(n=0): + def sentinel(n: int = 0) -> str: return f"sentinel({n})" @staticmethod - def nonnull(*args): + def nonnull(*args: Any) -> str: if args: return f"nonnull({', '.join(map(str, args))})" return "nonnull" @staticmethod - def returns_nonnull(): + def returns_nonnull() -> str: return "returns_nonnull" @staticmethod - def access(mode, *args): + def access(mode: Any, *args: Any) -> str: return f"access({mode}, {', '.join(map(str, args))})" @staticmethod - def cleanup(func): + def cleanup(func: str) -> str: return f'cleanup({func})' @staticmethod - def transparent_union(): + def transparent_union() -> str: return "transparent_union" @staticmethod - def mode(mode_name): + def mode(mode_name: str) -> str: return f"mode({mode_name})" @staticmethod - def vector_size(bytes): + def vector_size(bytes: int) -> str: return f"vector_size({bytes})" @staticmethod - def target(string): + def target(string: str) -> str: return f'target("{string}")' @staticmethod - def optimize(level): + def optimize(level: str) -> str: return f'optimize("{level}")' @staticmethod - def no_instrument_function(): + def no_instrument_function() -> str: return "no_instrument_function" @staticmethod - def no_sanitize(type): + def no_sanitize(type: str) -> str: return f"no_sanitize({type})" @staticmethod - def no_stack_protector(): + def no_stack_protector() -> str: return "no_stack_protector" @staticmethod - def stack_protector(): + def stack_protector() -> str: return "stack_protector" @staticmethod - def error(msg): + def error(msg: str) -> str: return f'error("{msg}")' @staticmethod - def warning(msg): + def warning(msg: str) -> str: return f'warning("{msg}")' class llvm: @@ -1062,47 +1001,47 @@ class attr: """ class nobuiltin: - CName = '#attr.llvm.nobuiltin' + CName: ClassVar[str] = '#attr.llvm.nobuiltin' class nounwind: - CName = '#attr.llvm.nounwind' + CName: ClassVar[str] = '#attr.llvm.nounwind' class noredzone: - CName = '#attr.llvm.noredzone' + CName: ClassVar[str] = '#attr.llvm.noredzone' class willreturn: - CName = '#attr.llvm.willreturn' + CName: ClassVar[str] = '#attr.llvm.willreturn' class mustprogress: - CName = '#attr.llvm.mustprogress' + CName: ClassVar[str] = '#attr.llvm.mustprogress' class optnone: - CName = '#attr.llvm.optnone' + CName: ClassVar[str] = '#attr.llvm.optnone' class noinline: - CName = '#attr.llvm.noinline' + CName: ClassVar[str] = '#attr.llvm.noinline' class alwaysinline: - CName = '#attr.llvm.alwaysinline' + CName: ClassVar[str] = '#attr.llvm.alwaysinline' class readnone: - CName = '#attr.llvm.readnone' + CName: ClassVar[str] = '#attr.llvm.readnone' class readonly: - CName = '#attr.llvm.readonly' + CName: ClassVar[str] = '#attr.llvm.readonly' class writeonly: - CName = '#attr.llvm.writeonly' + CName: ClassVar[str] = '#attr.llvm.writeonly' class inaccessiblememonly: - CName = '#attr.llvm.inaccessiblememonly' + CName: ClassVar[str] = '#attr.llvm.inaccessiblememonly' class inaccessiblemem_or_argmemonly: - CName = '#attr.llvm.inaccessiblemem_or_argmemonly' + CName: ClassVar[str] = '#attr.llvm.inaccessiblemem_or_argmemonly' -def NewCType(size, signed): - ct = CType() +def NewCType(size: int, signed: Optional[bool]) -> CType: + ct: CType = CType() ct.Size = size ct.IsSigned = signed return ct @@ -1129,54 +1068,44 @@ class CTypeRegistry: - Python CType 类引用 (如 t.CInt32T) """ - _name_to_class = None - _cname_to_class = None + _name_to_class: ClassVar[Optional[dict[str, type]]] = None @classmethod - def _build(cls): + def _build(cls) -> None: if cls._name_to_class is not None: return - import sys - mod = sys.modules.get(__name__) + mod: Optional[types.ModuleType] = sys.modules.get(__name__) if mod is None: return cls._name_to_class = {} - cls._cname_to_class = {} for name, obj in vars(mod).items(): if not isinstance(obj, type) or not issubclass(obj, CType) or obj is CType: continue if obj in (CTypeDefault, BigEndian, LittleEndian): continue try: - inst = obj() + inst: Any = obj() except Exception: continue - pos = getattr(obj, 'position', frozenset()) + pos: frozenset[str] = getattr(obj, 'position', frozenset()) if CType.PREFIX in pos and CType.BASE not in pos: continue if CType.POINTER in pos and CType.BASE not in pos: cls._name_to_class[name] = obj continue - if getattr(inst, 'Size', None) is not None or getattr(inst, 'CName', ''): + # 注册基本类型(有 Size)和命名基本类型(CStruct/CUnion/CEnum/REnum)。 + # 不再依赖 CName 属性,依据 position/Size 推断。 + if getattr(inst, 'Size', None) is not None or CType.NAMED in pos: cls._name_to_class[name] = obj - cname = getattr(inst, 'CName', '') - if cname and cname not in cls._cname_to_class: - cls._cname_to_class[cname] = obj @classmethod - def GetClassByName(cls, name: str): + def GetClassByName(cls, name: str) -> Optional[type]: """根据 Python 类名获取 CType 类 (如 'CInt32T' -> t.CInt32T)""" cls._build() return cls._name_to_class.get(name) - @classmethod - def GetClassByCName(cls, cname: str): - """根据 C 类型名获取 CType 类 (如 'int32_t' -> t.CInt32T)""" - cls._build() - return cls._cname_to_class.get(cname) - @staticmethod - def CTypeToLLVM(ctype_class) -> str: + def CTypeToLLVM(ctype_class: Optional[type]) -> str: """从 CType 类的元属性推导 LLVM IR 类型字符串 规则: @@ -1188,77 +1117,44 @@ class CTypeRegistry: """ if ctype_class is None: return 'i8*' - pos = getattr(ctype_class, 'position', frozenset()) + pos: frozenset[str] = getattr(ctype_class, 'position', frozenset()) if CType.POINTER in pos and CType.BASE not in pos: return 'i8*' if CType.PREFIX in pos and CType.BASE not in pos: return '' try: - inst = ctype_class() + inst: Any = ctype_class() except Exception: return 'i8*' - size = getattr(inst, 'Size', None) - is_signed = getattr(inst, 'IsSigned', None) + size: Optional[int] = getattr(inst, 'Size', None) + is_signed: Optional[bool] = getattr(inst, 'IsSigned', None) if size is None or size == 0: if is_signed is None: return 'void' return 'i8*' if is_signed is None: - float_map = {8: 'half', 16: 'half', 32: 'float', 64: 'double', 128: 'fp128'} + float_map: dict[int, str] = {8: 'half', 16: 'half', 32: 'float', 64: 'double', 128: 'fp128'} return float_map.get(size, f'f{size}') return f'i{size}' - _llvm_to_ctype_cache = None + _llvm_to_ctype_cache: ClassVar[Optional[dict[str, type]]] = None @classmethod - def LLVMToCType(cls, llvm_str): + def LLVMToCType(cls, llvm_str: str) -> Optional[type]: if cls._llvm_to_ctype_cache is None: cls._build() cls._llvm_to_ctype_cache = {} for name, ctype_cls in cls._name_to_class.items(): - pos = getattr(ctype_cls, 'position', frozenset()) + pos: frozenset[str] = getattr(ctype_cls, 'position', frozenset()) if CType.PREFIX in pos and CType.BASE not in pos: continue - llvm_key = cls.CTypeToLLVM(ctype_cls) + llvm_key: str = cls.CTypeToLLVM(ctype_cls) if llvm_key and llvm_key not in cls._llvm_to_ctype_cache: cls._llvm_to_ctype_cache[llvm_key] = ctype_cls return cls._llvm_to_ctype_cache.get(llvm_str) - @staticmethod - def CTypeToCName(ctype_class) -> str: - """从 CType 类推导 C 类型名称 (用于 printf 格式化等) - - 规则: - - 优先使用 CName 属性 (如 'size_t', 'void', 'int32_t') - - IsSigned is None 且 Size > 0 → 浮点: float/double/long double - - IsSigned is True → 有符号整数: char/short/int/long long - - IsSigned is False → 无符号整数: unsigned char/unsigned short/unsigned int/unsigned long long - """ - if ctype_class is None: - return '' - try: - inst = ctype_class() - except Exception: - return '' - cname = getattr(inst, 'CName', None) - if cname: - return cname - size = getattr(inst, 'Size', None) - is_signed = getattr(inst, 'IsSigned', None) - if size is None: - return '' - if is_signed is None and size > 0: - float_cname = {32: 'float', 64: 'double', 128: 'long double'} - return float_cname.get(size, 'double') - int_cname_signed = {8: 'char', 16: 'short', 32: 'int', 64: 'long long'} - int_cname_unsigned = {8: 'unsigned char', 16: 'unsigned short', 32: 'unsigned int', 64: 'unsigned long long'} - if is_signed: - return int_cname_signed.get(size, 'int') - else: - return int_cname_unsigned.get(size, 'unsigned int') - @classmethod - def NameToLLVM(cls, name: str) -> str: + def NameToLLVM(cls, name: str) -> Optional[str]: """根据 Python 类型名推导 LLVM IR 类型 (如 'CFloat64T' -> 'double') 修饰符类型 (CConst, CStatic 等) 返回空字符串。 @@ -1266,35 +1162,20 @@ class CTypeRegistry: 未知类型返回 None。 """ cls._build() - import sys - mod = sys.modules.get(__name__) + mod: Optional[types.ModuleType] = sys.modules.get(__name__) if mod and hasattr(mod, name): - obj = getattr(mod, name) + obj: Any = getattr(mod, name) if isinstance(obj, type) and issubclass(obj, CType): return cls.CTypeToLLVM(obj) return None @classmethod - def NameToCName(cls, name: str) -> str: - """根据 Python 类型名推导 C 类型名 (如 'CInt32T' -> 'int')""" - ctype_class = cls.GetClassByName(name) - if ctype_class is not None: - return cls.CTypeToCName(ctype_class) - return None - - @classmethod - def CNameToClass(cls, cname: str): - """根据 C 类型名获取 CType 类 (如 'int32_t' -> t.CInt32T, 'unsigned char' -> t.CUnsignedChar)""" - cls._build() - return cls._cname_to_class.get(cname) - - @classmethod - def ResolveName(cls, name: str): + def ResolveName(cls, name: str) -> Optional[tuple[type, int]]: """解析类型名到 (CType类, 指针层级) - + 支持的格式: - Python 类名: 'CInt32T' -> (t.CInt32T, 0) - - C 类型名: 'int32_t' -> (t.CInt32T, 0) + - C 类型名/Python 内置名: 'int' -> (t.CInt, 0), 'bool' -> (t.CBool, 0) - stdint 大写别名: 'INT32' -> (t.CInt32T, 0) - 指针别名: 'INT32PTR' -> (t.CInt32T, 1) - 大写别名: 'BYTE' -> (t.CUnsignedChar, 0), 'DWORD' -> (t.CUInt32T, 0) @@ -1302,26 +1183,60 @@ class CTypeRegistry: - void指针: 'VOIDPTR' -> (t.CVoid, 1) """ cls._build() - direct = cls._name_to_class.get(name) + direct: Optional[type] = cls._name_to_class.get(name) if direct is not None: - pos = getattr(direct, 'position', frozenset()) - ptr_level = 1 if CType.POINTER in pos and CType.BASE not in pos else 0 + pos: frozenset[str] = getattr(direct, 'position', frozenset()) + ptr_level: int = 1 if CType.POINTER in pos and CType.BASE not in pos else 0 return (direct, ptr_level) - cnameres = cls._cname_to_class.get(name) - if cnameres is not None: - return (cnameres, 0) + # C 类型名 / Python 内置类型名 → Python 类名硬编码表。 + # 用于支持用户代码中的 `-> bool:`、`-> int:` 等写法。 + # 不再依赖运行时 CName 属性,所有映射在此固定。 + _CNAME_ALIAS: dict[str, str] = { + # Python 内置类型名 + 'bool': 'CBool', 'int': 'CInt', 'float': 'CFloat', + # C 基本类型名 + 'char': 'CChar', 'short': 'CShort', 'long': 'CLong', + 'long long': 'CLongLong', 'double': 'CDouble', 'void': 'CVoid', + 'unsigned': 'CUnsigned', 'signed': 'CInt', 'signed int': 'CInt', + 'signed char': 'CSignedChar', + 'unsigned char': 'CUnsignedChar', 'unsigned int': 'CUnsignedInt', + 'unsigned short': 'CUnsignedShort', 'unsigned long': 'CUnsignedLong', + 'unsigned long long': 'CUnsignedLongLong', + # stdint 固定宽度类型 + 'size_t': 'CSizeT', 'ssize_t': 'CLong', + 'int8_t': 'CInt8T', 'int16_t': 'CInt16T', + 'int32_t': 'CInt32T', 'int64_t': 'CInt64T', + 'uint8_t': 'CUInt8T', 'uint16_t': 'CUInt16T', + 'uint32_t': 'CUInt32T', 'uint64_t': 'CUInt64T', + 'intptr_t': 'CIntPtrT', 'uintptr_t': 'CUIntPtrT', + 'ptrdiff_t': 'CPtrDiffT', + # 宽字符 / 字符类型 + 'wchar_t': 'CWCharT', 'char8_t': 'CChar8T', + 'char16_t': 'CChar16T', 'char32_t': 'CChar32T', + # 浮点特化类型 + 'float8_t': 'CFloat8T', 'float16_t': 'CFloat16T', + 'float32_t': 'CFloat32T', 'float64_t': 'CFloat64T', + 'float128_t': 'CFloat128T', + # 其他 + '_Bool': 'CBool', + } + cname_alias: Optional[str] = _CNAME_ALIAS.get(name) + if cname_alias is not None: + alias_cls: Optional[type] = cls._name_to_class.get(cname_alias) + if alias_cls is not None: + return (alias_cls, 0) if name.endswith('PTR'): - base_name = name[:-3] - base_result = cls.ResolveName(base_name) + base_name: str = name[:-3] + base_result: Optional[tuple[type, int]] = cls.ResolveName(base_name) if base_result is not None: return (base_result[0], base_result[1] + 1) if name.startswith('FLOAT') and name[5:].isdigit(): - bits = int(name[5:]) - float_name = f'CFloat{bits}T' - float_cls = cls._name_to_class.get(float_name) + bits: int = int(name[5:]) + float_name: str = f'CFloat{bits}T' + float_cls: Optional[type] = cls._name_to_class.get(float_name) if float_cls is not None: return (float_cls, 0) - _UPPER_ALIAS = { + _UPPER_ALIAS: dict[str, str] = { 'BYTE': 'CUInt8T', 'INT8': 'CInt8T', 'UINT8': 'CUInt8T', 'WORD': 'CUInt16T', 'INT16': 'CInt16T', 'UINT16': 'CUInt16T', 'DWORD': 'CUInt32T', 'INT32': 'CInt32T', 'UINT32': 'CUInt32T', @@ -1331,12 +1246,9 @@ class CTypeRegistry: 'SIZE_T': 'CSizeT', 'SSIZE_T': 'CPtrDiffT', 'PTRDIFF_T': 'CPtrDiffT', 'VOID': 'CVoid', } - alias = _UPPER_ALIAS.get(name) - if alias: - alias_cls = cls._name_to_class.get(alias) - if alias_cls is not None: - return (alias_cls, 0) - return None - - -_build_type_maps() \ No newline at end of file + upper_alias: Optional[str] = _UPPER_ALIAS.get(name) + if upper_alias: + upper_cls: Optional[type] = cls._name_to_class.get(upper_alias) + if upper_cls is not None: + return (upper_cls, 0) + return None \ No newline at end of file diff --git a/lib/utils/helpers.py b/lib/utils/helpers.py index 5519a70..a5e29f6 100644 --- a/lib/utils/helpers.py +++ b/lib/utils/helpers.py @@ -1,20 +1,27 @@ # 工具函数 +from __future__ import annotations import os import subprocess + from lib.constants.config import ERROR_MESSAGES +from lib.core.VLogger import get_logger as _vlog -def DetectFileType(FilePath): +def DetectFileType(FilePath: str) -> str: """检测文件类型""" + _: str + ext: str _, ext = os.path.splitext(FilePath) return ext.lower() -def ExecuteCommand(command, shell=True, CaptureOutput=True, text=True): - """执行命令""" +def ExecuteCommand(command: list[str], shell: bool = False, CaptureOutput: bool = True, text: bool = True) -> subprocess.CompletedProcess[str] | None: + """执行命令 + command 应该是列表形式(如 ['gcc', 'file.c', '-o', 'file.exe']) + 避免字符串拼接以防止 shell 注入""" try: - result = subprocess.run( + result: subprocess.CompletedProcess[str] = subprocess.run( command, shell=shell, check=True, @@ -23,13 +30,13 @@ def ExecuteCommand(command, shell=True, CaptureOutput=True, text=True): ) return result except subprocess.CalledProcessError as e: - print(f'{ERROR_MESSAGES["COMPILE_FAILED"]}: {e}') + _vlog().error(f'编译失败: {e}') if e.stderr: - print(f'Error output: {e.stderr}') + _vlog().error(f'错误输出: {e.stderr}') return None -def AppendFileContent(FilePath, content): +def AppendFileContent(FilePath: str, content: str) -> bool: """追加文件内容""" try: with open(FilePath, 'a', encoding='utf-8') as f: @@ -37,5 +44,5 @@ def AppendFileContent(FilePath, content): f.write('\n') return True except Exception as e: - print(f'Failed to append to file {FilePath}: {e}') + _vlog().error(f'写入文件失败 {FilePath}: {e}') return False diff --git a/stderr.txt b/stderr.txt new file mode 100644 index 0000000..02bd8c6 --- /dev/null +++ b/stderr.txt @@ -0,0 +1,81 @@ +[DBG _GetFuncSig] FuncName=list[str].__len__ returns=Attribute(value=Name(id='t', ctx=Load()), attr='CSizeT', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=0 +[DBG _GetFuncSig] FuncName=list[str].get returns=Name(id='str', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=1 +[DBG _GetFuncSig] FuncName=list[str].pop returns=Name(id='str', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=1 +[DBG _GetFuncSig] FuncName=__atomic_test_and_set returns=Attribute(value=Name(id='t', ctx=Load()), attr='CBool', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=0 +[DBG _GetFuncSig] FuncName=__atomic_clear returns=Attribute(value=Name(id='t', ctx=Load()), attr='CVoid', ctx=Load()) has_templates=True in_templates=False ret_void=True ret_base_none=False ptr_count=0 +[DBG _GetFuncSig] FuncName=__atomic_thread_fence returns=Attribute(value=Name(id='t', ctx=Load()), attr='CVoid', ctx=Load()) has_templates=True in_templates=False ret_void=True ret_base_none=False ptr_count=0 +[DBG _GetFuncSig] FuncName=__atomic_signal_fence returns=Attribute(value=Name(id='t', ctx=Load()), attr='CVoid', ctx=Load()) has_templates=True in_templates=False ret_void=True ret_base_none=False ptr_count=0 +[DBG _GetFuncSig] FuncName=__atomic_always_lock_free returns=Attribute(value=Name(id='t', ctx=Load()), attr='CBool', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=0 +[DBG _GetFuncSig] FuncName=__atomic_is_lock_free returns=Attribute(value=Name(id='t', ctx=Load()), attr='CBool', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=0 +[DBG _GetFuncSig] FuncName=strcpy returns=Name(id='str', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=1 +[DBG _GetFuncSig] FuncName=strncpy returns=Name(id='str', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=1 +[DBG _GetFuncSig] FuncName=strcmp returns=Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=0 +[DBG _GetFuncSig] FuncName=samestr returns=Name(id='bool', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=0 +[DBG _GetFuncSig] FuncName=strncmp returns=Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=0 +[DBG _GetFuncSig] FuncName=memcmp returns=Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=0 +[DBG _GetFuncSig] FuncName=strchr returns=Name(id='str', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=1 +[DBG _GetFuncSig] FuncName=strrchr returns=Name(id='str', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=1 +[DBG _GetFuncSig] FuncName=strspn returns=Name(id='int', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=0 +[DBG _GetFuncSig] FuncName=atoi returns=Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=0 +[DBG _GetFuncSig] FuncName=atoll returns=Attribute(value=Name(id='t', ctx=Load()), attr='CInt64T', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=0 +[DBG _GetFuncSig] FuncName=atof returns=Attribute(value=Name(id='t', ctx=Load()), attr='CDouble', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=0 +[DBG _GetFuncSig] FuncName=split returns=Name(id='int', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=0 +[DBG _GetFuncSig2] FuncName=split ReturnType=< i32> ReturnTypeInfo.BaseType=CType(, IsBasicType=False) PtrCount=0 +[DBG _GetFuncSig] FuncName=_largest_pow2_le returns=Attribute(value=Name(id='t', ctx=Load()), attr='CSizeT', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=0 +[DBG _GetFuncSig] FuncName=_block_size_at_order returns=Attribute(value=Name(id='t', ctx=Load()), attr='CSizeT', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=0 +[DBG _GetFuncSig] FuncName=MBuddy._fl_find_and_remove returns=Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=0 +[DBG _GetFuncSig] FuncName=MBuddy._order_for_size returns=Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=0 +[DBG _GetFuncSig2] FuncName=MBuddy._split_to_order ReturnType=< i8*> ReturnTypeInfo.BaseType=CType(, IsBasicType=False) PtrCount=1 +[DBG _GetFuncSig] FuncName=MBuddy._is_valid_ptr returns=Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=0 +[DBG _GetFuncSig] FuncName=MBuddy._fl_count returns=Attribute(value=Name(id='t', ctx=Load()), attr='CSizeT', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=0 +[DBG _GetFuncSig] FuncName=MBuddy.stats returns=Attribute(value=Name(id='t', ctx=Load()), attr='CSizeT', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=0 +[DBG _GetFuncSig] FuncName=MBuddy.free_count returns=Attribute(value=Name(id='t', ctx=Load()), attr='CSizeT', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=0 +[DBG _GetFuncSig] FuncName=MBuddy.self_check returns=Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=0 +[DBG _GetFuncSig] FuncName=_Type.type_id returns=Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=0 +[DBG _GetFuncSig] FuncName=_str.b returns=Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=0 +[DBG _GetFuncSig] FuncName=_str.SELF returns=Name(id='str', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=1 +[DBG _GetFuncSig] FuncName=_str.upper returns=Name(id='str', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=1 +[DBG _GetFuncSig] FuncName=_str.lower returns=Name(id='str', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=1 +[DBG _GetFuncSig] FuncName=_str.capitalize returns=Name(id='str', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=1 +[DBG _GetFuncSig] FuncName=_str.swapcase returns=Name(id='str', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=1 +[DBG _GetFuncSig] FuncName=_str.title returns=Name(id='str', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=1 +[DBG _GetFuncSig] FuncName=_str.casefold returns=Name(id='str', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=1 +[DBG _GetFuncSig] FuncName=_str.isupper returns=Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=0 +[DBG _GetFuncSig] FuncName=_str.islower returns=Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=0 +[DBG _GetFuncSig] FuncName=_str.isalpha returns=Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=0 +[DBG _GetFuncSig] FuncName=_str.isdigit returns=Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=0 +[DBG _GetFuncSig] FuncName=_str.isalnum returns=Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=0 +[DBG _GetFuncSig] FuncName=_str.isspace returns=Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=0 +[DBG _GetFuncSig] FuncName=_str.isascii returns=Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=0 +[DBG _GetFuncSig] FuncName=_str.istitle returns=Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=0 +[DBG _GetFuncSig] FuncName=_str.split returns=Subscript(value=Name(id='list', ctx=Load()), slice=Name(id='str', ctx=Load()), ctx=Load()) has_templates=True in_templates=True ret_void=False ret_base_none=True ptr_count=0 +[DBG _GetFuncSig] FuncName=list[str].__len__ returns=Attribute(value=Name(id='t', ctx=Load()), attr='CSizeT', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=0 +[DBG _GetFuncSig] FuncName=list[str].get returns=Name(id='str', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=1 +[DBG _GetFuncSig] FuncName=list[str].pop returns=Name(id='str', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=1 +[DBG _GetFuncSig] spec_name2='list[str]' in_structs=True +[DBG _GetFuncSig2] FuncName=_str.split ReturnType=< %"dc80f82cf33a6264.list[str]"*> ReturnTypeInfo.BaseType=CType(, IsBasicType=False) PtrCount=1 +[DBG _GetFuncSig] FuncName=end returns=Attribute(value=Name(id='t', ctx=Load()), attr='CInt', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=0 +[DBG _GetFuncSig] FuncName=SetLastError returns=Attribute(value=Name(id='t', ctx=Load()), attr='State', ctx=Load()) has_templates=True in_templates=False ret_void=True ret_base_none=False ptr_count=0 +[DBG _GetFuncSig] FuncName=GetSystemTime returns=Attribute(value=Name(id='t', ctx=Load()), attr='State', ctx=Load()) has_templates=True in_templates=False ret_void=True ret_base_none=False ptr_count=0 +[DBG _GetFuncSig] FuncName=GetLocalTime returns=Attribute(value=Name(id='t', ctx=Load()), attr='State', ctx=Load()) has_templates=True in_templates=False ret_void=True ret_base_none=False ptr_count=0 +[DBG _GetFuncSig] FuncName=Sleep returns=Attribute(value=Name(id='t', ctx=Load()), attr='State', ctx=Load()) has_templates=True in_templates=False ret_void=True ret_base_none=False ptr_count=0 +[DBG _GetFuncSig] FuncName=File.read returns=Name(id='LONG', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=0 +[DBG _GetFuncSig] FuncName=File.write returns=Name(id='LONG', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=0 +[DBG _GetFuncSig] FuncName=File.write_str returns=Name(id='LONG', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=0 +[DBG _GetFuncSig] FuncName=File.seek returns=Name(id='LONG', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=0 +[DBG _GetFuncSig] FuncName=File.tell returns=Name(id='LONG', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=0 +[DBG _GetFuncSig] FuncName=File.close returns=Name(id='LONG', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=0 +[DBG _GetFuncSig] FuncName=File.flush returns=Name(id='LONG', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=0 +[DBG _GetFuncSig] FuncName=File.size returns=Name(id='LONGLONG', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=0 +[DBG _GetFuncSig] FuncName=File.readline returns=Name(id='LONG', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=0 +[DBG _GetFuncSig] FuncName=File.read_all returns=Name(id='LONG', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=0 +[DBG _GetFuncSig] FuncName=FileW.read returns=Name(id='LONG', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=0 +[DBG _GetFuncSig] FuncName=FileW.write returns=Name(id='LONG', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=0 +[DBG _GetFuncSig] FuncName=FileW.write_str returns=Name(id='LONG', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=0 +[DBG _GetFuncSig] FuncName=FileW.seek returns=Name(id='LONG', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=0 +[DBG _GetFuncSig] FuncName=FileW.tell returns=Name(id='LONG', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=0 +[DBG _GetFuncSig] FuncName=FileW.close returns=Name(id='LONG', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=0 +[DBG _GetFuncSig] FuncName=FileW.flush returns=Name(id='LONG', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=0 +[DBG _GetFuncSig] FuncName=FileW.size returns=Name(id='LONGLONG', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=0 +[DBG _GetFuncSig] FuncName=FileW.readline returns=Name(id='LONG', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=0 +[DBG _GetFuncSig] FuncName=FileW.read_all returns=Name(id='LONG', ctx=Load()) has_templates=True in_templates=False ret_void=False ret_base_none=False ptr_count=0 diff --git a/stdout.txt b/stdout.txt new file mode 100644 index 0000000..616611d --- /dev/null +++ b/stdout.txt @@ -0,0 +1,261 @@ +├ INFO: 读取配置文件: ./Test/FakeDuckTest/project.json +├ INFO: 项目目录: d:\Users\TermiNexus\Desktop\TransPyC\Test\FakeDuckTest +├ INFO: 源目录: d:\Users\TermiNexus\Desktop\TransPyC\Test\FakeDuckTest\App +├ INFO: 临时目录: d:\Users\TermiNexus\Desktop\TransPyC\Test\FakeDuckTest\temp +├ INFO: 输出目录: d:\Users\TermiNexus\Desktop\TransPyC\Test\FakeDuckTest\output +├ INFO: 阶段: all +├ INFO: 编译器: llc -filetype=obj -relocation-model=pic +├ INFO: 目标三元组: x86_64-pc-windows-gnu +├ INFO: 数据布局: e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128 +├ INFO: output: 已清空 d:\Users\TermiNexus\Desktop\TransPyC\Test\FakeDuckTest\output +├ INFO: temp: 已清空 d:\Users\TermiNexus\Desktop\TransPyC\Test\FakeDuckTest\temp +├ INFO: 清理完成 +├ INFO: 找到 1 个可达源文件(从入口遍历) +├ INFO: [1/1] 生成签名: main.py +├ INFO: -> d09c71f1a3da4caf.pyi (签名) +├ INFO: 处理 10 个被引用的 Python 库文件 +├ INFO: 生成签名: _fakeduck.py -> 18e6990aa81cc5b6.pyi +├ INFO: 生成签名: atom.py -> 271ea3decb810db2.pyi +├ INFO: 生成签名: mbuddy.py -> e1937873ebfba8c3.pyi +├ INFO: 生成签名: stdint.py -> 49bd8cba55979f76.pyi +├ INFO: 生成签名: stdio.py -> 73edbcf76e32d00b.pyi +├ INFO: 生成签名: stdlib.py -> 6c2029b306556c00.pyi +├ INFO: 生成签名: string.py -> b5f1dc665c52a1bd.pyi +├ INFO: 生成签名: testcheck.py -> 9dbecd0942a39782.pyi +├ INFO: 生成签名: w32\win32base.py -> 5a6a2137958c28c5.pyi +├ INFO: 生成签名: w32\win32console.py -> bbdf3bbd4c3bc28c.pyi +├ INFO: 结构体注册表: 19 个类型, 0 个枚举 +├ INFO: -> d09c71f1a3da4caf.stub.ll (声明) +├ INFO: 生成声明: _fakeduck.py -> 18e6990aa81cc5b6.stub.ll +├ INFO: 生成声明: atom.py -> 271ea3decb810db2.stub.ll +├ INFO: 生成声明: mbuddy.py -> e1937873ebfba8c3.stub.ll +├ INFO: 生成声明: stdint.py -> 49bd8cba55979f76.stub.ll +├ INFO: 生成声明: stdio.py -> 73edbcf76e32d00b.stub.ll +├ INFO: 生成声明: stdlib.py -> 6c2029b306556c00.stub.ll +├ INFO: 生成声明: string.py -> b5f1dc665c52a1bd.stub.ll +├ INFO: 生成声明: testcheck.py -> 9dbecd0942a39782.stub.ll +├ INFO: 生成声明: w32\win32base.py -> 5a6a2137958c28c5.stub.ll +├ INFO: 生成声明: w32\win32console.py -> bbdf3bbd4c3bc28c.stub.ll +├ SUCCESS: 声明接口生成到: d:\Users\TermiNexus\Desktop\TransPyC\Test\FakeDuckTest\temp +├ INFO: SHA1 映射表 (11 个文件): +├ INFO: 找到 1 个可达源文件(已按依赖排序) +├ INFO: 处理顺序: +├ INFO: 1. main.py +├ INFO: [缓存] 构建共享符号表数据... +├ INFO: [缓存] 共享符号表构建完成 (0.15s, 485 符号, 2 泛型模板) +├ INFO: +需要翻译 1 个文件 +├ INFO: -> d09c71f1a3da4caf.ll +├ INFO: [1/1] main.py (0.1s) +├ INFO: 翻译总耗时: 0.1s +├ INFO: +[阶段二完成] .ll 文件生成到: d:\Users\TermiNexus\Desktop\TransPyC\Test\FakeDuckTest\output +├ INFO: [includes] 发现 Python 源文件: mbuddy.py +├ INFO: [includes] 发现 Python 源文件: stdint.py +├ INFO: [includes] 发现 Python 源文件: _fakeduck.py +├ INFO: [includes] 发现 Python 源文件: stdlib.py +├ INFO: [includes] 发现 Python 源文件: testcheck.py +├ INFO: [includes] 发现 Python 源文件: stdio.py +├ INFO: [includes] 发现 Python 源文件: string.py +├ INFO: [includes] 发现 Python 包文件: w32\fileio.py +├ INFO: [includes] 发现 Python 包文件: w32\win32base.py +├ INFO: [includes] 发现 Python 包文件: w32\win32console.py +├ INFO: [includes] 发现 Python 包文件: w32\win32file.py +├ INFO: [includes] 发现 Python 包文件: w32\win32memory.py +├ INFO: [includes] 发现 Python 包文件: w32\win32process.py +├ INFO: [includes] 发现 Python 包文件: w32\win32sync.py +├ INFO: [includes] 发现间接依赖: atom.py +├ INFO: +[includes 编译] 找到 15 个 Python 源文件 +├ INFO: 翻译: atom.py -> 271ea3decb810db2.ll +├ INFO: -> 271ea3decb810db2.ll +├ INFO: 编译: 271ea3decb810db2.ll -> 271ea3decb810db2.obj +├ SUCCESS: 编译成功 +├ INFO: 跳过(声明文件): stdint.py +├ INFO: 跳过(声明文件): stdio.py +├ INFO: 跳过(声明文件): stdlib.py +├ INFO: 翻译: string.py -> b5f1dc665c52a1bd.ll +├ INFO: -> b5f1dc665c52a1bd.ll +├ INFO: 编译: b5f1dc665c52a1bd.ll -> b5f1dc665c52a1bd.obj +├ SUCCESS: 编译成功 +├ INFO: 翻译: mbuddy.py -> e1937873ebfba8c3.ll +├ INFO: -> e1937873ebfba8c3.ll +├ INFO: 编译: e1937873ebfba8c3.ll -> e1937873ebfba8c3.obj +├ SUCCESS: 编译成功 +├ INFO: 翻译: _fakeduck.py -> 18e6990aa81cc5b6.ll +├ INFO: -> 18e6990aa81cc5b6.ll +├ INFO: 编译: 18e6990aa81cc5b6.ll -> 18e6990aa81cc5b6.obj +├ WARN: 编译失败: llc.exe: error: llc.exe: d:\Users\TermiNexus\Desktop\TransPyC\Test\FakeDuckTest\output\18e6990aa81cc5b6_dso.ll:2012:7: error: value doesn't match function result type 'void' + ret %"dc80f82cf33a6264.list[str]"* %"result.3" + ^ +├ INFO: 翻译: testcheck.py -> 9dbecd0942a39782.ll +├ INFO: -> 9dbecd0942a39782.ll +├ INFO: 编译: 9dbecd0942a39782.ll -> 9dbecd0942a39782.obj +├ SUCCESS: 编译成功 +├ INFO: 翻译: win32base.py -> 5a6a2137958c28c5.ll +├ INFO: -> 5a6a2137958c28c5.ll +├ INFO: 编译: 5a6a2137958c28c5.ll -> 5a6a2137958c28c5.obj +├ SUCCESS: 编译成功 +├ INFO: 翻译: win32console.py -> bbdf3bbd4c3bc28c.ll +├ INFO: -> bbdf3bbd4c3bc28c.ll +├ INFO: 编译: bbdf3bbd4c3bc28c.ll -> bbdf3bbd4c3bc28c.obj +├ SUCCESS: 编译成功 +├ INFO: 翻译: win32file.py -> abf9ce3160c9279e.ll +├ INFO: -> abf9ce3160c9279e.ll +├ INFO: 编译: abf9ce3160c9279e.ll -> abf9ce3160c9279e.obj +├ SUCCESS: 编译成功 +├ INFO: 翻译: fileio.py -> fa3691e66b426950.ll +├ INFO: -> fa3691e66b426950.ll +├ INFO: 编译: fa3691e66b426950.ll -> fa3691e66b426950.obj +├ SUCCESS: 编译成功 +├ INFO: 翻译: win32memory.py -> 72e2d5ccb7cedcf1.ll +├ INFO: -> 72e2d5ccb7cedcf1.ll +├ INFO: 编译: 72e2d5ccb7cedcf1.ll -> 72e2d5ccb7cedcf1.obj +├ SUCCESS: 编译成功 +├ INFO: 翻译: win32process.py -> 067c78e9f121dce3.ll +├ INFO: -> 067c78e9f121dce3.ll +├ INFO: 编译: 067c78e9f121dce3.ll -> 067c78e9f121dce3.obj +├ SUCCESS: 编译成功 +├ INFO: 翻译: win32sync.py -> 29813d57621099a9.ll +├ INFO: -> 29813d57621099a9.ll +├ INFO: 编译: 29813d57621099a9.ll -> 29813d57621099a9.obj +├ SUCCESS: 编译成功 +├ INFO: [清理] 删除 1 个过时文件 +├ INFO: +[编译] 找到 1 个 .ll 文件需要编译 +├ INFO: 并行编译 1 个文件 (workers=1) +├ INFO: [DEBUG] replaced_declare_names: {'sprintf', 'e1937873ebfba8c3.MBuddy.free_count', 'e1937873ebfba8c3.MBuddy.calloc', 'e1937873ebfba8c3.MBuddy._fl_find_and_remove', 'SetConsoleCursorInfo', 'b5f1dc665c52a1bd.strspn', 'GetConsoleTitleW', 'e1937873ebfba8c3.MBuddy._buddy_of', 'fgets', 'snprintf', 'b5f1dc665c52a1bd.atoll', 'e1937873ebfba8c3.MBuddy.stats', 'e1937873ebfba8c3._block_size_at_order', '9dbecd0942a39782.ok', 'SetConsoleTitleW', 'e1937873ebfba8c3.MBuddy.alloc', 'e1937873ebfba8c3.MBuddy._fl_pop', '9dbecd0942a39782.section', 'strlen', 'SetConsoleScreenBufferSize', 'b5f1dc665c52a1bd.samestr', 'b5f1dc665c52a1bd.strcmp', 'FillConsoleOutputAttribute', 'e1937873ebfba8c3.MBuddy.__exit__', 'e1937873ebfba8c3.MBuddy._unlock', 'b5f1dc665c52a1bd.strchr', 'b5f1dc665c52a1bd.memcmp', 'b5f1dc665c52a1bd.memset32', '9dbecd0942a39782.info', 'e1937873ebfba8c3.MBuddy._order_for_size', 'FillConsoleOutputCharacterA', 'ReadConsoleW', 'e1937873ebfba8c3.MBuddy.free', 'GetNumberOfConsoleInputEvents', 'e1937873ebfba8c3.MBuddy._is_valid_ptr', '9dbecd0942a39782.check', 'SetConsoleTextAttribute', 'fputs', 'e1937873ebfba8c3.MBuddy._fl_count', 'b5f1dc665c52a1bd.atof', 'GetConsoleMode', 'GetConsoleTitleA', 'b5f1dc665c52a1bd.split', 'e1937873ebfba8c3.MBuddy.__enter__', 'FlushConsoleInputBuffer', 'b5f1dc665c52a1bd.strcpy', 'fprintf', 'ReadConsoleInputA', 'memcpy', 'SetConsoleTitleA', 'SetConsoleCursorPosition', 'WriteConsoleA', 'e1937873ebfba8c3.MBuddy._fl_push', 'e1937873ebfba8c3.MBuddy.realloc', '18e6990aa81cc5b6._Type.type_id', 'e1937873ebfba8c3.MBuddy.reset', 'b5f1dc665c52a1bd.atoi', 'e1937873ebfba8c3.MBuddy.self_check', 'fflush', 'e1937873ebfba8c3.MBuddy._lock', '9dbecd0942a39782.fail', 'b5f1dc665c52a1bd.strncmp', 'WriteConsoleW', 'GetConsoleScreenBufferInfo', 'FillConsoleOutputCharacterW', 'e1937873ebfba8c3.MBuddy._split_to_order', 'memset', '9dbecd0942a39782.begin', 'b5f1dc665c52a1bd.strncpy', 'GetConsoleCursorInfo', 'puts', 'ReadConsoleInputW', 'b5f1dc665c52a1bd.memmove', 'ReadConsoleA', 'e1937873ebfba8c3.MBuddy.__before_init__', 'SetConsoleCP', 'e1937873ebfba8c3.MBuddy.__init__', 'e1937873ebfba8c3._largest_pow2_le', 'e1937873ebfba8c3.MBuddy._coalesce', 'SetConsoleOutputCP', 'b5f1dc665c52a1bd.strrchr', 'printf', 'SetConsoleMode', 'SetConsoleWindowInfo', 'ScrollConsoleScreenBufferA'} +├ INFO: [DEBUG] removing lines {110} for sprintf +├ INFO: [DEBUG] removing lines {215} for e1937873ebfba8c3.MBuddy.free_count +├ INFO: [DEBUG] removing lines {209} for e1937873ebfba8c3.MBuddy.calloc +├ INFO: [DEBUG] removing lines {187} for e1937873ebfba8c3.MBuddy._fl_find_and_remove +├ INFO: [DEBUG] removing lines {20} for SetConsoleCursorInfo +├ INFO: [DEBUG] removing lines {151} for b5f1dc665c52a1bd.strspn +├ INFO: [DEBUG] removing lines {56} for GetConsoleTitleW +├ INFO: [DEBUG] removing lines {189} for e1937873ebfba8c3.MBuddy._buddy_of +├ INFO: [DEBUG] removing lines {118} for fgets +├ INFO: [DEBUG] removing lines {112} for snprintf +├ INFO: [DEBUG] removing lines {163} for b5f1dc665c52a1bd.atoll +├ INFO: [DEBUG] removing lines {213} for e1937873ebfba8c3.MBuddy.stats +├ INFO: [DEBUG] removing lines {171} for e1937873ebfba8c3._block_size_at_order +├ INFO: [DEBUG] removing lines {223} for 9dbecd0942a39782.ok +├ INFO: [DEBUG] removing lines {52} for SetConsoleTitleW +├ INFO: [DEBUG] removing lines {205} for e1937873ebfba8c3.MBuddy.alloc +├ INFO: [DEBUG] removing lines {185} for e1937873ebfba8c3.MBuddy._fl_pop +├ INFO: [DEBUG] removing lines {221} for 9dbecd0942a39782.section +├ INFO: [DEBUG] removing lines {137} for strlen +├ INFO: [DEBUG] removing lines {14} for SetConsoleScreenBufferSize +├ INFO: [DEBUG] removing lines {141} for b5f1dc665c52a1bd.samestr +├ INFO: [DEBUG] removing lines {139} for b5f1dc665c52a1bd.strcmp +├ INFO: [DEBUG] removing lines {28} for FillConsoleOutputAttribute +├ INFO: [DEBUG] removing lines {179} for e1937873ebfba8c3.MBuddy.__exit__ +├ INFO: [DEBUG] removing lines {203} for e1937873ebfba8c3.MBuddy._unlock +├ INFO: [DEBUG] removing lines {147} for b5f1dc665c52a1bd.strchr +├ INFO: [DEBUG] removing lines {145} for b5f1dc665c52a1bd.memcmp +├ INFO: [DEBUG] removing lines {155} for b5f1dc665c52a1bd.memset32 +├ INFO: [DEBUG] removing lines {229} for 9dbecd0942a39782.info +├ INFO: [DEBUG] removing lines {191} for e1937873ebfba8c3.MBuddy._order_for_size +├ INFO: [DEBUG] removing lines {24} for FillConsoleOutputCharacterA +├ INFO: [DEBUG] removing lines {36} for ReadConsoleW +├ INFO: [DEBUG] removing lines {207} for e1937873ebfba8c3.MBuddy.free +├ INFO: [DEBUG] removing lines {46} for GetNumberOfConsoleInputEvents +├ INFO: [DEBUG] removing lines {197} for e1937873ebfba8c3.MBuddy._is_valid_ptr +├ INFO: [DEBUG] removing lines {227} for 9dbecd0942a39782.check +├ INFO: [DEBUG] removing lines {22} for SetConsoleTextAttribute +├ INFO: [DEBUG] removing lines {116} for fputs +├ INFO: [DEBUG] removing lines {199} for e1937873ebfba8c3.MBuddy._fl_count +├ INFO: [DEBUG] removing lines {165} for b5f1dc665c52a1bd.atof +├ INFO: [DEBUG] removing lines {38} for GetConsoleMode +├ INFO: [DEBUG] removing lines {54} for GetConsoleTitleA +├ INFO: [DEBUG] removing lines {167} for b5f1dc665c52a1bd.split +├ INFO: [DEBUG] removing lines {177} for e1937873ebfba8c3.MBuddy.__enter__ +├ INFO: [DEBUG] removing lines {48} for FlushConsoleInputBuffer +├ INFO: [DEBUG] removing lines {133} for b5f1dc665c52a1bd.strcpy +├ INFO: [DEBUG] removing lines {108} for fprintf +├ INFO: [DEBUG] removing lines {42} for ReadConsoleInputA +├ INFO: [DEBUG] removing lines {157} for memcpy +├ INFO: [DEBUG] removing lines {50} for SetConsoleTitleA +├ INFO: [DEBUG] removing lines {16} for SetConsoleCursorPosition +├ INFO: [DEBUG] removing lines {30} for WriteConsoleA +├ INFO: [DEBUG] removing lines {183} for e1937873ebfba8c3.MBuddy._fl_push +├ INFO: [DEBUG] removing lines {211} for e1937873ebfba8c3.MBuddy.realloc +├ INFO: [DEBUG] removing lines {68} for 18e6990aa81cc5b6._Type.type_id +├ INFO: [DEBUG] removing lines {181} for e1937873ebfba8c3.MBuddy.reset +├ INFO: [DEBUG] removing lines {161} for b5f1dc665c52a1bd.atoi +├ INFO: [DEBUG] removing lines {217} for e1937873ebfba8c3.MBuddy.self_check +├ INFO: [DEBUG] removing lines {120} for fflush +├ INFO: [DEBUG] removing lines {201} for e1937873ebfba8c3.MBuddy._lock +├ INFO: [DEBUG] removing lines {225} for 9dbecd0942a39782.fail +├ INFO: [DEBUG] removing lines {143} for b5f1dc665c52a1bd.strncmp +├ INFO: [DEBUG] removing lines {32} for WriteConsoleW +├ INFO: [DEBUG] removing lines {12} for GetConsoleScreenBufferInfo +├ INFO: [DEBUG] removing lines {26} for FillConsoleOutputCharacterW +├ INFO: [DEBUG] removing lines {193} for e1937873ebfba8c3.MBuddy._split_to_order +├ INFO: [DEBUG] removing lines {153} for memset +├ INFO: [DEBUG] removing lines {219} for 9dbecd0942a39782.begin +├ INFO: [DEBUG] removing lines {135} for b5f1dc665c52a1bd.strncpy +├ INFO: [DEBUG] removing lines {18} for GetConsoleCursorInfo +├ INFO: [DEBUG] removing lines {114} for puts +├ INFO: [DEBUG] removing lines {44} for ReadConsoleInputW +├ INFO: [DEBUG] removing lines {159} for b5f1dc665c52a1bd.memmove +├ INFO: [DEBUG] removing lines {34} for ReadConsoleA +├ INFO: [DEBUG] removing lines {173} for e1937873ebfba8c3.MBuddy.__before_init__ +├ INFO: [DEBUG] removing lines {6} for SetConsoleCP +├ INFO: [DEBUG] removing lines {175} for e1937873ebfba8c3.MBuddy.__init__ +├ INFO: [DEBUG] removing lines {169} for e1937873ebfba8c3._largest_pow2_le +├ INFO: [DEBUG] removing lines {195} for e1937873ebfba8c3.MBuddy._coalesce +├ INFO: [DEBUG] removing lines {4} for SetConsoleOutputCP +├ INFO: [DEBUG] removing lines {149} for b5f1dc665c52a1bd.strrchr +├ INFO: [DEBUG] removing lines {106} for printf +├ INFO: [DEBUG] removing lines {40} for SetConsoleMode +├ INFO: [DEBUG] removing lines {62} for SetConsoleWindowInfo +├ INFO: [DEBUG] removing lines {64} for ScrollConsoleScreenBufferA +├ SUCCESS: d09c71f1a3da4caf.ll +├ INFO: +[链接] 找到 1 个 .obj 文件 +├ INFO: [链接] 额外库文件: 11 个 +├ INFO: - 271ea3decb810db2.obj +├ INFO: - b5f1dc665c52a1bd.obj +├ INFO: - e1937873ebfba8c3.obj +├ INFO: - 9dbecd0942a39782.obj +├ INFO: - 5a6a2137958c28c5.obj +├ INFO: - bbdf3bbd4c3bc28c.obj +├ INFO: - abf9ce3160c9279e.obj +├ INFO: - fa3691e66b426950.obj +├ INFO: - 72e2d5ccb7cedcf1.obj +├ INFO: - 067c78e9f121dce3.obj +├ INFO: - 29813d57621099a9.obj +├ INFO: 执行: clang++ -Wl,--allow-multiple-definition -o d:\Users\TermiNexus\Desktop\TransPyC\Test\FakeDuckTest\output\FakeDuckTest.exe d:\Users\TermiNexus\Desktop\TransPyC\Test\FakeDuckTest\output\d09c71f1a3da4caf.obj d:\Users\TermiNexus\Desktop\TransPyC\Test\FakeDuckTest\output\271ea3decb810db2.obj d:\Users\TermiNexus\Desktop\TransPyC\Test\FakeDuckTest\output\b5f1dc665c52a1bd.obj d:\Users\TermiNexus\Desktop\TransPyC\Test\FakeDuckTest\output\e1937873ebfba8c3.obj d:\Users\TermiNexus\Desktop\TransPyC\Test\FakeDuckTest\output\9dbecd0942a39782.obj d:\Users\TermiNexus\Desktop\TransPyC\Test\FakeDuckTest\output\5a6a2137958c28c5.obj d:\Users\TermiNexus\Desktop\TransPyC\Test\FakeDuckTest\output\bbdf3bbd4c3bc28c.obj d:\Users\TermiNexus\Desktop\TransPyC\Test\FakeDuckTest\output\abf9ce3160c9279e.obj d:\Users\TermiNexus\Desktop\TransPyC\Test\FakeDuckTest\output\fa3691e66b426950.obj d:\Users\TermiNexus\Desktop\TransPyC\Test\FakeDuckTest\output\72e2d5ccb7cedcf1.obj d:\Users\TermiNexus\Desktop\TransPyC\Test\FakeDuckTest\output\067c78e9f121dce3.obj d:\Users\TermiNexus\Desktop\TransPyC\Test\FakeDuckTest\output\29813d57621099a9.obj -lmsvcrt -lucrt -lpthread -lmingwex -lkernel32 +├ ERROR: 链接失败: D:/msys64/mingw64/bin/ld: d:\Users\TermiNexus\Desktop\TransPyC\Test\FakeDuckTest\output\d09c71f1a3da4caf.obj:d09c71f1a3da4caf_dso.ll:(.text+0x56): undefined reference to `18e6990aa81cc5b6._str.b' +D:/msys64/mingw64/bin/ld: d:\Users\TermiNexus\Desktop\TransPyC\Test\FakeDuckTest\output\d09c71f1a3da4caf.obj:d09c71f1a3da4caf_dso.ll:(.text+0x89): undefined reference to `18e6990aa81cc5b6._Type.type_id' +D:/msys64/mingw64/bin/ld: d:\Users\TermiNexus\Desktop\TransPyC\Test\FakeDuckTest\output\d09c71f1a3da4caf.obj:d09c71f1a3da4caf_dso.ll:(.text+0xbf): undefined reference to `18e6990aa81cc5b6._str.SELF' +D:/msys64/mingw64/bin/ld: d:\Users\TermiNexus\Desktop\TransPyC\Test\FakeDuckTest\output\d09c71f1a3da4caf.obj:d09c71f1a3da4caf_dso.ll:(.text+0x16d): undefined reference to `18e6990aa81cc5b6._str.upper' +D:/msys64/mingw64/bin/ld: d:\Users\TermiNexus\Desktop\TransPyC\Test\FakeDuckTest\output\d09c71f1a3da4caf.obj:d09c71f1a3da4caf_dso.ll:(.text+0x1f5): undefined reference to `18e6990aa81cc5b6._str.upper' +D:/msys64/mingw64/bin/ld: d:\Users\TermiNexus\Desktop\TransPyC\Test\FakeDuckTest\output\d09c71f1a3da4caf.obj:d09c71f1a3da4caf_dso.ll:(.text+0x225): undefined reference to `18e6990aa81cc5b6._str.lower' +D:/msys64/mingw64/bin/ld: d:\Users\TermiNexus\Desktop\TransPyC\Test\FakeDuckTest\output\d09c71f1a3da4caf.obj:d09c71f1a3da4caf_dso.ll:(.text+0x255): undefined reference to `18e6990aa81cc5b6._str.capitalize' +D:/msys64/mingw64/bin/ld: d:\Users\TermiNexus\Desktop\TransPyC\Test\FakeDuckTest\output\d09c71f1a3da4caf.obj:d09c71f1a3da4caf_dso.ll:(.text+0x285): undefined reference to `18e6990aa81cc5b6._str.swapcase' +D:/msys64/mingw64/bin/ld: d:\Users\TermiNexus\Desktop\TransPyC\Test\FakeDuckTest\output\d09c71f1a3da4caf.obj:d09c71f1a3da4caf_dso.ll:(.text+0x2b5): undefined reference to `18e6990aa81cc5b6._str.casefold' +D:/msys64/mingw64/bin/ld: d:\Users\TermiNexus\Desktop\TransPyC\Test\FakeDuckTest\output\d09c71f1a3da4caf.obj:d09c71f1a3da4caf_dso.ll:(.text+0x30f): undefined reference to `18e6990aa81cc5b6._str.title' +D:/msys64/mingw64/bin/ld: d:\Users\TermiNexus\Desktop\TransPyC\Test\FakeDuckTest\output\d09c71f1a3da4caf.obj:d09c71f1a3da4caf_dso.ll:(.text+0x42a): undefined reference to `18e6990aa81cc5b6._str.isupper' +D:/msys64/mingw64/bin/ld: d:\Users\TermiNexus\Desktop\TransPyC\Test\FakeDuckTest\output\d09c71f1a3da4caf.obj:d09c71f1a3da4caf_dso.ll:(.text+0x444): undefined reference to `18e6990aa81cc5b6._str.isupper' +D:/msys64/mingw64/bin/ld: d:\Users\TermiNexus\Desktop\TransPyC\Test\FakeDuckTest\output\d09c71f1a3da4caf.obj:d09c71f1a3da4caf_dso.ll:(.text+0x462): undefined reference to `18e6990aa81cc5b6._str.islower' +D:/msys64/mingw64/bin/ld: d:\Users\TermiNexus\Desktop\TransPyC\Test\FakeDuckTest\output\d09c71f1a3da4caf.obj:d09c71f1a3da4caf_dso.ll:(.text+0x47c): undefined reference to `18e6990aa81cc5b6._str.islower' +D:/msys64/mingw64/bin/ld: d:\Users\TermiNexus\Desktop\TransPyC\Test\FakeDuckTest\output\d09c71f1a3da4caf.obj:d09c71f1a3da4caf_dso.ll:(.text+0x496): undefined reference to `18e6990aa81cc5b6._str.isalpha' +D:/msys64/mingw64/bin/ld: d:\Users\TermiNexus\Desktop\TransPyC\Test\FakeDuckTest\output\d09c71f1a3da4caf.obj:d09c71f1a3da4caf_dso.ll:(.text+0x4b7): undefined reference to `18e6990aa81cc5b6._str.isalpha' +D:/msys64/mingw64/bin/ld: d:\Users\TermiNexus\Desktop\TransPyC\Test\FakeDuckTest\output\d09c71f1a3da4caf.obj:d09c71f1a3da4caf_dso.ll:(.text+0x4d5): undefined reference to `18e6990aa81cc5b6._str.isdigit' +D:/msys64/mingw64/bin/ld: d:\Users\TermiNexus\Desktop\TransPyC\Test\FakeDuckTest\output\d09c71f1a3da4caf.obj:d09c71f1a3da4caf_dso.ll:(.text+0x4ef): undefined reference to `18e6990aa81cc5b6._str.isdigit' +D:/msys64/mingw64/bin/ld: d:\Users\TermiNexus\Desktop\TransPyC\Test\FakeDuckTest\output\d09c71f1a3da4caf.obj:d09c71f1a3da4caf_dso.ll:(.text+0x509): undefined reference to `18e6990aa81cc5b6._str.isalnum' +D:/msys64/mingw64/bin/ld: d:\Users\TermiNexus\Desktop\TransPyC\Test\FakeDuckTest\output\d09c71f1a3da4caf.obj:d09c71f1a3da4caf_dso.ll:(.text+0x527): undefined reference to `18e6990aa81cc5b6._str.isalnum' +D:/msys64/mingw64/bin/ld: d:\Users\TermiNexus\Desktop\TransPyC\Test\FakeDuckTest\output\d09c71f1a3da4caf.obj:d09c71f1a3da4caf_dso.ll:(.text+0x545): undefined reference to `18e6990aa81cc5b6._str.isspace' +D:/msys64/mingw64/bin/ld: d:\Users\TermiNexus\Desktop\TransPyC\Test\FakeDuckTest\output\d09c71f1a3da4caf.obj:d09c71f1a3da4caf_dso.ll:(.text+0x55f): undefined reference to `18e6990aa81cc5b6._str.isspace' +D:/msys64/mingw64/bin/ld: d:\Users\TermiNexus\Desktop\TransPyC\Test\FakeDuckTest\output\d09c71f1a3da4caf.obj:d09c71f1a3da4caf_dso.ll:(.text+0x579): undefined reference to `18e6990aa81cc5b6._str.isascii' +D:/msys64/mingw64/bin/ld: d:\Users\TermiNexus\Desktop\TransPyC\Test\FakeDuckTest\output\d09c71f1a3da4caf.obj:d09c71f1a3da4caf_dso.ll:(.text+0x597): undefined reference to `18e6990aa81cc5b6._str.istitle' +D:/msys64/mingw64/bin/ld: d:\Users\TermiNexus\Desktop\TransPyC\Test\FakeDuckTest\output\d09c71f1a3da4caf.obj:d09c71f1a3da4caf_dso.ll:(.text+0x5b1): undefined reference to `18e6990aa81cc5b6._str.istitle' +D:/msys64/mingw64/bin/ld: d:\Users\TermiNexus\Desktop\TransPyC\Test\FakeDuckTest\output\d09c71f1a3da4caf.obj:d09c71f1a3da4caf_dso.ll:(.text+0x605): undefined reference to `18e6990aa81cc5b6._str.split' +D:/msys64/mingw64/bin/ld: d:\Users\TermiNexus\Desktop\TransPyC\Test\FakeDuckTest\output\d09c71f1a3da4caf.obj:d09c71f1a3da4caf_dso.ll:(.text+0x7aa): undefined reference to `18e6990aa81cc5b6._str.split' +D:/msys64/mingw64/bin/ld: d:\Users\TermiNexus\Desktop\TransPyC\Test\FakeDuckTest\output\d09c71f1a3da4caf.obj:d09c71f1a3da4caf_dso.ll:(.text+0x875): undefined reference to `18e6990aa81cc5b6._str.split' +D:/msys64/mingw64/bin/ld: d:\Users\TermiNexus\Desktop\TransPyC\Test\FakeDuckTest\output\d09c71f1a3da4caf.obj:d09c71f1a3da4caf_dso.ll:(.text+0xa08): undefined reference to `18e6990aa81cc5b6._str.split' +D:/msys64/mingw64/bin/ld: d:\Users\TermiNexus\Desktop\TransPyC\Test\FakeDuckTest\output\d09c71f1a3da4caf.obj:d09c71f1a3da4caf_dso.ll:(.text+0xa86): undefined reference to `18e6990aa81cc5b6._str.split' +clang++: error: linker command failed with exit code 1 (use -v to see invocation) +├ ERROR: +链接失败,立即终止编译。 diff --git a/temp_build_log.txt b/temp_build_log.txt new file mode 100644 index 0000000..b5b7fc3 --- /dev/null +++ b/temp_build_log.txt @@ -0,0 +1 @@ +├ INFO: [剥离] 调试段已移除 (llvm-strip)