From cfc30d735c1994b5073d5cb3c7352a305fee6bbd Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Thu, 30 Jul 2026 16:33:56 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B0=86=20.py=20=E5=92=8C=20.pyi=20=E5=90=8E?= =?UTF-8?q?=E7=BC=80=E5=90=8D=E6=94=B9=E4=B8=BA=E4=BA=86=20.vp=20=E5=92=8C?= =?UTF-8?q?=20.vpi=20=E5=90=8E=E7=BC=80=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .transpyc_cache/067c78e9f121dce3.pyi | 2 +- .transpyc_cache/06f53cc594b4ac6c.pyi | 2 +- .transpyc_cache/271ea3decb810db2.pyi | 26 - .transpyc_cache/6446627d4f07a1b5.pyi | 2 +- .transpyc_cache/72e2d5ccb7cedcf1.pyi | 2 +- .transpyc_cache/bbdf3bbd4c3bc28c.pyi | 2 +- .transpyc_cache/c9f4be41ca1cc2b4.pyi | 2 +- .transpyc_cache/f5522571bcce7bcb.pyi | 2 +- .transpyc_cache/f6b51804a0ba8ff0.pyi | 2 +- Test/ArgparseTest/App/{main.py => main.vp} | 0 Test/AstTest/App/{main.py => main.vp} | 0 Test/BuddyTest/App/{main.py => main.vp} | 0 .../App/{mbuddytest.py => mbuddytest.vp} | 0 .../App/{main.py => main.vp} | 0 .../App/{cpython.py => cpython.vp} | 0 Test/CPythonTest/App/{main.py => main.vp} | 0 Test/ClosureCallTest/App/{main.py => main.vp} | 0 Test/ClosureTest/App/{main.py => main.vp} | 0 Test/ClosureTest2/App/{main.py => main.vp} | 0 .../App/{main.py => main.vp} | 0 Test/DecoratorTest/App/{main.py => main.vp} | 0 Test/DictTest/App/{main.py => main.vp} | 0 Test/DocTest/App/{main.py => main.vp} | 0 Test/DocTest/App/{remote.py => remote.vp} | 0 Test/EdgeCaseTest/App/{main.py => main.vp} | 0 Test/EqTest/App/{main.py => main.vp} | 0 Test/Extern2Test/App/{main.py => main.vp} | 0 Test/FakeDuckTest/App/{main.py => main.vp} | 0 Test/ForAndLoopTest/App/{main.py => main.vp} | 0 .../FormatStringTest/App/{main.py => main.vp} | 0 Test/FuncTest/App/{main.py => main.vp} | 0 Test/G3/App/{main.py => main.vp} | 0 Test/G4/App/{caller1.py => caller1.vp} | 0 Test/G4/App/{caller2.py => caller2.vp} | 0 Test/G4/App/{caller3.py => caller3.vp} | 0 Test/G4/App/{main.py => main.vp} | 0 Test/G4/includes/{g4node.py => g4node.vp} | 0 Test/G5/App/{main.py => main.vp} | 0 .../{g5container.py => g5container.vp} | 0 Test/G6/App/{main.py => main.vp} | 0 Test/G7/App/{main.py => main.vp} | 0 .../{conflict_node.py => conflict_node.vp} | 0 Test/GenericTest/App/{main.py => main.vp} | 0 Test/GenericTest2/App/{main.py => main.vp} | 0 Test/GenericTest3/App/{main.py => main.vp} | 0 Test/GenericTest4/App/{main.py => main.vp} | 0 Test/HashTableTest/App/{main.py => main.vp} | 0 Test/IterTest/App/{main.py => main.vp} | 0 Test/JsonTest/App/{main.py => main.vp} | 0 Test/LLvmLiteTest/App/{main.py => main.vp} | 0 Test/ListTest/App/{main.py => main.vp} | 0 Test/LoopTest/App/{main.py => main.vp} | 0 Test/MemhubTest/App/{main.py => main.vp} | 0 Test/NewAstTest/App/{main.py => main.vp} | 0 Test/NoVTableTest/App/{main.py => main.vp} | 0 Test/PointerTest/App/{main.py => main.vp} | 0 .../ShortCircuitTest/App/{main.py => main.vp} | 0 Test/SimdTest/App/{main.py => main.vp} | 0 Test/SlotsBugTest/App/{main.py => main.vp} | 0 Test/SprintfTest/App/{main.py => main.vp} | 0 .../App/{inline_test.py => inline_test.vp} | 0 Test/StringIterTest/App/{main.py => main.vp} | 0 Test/StringTest/App/{main.py => main.vp} | 0 Test/StructTest/App/{main.py => main.vp} | 0 Test/SysLibTest/App/{main.py => main.vp} | 0 .../App/{os_backend.py => os_backend.vp} | 0 ...{syslibtest_impl.py => syslibtest_impl.vp} | 0 Test/TestFBProject/App/{main.py => main.vp} | 0 .../App/{BINASCII.py => BINASCII.vp} | 0 .../App/{HASHLIB.py => HASHLIB.vp} | 0 Test/TestProject/App/{config.py => config.vp} | 0 Test/TestProject/App/{main.py => main.vp} | 0 .../App/{test_numpy.py => test_numpy.vp} | 0 .../App/{test_zlib.py => test_zlib.vp} | 0 .../App/zc/{class_test.py => class_test.vp} | 0 .../App/zc/{config.py => config.vp} | 0 .../App/zc/{logic_test.py => logic_test.vp} | 0 Test/TestProject/App/zc/{test.py => test.vp} | 0 Test/TestProject2/App/{main.py => main.vp} | 0 .../App/zc/{class_test.py => class_test.vp} | 0 .../App/zc/{config.py => config.vp} | 0 .../App/zc/{logic_test.py => logic_test.vp} | 0 Test/TestProject2/App/zc/{test.py => test.vp} | 0 .../App/{definetest.py => definetest.vp} | 0 .../App/{enumtest.py => enumtest.vp} | 0 .../App/{fileiotest.py => fileiotest.vp} | 0 Test/TestProject3/App/{main.py => main.vp} | 0 .../App/{mpooltest.py => mpooltest.vp} | 0 .../App/{vectortest.py => vectortest.vp} | 0 Test/TypeCastTest/App/{main.py => main.vp} | 0 Test/VRandomTest/App/{main.py => main.vp} | 0 Test/VariadicTest/App/{main.py => main.vp} | 0 Test/WebTest/App/{main.py => main.vp} | 0 .../App/__zlib/{__init__.py => __init__.vp} | 0 .../App/__zlib/{pyzlib.py => pyzlib.vp} | 0 .../__zlib/{test_pyzlib.py => test_pyzlib.vp} | 0 .../App/__zlib/{zchecksum.py => zchecksum.vp} | 0 Test/ZlibTest/App/__zlib/{zdef.py => zdef.vp} | 0 .../App/__zlib/{zdeflate.py => zdeflate.vp} | 0 .../App/__zlib/{zhuff.py => zhuff.vp} | 0 .../App/__zlib/{zinflate.py => zinflate.vp} | 0 Test/ZlibTest/App/{main.py => main.vp} | 0 TransPyV/App/lib/Projectrans/Config.py | 397 -- TransPyV/App/lib/Projectrans/Utils.py | 130 - TransPyV/App/lib/Projectrans/__init__.py | 12 - TransPyV/App/lib/__init__.py | 28 - TransPyV/App/lib/core/BuildPipeline.py | 624 -- .../App/lib/core/Handles/HandlesAnnAssign.py | 504 -- .../App/lib/core/Handles/HandlesAssign.py | 389 -- .../App/lib/core/Handles/HandlesAugAssign.py | 315 -- TransPyV/App/lib/core/Handles/HandlesBase.py | 262 - TransPyV/App/lib/core/Handles/HandlesBody.py | 230 - .../App/lib/core/Handles/HandlesClassDef.py | 3412 ----------- TransPyV/App/lib/core/Handles/HandlesEnum.py | 238 - TransPyV/App/lib/core/Handles/HandlesExpr.py | 2970 ---------- .../App/lib/core/Handles/HandlesExprCall.py | 5037 ----------------- .../App/lib/core/Handles/HandlesExprOps.py | 289 - TransPyV/App/lib/core/Handles/HandlesFor.py | 398 -- .../App/lib/core/Handles/HandlesFunctions.py | 995 ---- TransPyV/App/lib/core/Handles/HandlesIf.py | 141 - .../App/lib/core/Handles/HandlesImports.py | 596 -- TransPyV/App/lib/core/Handles/HandlesMain.py | 492 -- .../App/lib/core/Handles/HandlesNonlocal.py | 127 - .../App/lib/core/Handles/HandlesReturn.py | 117 - .../App/lib/core/Handles/HandlesStruct.py | 1179 ---- .../App/lib/core/Handles/HandlesTranslator.py | 434 -- TransPyV/App/lib/core/Handles/HandlesType.py | 1387 ----- TransPyV/App/lib/core/Handles/HandlesVar.py | 406 -- TransPyV/App/lib/core/Handles/HandlesWhile.py | 130 - TransPyV/App/lib/core/Handles/__init__.py | 23 - TransPyV/App/lib/core/IncludesScanner.py | 365 -- TransPyV/App/lib/core/Phase1.py | 1204 ---- TransPyV/App/lib/core/Phase2.py | 953 ---- TransPyV/App/lib/core/StubMerger.py | 2043 ------- TransPyV/App/lib/core/VLogger.py | 291 - TransPyV/App/lib/core/__init__.py | 9 - TransPyV/App/main.py | 560 -- TransPyV/Test/App/asm_test.py | 47 - TransPyV/Test/App/attr_test.py | 234 - TransPyV/Test/App/augassign_test.py | 58 - TransPyV/Test/App/closure_test.py | 45 - TransPyV/Test/App/deco_test.py | 183 - TransPyV/Test/App/deref_min_test.py | 9 - TransPyV/Test/App/deref_test.py | 13 - TransPyV/Test/App/eq_test.py | 144 - TransPyV/Test/App/float_test.py | 84 - TransPyV/Test/App/flow_test.py | 23 - TransPyV/Test/App/for_test.py | 8 - TransPyV/Test/App/func_test.py | 68 - TransPyV/Test/App/func_vtable_test.py | 116 - TransPyV/Test/App/inherit_test.py | 121 - TransPyV/Test/App/llvmir_test.py | 247 - TransPyV/Test/App/namespace_defs.py | 60 - TransPyV/Test/App/namespace_test.py | 111 - TransPyV/Test/App/new_test.py | 119 - TransPyV/Test/App/oop_test.py | 129 - TransPyV/Test/App/opovl_test.py | 253 - TransPyV/Test/App/ptr_only_test.py | 26 - TransPyV/Test/App/ptr_test.py | 111 - TransPyV/Test/App/simple_test.py | 6 - TransPyV/Test/App/string_min_test.py | 9 - TransPyV/Test/App/string_test.py | 106 - TransPyV/Test/App/struct_test.py | 235 - TransPyV/Test/App/test_main.py | 113 - TransPyV/Test/App/testcheck_test.py | 37 - TransPyV/Test/App/type_bit_test.py | 26 - TransPyV/Test/App/virtual_dispatch_test.py | 83 - TransPyV/Test/App/vtable_test.py | 63 - TransPyV/Test/NegativeTest/App/defs.py | 20 - TransPyV/Test/NegativeTest/App/main.py | 21 - TransPyV/Test/Sha1Test/App/main.py | 62 - TransPyV/output/51f0144d6e8188d9.deps.json | 1 - TransPyV/output/66de93aaeebc0601.deps.json | 1 - TransPyV/output/81eb28ba912467a6.deps.json | 2 +- TransPyV/output/af9484a65085bf4b.deps.json | 2 +- TransPyV/project.json | 2 +- TransPyV/temp/067c78e9f121dce3.pyi | 136 - TransPyV/temp/06f53cc594b4ac6c.pyi | 109 - TransPyV/temp/0df65b8ed15664b0.pyi | 30 - TransPyV/temp/19f8024d10c828e8.pyi | 35 - TransPyV/temp/20cd49775c100a38.pyi | 22 - TransPyV/temp/240a9a4157959a9f.pyi | 38 - TransPyV/temp/271ea3decb810db2.pyi | 26 - TransPyV/temp/4337fb260448bbe2.pyi | 73 - TransPyV/temp/4dd6b3f1427d1cc5.pyi | 82 - TransPyV/temp/51f0144d6e8188d9.doc.json | 1 - TransPyV/temp/51f0144d6e8188d9.pyi | 25 - TransPyV/temp/57288496f7c2d1ad.pyi | 71 - TransPyV/temp/6446627d4f07a1b5.pyi | 86 - TransPyV/temp/657e182b27c2a022.pyi | 226 - TransPyV/temp/66de93aaeebc0601.doc.json | 1 - TransPyV/temp/66de93aaeebc0601.pyi | 25 - TransPyV/temp/6ff26590374ae6fc.pyi | 39 - TransPyV/temp/71e0a3ffcb3ebfad.pyi | 20 - TransPyV/temp/72e2d5ccb7cedcf1.pyi | 91 - TransPyV/temp/81eb28ba912467a6.pyi | 35 - TransPyV/temp/96837bcc64032444.pyi | 13 - TransPyV/temp/_phase1_manifest.json | 2 +- TransPyV/temp/_sha1_map.txt | 160 +- TransPyV/temp/_shared_sym.json | Bin 1931421 -> 1935807 bytes TransPyV/temp/af9484a65085bf4b.pyi | 21 - TransPyV/temp/b547ac4f380bddb6.pyi | 166 - TransPyV/temp/bbdf3bbd4c3bc28c.pyi | 138 - TransPyV/temp/c9d54a4158f7f5a8.pyi | 34 - TransPyV/temp/c9f4be41ca1cc2b4.pyi | 22 - TransPyV/temp/f5522571bcce7bcb.pyi | 100 - TransPyV/temp/f6b51804a0ba8ff0.pyi | 192 - ViperQtHelloWorld/App/{main.py => main.vp} | 0 includes/{_dict.py => _dict.vp} | 0 includes/{_fakeduck.py => _fakeduck.vp} | 0 includes/{_list.py => _list.vp} | 0 includes/{_variant.py => _variant.vp} | 0 includes/{_withcontent.py => _withcontent.vp} | 0 includes/{argparse.py => argparse.vp} | 0 includes/{asm.py => asm.vp} | 0 includes/ast/{__init__.py => __init__.vp} | 0 includes/ast/{astaux.py => astaux.vp} | 0 includes/ast/{base.py => base.vp} | 0 includes/ast/{exprs.py => exprs.vp} | 0 includes/ast/{lexer.py => lexer.vp} | 0 includes/ast/{match.py => match.vp} | 0 includes/ast/{parser.py => parser.vp} | 0 includes/ast/{stmts.py => stmts.vp} | 0 includes/ast/{tokens.py => tokens.vp} | 0 includes/{atom.py => atom.vp} | 0 includes/{base64.py => base64.vp} | 0 includes/{binascii.py => binascii.vp} | 0 includes/{builtins.py => builtins.vp} | 0 includes/{condition.py => condition.vp} | 0 includes/{ctraits.pyi => ctraits.vpi} | 0 includes/{event.py => event.vp} | 0 includes/hashlib/{__init__.py => __init__.vp} | 0 includes/hashlib/{__md5.py => __md5.vp} | 0 includes/hashlib/{__sha1.py => __sha1.vp} | 0 includes/hashlib/{__sha256.py => __sha256.vp} | 0 includes/hashlib/{__sha512.py => __sha512.vp} | 0 includes/{hashtable.py => hashtable.vp} | 0 includes/{hello.py => hello.vp} | 0 includes/json/{__init__.py => __init__.vp} | 0 includes/json/{__parser.py => __parser.vp} | 0 includes/json/{__writer.py => __writer.vp} | 0 includes/{linkedlist.py => linkedlist.vp} | 0 .../llvmlite/{__builder.py => __builder.vp} | 0 .../llvmlite/{__function.py => __function.vp} | 0 .../llvmlite/{__init__.py => __init__.vp} | 0 .../llvmlite/{__module.py => __module.vp} | 0 includes/llvmlite/{__types.py => __types.vp} | 0 .../llvmlite/{__values.py => __values.vp} | 0 .../llvmlite/{__verify.py => __verify.vp} | 0 includes/{lock.py => lock.vp} | 0 includes/{memhub.py => memhub.vp} | 0 includes/numpy/{__init__.py => __init__.vp} | 0 includes/os/{__init__.py => __init__.vp} | 0 includes/os/{_posix.py => _posix.vp} | 0 includes/os/{_win32.py => _win32.vp} | 0 includes/os/{path.py => path.vp} | 0 includes/{platmacro.py => platmacro.vp} | 0 includes/{posix.py => posix.vp} | 0 includes/{requests.py => requests.vp} | 0 includes/{rwlock.py => rwlock.vp} | 0 includes/{shutil.py => shutil.vp} | 0 includes/{socket.py => socket.vp} | 0 includes/{spinlock.py => spinlock.vp} | 0 includes/{stdarg.py => stdarg.vp} | 0 includes/{stdint.py => stdint.vp} | 0 includes/{stdio.py => stdio.vp} | 0 includes/{stdlib.py => stdlib.vp} | 0 includes/{string.py => string.vp} | 0 includes/{subprocess.py => subprocess.vp} | 0 includes/{sys.py => sys.vp} | 0 includes/{testcheck.py => testcheck.vp} | 0 includes/{this.py => this.vp} | 0 includes/{vector.py => vector.vp} | 0 includes/{viperio.py => viperio.vp} | 0 includes/{viperlib.py => viperlib.vp} | 0 includes/{vipermath.py => vipermath.vp} | 0 includes/{vipersimd.py => vipersimd.vp} | 0 includes/{viperstring.py => viperstring.vp} | 0 .../vqt6 copy/{__init__.py => __init__.vp} | 0 includes/vqt6 copy/{_qtcore.py => _qtcore.vp} | 0 includes/vqt6 copy/{_qtgui.py => _qtgui.vp} | 0 .../{_qtnetwork.py => _qtnetwork.vp} | 0 .../{_qtwidgets.py => _qtwidgets.vp} | 0 includes/vqt6 copy/{_types.py => _types.vp} | 0 includes/vqt6/{__init__.py => __init__.vp} | 0 includes/vqt6/{_qtcore.py => _qtcore.vp} | 0 includes/vqt6/{_qtgui.py => _qtgui.vp} | 0 .../vqt6/{_qtnetwork.py => _qtnetwork.vp} | 0 .../vqt6/{_qtwidgets.py => _qtwidgets.vp} | 0 includes/vqt6/{_types.py => _types.vp} | 0 includes/{vrandom.py => vrandom.vp} | 0 includes/{vthreading.py => vthreading.vp} | 0 includes/w32/{fileio.py => fileio.vp} | 0 includes/w32/{win32base.py => win32base.vp} | 0 .../w32/{win32console.py => win32console.vp} | 0 includes/w32/{win32file.py => win32file.vp} | 0 .../w32/{win32memory.py => win32memory.vp} | 0 .../w32/{win32process.py => win32process.vp} | 0 includes/w32/{win32sync.py => win32sync.vp} | 0 includes/w32/{winsock2.py => winsock2.vp} | 0 includes/zlib/{__init__.py => __init__.vp} | 0 includes/zlib/{pyzlib.py => pyzlib.vp} | 0 includes/zlib/{zchecksum.py => zchecksum.vp} | 0 includes/zlib/{zdef.py => zdef.vp} | 0 includes/zlib/{zdeflate.py => zdeflate.vp} | 0 includes/zlib/{zhuff.py => zhuff.vp} | 0 includes/zlib/{zinflate.py => zinflate.vp} | 0 lib/Projectrans/Config.py | 2 +- lib/Projectrans/Phase1Generator.py | 45 +- lib/Projectrans/Phase2Translator.py | 69 +- lib/Projectrans/Utils.py | 8 +- lib/Shell/TransPyC.py | 10 +- lib/StubGen/Config.py | 4 +- lib/StubGen/Converter.py | 2 +- lib/StubGen/Generator.py | 6 +- lib/constants/config.py | 2 +- lib/core/Handles/HandlesExprCall.py | 7 +- lib/core/Handles/HandlesImports.py | 111 +- lib/core/LLVMCG/FuncGen.py | 4 +- lib/core/stub_generator.py | 2 +- test.py => test.vp | 0 thistest/App/{main.py => main.vp} | 0 322 files changed, 246 insertions(+), 31772 deletions(-) delete mode 100644 .transpyc_cache/271ea3decb810db2.pyi rename Test/ArgparseTest/App/{main.py => main.vp} (100%) rename Test/AstTest/App/{main.py => main.vp} (100%) rename Test/BuddyTest/App/{main.py => main.vp} (100%) rename Test/BuddyTest/App/{mbuddytest.py => mbuddytest.vp} (100%) rename Test/BuiltinDecoratorTest/App/{main.py => main.vp} (100%) rename Test/CPythonTest/App/{cpython.py => cpython.vp} (100%) rename Test/CPythonTest/App/{main.py => main.vp} (100%) rename Test/ClosureCallTest/App/{main.py => main.vp} (100%) rename Test/ClosureTest/App/{main.py => main.vp} (100%) rename Test/ClosureTest2/App/{main.py => main.vp} (100%) rename Test/DecoratorMarkerTest/App/{main.py => main.vp} (100%) rename Test/DecoratorTest/App/{main.py => main.vp} (100%) rename Test/DictTest/App/{main.py => main.vp} (100%) rename Test/DocTest/App/{main.py => main.vp} (100%) rename Test/DocTest/App/{remote.py => remote.vp} (100%) rename Test/EdgeCaseTest/App/{main.py => main.vp} (100%) rename Test/EqTest/App/{main.py => main.vp} (100%) rename Test/Extern2Test/App/{main.py => main.vp} (100%) rename Test/FakeDuckTest/App/{main.py => main.vp} (100%) rename Test/ForAndLoopTest/App/{main.py => main.vp} (100%) rename Test/FormatStringTest/App/{main.py => main.vp} (100%) rename Test/FuncTest/App/{main.py => main.vp} (100%) rename Test/G3/App/{main.py => main.vp} (100%) rename Test/G4/App/{caller1.py => caller1.vp} (100%) rename Test/G4/App/{caller2.py => caller2.vp} (100%) rename Test/G4/App/{caller3.py => caller3.vp} (100%) rename Test/G4/App/{main.py => main.vp} (100%) rename Test/G4/includes/{g4node.py => g4node.vp} (100%) rename Test/G5/App/{main.py => main.vp} (100%) rename Test/G5/includes/{g5container.py => g5container.vp} (100%) rename Test/G6/App/{main.py => main.vp} (100%) rename Test/G7/App/{main.py => main.vp} (100%) rename Test/G7/includes/{conflict_node.py => conflict_node.vp} (100%) rename Test/GenericTest/App/{main.py => main.vp} (100%) rename Test/GenericTest2/App/{main.py => main.vp} (100%) rename Test/GenericTest3/App/{main.py => main.vp} (100%) rename Test/GenericTest4/App/{main.py => main.vp} (100%) rename Test/HashTableTest/App/{main.py => main.vp} (100%) rename Test/IterTest/App/{main.py => main.vp} (100%) rename Test/JsonTest/App/{main.py => main.vp} (100%) rename Test/LLvmLiteTest/App/{main.py => main.vp} (100%) rename Test/ListTest/App/{main.py => main.vp} (100%) rename Test/LoopTest/App/{main.py => main.vp} (100%) rename Test/MemhubTest/App/{main.py => main.vp} (100%) rename Test/NewAstTest/App/{main.py => main.vp} (100%) rename Test/NoVTableTest/App/{main.py => main.vp} (100%) rename Test/PointerTest/App/{main.py => main.vp} (100%) rename Test/ShortCircuitTest/App/{main.py => main.vp} (100%) rename Test/SimdTest/App/{main.py => main.vp} (100%) rename Test/SlotsBugTest/App/{main.py => main.vp} (100%) rename Test/SprintfTest/App/{main.py => main.vp} (100%) rename Test/StringIterTest/App/{inline_test.py => inline_test.vp} (100%) rename Test/StringIterTest/App/{main.py => main.vp} (100%) rename Test/StringTest/App/{main.py => main.vp} (100%) rename Test/StructTest/App/{main.py => main.vp} (100%) rename Test/SysLibTest/App/{main.py => main.vp} (100%) rename Test/SysLibTest/App/{os_backend.py => os_backend.vp} (100%) rename Test/SysLibTest/App/{syslibtest_impl.py => syslibtest_impl.vp} (100%) rename Test/TestFBProject/App/{main.py => main.vp} (100%) rename Test/TestProject/App/{BINASCII.py => BINASCII.vp} (100%) rename Test/TestProject/App/{HASHLIB.py => HASHLIB.vp} (100%) rename Test/TestProject/App/{config.py => config.vp} (100%) rename Test/TestProject/App/{main.py => main.vp} (100%) rename Test/TestProject/App/{test_numpy.py => test_numpy.vp} (100%) rename Test/TestProject/App/{test_zlib.py => test_zlib.vp} (100%) rename Test/TestProject/App/zc/{class_test.py => class_test.vp} (100%) rename Test/TestProject/App/zc/{config.py => config.vp} (100%) rename Test/TestProject/App/zc/{logic_test.py => logic_test.vp} (100%) rename Test/TestProject/App/zc/{test.py => test.vp} (100%) rename Test/TestProject2/App/{main.py => main.vp} (100%) rename Test/TestProject2/App/zc/{class_test.py => class_test.vp} (100%) rename Test/TestProject2/App/zc/{config.py => config.vp} (100%) rename Test/TestProject2/App/zc/{logic_test.py => logic_test.vp} (100%) rename Test/TestProject2/App/zc/{test.py => test.vp} (100%) rename Test/TestProject3/App/{definetest.py => definetest.vp} (100%) rename Test/TestProject3/App/{enumtest.py => enumtest.vp} (100%) rename Test/TestProject3/App/{fileiotest.py => fileiotest.vp} (100%) rename Test/TestProject3/App/{main.py => main.vp} (100%) rename Test/TestProject3/App/{mpooltest.py => mpooltest.vp} (100%) rename Test/TestProject3/App/{vectortest.py => vectortest.vp} (100%) rename Test/TypeCastTest/App/{main.py => main.vp} (100%) rename Test/VRandomTest/App/{main.py => main.vp} (100%) rename Test/VariadicTest/App/{main.py => main.vp} (100%) rename Test/WebTest/App/{main.py => main.vp} (100%) rename Test/ZlibTest/App/__zlib/{__init__.py => __init__.vp} (100%) rename Test/ZlibTest/App/__zlib/{pyzlib.py => pyzlib.vp} (100%) rename Test/ZlibTest/App/__zlib/{test_pyzlib.py => test_pyzlib.vp} (100%) rename Test/ZlibTest/App/__zlib/{zchecksum.py => zchecksum.vp} (100%) rename Test/ZlibTest/App/__zlib/{zdef.py => zdef.vp} (100%) rename Test/ZlibTest/App/__zlib/{zdeflate.py => zdeflate.vp} (100%) rename Test/ZlibTest/App/__zlib/{zhuff.py => zhuff.vp} (100%) rename Test/ZlibTest/App/__zlib/{zinflate.py => zinflate.vp} (100%) rename Test/ZlibTest/App/{main.py => main.vp} (100%) delete mode 100644 TransPyV/App/lib/Projectrans/Config.py delete mode 100644 TransPyV/App/lib/Projectrans/Utils.py delete mode 100644 TransPyV/App/lib/Projectrans/__init__.py delete mode 100644 TransPyV/App/lib/__init__.py delete mode 100644 TransPyV/App/lib/core/BuildPipeline.py delete mode 100644 TransPyV/App/lib/core/Handles/HandlesAnnAssign.py delete mode 100644 TransPyV/App/lib/core/Handles/HandlesAssign.py delete mode 100644 TransPyV/App/lib/core/Handles/HandlesAugAssign.py delete mode 100644 TransPyV/App/lib/core/Handles/HandlesBase.py delete mode 100644 TransPyV/App/lib/core/Handles/HandlesBody.py delete mode 100644 TransPyV/App/lib/core/Handles/HandlesClassDef.py delete mode 100644 TransPyV/App/lib/core/Handles/HandlesEnum.py delete mode 100644 TransPyV/App/lib/core/Handles/HandlesExpr.py delete mode 100644 TransPyV/App/lib/core/Handles/HandlesExprCall.py delete mode 100644 TransPyV/App/lib/core/Handles/HandlesExprOps.py delete mode 100644 TransPyV/App/lib/core/Handles/HandlesFor.py delete mode 100644 TransPyV/App/lib/core/Handles/HandlesFunctions.py delete mode 100644 TransPyV/App/lib/core/Handles/HandlesIf.py delete mode 100644 TransPyV/App/lib/core/Handles/HandlesImports.py delete mode 100644 TransPyV/App/lib/core/Handles/HandlesMain.py delete mode 100644 TransPyV/App/lib/core/Handles/HandlesNonlocal.py delete mode 100644 TransPyV/App/lib/core/Handles/HandlesReturn.py delete mode 100644 TransPyV/App/lib/core/Handles/HandlesStruct.py delete mode 100644 TransPyV/App/lib/core/Handles/HandlesTranslator.py delete mode 100644 TransPyV/App/lib/core/Handles/HandlesType.py delete mode 100644 TransPyV/App/lib/core/Handles/HandlesVar.py delete mode 100644 TransPyV/App/lib/core/Handles/HandlesWhile.py delete mode 100644 TransPyV/App/lib/core/Handles/__init__.py delete mode 100644 TransPyV/App/lib/core/IncludesScanner.py delete mode 100644 TransPyV/App/lib/core/Phase1.py delete mode 100644 TransPyV/App/lib/core/Phase2.py delete mode 100644 TransPyV/App/lib/core/StubMerger.py delete mode 100644 TransPyV/App/lib/core/VLogger.py delete mode 100644 TransPyV/App/lib/core/__init__.py delete mode 100644 TransPyV/App/main.py delete mode 100644 TransPyV/Test/App/asm_test.py delete mode 100644 TransPyV/Test/App/attr_test.py delete mode 100644 TransPyV/Test/App/augassign_test.py delete mode 100644 TransPyV/Test/App/closure_test.py delete mode 100644 TransPyV/Test/App/deco_test.py delete mode 100644 TransPyV/Test/App/deref_min_test.py delete mode 100644 TransPyV/Test/App/deref_test.py delete mode 100644 TransPyV/Test/App/eq_test.py delete mode 100644 TransPyV/Test/App/float_test.py delete mode 100644 TransPyV/Test/App/flow_test.py delete mode 100644 TransPyV/Test/App/for_test.py delete mode 100644 TransPyV/Test/App/func_test.py delete mode 100644 TransPyV/Test/App/func_vtable_test.py delete mode 100644 TransPyV/Test/App/inherit_test.py delete mode 100644 TransPyV/Test/App/llvmir_test.py delete mode 100644 TransPyV/Test/App/namespace_defs.py delete mode 100644 TransPyV/Test/App/namespace_test.py delete mode 100644 TransPyV/Test/App/new_test.py delete mode 100644 TransPyV/Test/App/oop_test.py delete mode 100644 TransPyV/Test/App/opovl_test.py delete mode 100644 TransPyV/Test/App/ptr_only_test.py delete mode 100644 TransPyV/Test/App/ptr_test.py delete mode 100644 TransPyV/Test/App/simple_test.py delete mode 100644 TransPyV/Test/App/string_min_test.py delete mode 100644 TransPyV/Test/App/string_test.py delete mode 100644 TransPyV/Test/App/struct_test.py delete mode 100644 TransPyV/Test/App/test_main.py delete mode 100644 TransPyV/Test/App/testcheck_test.py delete mode 100644 TransPyV/Test/App/type_bit_test.py delete mode 100644 TransPyV/Test/App/virtual_dispatch_test.py delete mode 100644 TransPyV/Test/App/vtable_test.py delete mode 100644 TransPyV/Test/NegativeTest/App/defs.py delete mode 100644 TransPyV/Test/NegativeTest/App/main.py delete mode 100644 TransPyV/Test/Sha1Test/App/main.py delete mode 100644 TransPyV/output/51f0144d6e8188d9.deps.json delete mode 100644 TransPyV/output/66de93aaeebc0601.deps.json delete mode 100644 TransPyV/temp/067c78e9f121dce3.pyi delete mode 100644 TransPyV/temp/06f53cc594b4ac6c.pyi delete mode 100644 TransPyV/temp/0df65b8ed15664b0.pyi delete mode 100644 TransPyV/temp/19f8024d10c828e8.pyi delete mode 100644 TransPyV/temp/20cd49775c100a38.pyi delete mode 100644 TransPyV/temp/240a9a4157959a9f.pyi delete mode 100644 TransPyV/temp/271ea3decb810db2.pyi delete mode 100644 TransPyV/temp/4337fb260448bbe2.pyi delete mode 100644 TransPyV/temp/4dd6b3f1427d1cc5.pyi delete mode 100644 TransPyV/temp/51f0144d6e8188d9.doc.json delete mode 100644 TransPyV/temp/51f0144d6e8188d9.pyi delete mode 100644 TransPyV/temp/57288496f7c2d1ad.pyi delete mode 100644 TransPyV/temp/6446627d4f07a1b5.pyi delete mode 100644 TransPyV/temp/657e182b27c2a022.pyi delete mode 100644 TransPyV/temp/66de93aaeebc0601.doc.json delete mode 100644 TransPyV/temp/66de93aaeebc0601.pyi delete mode 100644 TransPyV/temp/6ff26590374ae6fc.pyi delete mode 100644 TransPyV/temp/71e0a3ffcb3ebfad.pyi delete mode 100644 TransPyV/temp/72e2d5ccb7cedcf1.pyi delete mode 100644 TransPyV/temp/81eb28ba912467a6.pyi delete mode 100644 TransPyV/temp/96837bcc64032444.pyi delete mode 100644 TransPyV/temp/af9484a65085bf4b.pyi delete mode 100644 TransPyV/temp/b547ac4f380bddb6.pyi delete mode 100644 TransPyV/temp/bbdf3bbd4c3bc28c.pyi delete mode 100644 TransPyV/temp/c9d54a4158f7f5a8.pyi delete mode 100644 TransPyV/temp/c9f4be41ca1cc2b4.pyi delete mode 100644 TransPyV/temp/f5522571bcce7bcb.pyi delete mode 100644 TransPyV/temp/f6b51804a0ba8ff0.pyi rename ViperQtHelloWorld/App/{main.py => main.vp} (100%) rename includes/{_dict.py => _dict.vp} (100%) rename includes/{_fakeduck.py => _fakeduck.vp} (100%) rename includes/{_list.py => _list.vp} (100%) rename includes/{_variant.py => _variant.vp} (100%) rename includes/{_withcontent.py => _withcontent.vp} (100%) rename includes/{argparse.py => argparse.vp} (100%) rename includes/{asm.py => asm.vp} (100%) rename includes/ast/{__init__.py => __init__.vp} (100%) rename includes/ast/{astaux.py => astaux.vp} (100%) rename includes/ast/{base.py => base.vp} (100%) rename includes/ast/{exprs.py => exprs.vp} (100%) rename includes/ast/{lexer.py => lexer.vp} (100%) rename includes/ast/{match.py => match.vp} (100%) rename includes/ast/{parser.py => parser.vp} (100%) rename includes/ast/{stmts.py => stmts.vp} (100%) rename includes/ast/{tokens.py => tokens.vp} (100%) rename includes/{atom.py => atom.vp} (100%) rename includes/{base64.py => base64.vp} (100%) rename includes/{binascii.py => binascii.vp} (100%) rename includes/{builtins.py => builtins.vp} (100%) rename includes/{condition.py => condition.vp} (100%) rename includes/{ctraits.pyi => ctraits.vpi} (100%) rename includes/{event.py => event.vp} (100%) rename includes/hashlib/{__init__.py => __init__.vp} (100%) rename includes/hashlib/{__md5.py => __md5.vp} (100%) rename includes/hashlib/{__sha1.py => __sha1.vp} (100%) rename includes/hashlib/{__sha256.py => __sha256.vp} (100%) rename includes/hashlib/{__sha512.py => __sha512.vp} (100%) rename includes/{hashtable.py => hashtable.vp} (100%) rename includes/{hello.py => hello.vp} (100%) rename includes/json/{__init__.py => __init__.vp} (100%) rename includes/json/{__parser.py => __parser.vp} (100%) rename includes/json/{__writer.py => __writer.vp} (100%) rename includes/{linkedlist.py => linkedlist.vp} (100%) rename includes/llvmlite/{__builder.py => __builder.vp} (100%) rename includes/llvmlite/{__function.py => __function.vp} (100%) rename includes/llvmlite/{__init__.py => __init__.vp} (100%) rename includes/llvmlite/{__module.py => __module.vp} (100%) rename includes/llvmlite/{__types.py => __types.vp} (100%) rename includes/llvmlite/{__values.py => __values.vp} (100%) rename includes/llvmlite/{__verify.py => __verify.vp} (100%) rename includes/{lock.py => lock.vp} (100%) rename includes/{memhub.py => memhub.vp} (100%) rename includes/numpy/{__init__.py => __init__.vp} (100%) rename includes/os/{__init__.py => __init__.vp} (100%) rename includes/os/{_posix.py => _posix.vp} (100%) rename includes/os/{_win32.py => _win32.vp} (100%) rename includes/os/{path.py => path.vp} (100%) rename includes/{platmacro.py => platmacro.vp} (100%) rename includes/{posix.py => posix.vp} (100%) rename includes/{requests.py => requests.vp} (100%) rename includes/{rwlock.py => rwlock.vp} (100%) rename includes/{shutil.py => shutil.vp} (100%) rename includes/{socket.py => socket.vp} (100%) rename includes/{spinlock.py => spinlock.vp} (100%) rename includes/{stdarg.py => stdarg.vp} (100%) rename includes/{stdint.py => stdint.vp} (100%) rename includes/{stdio.py => stdio.vp} (100%) rename includes/{stdlib.py => stdlib.vp} (100%) rename includes/{string.py => string.vp} (100%) rename includes/{subprocess.py => subprocess.vp} (100%) rename includes/{sys.py => sys.vp} (100%) rename includes/{testcheck.py => testcheck.vp} (100%) rename includes/{this.py => this.vp} (100%) rename includes/{vector.py => vector.vp} (100%) rename includes/{viperio.py => viperio.vp} (100%) rename includes/{viperlib.py => viperlib.vp} (100%) rename includes/{vipermath.py => vipermath.vp} (100%) rename includes/{vipersimd.py => vipersimd.vp} (100%) rename includes/{viperstring.py => viperstring.vp} (100%) rename includes/vqt6 copy/{__init__.py => __init__.vp} (100%) rename includes/vqt6 copy/{_qtcore.py => _qtcore.vp} (100%) rename includes/vqt6 copy/{_qtgui.py => _qtgui.vp} (100%) rename includes/vqt6 copy/{_qtnetwork.py => _qtnetwork.vp} (100%) rename includes/vqt6 copy/{_qtwidgets.py => _qtwidgets.vp} (100%) rename includes/vqt6 copy/{_types.py => _types.vp} (100%) rename includes/vqt6/{__init__.py => __init__.vp} (100%) rename includes/vqt6/{_qtcore.py => _qtcore.vp} (100%) rename includes/vqt6/{_qtgui.py => _qtgui.vp} (100%) rename includes/vqt6/{_qtnetwork.py => _qtnetwork.vp} (100%) rename includes/vqt6/{_qtwidgets.py => _qtwidgets.vp} (100%) rename includes/vqt6/{_types.py => _types.vp} (100%) rename includes/{vrandom.py => vrandom.vp} (100%) rename includes/{vthreading.py => vthreading.vp} (100%) rename includes/w32/{fileio.py => fileio.vp} (100%) rename includes/w32/{win32base.py => win32base.vp} (100%) rename includes/w32/{win32console.py => win32console.vp} (100%) rename includes/w32/{win32file.py => win32file.vp} (100%) rename includes/w32/{win32memory.py => win32memory.vp} (100%) rename includes/w32/{win32process.py => win32process.vp} (100%) rename includes/w32/{win32sync.py => win32sync.vp} (100%) rename includes/w32/{winsock2.py => winsock2.vp} (100%) rename includes/zlib/{__init__.py => __init__.vp} (100%) rename includes/zlib/{pyzlib.py => pyzlib.vp} (100%) rename includes/zlib/{zchecksum.py => zchecksum.vp} (100%) rename includes/zlib/{zdef.py => zdef.vp} (100%) rename includes/zlib/{zdeflate.py => zdeflate.vp} (100%) rename includes/zlib/{zhuff.py => zhuff.vp} (100%) rename includes/zlib/{zinflate.py => zinflate.vp} (100%) rename test.py => test.vp (100%) rename thistest/App/{main.py => main.vp} (100%) diff --git a/.transpyc_cache/067c78e9f121dce3.pyi b/.transpyc_cache/067c78e9f121dce3.pyi index f4f767c..a606126 100644 --- a/.transpyc_cache/067c78e9f121dce3.pyi +++ b/.transpyc_cache/067c78e9f121dce3.pyi @@ -1,5 +1,5 @@ """ -Auto-generated Python stub file from w32.win32process.py +Auto-generated Python stub file from w32.win32process.vp Module: w32.win32process """ diff --git a/.transpyc_cache/06f53cc594b4ac6c.pyi b/.transpyc_cache/06f53cc594b4ac6c.pyi index 8b5a8cf..ac278f4 100644 --- a/.transpyc_cache/06f53cc594b4ac6c.pyi +++ b/.transpyc_cache/06f53cc594b4ac6c.pyi @@ -1,5 +1,5 @@ """ -Auto-generated Python stub file from w32.win32sync.py +Auto-generated Python stub file from w32.win32sync.vp Module: w32.win32sync """ diff --git a/.transpyc_cache/271ea3decb810db2.pyi b/.transpyc_cache/271ea3decb810db2.pyi deleted file mode 100644 index 3d637bf..0000000 --- a/.transpyc_cache/271ea3decb810db2.pyi +++ /dev/null @@ -1,26 +0,0 @@ -""" -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/.transpyc_cache/6446627d4f07a1b5.pyi b/.transpyc_cache/6446627d4f07a1b5.pyi index d7bcff4..55f6a1f 100644 --- a/.transpyc_cache/6446627d4f07a1b5.pyi +++ b/.transpyc_cache/6446627d4f07a1b5.pyi @@ -1,5 +1,5 @@ """ -Auto-generated Python stub file from w32.winsock2.py +Auto-generated Python stub file from w32.winsock2.vp Module: w32.winsock2 """ diff --git a/.transpyc_cache/72e2d5ccb7cedcf1.pyi b/.transpyc_cache/72e2d5ccb7cedcf1.pyi index 5fceb08..f85ee45 100644 --- a/.transpyc_cache/72e2d5ccb7cedcf1.pyi +++ b/.transpyc_cache/72e2d5ccb7cedcf1.pyi @@ -1,5 +1,5 @@ """ -Auto-generated Python stub file from w32.win32memory.py +Auto-generated Python stub file from w32.win32memory.vp Module: w32.win32memory """ diff --git a/.transpyc_cache/bbdf3bbd4c3bc28c.pyi b/.transpyc_cache/bbdf3bbd4c3bc28c.pyi index 70dcdbc..4709b3e 100644 --- a/.transpyc_cache/bbdf3bbd4c3bc28c.pyi +++ b/.transpyc_cache/bbdf3bbd4c3bc28c.pyi @@ -1,5 +1,5 @@ """ -Auto-generated Python stub file from w32.win32console.py +Auto-generated Python stub file from w32.win32console.vp Module: w32.win32console """ diff --git a/.transpyc_cache/c9f4be41ca1cc2b4.pyi b/.transpyc_cache/c9f4be41ca1cc2b4.pyi index 12ff3c2..f7ed5fd 100644 --- a/.transpyc_cache/c9f4be41ca1cc2b4.pyi +++ b/.transpyc_cache/c9f4be41ca1cc2b4.pyi @@ -1,5 +1,5 @@ """ -Auto-generated Python stub file from viperio.py +Auto-generated Python stub file from viperio.vp Module: viperio """ diff --git a/.transpyc_cache/f5522571bcce7bcb.pyi b/.transpyc_cache/f5522571bcce7bcb.pyi index 106a202..f0bc071 100644 --- a/.transpyc_cache/f5522571bcce7bcb.pyi +++ b/.transpyc_cache/f5522571bcce7bcb.pyi @@ -1,5 +1,5 @@ """ -Auto-generated Python stub file from stdint.py +Auto-generated Python stub file from stdint.vp Module: stdint """ diff --git a/.transpyc_cache/f6b51804a0ba8ff0.pyi b/.transpyc_cache/f6b51804a0ba8ff0.pyi index 0036d89..6ee80a6 100644 --- a/.transpyc_cache/f6b51804a0ba8ff0.pyi +++ b/.transpyc_cache/f6b51804a0ba8ff0.pyi @@ -1,5 +1,5 @@ """ -Auto-generated Python stub file from w32.win32file.py +Auto-generated Python stub file from w32.win32file.vp Module: w32.win32file """ diff --git a/Test/ArgparseTest/App/main.py b/Test/ArgparseTest/App/main.vp similarity index 100% rename from Test/ArgparseTest/App/main.py rename to Test/ArgparseTest/App/main.vp diff --git a/Test/AstTest/App/main.py b/Test/AstTest/App/main.vp similarity index 100% rename from Test/AstTest/App/main.py rename to Test/AstTest/App/main.vp diff --git a/Test/BuddyTest/App/main.py b/Test/BuddyTest/App/main.vp similarity index 100% rename from Test/BuddyTest/App/main.py rename to Test/BuddyTest/App/main.vp diff --git a/Test/BuddyTest/App/mbuddytest.py b/Test/BuddyTest/App/mbuddytest.vp similarity index 100% rename from Test/BuddyTest/App/mbuddytest.py rename to Test/BuddyTest/App/mbuddytest.vp diff --git a/Test/BuiltinDecoratorTest/App/main.py b/Test/BuiltinDecoratorTest/App/main.vp similarity index 100% rename from Test/BuiltinDecoratorTest/App/main.py rename to Test/BuiltinDecoratorTest/App/main.vp diff --git a/Test/CPythonTest/App/cpython.py b/Test/CPythonTest/App/cpython.vp similarity index 100% rename from Test/CPythonTest/App/cpython.py rename to Test/CPythonTest/App/cpython.vp diff --git a/Test/CPythonTest/App/main.py b/Test/CPythonTest/App/main.vp similarity index 100% rename from Test/CPythonTest/App/main.py rename to Test/CPythonTest/App/main.vp diff --git a/Test/ClosureCallTest/App/main.py b/Test/ClosureCallTest/App/main.vp similarity index 100% rename from Test/ClosureCallTest/App/main.py rename to Test/ClosureCallTest/App/main.vp diff --git a/Test/ClosureTest/App/main.py b/Test/ClosureTest/App/main.vp similarity index 100% rename from Test/ClosureTest/App/main.py rename to Test/ClosureTest/App/main.vp diff --git a/Test/ClosureTest2/App/main.py b/Test/ClosureTest2/App/main.vp similarity index 100% rename from Test/ClosureTest2/App/main.py rename to Test/ClosureTest2/App/main.vp diff --git a/Test/DecoratorMarkerTest/App/main.py b/Test/DecoratorMarkerTest/App/main.vp similarity index 100% rename from Test/DecoratorMarkerTest/App/main.py rename to Test/DecoratorMarkerTest/App/main.vp diff --git a/Test/DecoratorTest/App/main.py b/Test/DecoratorTest/App/main.vp similarity index 100% rename from Test/DecoratorTest/App/main.py rename to Test/DecoratorTest/App/main.vp diff --git a/Test/DictTest/App/main.py b/Test/DictTest/App/main.vp similarity index 100% rename from Test/DictTest/App/main.py rename to Test/DictTest/App/main.vp diff --git a/Test/DocTest/App/main.py b/Test/DocTest/App/main.vp similarity index 100% rename from Test/DocTest/App/main.py rename to Test/DocTest/App/main.vp diff --git a/Test/DocTest/App/remote.py b/Test/DocTest/App/remote.vp similarity index 100% rename from Test/DocTest/App/remote.py rename to Test/DocTest/App/remote.vp diff --git a/Test/EdgeCaseTest/App/main.py b/Test/EdgeCaseTest/App/main.vp similarity index 100% rename from Test/EdgeCaseTest/App/main.py rename to Test/EdgeCaseTest/App/main.vp diff --git a/Test/EqTest/App/main.py b/Test/EqTest/App/main.vp similarity index 100% rename from Test/EqTest/App/main.py rename to Test/EqTest/App/main.vp diff --git a/Test/Extern2Test/App/main.py b/Test/Extern2Test/App/main.vp similarity index 100% rename from Test/Extern2Test/App/main.py rename to Test/Extern2Test/App/main.vp diff --git a/Test/FakeDuckTest/App/main.py b/Test/FakeDuckTest/App/main.vp similarity index 100% rename from Test/FakeDuckTest/App/main.py rename to Test/FakeDuckTest/App/main.vp diff --git a/Test/ForAndLoopTest/App/main.py b/Test/ForAndLoopTest/App/main.vp similarity index 100% rename from Test/ForAndLoopTest/App/main.py rename to Test/ForAndLoopTest/App/main.vp diff --git a/Test/FormatStringTest/App/main.py b/Test/FormatStringTest/App/main.vp similarity index 100% rename from Test/FormatStringTest/App/main.py rename to Test/FormatStringTest/App/main.vp diff --git a/Test/FuncTest/App/main.py b/Test/FuncTest/App/main.vp similarity index 100% rename from Test/FuncTest/App/main.py rename to Test/FuncTest/App/main.vp diff --git a/Test/G3/App/main.py b/Test/G3/App/main.vp similarity index 100% rename from Test/G3/App/main.py rename to Test/G3/App/main.vp diff --git a/Test/G4/App/caller1.py b/Test/G4/App/caller1.vp similarity index 100% rename from Test/G4/App/caller1.py rename to Test/G4/App/caller1.vp diff --git a/Test/G4/App/caller2.py b/Test/G4/App/caller2.vp similarity index 100% rename from Test/G4/App/caller2.py rename to Test/G4/App/caller2.vp diff --git a/Test/G4/App/caller3.py b/Test/G4/App/caller3.vp similarity index 100% rename from Test/G4/App/caller3.py rename to Test/G4/App/caller3.vp diff --git a/Test/G4/App/main.py b/Test/G4/App/main.vp similarity index 100% rename from Test/G4/App/main.py rename to Test/G4/App/main.vp diff --git a/Test/G4/includes/g4node.py b/Test/G4/includes/g4node.vp similarity index 100% rename from Test/G4/includes/g4node.py rename to Test/G4/includes/g4node.vp diff --git a/Test/G5/App/main.py b/Test/G5/App/main.vp similarity index 100% rename from Test/G5/App/main.py rename to Test/G5/App/main.vp diff --git a/Test/G5/includes/g5container.py b/Test/G5/includes/g5container.vp similarity index 100% rename from Test/G5/includes/g5container.py rename to Test/G5/includes/g5container.vp diff --git a/Test/G6/App/main.py b/Test/G6/App/main.vp similarity index 100% rename from Test/G6/App/main.py rename to Test/G6/App/main.vp diff --git a/Test/G7/App/main.py b/Test/G7/App/main.vp similarity index 100% rename from Test/G7/App/main.py rename to Test/G7/App/main.vp diff --git a/Test/G7/includes/conflict_node.py b/Test/G7/includes/conflict_node.vp similarity index 100% rename from Test/G7/includes/conflict_node.py rename to Test/G7/includes/conflict_node.vp diff --git a/Test/GenericTest/App/main.py b/Test/GenericTest/App/main.vp similarity index 100% rename from Test/GenericTest/App/main.py rename to Test/GenericTest/App/main.vp diff --git a/Test/GenericTest2/App/main.py b/Test/GenericTest2/App/main.vp similarity index 100% rename from Test/GenericTest2/App/main.py rename to Test/GenericTest2/App/main.vp diff --git a/Test/GenericTest3/App/main.py b/Test/GenericTest3/App/main.vp similarity index 100% rename from Test/GenericTest3/App/main.py rename to Test/GenericTest3/App/main.vp diff --git a/Test/GenericTest4/App/main.py b/Test/GenericTest4/App/main.vp similarity index 100% rename from Test/GenericTest4/App/main.py rename to Test/GenericTest4/App/main.vp diff --git a/Test/HashTableTest/App/main.py b/Test/HashTableTest/App/main.vp similarity index 100% rename from Test/HashTableTest/App/main.py rename to Test/HashTableTest/App/main.vp diff --git a/Test/IterTest/App/main.py b/Test/IterTest/App/main.vp similarity index 100% rename from Test/IterTest/App/main.py rename to Test/IterTest/App/main.vp diff --git a/Test/JsonTest/App/main.py b/Test/JsonTest/App/main.vp similarity index 100% rename from Test/JsonTest/App/main.py rename to Test/JsonTest/App/main.vp diff --git a/Test/LLvmLiteTest/App/main.py b/Test/LLvmLiteTest/App/main.vp similarity index 100% rename from Test/LLvmLiteTest/App/main.py rename to Test/LLvmLiteTest/App/main.vp diff --git a/Test/ListTest/App/main.py b/Test/ListTest/App/main.vp similarity index 100% rename from Test/ListTest/App/main.py rename to Test/ListTest/App/main.vp diff --git a/Test/LoopTest/App/main.py b/Test/LoopTest/App/main.vp similarity index 100% rename from Test/LoopTest/App/main.py rename to Test/LoopTest/App/main.vp diff --git a/Test/MemhubTest/App/main.py b/Test/MemhubTest/App/main.vp similarity index 100% rename from Test/MemhubTest/App/main.py rename to Test/MemhubTest/App/main.vp diff --git a/Test/NewAstTest/App/main.py b/Test/NewAstTest/App/main.vp similarity index 100% rename from Test/NewAstTest/App/main.py rename to Test/NewAstTest/App/main.vp diff --git a/Test/NoVTableTest/App/main.py b/Test/NoVTableTest/App/main.vp similarity index 100% rename from Test/NoVTableTest/App/main.py rename to Test/NoVTableTest/App/main.vp diff --git a/Test/PointerTest/App/main.py b/Test/PointerTest/App/main.vp similarity index 100% rename from Test/PointerTest/App/main.py rename to Test/PointerTest/App/main.vp diff --git a/Test/ShortCircuitTest/App/main.py b/Test/ShortCircuitTest/App/main.vp similarity index 100% rename from Test/ShortCircuitTest/App/main.py rename to Test/ShortCircuitTest/App/main.vp diff --git a/Test/SimdTest/App/main.py b/Test/SimdTest/App/main.vp similarity index 100% rename from Test/SimdTest/App/main.py rename to Test/SimdTest/App/main.vp diff --git a/Test/SlotsBugTest/App/main.py b/Test/SlotsBugTest/App/main.vp similarity index 100% rename from Test/SlotsBugTest/App/main.py rename to Test/SlotsBugTest/App/main.vp diff --git a/Test/SprintfTest/App/main.py b/Test/SprintfTest/App/main.vp similarity index 100% rename from Test/SprintfTest/App/main.py rename to Test/SprintfTest/App/main.vp diff --git a/Test/StringIterTest/App/inline_test.py b/Test/StringIterTest/App/inline_test.vp similarity index 100% rename from Test/StringIterTest/App/inline_test.py rename to Test/StringIterTest/App/inline_test.vp diff --git a/Test/StringIterTest/App/main.py b/Test/StringIterTest/App/main.vp similarity index 100% rename from Test/StringIterTest/App/main.py rename to Test/StringIterTest/App/main.vp diff --git a/Test/StringTest/App/main.py b/Test/StringTest/App/main.vp similarity index 100% rename from Test/StringTest/App/main.py rename to Test/StringTest/App/main.vp diff --git a/Test/StructTest/App/main.py b/Test/StructTest/App/main.vp similarity index 100% rename from Test/StructTest/App/main.py rename to Test/StructTest/App/main.vp diff --git a/Test/SysLibTest/App/main.py b/Test/SysLibTest/App/main.vp similarity index 100% rename from Test/SysLibTest/App/main.py rename to Test/SysLibTest/App/main.vp diff --git a/Test/SysLibTest/App/os_backend.py b/Test/SysLibTest/App/os_backend.vp similarity index 100% rename from Test/SysLibTest/App/os_backend.py rename to Test/SysLibTest/App/os_backend.vp diff --git a/Test/SysLibTest/App/syslibtest_impl.py b/Test/SysLibTest/App/syslibtest_impl.vp similarity index 100% rename from Test/SysLibTest/App/syslibtest_impl.py rename to Test/SysLibTest/App/syslibtest_impl.vp diff --git a/Test/TestFBProject/App/main.py b/Test/TestFBProject/App/main.vp similarity index 100% rename from Test/TestFBProject/App/main.py rename to Test/TestFBProject/App/main.vp diff --git a/Test/TestProject/App/BINASCII.py b/Test/TestProject/App/BINASCII.vp similarity index 100% rename from Test/TestProject/App/BINASCII.py rename to Test/TestProject/App/BINASCII.vp diff --git a/Test/TestProject/App/HASHLIB.py b/Test/TestProject/App/HASHLIB.vp similarity index 100% rename from Test/TestProject/App/HASHLIB.py rename to Test/TestProject/App/HASHLIB.vp diff --git a/Test/TestProject/App/config.py b/Test/TestProject/App/config.vp similarity index 100% rename from Test/TestProject/App/config.py rename to Test/TestProject/App/config.vp diff --git a/Test/TestProject/App/main.py b/Test/TestProject/App/main.vp similarity index 100% rename from Test/TestProject/App/main.py rename to Test/TestProject/App/main.vp diff --git a/Test/TestProject/App/test_numpy.py b/Test/TestProject/App/test_numpy.vp similarity index 100% rename from Test/TestProject/App/test_numpy.py rename to Test/TestProject/App/test_numpy.vp diff --git a/Test/TestProject/App/test_zlib.py b/Test/TestProject/App/test_zlib.vp similarity index 100% rename from Test/TestProject/App/test_zlib.py rename to Test/TestProject/App/test_zlib.vp diff --git a/Test/TestProject/App/zc/class_test.py b/Test/TestProject/App/zc/class_test.vp similarity index 100% rename from Test/TestProject/App/zc/class_test.py rename to Test/TestProject/App/zc/class_test.vp diff --git a/Test/TestProject/App/zc/config.py b/Test/TestProject/App/zc/config.vp similarity index 100% rename from Test/TestProject/App/zc/config.py rename to Test/TestProject/App/zc/config.vp diff --git a/Test/TestProject/App/zc/logic_test.py b/Test/TestProject/App/zc/logic_test.vp similarity index 100% rename from Test/TestProject/App/zc/logic_test.py rename to Test/TestProject/App/zc/logic_test.vp diff --git a/Test/TestProject/App/zc/test.py b/Test/TestProject/App/zc/test.vp similarity index 100% rename from Test/TestProject/App/zc/test.py rename to Test/TestProject/App/zc/test.vp diff --git a/Test/TestProject2/App/main.py b/Test/TestProject2/App/main.vp similarity index 100% rename from Test/TestProject2/App/main.py rename to Test/TestProject2/App/main.vp diff --git a/Test/TestProject2/App/zc/class_test.py b/Test/TestProject2/App/zc/class_test.vp similarity index 100% rename from Test/TestProject2/App/zc/class_test.py rename to Test/TestProject2/App/zc/class_test.vp diff --git a/Test/TestProject2/App/zc/config.py b/Test/TestProject2/App/zc/config.vp similarity index 100% rename from Test/TestProject2/App/zc/config.py rename to Test/TestProject2/App/zc/config.vp diff --git a/Test/TestProject2/App/zc/logic_test.py b/Test/TestProject2/App/zc/logic_test.vp similarity index 100% rename from Test/TestProject2/App/zc/logic_test.py rename to Test/TestProject2/App/zc/logic_test.vp diff --git a/Test/TestProject2/App/zc/test.py b/Test/TestProject2/App/zc/test.vp similarity index 100% rename from Test/TestProject2/App/zc/test.py rename to Test/TestProject2/App/zc/test.vp diff --git a/Test/TestProject3/App/definetest.py b/Test/TestProject3/App/definetest.vp similarity index 100% rename from Test/TestProject3/App/definetest.py rename to Test/TestProject3/App/definetest.vp diff --git a/Test/TestProject3/App/enumtest.py b/Test/TestProject3/App/enumtest.vp similarity index 100% rename from Test/TestProject3/App/enumtest.py rename to Test/TestProject3/App/enumtest.vp diff --git a/Test/TestProject3/App/fileiotest.py b/Test/TestProject3/App/fileiotest.vp similarity index 100% rename from Test/TestProject3/App/fileiotest.py rename to Test/TestProject3/App/fileiotest.vp diff --git a/Test/TestProject3/App/main.py b/Test/TestProject3/App/main.vp similarity index 100% rename from Test/TestProject3/App/main.py rename to Test/TestProject3/App/main.vp diff --git a/Test/TestProject3/App/mpooltest.py b/Test/TestProject3/App/mpooltest.vp similarity index 100% rename from Test/TestProject3/App/mpooltest.py rename to Test/TestProject3/App/mpooltest.vp diff --git a/Test/TestProject3/App/vectortest.py b/Test/TestProject3/App/vectortest.vp similarity index 100% rename from Test/TestProject3/App/vectortest.py rename to Test/TestProject3/App/vectortest.vp diff --git a/Test/TypeCastTest/App/main.py b/Test/TypeCastTest/App/main.vp similarity index 100% rename from Test/TypeCastTest/App/main.py rename to Test/TypeCastTest/App/main.vp diff --git a/Test/VRandomTest/App/main.py b/Test/VRandomTest/App/main.vp similarity index 100% rename from Test/VRandomTest/App/main.py rename to Test/VRandomTest/App/main.vp diff --git a/Test/VariadicTest/App/main.py b/Test/VariadicTest/App/main.vp similarity index 100% rename from Test/VariadicTest/App/main.py rename to Test/VariadicTest/App/main.vp diff --git a/Test/WebTest/App/main.py b/Test/WebTest/App/main.vp similarity index 100% rename from Test/WebTest/App/main.py rename to Test/WebTest/App/main.vp diff --git a/Test/ZlibTest/App/__zlib/__init__.py b/Test/ZlibTest/App/__zlib/__init__.vp similarity index 100% rename from Test/ZlibTest/App/__zlib/__init__.py rename to Test/ZlibTest/App/__zlib/__init__.vp diff --git a/Test/ZlibTest/App/__zlib/pyzlib.py b/Test/ZlibTest/App/__zlib/pyzlib.vp similarity index 100% rename from Test/ZlibTest/App/__zlib/pyzlib.py rename to Test/ZlibTest/App/__zlib/pyzlib.vp diff --git a/Test/ZlibTest/App/__zlib/test_pyzlib.py b/Test/ZlibTest/App/__zlib/test_pyzlib.vp similarity index 100% rename from Test/ZlibTest/App/__zlib/test_pyzlib.py rename to Test/ZlibTest/App/__zlib/test_pyzlib.vp diff --git a/Test/ZlibTest/App/__zlib/zchecksum.py b/Test/ZlibTest/App/__zlib/zchecksum.vp similarity index 100% rename from Test/ZlibTest/App/__zlib/zchecksum.py rename to Test/ZlibTest/App/__zlib/zchecksum.vp diff --git a/Test/ZlibTest/App/__zlib/zdef.py b/Test/ZlibTest/App/__zlib/zdef.vp similarity index 100% rename from Test/ZlibTest/App/__zlib/zdef.py rename to Test/ZlibTest/App/__zlib/zdef.vp diff --git a/Test/ZlibTest/App/__zlib/zdeflate.py b/Test/ZlibTest/App/__zlib/zdeflate.vp similarity index 100% rename from Test/ZlibTest/App/__zlib/zdeflate.py rename to Test/ZlibTest/App/__zlib/zdeflate.vp diff --git a/Test/ZlibTest/App/__zlib/zhuff.py b/Test/ZlibTest/App/__zlib/zhuff.vp similarity index 100% rename from Test/ZlibTest/App/__zlib/zhuff.py rename to Test/ZlibTest/App/__zlib/zhuff.vp diff --git a/Test/ZlibTest/App/__zlib/zinflate.py b/Test/ZlibTest/App/__zlib/zinflate.vp similarity index 100% rename from Test/ZlibTest/App/__zlib/zinflate.py rename to Test/ZlibTest/App/__zlib/zinflate.vp diff --git a/Test/ZlibTest/App/main.py b/Test/ZlibTest/App/main.vp similarity index 100% rename from Test/ZlibTest/App/main.py rename to Test/ZlibTest/App/main.vp diff --git a/TransPyV/App/lib/Projectrans/Config.py b/TransPyV/App/lib/Projectrans/Config.py deleted file mode 100644 index 7322da9..0000000 --- a/TransPyV/App/lib/Projectrans/Config.py +++ /dev/null @@ -1,397 +0,0 @@ -import t, c -from stdint import * -import memhub -import string -import stdio -import stdlib -import viperlib -import lib.core.VLogger as VLogger -from json.__parser import parse as json_parse -from json import JsonValue, JSON_OBJECT, JSON_INT -import w32.fileio as fileio - - -# ============================================================ -# Config - 工程配置 -# ============================================================ - -# 全局 mbuddy 指针 -_mbuddy: memhub.MemManager | t.CPtr - -# 配置值(从 project.vpj 加载) -SourceDir: str -BuildDir: str -TempDir: str # = {BuildDir}/temp(自动计算) -OutputDir: str # = {BuildDir}/output(自动计算) -ProjectName: str -ProjectVersion: str -CompilerCmd: str -CompilerFlags: str # 编译器参数(空格分隔,从 compiler.flags 数组拼接) -LinkerCmd: str -LinkerFlags: str # 链接器参数(空格分隔,从 linker.flags 数组拼接) -LinkerOutput: str -TargetTriple: str -TargetDataLayout: str -Sha1SliceLevel: t.CInt # SHA1 切片层数(目录分散等级) -StrictMode: t.CInt -IncludesDir: str # includes 目录路径(从 includes 数组首元素) - - -def Load_project_config(path: str) -> int: - """加载工程配置文件(project.vpj) - - Args: - path: 配置文件路径 - - Returns: - 0 表示成功,非 0 表示失败 - """ - global SourceDir, BuildDir, TempDir, OutputDir, ProjectName, ProjectVersion - global CompilerCmd, CompilerFlags, LinkerCmd, LinkerFlags, LinkerOutput - global TargetTriple, TargetDataLayout, Sha1SliceLevel, StrictMode - global IncludesDir - - if path is None: - return 1 - if _mbuddy is None: - return 1 - - # 打开文件 - f: fileio.File | t.CPtr = fileio.File(path, fileio.MODE.R) - if f is None: - return 1 - if f.closed: - return 1 - - # 分配读取缓冲区 - CFG_BUF_SIZE: t.CSizeT = 8192 - buf: bytes = _mbuddy.alloc(CFG_BUF_SIZE) - if buf is None: - f.close() - return 1 - - bytes_read: t.CInt64T = f.read_all(buf, CFG_BUF_SIZE) - f.close() - - if bytes_read <= 0: - return 1 - - # 解析 JSON - root: JsonValue | t.CPtr = json_parse(_mbuddy, buf) - if root is None: - return 1 - if not root.is_object(): - return 1 - - # 读取顶层字段(使用显式 __getitem__ 调用,兼容旧编译器二进制) - sd_val: JsonValue | t.CPtr = root.__getitem__("source_dir") - SourceDir = sd_val.as_string() if sd_val is not None else None - # build_dir: 统一构建目录(默认 ./.tpv_build),temp 和 output 作为其子目录 - bd_val: JsonValue | t.CPtr = root.__getitem__("build_dir") - if bd_val is not None and bd_val.is_string(): - BuildDir = bd_val.as_string() - else: - BuildDir = "./.tpv_build" - name_val: JsonValue | t.CPtr = root.__getitem__("name") - ProjectName = name_val.as_string() if name_val is not None else None - ver_val: JsonValue | t.CPtr = root.__getitem__("version") - ProjectVersion = ver_val.as_string() if ver_val is not None else None - - # 读取 compiler 子对象 - compiler: JsonValue | t.CPtr = root.__getitem__("compiler") - if compiler is not None and compiler.is_object(): - cc_cmd_val: JsonValue | t.CPtr = compiler.__getitem__("cmd") - CompilerCmd = cc_cmd_val.as_string() if cc_cmd_val is not None else None - # 读取 compiler.flags 数组,拼接成空格分隔的字符串 - cc_flags_val: JsonValue | t.CPtr = compiler.__getitem__("flags") - CompilerFlags = _join_flags_array(cc_flags_val) - - # 读取 linker 子对象 - linker: JsonValue | t.CPtr = root.__getitem__("linker") - if linker is not None and linker.is_object(): - ld_cmd_val: JsonValue | t.CPtr = linker.__getitem__("cmd") - LinkerCmd = ld_cmd_val.as_string() if ld_cmd_val is not None else None - ld_out_val: JsonValue | t.CPtr = linker.__getitem__("output") - LinkerOutput = ld_out_val.as_string() if ld_out_val is not None else None - # 读取 linker.flags 数组,拼接成空格分隔的字符串 - ld_flags_val: JsonValue | t.CPtr = linker.__getitem__("flags") - LinkerFlags = _join_flags_array(ld_flags_val) - - # 读取 target 子对象 - target: JsonValue | t.CPtr = root.__getitem__("target") - if target is not None and target.is_object(): - tgt_triple_val: JsonValue | t.CPtr = target.__getitem__("triple") - TargetTriple = tgt_triple_val.as_string() if tgt_triple_val is not None else None - tgt_dl_val: JsonValue | t.CPtr = target.__getitem__("datalayout") - TargetDataLayout = tgt_dl_val.as_string() if tgt_dl_val is not None else None - - # 读取 options 子对象 - # Sha1SliceLevel: SHA1 切片层数(默认 1,每层取 SHA1 前 2 字符作为子目录) - # level=0 → 不切片,文件直接放 base_dir - # level=1 → b7/{sha1}.ext - # level=2 → b7/90/{sha1}.ext - options: JsonValue | t.CPtr = root.__getitem__("options") - Sha1SliceLevel = 1 - StrictMode = 1 - if options is not None and options.is_object(): - sl: JsonValue | t.CPtr = options.__getitem__("sha1_slice_level") - if sl is not None and sl.is_int(): - Sha1SliceLevel = sl.as_int() - sm: JsonValue | t.CPtr = options.__getitem__("strict_mode") - if sm is not None and sm.is_bool(): - StrictMode = 1 if sm.as_bool() else 0 - - # 读取 includes 数组(取首个元素作为 includes 目录) - includes_val: JsonValue | t.CPtr = root.__getitem__("includes") - if includes_val is not None and includes_val.is_array(): - arr_len: t.CSizeT = includes_val.__len__() - if arr_len > 0: - first_inc: JsonValue | t.CPtr = includes_val.get_item(0) - if first_inc is not None and first_inc.is_string(): - IncludesDir = first_inc.as_string() - - return 0 - - -def _join_flags_array(flags_val: JsonValue | t.CPtr) -> str: - """将 JSON 字符串数组拼接成空格分隔的字符串 - - 用于 linker.flags 和 compiler.flags 数组。 - 用 while + 索引遍历,避免 list 迭代器 bug。 - - Args: - flags_val: JsonValue,应为字符串数组 - - Returns: - 空格分隔的字符串,或 None 如果 flags_val 为 None 或非数组或空数组 - """ - if flags_val is None: - return None - if not flags_val.is_array(): - return None - - arr_len: t.CSizeT = flags_val.__len__() - if arr_len == 0: - return None - - # 第一遍:计算总长度(所有 flag 长度 + 空格分隔符) - total_len: t.CSizeT = 0 - i: t.CSizeT = 0 - while i < arr_len: - item: JsonValue | t.CPtr = flags_val.get_item(i) - if item is not None and item.is_string(): - s: str = item.as_string() - if s is not None: - total_len += string.strlen(s) + 1 # +1 for space - i += 1 - - if total_len == 0: - return None - - # 分配缓冲区(total_len 已含每个 flag 后的空格,最后一个是 '\0') - buf: str = _mbuddy.alloc(total_len + 1) - if buf is None: - return None - - # 第二遍:拼接(flag 之间用空格分隔) - pos: t.CSizeT = 0 - i = 0 - while i < arr_len: - item = flags_val.get_item(i) - if item is not None and item.is_string(): - s = item.as_string() - if s is not None: - slen: t.CSizeT = string.strlen(s) - if pos > 0: - buf[pos] = ' ' - pos += 1 - string.strcpy(buf + pos, s) - pos += slen - i += 1 - buf[pos] = '\0' - return buf - - -def _join_path(rel: str, project_dir: str) -> str: - """将相对路径与 project_dir 拼接为绝对路径 - - - ./App + Test → Test/App - - ./temp + Test → Test/temp - - ../includes + Test → Test/../includes(OS 解析为 includes) - - 绝对路径保持不变 - - None 返回 None - """ - if rel is None: - return None - # 绝对路径(以 / 或 \ 开头)保持不变 - if rel[0] == '/' or rel[0] == '\\': - return rel - - rel_len: t.CSizeT = string.strlen(rel) - dir_len: t.CSizeT = string.strlen(project_dir) - - # 处理 ../ 或 ..\\ 前缀:拼接 project_dir/../... - if rel_len >= 3 and rel[0] == '.' and rel[1] == '.': - if rel[2] == '/' or rel[2] == '\\': - if dir_len == 0: - return rel - total_len: t.CSizeT = dir_len + 1 + rel_len + 1 - buf: str = _mbuddy.alloc(total_len) - if buf is None: - return rel - viperlib.snprintf(buf, total_len, "%s/%s", project_dir, rel) - return buf - - # 处理 ./ 或 .\\ 前缀:拼接 project_dir + rel[2:] - rel_off: t.CSizeT = 0 - if rel_len >= 2 and rel[0] == '.': - if rel[1] == '/' or rel[1] == '\\': - rel_off = 2 - else: - return rel # 不是 ./ 开头,保持不变 - else: - return rel # 不是 . 开头,保持不变 - - if dir_len == 0: - # project_dir 为空(当前目录),去掉 ./ 前缀即可 - return rel + rel_off - # 拼接: project_dir + "/" + rel[rel_off:] - total_len = dir_len + 1 + (rel_len - rel_off) + 1 - buf = _mbuddy.alloc(total_len) - if buf is None: - return rel # 分配失败,返回原路径 - viperlib.snprintf(buf, total_len, "%s/%s", project_dir, rel + rel_off) - return buf - - -def resolve_paths(project_dir: str) -> int: - """解析并规范化工程路径(src/build/includes) - - 将 project.vpj 中的相对路径(以 ./ 开头)转换为基于 project_dir 的路径。 - BuildDir 解析后,TempDir = {BuildDir}/temp,OutputDir = {BuildDir}/output。 - - Args: - project_dir: 工程根目录(project.vpj 所在目录) - - Returns: - 0 表示成功,非 0 表示失败 - """ - global SourceDir, BuildDir, TempDir, OutputDir, IncludesDir - if project_dir is None: - return 1 - if _mbuddy is None: - return 1 - - SourceDir = _join_path(SourceDir, project_dir) - BuildDir = _join_path(BuildDir, project_dir) - - # TempDir = {BuildDir}/temp - if BuildDir is not None: - bd_len: t.CSizeT = string.strlen(BuildDir) - temp_buf: str = _mbuddy.alloc(bd_len + 8) - if temp_buf is not None: - viperlib.snprintf(temp_buf, bd_len + 8, "%s/temp", BuildDir) - TempDir = temp_buf - # OutputDir = {BuildDir}/output - output_buf: str = _mbuddy.alloc(bd_len + 8) - if output_buf is not None: - viperlib.snprintf(output_buf, bd_len + 8, "%s/output", BuildDir) - OutputDir = output_buf - - # includes 路径可能是 ../includes 形式,需要基于 project_dir 解析 - if IncludesDir is not None: - IncludesDir = _join_path(IncludesDir, project_dir) - return 0 - - -def get_includes_binary_dir() -> str: - """获取 includes.binary 目录路径(includes 目录 + .binary 后缀) - - includes 目录如 ../includes,则 includes.binary 为 ../includes.binary - """ - if IncludesDir is None: - return None - inc_len: t.CSizeT = string.strlen(IncludesDir) - buf: str = _mbuddy.alloc(inc_len + 8) - if buf is None: - return None - viperlib.snprintf(buf, inc_len + 8, "%s.binary", IncludesDir) - return buf - - -def print_config(): - """打印当前配置""" - buf: t.CChar | t.CPtr = VLogger.fmt_buf() - if buf is None: - return - if ProjectName is not None: - viperlib.snprintf(buf, 1024, "project: %s v%s", ProjectName, - ProjectVersion if ProjectVersion is not None else "?") - VLogger.info(buf, "config") - if SourceDir is not None: - viperlib.snprintf(buf, 1024, "source_dir: %s", SourceDir) - VLogger.info(buf, "config") - if BuildDir is not None: - viperlib.snprintf(buf, 1024, "build_dir: %s", BuildDir) - VLogger.info(buf, "config") - if TempDir is not None: - viperlib.snprintf(buf, 1024, "temp_dir: %s", TempDir) - VLogger.info(buf, "config") - if OutputDir is not None: - viperlib.snprintf(buf, 1024, "output_dir: %s", OutputDir) - VLogger.info(buf, "config") - if CompilerCmd is not None: - viperlib.snprintf(buf, 1024, "compiler: %s", CompilerCmd) - VLogger.info(buf, "config") - if LinkerCmd is not None: - viperlib.snprintf(buf, 1024, "linker: %s -> %s", LinkerCmd, - LinkerOutput if LinkerOutput is not None else "?") - VLogger.info(buf, "config") - if IncludesDir is not None: - viperlib.snprintf(buf, 1024, "includes: %s", IncludesDir) - VLogger.info(buf, "config") - viperlib.snprintf(buf, 1024, "sha1_slice_level: %d", Sha1SliceLevel) - VLogger.info(buf, "config") - - -# ============================================================ -# slice_subdir - 根据 SHA1 和切片层数返回子目录路径 -# -# 每层取 SHA1 的 2 个字符作为子目录名: -# level=0 → None(不切片) -# level=1 → "b7" -# level=2 → "b7/90" -# level=3 → "b7/90/23" -# -# Args: -# sha1: SHA1 字符串(至少 2*level 字符) -# level: 切片层数 -# -# Returns: -# 子目录路径字符串(mbuddy 分配,无需释放),level<=0 时返回 None -# ============================================================ -def slice_subdir(sha1: str, level: int) -> str: - """根据 SHA1 和切片层数返回子目录路径""" - if level <= 0 or sha1 is None: - return None - if _mbuddy is None: - return None - # 每层 2 字符 + 分隔符,最后无分隔符 + null - # buf 大小: level * 2 + (level - 1) + 1 = level * 3 - buf_len: t.CSizeT = t.CSizeT(level * 3) - buf: str = _mbuddy.alloc(buf_len) - if buf is None: - return None - pos: int = 0 - i: int = 0 - while i < level: - if i > 0: - buf[pos] = '/' - pos += 1 - idx: int = i * 2 - buf[pos] = sha1[idx] - buf[pos + 1] = sha1[idx + 1] - pos += 2 - i += 1 - buf[pos] = '\0' - return buf \ No newline at end of file diff --git a/TransPyV/App/lib/Projectrans/Utils.py b/TransPyV/App/lib/Projectrans/Utils.py deleted file mode 100644 index 6563957..0000000 --- a/TransPyV/App/lib/Projectrans/Utils.py +++ /dev/null @@ -1,130 +0,0 @@ -import t, c -from stdint import * -import memhub -import string -import stdlib -import viperlib -import hashlib -import w32.win32file -import w32.win32base - - -# ============================================================ -# Utils - 工程工具函数 -# -# 提供 SHA1 计算和目录清理等通用工具函数。 -# ============================================================ - -# 全局 mbuddy 指针 -_mbuddy: memhub.MemBuddy | t.CPtr - - -# ============================================================ -# compute_sha1 - 计算字符串的 SHA1,返回前 16 个十六进制字符 -# -# 使用 includes/hashlib 库的 sha1 类计算摘要,转为十六进制字符串。 -# 参考 Projectrans.py 的 compute_sha1(hashlib.sha1().hexdigest()[:16])。 -# ============================================================ -def compute_sha1(pool: memhub.MemBuddy | t.CPtr, content: str) -> str: - """计算字符串的 SHA1,返回前 16 个十六进制字符(用于文件命名)""" - if content is None or pool is None: - return None - - # 构造 sha1 对象(__init__ 会初始化 state/count/buf) - # ctx 在栈上分配(alloca),函数内使用完即丢弃,无需堆分配 - ctx: hashlib.sha1 | t.CPtr = hashlib.sha1() - if ctx is None: - return None - - # 计算摘要 - ctx.update(content) - digest: bytes = pool.alloc(hashlib.SHA1_DIGEST_LEN) - if digest is None: - return None - ctx.final(digest) - - # 转为十六进制字符串(取前 8 字节 = 16 个十六进制字符) - hex_buf: str = pool.alloc(17) - if hex_buf is None: - return None - for i in range(8): - hi: int = (digest[i] >> 4) & 0xF - lo: int = digest[i] & 0xF - if hi < 10: - hex_buf[i * 2] = '0' + hi - else: - hex_buf[i * 2] = 'a' + (hi - 10) - if lo < 10: - hex_buf[i * 2 + 1] = '0' + lo - else: - hex_buf[i * 2 + 1] = 'a' + (lo - 10) - hex_buf[16] = '\0' - return hex_buf - - -# ============================================================ -# CleanDir - 递归删除目录中所有文件和子目录(保留 dir_path 本身) -# -# 用于 --clean 选项:清理 temp_dir 和 output_dir 中的旧文件。 -# SHA1 分片目录结构(如 temp/1c/、temp/7a/)需要递归清理, -# 否则旧的截断文件(如 256KB text.ll)会被 Phase1 跳过逻辑复用。 -# ============================================================ -def CleanDir(dir_path: str) -> int: - """递归删除目录中所有文件和子目录,保留 dir_path 本身,返回删除的文件数,-1 表示错误""" - if dir_path is None: - return -1 - dir_len: t.CSizeT = string.strlen(dir_path) - pattern: bytes = stdlib.malloc(dir_len + 8) - if pattern is None: - return -1 - viperlib.snprintf(pattern, dir_len + 8, "%s/*", dir_path) - - find_data: w32.win32file.WIN32_FIND_DATAA | t.CPtr = stdlib.malloc(w32.win32file.WIN32_FIND_DATAA.__sizeof__()) - if find_data is None: - stdlib.free(pattern) - return -1 - string.memset(find_data, 0, w32.win32file.WIN32_FIND_DATAA.__sizeof__()) - - handle: w32.win32base.HANDLE = w32.win32file.FindFirstFileA(pattern, find_data) - if handle == w32.win32base.INVALID_HANDLE_VALUE: - stdlib.free(pattern) - stdlib.free(find_data) - return 0 - - deleted: int = 0 - while 1: - fname: str = find_data.cFileName - if fname is not None: - # 跳过 . 和 .. - if fname[0] == '.': - if fname[1] == '\0': - fname = None - elif fname[1] == '.' and fname[2] == '\0': - fname = None - if fname is not None: - fname_len: t.CSizeT = string.strlen(fname) - full_path: bytes = stdlib.malloc(dir_len + fname_len + 2) - if full_path is not None: - viperlib.snprintf(full_path, dir_len + fname_len + 2, "%s/%s", dir_path, fname) - # 检查是否为目录(dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - is_dir: t.CUInt32T = find_data.dwFileAttributes & w32.win32file.FILE_ATTRIBUTE_DIRECTORY - if is_dir != 0: - # 递归清理子目录中的文件 - sub_deleted: int = CleanDir(full_path) - if sub_deleted > 0: - deleted += sub_deleted - # 删除空子目录(RemoveDirectoryA 要求目录为空) - w32.win32file.RemoveDirectoryA(full_path) - else: - # 删除文件 - if w32.win32file.DeleteFileA(full_path) != 0: - deleted += 1 - stdlib.free(full_path) - - if w32.win32file.FindNextFileA(handle, find_data) == 0: - break - - w32.win32file.FindClose(handle) - stdlib.free(pattern) - stdlib.free(find_data) - return deleted diff --git a/TransPyV/App/lib/Projectrans/__init__.py b/TransPyV/App/lib/Projectrans/__init__.py deleted file mode 100644 index 64656ea..0000000 --- a/TransPyV/App/lib/Projectrans/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -import t, c -from stdint import * - -from .Config import Load_project_config, resolve_paths -from .Utils import compute_sha1, CleanDir - -__all__ = [ - 'Load_project_config', - 'resolve_paths', - 'compute_sha1', - 'CleanDir', -] diff --git a/TransPyV/App/lib/__init__.py b/TransPyV/App/lib/__init__.py deleted file mode 100644 index fb867ea..0000000 --- a/TransPyV/App/lib/__init__.py +++ /dev/null @@ -1,28 +0,0 @@ -import t, c -from stdint import * -import memhub -import lib.core.VLogger as VLogger - - -# ============================================================ -# lib 包入口 - 声明全局 _mbuddy 内存池指针 -# ============================================================ - -# 全局 mbuddy 内存池指针(由 App/main.py 初始化后注入) -# 注意: 使用 MemBuddy 类型而非 MemManager,避免虚函数分派不工作时调用父类 alloc 返回 None -_mbuddy: memhub.MemBuddy | t.CPtr - - -def InitLib(mb: memhub.MemBuddy | t.CPtr) -> int: - """初始化 lib 包的全局 _mbuddy 指针,并级联注入到所有子模块。 - - Args: - mb: memhub.MemBuddy 实例指针 - - Returns: - 0 表示成功,非 0 表示失败 - """ - if mb is None: - return 1 - VLogger._mbuddy = mb - return 0 diff --git a/TransPyV/App/lib/core/BuildPipeline.py b/TransPyV/App/lib/core/BuildPipeline.py deleted file mode 100644 index b39aa8b..0000000 --- a/TransPyV/App/lib/core/BuildPipeline.py +++ /dev/null @@ -1,624 +0,0 @@ -import t, c -from stdint import * -import stdio -import string -import stdlib -import memhub -import w32.fileio as fileio -import w32.win32file -import w32.win32base -import subprocess -import viperlib -import ast -import lib.core.VLogger as VLogger -import lib.core.Handles.HandlesTranslator as HandlesTranslator -import lib.core.Handles.HandlesStruct as HandlesStruct -import lib.core.Handles.HandlesType as HandlesType -import lib.core.Handles.HandlesImports as HandlesImports -import lib.Projectrans.Config as Config - -# ============================================================ -# BuildPipeline - 编译管线 -# -# 负责将 LLVM IR 编译为可执行文件: -# 1. 写 .ll 文件到 temp 目录 -# 2. 调用 llc 编译 .ll → .obj -# 3. 调用 clang++ 链接 .obj → .exe -# ============================================================ - -# 全局 mbuddy 指针 -_mbuddy: memhub.MemBuddy | t.CPtr - -# 源代码缓冲区大小(1MB) -SRC_BUF_SIZE: t.CDefine = 1048576 - - -# ============================================================ -# TranslateFileGetTrans - 翻译单个文件,返回 Translator 对象 -# -# 读取文件 → AST 解析 → LLVM IR 翻译,返回 Translator 对象供 -# 调用者 dump_ir。命名空间隔离:includes 文件宽松模式(全部可见), -# 用户文件严格模式(仅本地+import)。 -# -# Args: -# mb: 内存池 -# file_path: 源文件路径 -# sha1_val: 文件内容的 SHA1 前16字符(用于函数名混淆) -# -# Returns: -# Translator 对象(None 失败) -# ============================================================ -def TranslateFileGetTrans(mb: memhub.MemBuddy | t.CPtr, file_path: str, - sha1_val: str, - current_package: str = None, - declare_only: int = 0) -> HandlesTranslator.Translator | t.CPtr: - """翻译文件,返回 Translator 对象(调用者负责 dump_ir),None 失败 - - current_package: 当前文件所属包名(用于解析相对导入),None 表示顶级模块 - declare_only: 0=全量翻译(默认),1=仅注册 struct/enum/union(不翻译方法体) - """ - if file_path is None: - return None - f: fileio.File | t.CPtr = fileio.File(file_path, fileio.MODE.R) - if f.closed: - return None - src_buf: bytes = stdlib.malloc(SRC_BUF_SIZE) - if src_buf is None: - f.close() - return None - bytes_read: LONG = f.read_all(src_buf, SRC_BUF_SIZE) - f.close() - if bytes_read <= 0: - stdlib.free(src_buf) - return None - if bytes_read < SRC_BUF_SIZE: - src_buf[bytes_read] = 0 - else: - src_buf[SRC_BUF_SIZE - 1] = 0 - lx: ast.Lexer | t.CPtr = ast.new_lexer(mb) - ast._lexer_init(lx, src_buf, mb) - tokens: ast.Token | t.CPtr = ast.tokenize(lx) - tree: ast.AST | t.CPtr = ast.parse_tokens(mb, tokens) - # parse 完成后 AST 树已独立,释放源代码缓冲区(避免 1MB/文件泄漏) - stdlib.free(src_buf) - if tree is None: - return None - tr: HandlesTranslator.Translator | t.CPtr = mb.alloc(HandlesTranslator.Translator.__sizeof__()) - tr.__before_init__() - tr.__init__() - tr.ModuleSha1 = sha1_val - tr.CurrentPackage = current_package - tr._declare_only = declare_only - # 设置当前文件名(供报错使用) - HandlesType.set_current_file(file_path) - # 模块切换:清空 CDefine 常量表,确保每个模块的 CDefine 常量正确隔离 - HandlesType.clear_cdefine_constants() - # 命名空间隔离:includes 文件宽松模式(全部可见),用户文件严格模式(仅本地+import) - strict_mode: int = 1 - if string.strstr(file_path, "includes") is not None: - strict_mode = 0 - HandlesStruct.reset_visible_structs(mb, strict_mode) - ret: int = tr.translate(tree) - if ret != 0: - return None - return tr - - -class BuildResult: - Success: t.CInt - OutputPath: str - ErrorMsg: str - - def __new__(self) -> t.CPtr: - return t.CPtr(_mbuddy.alloc(BuildResult.__sizeof__())) - - def __init__(self): - self.Success = 0 - self.OutputPath = None - self.ErrorMsg = None - - -def ensure_dir(path: str) -> int: - """递归创建目录(类似 mkdir -p),目录已存在视为成功 - - Args: - path: 目录路径(支持 / 或 \\ 分隔符) - - Returns: - 0 成功(包括目录已存在),非 0 失败 - """ - if path is None: - return 1 - - path_len: t.CSizeT = string.strlen(path) - if path_len == 0: - return 0 - - # 复制路径到可写缓冲区(逐级截断用) - buf: bytes = _mbuddy.alloc(path_len + 1) - if buf is None: - return 1 - string.strcpy(buf, path) - - # 遇到分隔符时临时截断,创建每一层目录 - # CreateDirectoryA 在目录已存在时返回 0(失败),忽略即可 - i: int = 0 - plen: int = path_len - while i < plen: - ch: int = buf[i] - if ch == 47 or ch == 92: # '/' = 47, '\\' = 92 - saved: int = ch - buf[i] = '\0' - w32.win32file.CreateDirectoryA(buf, None) - buf[i] = saved - i += 1 - - # 创建最终目录 - w32.win32file.CreateDirectoryA(buf, None) - return 0 - - -# ============================================================ -# build_sliced_path - 构建切片路径并确保目录存在 -# -# 根据 Config.Sha1SliceLevel 将文件分散到 SHA1 前缀子目录: -# level=0 → {base_dir}/{sha1}.{ext} -# level=1 → {base_dir}/b7/{sha1}.{ext} -# level=2 → {base_dir}/b7/90/{sha1}.{ext} -# -# 自动调用 ensure_dir 创建子目录。 -# -# Args: -# base_dir: 基础目录(如 temp_dir) -# sha1: SHA1 字符串 -# ext: 文件扩展名(如 "stub.ll") -# -# Returns: -# 完整文件路径(mbuddy 分配),None 失败 -# ============================================================ -def build_sliced_path(base_dir: str, sha1: str, ext: str) -> str: - """构建切片路径并确保目录存在""" - if base_dir is None or sha1 is None or ext is None: - return None - - subdir: str = Config.slice_subdir(sha1, Config.Sha1SliceLevel) - base_len: t.CSizeT = string.strlen(base_dir) - sha1_len: t.CSizeT = string.strlen(sha1) - ext_len: t.CSizeT = string.strlen(ext) - - if subdir is not None: - sub_len: t.CSizeT = string.strlen(subdir) - # ensure_dir({base_dir}/{subdir}) - dir_path: str = _mbuddy.alloc(base_len + sub_len + 2) - if dir_path is not None: - viperlib.snprintf(dir_path, base_len + sub_len + 2, "%s/%s", base_dir, subdir) - ensure_dir(dir_path) - # 文件路径: {base_dir}/{subdir}/{sha1}.{ext} - path_len: t.CSizeT = base_len + sub_len + sha1_len + ext_len + 4 - path: str = _mbuddy.alloc(path_len) - if path is None: - return None - viperlib.snprintf(path, path_len, "%s/%s/%s.%s", base_dir, subdir, sha1, ext) - return path - else: - # 无切片: {base_dir}/{sha1}.{ext} - path_len = base_len + sha1_len + ext_len + 3 - path = _mbuddy.alloc(path_len) - if path is None: - return None - viperlib.snprintf(path, path_len, "%s/%s.%s", base_dir, sha1, ext) - return path - - -def write_ir_to_file(ir_buf: bytes, ir_len: t.CSizeT, output_dir: str, module_name: str) -> int: - """将 IR 缓冲区写入 .ll 文件 - - Args: - ir_buf: IR 文本缓冲区 - ir_len: IR 文本长度 - output_dir: 输出目录(temp 或 output) - module_name: 模块名(SHA1) - - Returns: - 0 成功,非 0 失败 - """ - if ir_buf is None or output_dir is None or module_name is None: - return 1 - - # 构造切片路径: output_dir/{sha1前缀}/{module_name}.ll - path: str = build_sliced_path(output_dir, module_name, "ll") - if path is None: - return 1 - - # 打开文件写入 - f: fileio.File | t.CPtr = fileio.File(path, fileio.MODE.W) - if f.closed: - return 1 - - written: t.CInt64T = f.write(ir_buf, ir_len) - f.close() - if written < 0: - return 1 - return 0 - - -def compile_ll_to_obj(ir_path: str, output_dir: str, module_name: str, cc_cmd: str, cc_flags: str) -> int: - """调用 llc 将 .ll 编译为 .obj - - Args: - ir_path: .ll 文件路径 - output_dir: 输出目录 - module_name: 模块名(SHA1,用于生成 .obj 文件名) - cc_cmd: 编译器命令(如 "llc") - cc_flags: 编译器参数(如 "-filetype=obj -relocation-model=pic") - - Returns: - 0 成功,非 0 失败 - """ - if ir_path is None or cc_cmd is None or output_dir is None or module_name is None: - return 1 - - # 构造切片 .obj 路径: output_dir/{sha1前缀}/{module_name}.obj - obj_path: str = build_sliced_path(output_dir, module_name, "obj") - if obj_path is None: - return 1 - - # 构造命令: llc -filetype=obj -o {obj_path} ir_path - cmd_len: t.CSizeT = string.strlen(cc_cmd) + string.strlen(cc_flags) + string.strlen(obj_path) + string.strlen(ir_path) + 64 - cmd: bytes = _mbuddy.alloc(cmd_len) - if cmd is None: - return 1 - viperlib.snprintf(cmd, cmd_len, "%s %s -o %s %s", cc_cmd, cc_flags, obj_path, ir_path) - - # 用 stdlib.system() 直接在控制台运行,输出直接显示 - # 避免 subprocess 管道捕获丢失输出 - sys_ret: int = stdlib.system(cmd) - if sys_ret != 0: - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "编译失败 (module=%s, cmd=%s)", module_name, cmd) - VLogger.error(fb, "LLC") - return 1 - return 0 - - -def _CollectObjFilesImpl(base_dir: str, bd_len: t.CSizeT, - out_buf: bytes, out_pos: t.CSizeT, out_size: t.CSizeT) -> t.CSizeT: - """递归扫描 base_dir,收集 .obj 文件路径到 out_buf,返回新的 out_pos - - 支持切片子目录(如 dir/43/{sha1}.obj)。 - """ - find_data: w32.win32file.WIN32_FIND_DATAA | t.CPtr = _mbuddy.alloc(w32.win32file.WIN32_FIND_DATAA.__sizeof__()) - if find_data is None: - return out_pos - string.memset(find_data, 0, w32.win32file.WIN32_FIND_DATAA.__sizeof__()) - - pattern: bytes = _mbuddy.alloc(bd_len + 8) - if pattern is None: - return out_pos - viperlib.snprintf(pattern, bd_len + 8, "%s/*", base_dir) - - handle: w32.win32base.HANDLE = w32.win32file.FindFirstFileA(pattern, find_data) - _mbuddy.free(pattern) - if handle == w32.win32base.INVALID_HANDLE_VALUE: - return out_pos - - while True: - fname: str = find_data.cFileName - if fname is not None: - fname_len: t.CSizeT = string.strlen(fname) - if fname_len > 0: - # 跳过 . 和 .. - is_dot: int = 0 - if fname_len == 1 and fname[0] == '.': - is_dot = 1 - elif fname_len == 2 and fname[0] == '.' and fname[1] == '.': - is_dot = 1 - if is_dot == 0: - attrs: ULONG = find_data.dwFileAttributes - is_dir: int = 0 - if (attrs & w32.win32file.FILE_ATTRIBUTE_DIRECTORY) != 0: - is_dir = 1 - if is_dir != 0: - # 递归扫描子目录 - sub_dir: bytes = _mbuddy.alloc(bd_len + fname_len + 2) - if sub_dir is not None: - viperlib.snprintf(sub_dir, bd_len + fname_len + 2, "%s/%s", base_dir, fname) - sub_len: t.CSizeT = string.strlen(sub_dir) - out_pos = _CollectObjFilesImpl(sub_dir, sub_len, out_buf, out_pos, out_size) - _mbuddy.free(sub_dir) - else: - # 检查是否是 .obj 文件 - if fname_len > 4: - if fname[fname_len - 4] == '.' and fname[fname_len - 3] == 'o' and fname[fname_len - 2] == 'b' and fname[fname_len - 1] == 'j': - need: t.CSizeT = bd_len + 1 + fname_len + 2 - if out_pos + need < out_size: - if out_pos > 0: - out_buf[out_pos] = ' ' - out_pos += 1 - viperlib.snprintf(out_buf + out_pos, need, "%s/%s", base_dir, fname) - out_pos += bd_len + 1 + fname_len - else: - break - - if w32.win32file.FindNextFileA(handle, find_data) == 0: - break - - w32.win32file.FindClose(handle) - return out_pos - - -def collect_obj_files(includes_binary_dir: str, out_buf: bytes, out_size: t.CSizeT) -> t.CSizeT: - """递归扫描 includes_binary_dir 目录,收集所有 .obj 文件路径到 out_buf - - 支持切片子目录(如 includes_binary_dir/43/{sha1}.obj)。 - - Args: - includes_binary_dir: includes.binary 目录路径 - out_buf: 输出缓冲区(用于存放空格分隔的 .obj 文件路径) - out_size: 输出缓冲区大小 - - Returns: - 写入的字节数(不含 null 终止符),0 表示无文件或错误 - """ - if includes_binary_dir is None or out_buf is None or out_size == 0: - return 0 - - out_buf[0] = '\0' - dir_len: t.CSizeT = string.strlen(includes_binary_dir) - out_pos: t.CSizeT = _CollectObjFilesImpl(includes_binary_dir, dir_len, out_buf, 0, out_size) - out_buf[out_pos] = '\0' - return out_pos - - -def link_obj_to_exe(output_dir: str, module_name: str, linker_cmd: str, linker_flags: str, linker_output: str, - includes_binary_dir: str) -> int: - """调用 clang++ 链接 .obj 为 .exe - - Args: - output_dir: 输出目录(包含 .obj 文件) - module_name: 模块名(SHA1) - linker_cmd: 链接器命令(如 "clang++") - linker_flags: 链接器参数 - linker_output: 输出文件名(如 "test.exe") - includes_binary_dir: includes.binary 目录路径(链接时附加预编译 .obj) - - Returns: - 0 成功,非 0 失败 - """ - if output_dir is None or linker_cmd is None or module_name is None: - return 1 - - # 构造切片 .obj 路径: output_dir/{sha1前缀}/{module_name}.obj - obj_path: str = build_sliced_path(output_dir, module_name, "obj") - if obj_path is None: - return 1 - - # 收集 includes.binary 的 .obj 文件路径 - EXTRA_BUF_SIZE: t.CSizeT = 32768 - extra_objs: bytes = _mbuddy.alloc(EXTRA_BUF_SIZE) - if extra_objs is None: - return 1 - extra_len: t.CSizeT = 0 - if includes_binary_dir is not None: - extra_len = collect_obj_files(includes_binary_dir, extra_objs, EXTRA_BUF_SIZE) - if extra_len > 0: - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "附加 %d 字节的 includes.binary .obj 文件", extra_len) - VLogger.info(fb, "link") - else: - fb = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "includes.binary 无 .obj 文件: %s", includes_binary_dir) - VLogger.warning(fb, "link") - - # 构造命令: clang++ {obj_path} extra_objs -o {output_dir}/{linker_output} linker_flags - # 注意: .obj 文件必须在 -l 库标志之前,否则链接器无法解析符号依赖 - cmd_len: t.CSizeT = string.strlen(linker_cmd) + string.strlen(obj_path) + string.strlen(linker_flags) + string.strlen(output_dir) + string.strlen(linker_output) + extra_len + 128 - cmd: bytes = _mbuddy.alloc(cmd_len) - if cmd is None: - return 1 - if extra_len > 0: - viperlib.snprintf(cmd, cmd_len, "%s %s %s -o %s/%s %s", - linker_cmd, obj_path, extra_objs, - output_dir, linker_output, linker_flags) - else: - viperlib.snprintf(cmd, cmd_len, "%s %s -o %s/%s %s", - linker_cmd, obj_path, output_dir, linker_output, - linker_flags) - - result: subprocess.CompletedProcess | t.CPtr = subprocess.run(cmd, True, True) - if result is None: - VLogger.error("subprocess.run 返回 None", "link") - return 1 - if result.returncode != 0: - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "链接失败,返回码: %d", result.returncode) - VLogger.error(fb, "link") - fb = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "命令: %s", cmd) - VLogger.error(fb, "link") - # 显示链接器错误输出 - # 注意: subprocess 在 Windows 下将 stderr 合并到 stdout,result.stderr 总是 None - if result.stdout is not None: - VLogger.error(result.stdout, "link") - else: - VLogger.error("无输出捕获", "link") - if result.stderr is not None: - VLogger.error(result.stderr, "link") - return 1 - return 0 - - -def compile_module_to_obj(ir_buf: bytes, ir_len: t.CSizeT, - temp_dir: str, output_dir: str, module_name: str, - cc_cmd: str, cc_flags: str) -> int: - """编译 IR 到 .obj(不链接) - - Args: - ir_buf: LLVM IR 文本缓冲区 - ir_len: IR 文本长度 - temp_dir: 临时目录 - output_dir: 输出目录 - module_name: 模块名(SHA1) - cc_cmd: 编译器命令 - cc_flags: 编译器参数 - - Returns: - 0 成功,非 0 失败 - """ - if ir_buf is None or temp_dir is None or output_dir is None or module_name is None: - return 1 - - # Step 1: 写 .ll 文件 - ret: int = write_ir_to_file(ir_buf, ir_len, temp_dir, module_name) - if ret != 0: - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "写 .ll 失败: %s", module_name) - VLogger.error(fb, "compile") - return 1 - - # Step 2: 构造切片 .ll 路径并编译 → .obj - ir_path: str = build_sliced_path(temp_dir, module_name, "ll") - if ir_path is None: - return 1 - - ret = compile_ll_to_obj(ir_path, output_dir, module_name, cc_cmd, cc_flags) - if ret != 0: - fb = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "llc 编译失败: %s", module_name) - VLogger.error(fb, "compile") - return 1 - return 0 - - -def link_objs_to_exe(obj_paths: str, obj_paths_len: t.CSizeT, - linker_cmd: str, linker_flags: str, linker_output: str, - includes_binary_dir: str) -> int: - """链接多个 .obj 文件为 .exe - - Args: - obj_paths: 空格分隔的 .obj 文件完整路径字符串 - obj_paths_len: obj_paths 长度 - linker_cmd: 链接器命令(如 "clang++") - linker_flags: 链接器参数 - linker_output: 输出文件完整路径 - includes_binary_dir: includes.binary 目录路径(链接时附加预编译 .obj) - - Returns: - 0 成功,非 0 失败 - """ - if obj_paths is None or obj_paths_len == 0 or linker_cmd is None: - return 1 - - # 收集 includes.binary 的 .obj 文件路径 - EXTRA_BUF_SIZE: t.CSizeT = 32768 - extra_objs: bytes = _mbuddy.alloc(EXTRA_BUF_SIZE) - if extra_objs is None: - return 1 - extra_len: t.CSizeT = 0 - if includes_binary_dir is not None: - extra_len = collect_obj_files(includes_binary_dir, extra_objs, EXTRA_BUF_SIZE) - - # 构造命令: clang++ obj_paths extra_objs -o linker_output linker_flags - cmd_len: t.CSizeT = string.strlen(linker_cmd) + obj_paths_len + string.strlen(linker_flags) + string.strlen(linker_output) + extra_len + 128 - cmd: bytes = _mbuddy.alloc(cmd_len) - if cmd is None: - return 1 - if extra_len > 0: - viperlib.snprintf(cmd, cmd_len, "%s %s %s -o %s %s", - linker_cmd, obj_paths, extra_objs, - linker_output, linker_flags) - else: - viperlib.snprintf(cmd, cmd_len, "%s %s -o %s %s", - linker_cmd, obj_paths, linker_output, linker_flags) - - # 用 subprocess.run 捕获 clang++ 的 stdout/stderr 输出 - # 之前用 stdlib.system() 无法捕获具体错误(undefined reference 等), - # 导致 1.txt 中只看到"链接失败,返回码: 1"而看不到未解析符号 - result: subprocess.CompletedProcess | t.CPtr = subprocess.run(cmd, True, True) - if result is None: - VLogger.error("subprocess.run 返回 None", "link") - return 1 - if result.returncode != 0: - # 先用 stdio.printf 直接输出 clang++ 的完整错误输出(含 undefined reference) - # 必须在 VLogger.error 之前输出,因为 VLogger.error 会调用 sys.exit(1) 终止进程 - if result.stdout is not None: - stdio.printf("=== clang++ 链接错误输出 ===\n%s\n", result.stdout) - if result.stderr is not None: - stdio.printf("=== clang++ stderr ===\n%s\n", result.stderr) - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "链接失败,返回码: %d, 命令: %s", result.returncode, cmd) - VLogger.error(fb, "link") - return 1 - return 0 - - -def run_pipeline(ir_buf: bytes, ir_len: t.CSizeT, - temp_dir: str, output_dir: str, module_name: str, - cc_cmd: str, cc_flags: str, - linker_cmd: str, linker_flags: str, linker_output: str, - includes_binary_dir: str) -> BuildResult | t.CPtr: - """执行完整编译管线 - - Args: - ir_buf: LLVM IR 文本缓冲区 - ir_len: IR 文本长度 - temp_dir: 临时目录 - output_dir: 输出目录 - module_name: 模块名 - cc_cmd: 编译器命令 - cc_flags: 编译器参数 - linker_cmd: 链接器命令 - linker_flags: 链接器参数 - linker_output: 输出文件名 - includes_binary_dir: includes.binary 目录路径(链接时附加预编译 .obj) - - Returns: - BuildResult 对象 - """ - result: BuildResult | t.CPtr = BuildResult() - if result is None: - return None - - # Step 0: 确保 temp/output 目录存在(自动创建,避免写文件失败) - ensure_dir(temp_dir) - ensure_dir(output_dir) - - # Step 1: 写 .ll 文件 - ret: int = write_ir_to_file(ir_buf, ir_len, temp_dir, module_name) - if ret != 0: - result.Success = 0 - result.ErrorMsg = "写 .ll 文件失败" - return result - - # Step 2: llc 编译 .ll → .obj - # 构造切片 .ll 文件路径 - ir_path: str = build_sliced_path(temp_dir, module_name, "ll") - if ir_path is None: - result.Success = 0 - result.ErrorMsg = "内存分配失败" - return result - - ret = compile_ll_to_obj(ir_path, output_dir, module_name, cc_cmd, cc_flags) - if ret != 0: - result.Success = 0 - result.ErrorMsg = "llc 编译失败" - return result - - # Step 3: clang++ 链接 .obj → .exe(附加 includes.binary 预编译 .obj) - ret = link_obj_to_exe(output_dir, module_name, linker_cmd, linker_flags, linker_output, - includes_binary_dir) - if ret != 0: - result.Success = 0 - result.ErrorMsg = "链接失败" - return result - - result.Success = 1 - return result \ No newline at end of file diff --git a/TransPyV/App/lib/core/Handles/HandlesAnnAssign.py b/TransPyV/App/lib/core/Handles/HandlesAnnAssign.py deleted file mode 100644 index 9096f84..0000000 --- a/TransPyV/App/lib/core/Handles/HandlesAnnAssign.py +++ /dev/null @@ -1,504 +0,0 @@ -import t, c -from stdint import * -import ast -import llvmlite -import memhub -import string -import stdio -import lib.core.Handles.HandlesBase as HandlesBase -import lib.core.Handles.HandlesTranslator as HT -import lib.core.Handles.HandlesVar as HandlesVar -import lib.core.Handles.HandlesExpr as HandlesExpr -import lib.core.Handles.HandlesType as HandlesType -import lib.core.Handles.HandlesNonlocal as HandlesNonlocal -import lib.core.Handles.HandlesClassDef as HandlesClassDef -import lib.core.Handles.HandlesExprCall as HandlesExprCall -import lib.core.Handles.HandlesStruct as HandlesStruct - - -# ============================================================ -# HandlesAnnAssign - AnnAssign 语句处理(Mixin 继承模式) -# ============================================================ - - -# ============================================================ -# is_cdefine_annotation - 检测注解是否为 t.CDefine(模块级函数) -# -# 支持两种形式: -# 1. Attribute(Name('t'), 'CDefine') -# 2. BinOp(... | Attribute(Name('t'), 'CDefine'))(联合注解) -# ============================================================ -def is_cdefine_annotation(annot: ast.AST | t.CPtr) -> int: - """检测注解是否为 t.CDefine,返回 1 表示是,0 表示否""" - if annot is None: - return 0 - k: int = annot.kind() - if k == ast.ASTKind.Attribute: - at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(annot) - if at.attr is not None and string.strcmp(at.attr, "CDefine") == 0: - return 1 - return 0 - if k == ast.ASTKind.BinOp: - bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(annot) - if is_cdefine_annotation(bop.left) != 0: - return 1 - if is_cdefine_annotation(bop.right) != 0: - return 1 - return 0 - - -# ============================================================ -# extract_cdefine_int_value - 从 AnnAssign.value 提取整数常量(模块级函数) -# -# 支持的表达式形式: -# 1. Constant(INT) — 如 0x0002, 42 -# 2. BinOp(BitOr/BitAnd) — 如 FOREGROUND_RED | FOREGROUND_GREEN -# 3. Name — 引用已注册的 CDefine 常量 -# 4. Call — 如 t.CUnsignedLong(-11) → 取第一个参数 -# 5. UnaryOp(USub/UAdd/Invert) — 如 -11 -# ============================================================ -def extract_cdefine_int_value(val_node: ast.AST | t.CPtr) -> int: - """从值节点提取整数常量(支持 Constant/BinOp/Name/Call/UnaryOp)""" - if val_node is None: - return 0 - k: int = val_node.kind() - - # Case 1: Constant(INT) — 如 0x0002 - if k == ast.ASTKind.Constant: - cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(val_node) - if cn.const_kind != ast.CONST_INT: - return 0 - return cn.int_val - - # Case 2: BinOp — 如 FOREGROUND_RED | FOREGROUND_GREEN - if k == ast.ASTKind.BinOp: - bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(val_node) - left_val: int = extract_cdefine_int_value(bop.left) - right_val: int = extract_cdefine_int_value(bop.right) - if bop.op == ast.OpKind.BitOr: - return left_val | right_val - if bop.op == ast.OpKind.BitAnd: - return left_val & right_val - if bop.op == ast.OpKind.Add: - return left_val + right_val - if bop.op == ast.OpKind.Sub: - return left_val - right_val - return 0 - - # Case 3: Name — 引用已注册的 CDefine 常量 - if k == ast.ASTKind.Name: - nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(val_node) - if nm.id is not None: - looked_up: int = HandlesType.lookup_cdefine_constant(nm.id) - if HandlesType.is_cdefine_found() != 0: - return looked_up - return 0 - - # Case 4: Call — 如 t.CUnsignedLong(-11) - if k == ast.ASTKind.Call: - cl: ast.Call | t.CPtr = (ast.Call | t.CPtr)(val_node) - if cl.args is not None and cl.args.__len__() > 0: - first_arg: ast.AST | t.CPtr = cl.args.get(0) - arg_val: int = extract_cdefine_int_value(first_arg) - return arg_val - return 0 - - # Case 5: UnaryOp — 如 -11 - if k == ast.ASTKind.UnaryOp: - uop: ast.UnaryOp | t.CPtr = (ast.UnaryOp | t.CPtr)(val_node) - operand_val: int = extract_cdefine_int_value(uop.operand) - if uop.op == ast.OpKind.USub: - return -operand_val - if uop.op == ast.OpKind.UAdd: - return operand_val - if uop.op == ast.OpKind.Invert: - return ~operand_val - return 0 - - return 0 - - -# ============================================================ -# _annotation_contains_name - 递归检查注解中是否包含指定名称 -# -# 支持 BinOp(BitOr) 递归,同时检查 Attribute.attr 和 Name.id。 -# ============================================================ -def _annotation_contains_name(annot: ast.AST | t.CPtr, name: str) -> int: - """递归检查注解中是否包含指定名称,返回 1=包含 / 0=不包含""" - if annot is None or name is None: - return 0 - k: int = annot.kind() - if k == ast.ASTKind.Attribute: - at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(annot) - if at.attr is not None and string.strcmp(at.attr, name) == 0: - return 1 - return 0 - if k == ast.ASTKind.Name: - nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(annot) - if nm.id is not None and string.strcmp(nm.id, name) == 0: - return 1 - return 0 - if k == ast.ASTKind.BinOp: - bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(annot) - if _annotation_contains_name(bop.left, name) != 0: - return 1 - if _annotation_contains_name(bop.right, name) != 0: - return 1 - return 0 - - -# ============================================================ -# _is_ptr_element_annotation - 检查注解是否为 bytes|t.CPtr 或 str|t.CPtr -# -# 返回 1=是(下标按 8 字节步长, i8** 语义), 0=否(下标按 1 字节步长, i8* 语义) -# -# 规则: -# bytes|t.CPtr / str|t.CPtr → i8**(8 字节步长)→ 返回 1 -# t.CChar|t.CPtr / t.CInt8T|t.CPtr → i8*(1 字节步长)→ 返回 0 -# 纯 bytes / str → i8*(1 字节步长)→ 返回 0 -# -# 注: 注解中的 "|" 是"和"的意思(组合类型),非右值中的位或运算 -# ============================================================ -def _is_ptr_element_annotation(annot: ast.AST | t.CPtr) -> int: - """检查注解是否为 bytes|t.CPtr 或 str|t.CPtr 形式""" - if annot is None: - return 0 - k: int = annot.kind() - if k != ast.ASTKind.BinOp: - return 0 - bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(annot) - if bop.op != ast.OpKind.BitOr: - return 0 - if _annotation_contains_name(annot, "str") != 0: - return 1 - if _annotation_contains_name(annot, "bytes") != 0: - return 1 - return 0 - - -# ============================================================ -# _init_global_array_from_list — 从列表字面量初始化全局数组 -# -# 为每个元素生成 GEP + store 指令,将值存入全局数组的对应位置。 -# 适用于模块级 t.CArray[elem_ty, count] = [v0, v1, ...] 的初始化。 -# -# Args: -# builder: IRBuilder -# pool: 编译器内存池 -# mod: LLVMModule -# array_alloca: 全局数组变量的 Value 引用(类型为 [N x elem_ty]*) -# list_node: ast.List 节点 -# trans: Translator 对象 -# -# Returns: -# 0 成功,1 失败 -# ============================================================ -def _init_global_array_from_list(builder: llvmlite.IRBuilder | t.CPtr, - pool: memhub.MemBuddy | t.CPtr, - mod: llvmlite.LLVMModule | t.CPtr, - array_alloca: llvmlite.Value | t.CPtr, - list_node: ast.AST | t.CPtr, - trans: HT.Translator | t.CPtr) -> int: - """从列表字面量初始化全局数组,为每个元素生成 GEP + store""" - if builder is None or array_alloca is None or list_node is None: - return 1 - - # 获取数组类型(Pointee of [N x elem_ty]*) - arr_ty: llvmlite.LLVMType | t.CPtr = None - if array_alloca.Ty is not None: - arr_ty = array_alloca.Ty.Pointee - if arr_ty is None: - return 1 - - # 匹配数组类型获取元素类型 - elem_ty: llvmlite.LLVMType | t.CPtr = None - match arr_ty: - case llvmlite.LLVMType.Array(et, _): - elem_ty = et - if elem_ty is None: - return 1 - - # 获取列表元素 - lst: ast.List | t.CPtr = (ast.List | t.CPtr)(list_node) - if lst is None or lst.elts is None: - return 1 - elts: list[ast.AST | t.CPtr] | t.CPtr = lst.elts - elts_count: t.CSizeT = elts.__len__() - - # 为每个元素生成 GEP + store - i: t.CSizeT = 0 - while i < elts_count: - elem_node: ast.AST | t.CPtr = elts.get(i) - elem_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( - builder, pool, mod, elem_node, None, 0, trans) - if elem_val is not None: - idx_val: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, i) - elem_ptr: llvmlite.Value | t.CPtr = llvmlite.build_gep_array( - builder, arr_ty, elem_ty, array_alloca, idx_val) - if elem_ptr is not None: - # 类型转换(如 i32 → i8 截断) - store_val: llvmlite.Value | t.CPtr = elem_val - if elem_ptr.Ty is not None and elem_ptr.Ty.Pointee is not None: - store_val = HandlesExpr.coerce_to_type( - builder, elem_val, elem_ptr.Ty.Pointee) - llvmlite.build_store(builder, store_val, elem_ptr) - i += 1 - - return 0 - - -@t.NoVTable -class AnnAssignHandle(HandlesBase.Mixin): - """AnnAssign 语句处理器:继承 Mixin 获得 Trans 回指针""" - - def __init__(self, trans: HT.Translator | t.CPtr): - self.Trans = trans - - # ============================================================ - # PreScan - 预扫描 AnnAssign,为有类型注解的变量提前创建 alloca - # - # 返回新增的变量数 - # ============================================================ - def PreScan(self, node: ast.AST | t.CPtr) -> int: - """预扫描 AnnAssign,提前创建 alloca 到 entry block 顶部""" - if node is None: - return 0 - k: int = node.kind() - if k != ast.ASTKind.AnnAssign: - return 0 - - aa: ast.AnnAssign | t.CPtr = (ast.AnnAssign | t.CPtr)(node) - if aa is None or aa.target is None: - return 0 - target: ast.AST | t.CPtr = aa.target - if target.kind() != ast.ASTKind.Name: - return 0 - - nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(target) - if nm.id is None: - return 0 - - # CDefine 注解: 不创建 alloca,但注册常量到全局表 - # 供后续 t.CArray[elem_ty, NAME] 编译期解析使用 - if is_cdefine_annotation(aa.annotation) != 0: - pool_ps: memhub.MemBuddy | t.CPtr = self.Trans.Pool - val_ps: int = extract_cdefine_int_value(aa.value) - HandlesType.register_cdefine_constant(pool_ps, nm.id, val_ps) - return 0 - - # global/nonlocal 变量不需要局部 alloca - if HT.is_global_name(self.Trans, nm.id) != 0: - return 0 - if HT.is_nonlocal_name(self.Trans, nm.id) != 0: - return 0 - - # 模块级全局变量已由 handle_module_level_var 注册到模块作用域, - # 不需要创建局部 alloca(否则会导致局部变量遮蔽全局变量) - if HandlesVar.lookup_module_var(self.Trans.SymTab, nm.id) is not None: - return 0 - - # 检查是否已存在 - existing: llvmlite.Value | t.CPtr = HandlesVar.lookup_current( - self.Trans.SymTab, nm.id) - if existing is not None: - return 0 - - pool: memhub.MemBuddy | t.CPtr = self.Trans.Pool - builder: llvmlite.IRBuilder | t.CPtr = self.Trans._cur_builder - - # 从 annotation 推断类型(修复:原硬编码 i32 导致 str 等类型错误) - var_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool) - annot: ast.AST | t.CPtr = aa.annotation - if annot is not None: - resolved: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type( - pool, annot, self.Trans._imported_modules, self.Trans._from_imports, self.Trans) - if resolved is None: - # 尝试特化泛型类注解(如 list[str]) - # resolve_annotation_type 返回 None 可能是因为泛型类未特化 - if annot.kind() == ast.ASTKind.Subscript: - sub_annot: ast.Subscript | t.CPtr = (ast.Subscript | t.CPtr)(annot) - if sub_annot.value is not None and sub_annot.value.kind() == ast.ASTKind.Name: - sub_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(sub_annot.value) - if sub_nm.id is not None: - template_cd: ast.ClassDef | t.CPtr = HandlesClassDef._find_generic_template(sub_nm.id) - if template_cd is not None: - type_args_ps: list[str] | t.CPtr = HandlesExprCall._extract_type_args_from_slice(pool, sub_annot.slice) - if type_args_ps is not None and type_args_ps.__len__() > 0: - spec_name_ps: str = HandlesClassDef._specialize_generic_class( - self.Trans, sub_nm.id, type_args_ps) - if spec_name_ps is not None: - resolved = HandlesType.resolve_annotation_type( - pool, annot, self.Trans._imported_modules, self.Trans._from_imports, self.Trans) - if resolved is not None: - var_ty = resolved - - # 确保跨模块结构体的完整定义在当前模块中可用(供 alloca 分配空间) - HandlesStruct.ensure_struct_def_in_module(pool, self.Trans.Module, var_ty) - alloca: llvmlite.Value | t.CPtr = HandlesVar._alloca_at_entry(builder, var_ty) - if alloca is not None: - if HandlesVar.define_var( - self.Trans.SymTab, nm.id, alloca) == 0: - # 存储原始类型注解的类名(方法调用检测时,Ptr(i8) 回退到类名查找结构体) - if annot is not None: - cls_nm_ps: str = HandlesType.extract_class_name_from_annotation( - annot, self.Trans._imported_modules) - if cls_nm_ps is not None: - HandlesVar.set_var_annot_class_name( - self.Trans.SymTab, nm.id, cls_nm_ps) - # 检查是否为 bytes|t.CPtr 或 str|t.CPtr(i8** 语义,8 字节步长) - if _is_ptr_element_annotation(annot) != 0: - HandlesVar.set_var_ptr_element( - self.Trans.SymTab, nm.id) - return 0 - return 0 - - # ============================================================ - # Handle - 翻译 AnnAssign 语句 - # - # 返回新增的变量数 - # ============================================================ - def Handle(self, node: ast.AST | t.CPtr) -> int: - """翻译 AnnAssign(target=Name, annotation=..., value=expr)""" - aa: ast.AnnAssign | t.CPtr = (ast.AnnAssign | t.CPtr)(node) - if aa is None: - return 0 - - target: ast.AST | t.CPtr = aa.target - if target is None or target.kind() != ast.ASTKind.Name: - return 0 - - nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(target) - if nm.id is None: - return 0 - - # CDefine 注解: 编译期常量,不生成运行时代码 - # 注册到全局 CDefine 表供 t.CArray[elem_ty, NAME] 解析 - # 注: PreScan 已注册过,此处保证即使跳过 PreScan 也能正确注册 - if is_cdefine_annotation(aa.annotation) != 0: - pool_cd: memhub.MemBuddy | t.CPtr = self.Trans.Pool - val_cd: int = extract_cdefine_int_value(aa.value) - HandlesType.register_cdefine_constant(pool_cd, nm.id, val_cd) - return 0 - - pool: memhub.MemBuddy | t.CPtr = self.Trans.Pool - builder: llvmlite.IRBuilder | t.CPtr = self.Trans._cur_builder - mod: llvmlite.LLVMModule | t.CPtr = self.Trans.Module - - # 确定类型(从 annotation 推断) - var_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool) - annot: ast.AST | t.CPtr = aa.annotation - if annot is not None: - resolved: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type( - pool, annot, self.Trans._imported_modules, self.Trans._from_imports, self.Trans) - if resolved is not None: - var_ty = resolved - - # global 变量:写入模块作用域中的全局变量 - if HT.is_global_name(self.Trans, nm.id) != 0: - mod_alloca: llvmlite.Value | t.CPtr = HandlesVar.lookup_module_var( - self.Trans.SymTab, nm.id) - if mod_alloca is not None and aa.value is not None: - rhs_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( - builder, pool, mod, aa.value, - None, 0, self.Trans) - if rhs_val is not None: - target_ty: llvmlite.LLVMType | t.CPtr = None - if mod_alloca.Ty is not None: - target_ty = mod_alloca.Ty.Pointee - if target_ty is not None: - rhs_val = HandlesExpr.coerce_to_type(builder, rhs_val, target_ty) - llvmlite.build_store(builder, rhs_val, mod_alloca) - return 0 - - # nonlocal 变量:通过闭包 env 写入 - if HT.is_nonlocal_name(self.Trans, nm.id) != 0: - if aa.value is not None: - rhs_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( - builder, pool, mod, aa.value, - None, 0, self.Trans) - if rhs_val is not None: - nl_ptr: llvmlite.Value | t.CPtr = HandlesNonlocal.get_nonlocal_var_ptr( - self.Trans, nm.id) - if nl_ptr is not None: - i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool) - rhs_coerced: llvmlite.Value | t.CPtr = HandlesExpr.coerce_to_type( - builder, rhs_val, i32_ty) - llvmlite.build_store(builder, rhs_coerced, nl_ptr) - return 0 - - # 模块级全局变量(由 handle_module_level_var 注册到模块作用域) - # 非函数内 global 声明,但变量已在模块作用域中(如模块级 t.CArray 初始化) - mod_glob: llvmlite.Value | t.CPtr = HandlesVar.lookup_module_var( - self.Trans.SymTab, nm.id) - if mod_glob is not None: - if aa.value is not None: - # 列表字面量 → 逐元素 GEP + store 初始化数组 - if aa.value.kind() == ast.ASTKind.List: - _init_global_array_from_list( - builder, pool, mod, mod_glob, aa.value, self.Trans) - else: - rhs_val_mg: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( - builder, pool, mod, aa.value, - None, 0, self.Trans) - if rhs_val_mg is not None: - target_ty_mg: llvmlite.LLVMType | t.CPtr = None - if mod_glob.Ty is not None: - target_ty_mg = mod_glob.Ty.Pointee - if target_ty_mg is not None: - rhs_val_mg = HandlesExpr.coerce_to_type(builder, rhs_val_mg, target_ty_mg) - llvmlite.build_store(builder, rhs_val_mg, mod_glob) - return 0 - - # 普通局部变量 - # 创建 alloca - alloca: llvmlite.Value | t.CPtr = HandlesVar.get_or_create_sym( - self.Trans.SymTab, pool, builder, nm.id, var_ty) - if alloca is None: - return 0 - # 存储原始类型注解的类名(方法调用检测时,Ptr(i8) 回退到类名查找结构体) - if annot is not None: - cls_nm_hd: str = HandlesType.extract_class_name_from_annotation( - annot, self.Trans._imported_modules) - if cls_nm_hd is not None: - HandlesVar.set_var_annot_class_name( - self.Trans.SymTab, nm.id, cls_nm_hd) - # 检查是否为 bytes|t.CPtr 或 str|t.CPtr(i8** 语义,8 字节步长) - if _is_ptr_element_annotation(annot) != 0: - HandlesVar.set_var_ptr_element( - self.Trans.SymTab, nm.id) - - new_vars: int = 0 - existing: llvmlite.Value | t.CPtr = HandlesVar.lookup_current( - self.Trans.SymTab, nm.id) - if existing is None: - new_vars = 1 - - # 如果有初始值,store - if aa.value is not None: - rhs_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( - builder, pool, mod, aa.value, - None, 0, self.Trans) - if rhs_val is not None: - # 类型转换:将 rhs_val 转换为 alloca 的 pointee 类型 - # 修复:整数字面量是 i32,但变量可能是 i8/i16/i64,需 trunc/sext - target_ty: llvmlite.LLVMType | t.CPtr = None - if alloca.Ty is not None: - target_ty = alloca.Ty.Pointee - if target_ty is not None: - rhs_val = HandlesExpr.coerce_to_type(builder, rhs_val, target_ty) - llvmlite.build_store(builder, rhs_val, alloca) - - return 0 - - -# ============================================================ -# NewAnnAssignHandle - 工厂函数 -# ============================================================ -def NewAnnAssignHandle(pool: memhub.MemBuddy | t.CPtr, - trans: HT.Translator | t.CPtr) -> AnnAssignHandle | t.CPtr: - h: AnnAssignHandle | t.CPtr = pool.alloc(AnnAssignHandle.__sizeof__()) - if h is None: - return None - string.memset(h, 0, AnnAssignHandle.__sizeof__()) - h.Trans = trans - return h diff --git a/TransPyV/App/lib/core/Handles/HandlesAssign.py b/TransPyV/App/lib/core/Handles/HandlesAssign.py deleted file mode 100644 index 765ce8b..0000000 --- a/TransPyV/App/lib/core/Handles/HandlesAssign.py +++ /dev/null @@ -1,389 +0,0 @@ -import t, c -from stdint import * -import ast -import llvmlite -import memhub -import string -import stdio -import viperlib -import lib.core.VLogger as VLogger -import lib.core.Handles.HandlesBase as HandlesBase -import lib.core.Handles.HandlesTranslator as HT -import lib.core.Handles.HandlesVar as HandlesVar -import lib.core.Handles.HandlesExpr as HandlesExpr -import lib.core.Handles.HandlesExprCall as HandlesExprCall -import lib.core.Handles.HandlesNonlocal as HandlesNonlocal -import lib.core.Handles.HandlesType as HandlesType -import lib.core.Handles.HandlesStruct as HandlesStruct -import lib.core.StubMerger as StubMerger - - -# ============================================================ -# HandlesAssign - Assign 语句处理(Mixin 继承模式) -# -# 对应 TransPyC 的 class AssignHandle(BaseHandle): -# @t.NoVTable 继承 Mixin 获得 Trans 字段(展平嵌入,无 vtable) -# 通过 self.Trans 访问共享状态(Pool/Module/_cur_builder/SymTab/...) -# 通过 self.Trans.ExprH / self.Trans.IfH 等访问其他 Handle -# ============================================================ - - -@t.NoVTable -class AssignHandle(HandlesBase.Mixin): - """Assign 语句处理器:继承 Mixin 获得 Trans 回指针 + 共享方法""" - _CurrentClass: str # 模块私有状态 - - def __init__(self, trans: HT.Translator | t.CPtr): - self.Trans = trans - self._CurrentClass = None - - # ============================================================ - # Handle - 处理 Assign 语句,返回新增变量数(0 或 1) - # - # 对应 TransPyC AssignHandle._HandleAssignLlvm - # 共享状态从 self.Trans 获取,无需 11 个参数 - # ============================================================ - def Handle(self, node: ast.AST | t.CPtr) -> int: - asgn: ast.Assign | t.CPtr = (ast.Assign | t.CPtr)(node) - if asgn is None: - VLogger.error("cast failed", "ASGN") - return 0 - - targets: list[ast.AST | t.CPtr] | t.CPtr = asgn.targets - if targets is None: - VLogger.error("targets is None", "ASGN") - return 0 - - # 从 self.Trans 取共享状态(替代 11 个参数) - pool: memhub.MemBuddy | t.CPtr = self.Trans.Pool - builder: llvmlite.IRBuilder | t.CPtr = self.Trans._cur_builder - mod: llvmlite.LLVMModule | t.CPtr = self.Trans.Module - - # 翻译 RHS 值 - rhs_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( - builder, pool, mod, asgn.value, None, 0, self.Trans) - if rhs_val is None: - # 增强错误信息:包含文件名 + lineno + AST 节点详情,便于定位 - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None and asgn.value is not None: - sha1: str = self.Trans.ModuleSha1 - val_kind: int = asgn.value.kind() - val_line: t.CInt = asgn.value.lineno - # 通过 sha1 查找文件名(人类可读) - rel_path: str = None - if sha1 is not None: - rel_path = StubMerger.LookupSha1RelPath(sha1) - # 根据 AST 节点类型提取详情 - if val_kind == ast.ASTKind.Attribute: - at_nv: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(asgn.value) - attr_nm: str = at_nv.attr - target_nm: str = "?" - if at_nv.value is not None: - if at_nv.value.kind() == ast.ASTKind.Name: - tn_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at_nv.value) - target_nm = tn_nm.id - if rel_path is not None: - viperlib.snprintf(fb, 1024, - "赋值右侧为 None: %s:%d '%s.%s' 属性访问失败", - rel_path, val_line, target_nm, attr_nm) - else: - viperlib.snprintf(fb, 1024, - "赋值右侧为 None: sha1=%s:%d '%s.%s' 属性访问失败", - sha1, val_line, target_nm, attr_nm) - elif val_kind == ast.ASTKind.Name: - nm_nv: ast.Name | t.CPtr = (ast.Name | t.CPtr)(asgn.value) - if rel_path is not None: - viperlib.snprintf(fb, 1024, - "赋值右侧为 None: %s:%d 变量 '%s' 未找到", - rel_path, val_line, nm_nv.id) - else: - viperlib.snprintf(fb, 1024, - "赋值右侧为 None: sha1=%s:%d 变量 '%s' 未找到", - sha1, val_line, nm_nv.id) - elif val_kind == ast.ASTKind.Call: - cl_nv: ast.Call | t.CPtr = (ast.Call | t.CPtr)(asgn.value) - func_nm: str = "?" - if cl_nv.func is not None: - if cl_nv.func.kind() == ast.ASTKind.Name: - fn_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(cl_nv.func) - func_nm = fn_nm.id - if rel_path is not None: - viperlib.snprintf(fb, 1024, - "赋值右侧为 None: %s:%d 调用 '%s(...)' 返回 None", - rel_path, val_line, func_nm) - else: - viperlib.snprintf(fb, 1024, - "赋值右侧为 None: sha1=%s:%d 调用 '%s(...)' 返回 None", - sha1, val_line, func_nm) - else: - if rel_path is not None: - viperlib.snprintf(fb, 1024, - "赋值右侧为 None: %s:%d [kind=%d]", - rel_path, val_line, val_kind) - else: - viperlib.snprintf(fb, 1024, - "赋值右侧为 None: sha1=%s:%d [kind=%d]", - sha1, val_line, val_kind) - VLogger.error(fb, "ASGN") - else: - VLogger.error("赋值右侧为 None (asgn.value 为空)", "ASGN") - return 0 - - new_vars: int = 0 - tn: t.CSizeT = targets.__len__() - for ti in range(tn): - target: ast.AST | t.CPtr = targets.get(ti) - if target is None: - continue - - tk: int = target.kind() - - # Subscript 赋值: arr[i] = val / ptr[i] = val / list[i] = val - if tk == ast.ASTKind.Subscript: - # 检查是否是 list[T] 类型的 Subscript(泛型类不注册 struct) - # list 的 subscript 赋值走 __setitem__ 内联路径 - list_obj: llvmlite.Value | t.CPtr = HandlesExpr.is_list_subscript( - target, self.Trans) - if list_obj is not None: - # list[T] 类型: 内联生成 __setitem__ 逻辑 - sub_node: ast.Subscript | t.CPtr = (ast.Subscript | t.CPtr)(target) - if sub_node is not None and sub_node.slice is not None: - list_idx_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( - builder, pool, mod, sub_node.slice, None, 0, self.Trans) - if list_idx_val is not None: - HandlesExpr.list_setitem_inline( - builder, pool, list_obj, list_idx_val, rhs_val) - continue - # 普通 Subscript 赋值 - elem_ptr: llvmlite.Value | t.CPtr = HandlesExpr.get_subscript_ptr( - builder, pool, mod, target, self.Trans) - if elem_ptr is not None: - store_val: llvmlite.Value | t.CPtr = rhs_val - if elem_ptr.Ty is not None: - elem_ty: llvmlite.LLVMType | t.CPtr = elem_ptr.Ty.Pointee - if elem_ty is not None: - store_val = HandlesExpr.coerce_to_type( - builder, rhs_val, elem_ty) - llvmlite.build_store(builder, store_val, elem_ptr) - else: - # get_subscript_ptr 返回 None: 尝试 __setitem__ 运算符重载 - # 适用于自定义类(如 hashtable[key]=val → hashtable.__setitem__(key, val)) - sub_asgn: ast.Subscript | t.CPtr = (ast.Subscript | t.CPtr)(target) - setitem_done: int = 0 - if sub_asgn is not None and sub_asgn.value is not None: - if sub_asgn.value.kind() == ast.ASTKind.Name: - sub_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(sub_asgn.value) - if sub_nm.id is not None: - sub_alloca: llvmlite.Value | t.CPtr = HandlesVar.lookup_var( - self.Trans.SymTab, sub_nm.id) - if sub_alloca is not None and sub_alloca.Ty is not None: - if HandlesExpr.is_ptr_type(sub_alloca.Ty) != 0: - sub_pointee: llvmlite.LLVMType | t.CPtr = sub_alloca.Ty.Pointee - if sub_pointee is not None: - cls_nm_set: str = HandlesStruct.get_class_name_by_type(pool, sub_pointee) - obj_val_set: llvmlite.Value | t.CPtr = llvmlite.build_load( - builder, sub_pointee, sub_alloca) - # 指针类型变量 (X|t.CPtr): sub_pointee 是 Ptr(Struct), - # 需 load 获取 Ptr(Struct) 再检查 inner struct - if cls_nm_set is None and obj_val_set is not None: - if HandlesExpr.is_ptr_type(sub_pointee) != 0: - inner_ty_set: llvmlite.LLVMType | t.CPtr = sub_pointee.Pointee - if inner_ty_set is not None: - cls_nm_set = HandlesStruct.get_class_name_by_type(pool, inner_ty_set) - if cls_nm_set is not None and obj_val_set is not None: - key_val_set: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( - builder, pool, mod, sub_asgn.slice, None, 0, self.Trans) - if key_val_set is not None: - arg_vals_set: t.CSizeT | t.CPtr = pool.alloc(16) - if arg_vals_set is not None: - arg_vals_set[0] = t.CSizeT(key_val_set) - arg_vals_set[1] = t.CSizeT(rhs_val) - HandlesExprCall._call_method_on_ptr( - pool, builder, mod, cls_nm_set, "__setitem__", - obj_val_set, arg_vals_set, 2, self.Trans) - setitem_done = 1 - elif sub_asgn.value.kind() == ast.ASTKind.Attribute: - # self._ht[key] = val → self._ht.__setitem__(key, val) - # 通过 get_attribute_ptr 获取字段指针,再调用 __setitem__ - field_ptr_set: llvmlite.Value | t.CPtr = HandlesExpr.get_attribute_ptr( - builder, pool, mod, sub_asgn.value, self.Trans) - if field_ptr_set is not None and field_ptr_set.Ty is not None: - if HandlesExpr.is_ptr_type(field_ptr_set.Ty) != 0: - field_pointee_set: llvmlite.LLVMType | t.CPtr = field_ptr_set.Ty.Pointee - if field_pointee_set is not None: - cls_nm_attr: str = HandlesStruct.get_class_name_by_type(pool, field_pointee_set) - obj_val_attr: llvmlite.Value | t.CPtr = field_ptr_set - # field_ptr 是 Ptr(Ptr(Struct)) (X|t.CPtr 字段): - # load 解引用获取 Ptr(Struct) - if cls_nm_attr is None and HandlesExpr.is_ptr_type(field_pointee_set) != 0: - inner_struct_attr: llvmlite.LLVMType | t.CPtr = field_pointee_set.Pointee - if inner_struct_attr is not None: - cls_nm_attr = HandlesStruct.get_class_name_by_type(pool, inner_struct_attr) - if cls_nm_attr is not None: - obj_val_attr = llvmlite.build_load( - builder, field_pointee_set, field_ptr_set) - if cls_nm_attr is not None and obj_val_attr is not None: - key_val_attr: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( - builder, pool, mod, sub_asgn.slice, None, 0, self.Trans) - if key_val_attr is not None: - arg_vals_attr: t.CSizeT | t.CPtr = pool.alloc(16) - if arg_vals_attr is not None: - arg_vals_attr[0] = t.CSizeT(key_val_attr) - arg_vals_attr[1] = t.CSizeT(rhs_val) - HandlesExprCall._call_method_on_ptr( - pool, builder, mod, cls_nm_attr, "__setitem__", - obj_val_attr, arg_vals_attr, 2, self.Trans) - setitem_done = 1 - if setitem_done == 0: - # 通用 fallback: 翻译 sub.value 并尝试 __setitem__ 或直接 GEP+store - # 处理 Name/Attribute 之外的节点以及 SymTab 查找失败的情况 - if sub_asgn is not None and sub_asgn.value is not None: - obj_val_gen: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( - builder, pool, mod, sub_asgn.value, None, 0, self.Trans) - key_val_gen: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( - builder, pool, mod, sub_asgn.slice, None, 0, self.Trans) - if obj_val_gen is not None and key_val_gen is not None \ - and obj_val_gen.Ty is not None: - # 内联 _get_custom_struct_cls_nm 逻辑(避免依赖新函数) - cls_nm_gen: str = HandlesStruct.get_class_name_by_type( - pool, obj_val_gen.Ty) - if cls_nm_gen is None and HandlesExpr.is_ptr_type(obj_val_gen.Ty) != 0: - inner_gen: llvmlite.LLVMType | t.CPtr = obj_val_gen.Ty.Pointee - if inner_gen is not None: - cls_nm_gen = HandlesStruct.get_class_name_by_type(pool, inner_gen) - if cls_nm_gen is not None: - # 自定义结构体: 调用 __setitem__ - arg_vals_gen: t.CSizeT | t.CPtr = pool.alloc(16) - if arg_vals_gen is not None: - arg_vals_gen[0] = t.CSizeT(key_val_gen) - arg_vals_gen[1] = t.CSizeT(rhs_val) - HandlesExprCall._call_method_on_ptr( - pool, builder, mod, cls_nm_gen, "__setitem__", - obj_val_gen, arg_vals_gen, 2, self.Trans) - setitem_done = 1 - else: - # 非自定义结构体: 直接 GEP + store - # 处理 get_subscript_ptr 因边界情况返回 None 的指针下标 - if HandlesExpr.is_ptr_type(obj_val_gen.Ty) != 0: - elem_gen: llvmlite.LLVMType | t.CPtr = obj_val_gen.Ty.Pointee - if elem_gen is not None: - store_val_gen: llvmlite.Value | t.CPtr = rhs_val - elem_ptr_gen: llvmlite.Value | t.CPtr = None - match elem_gen: - case llvmlite.LLVMType.Array(arr_elem_gen, _): - elem_ptr_gen = llvmlite.build_gep_array( - builder, elem_gen, arr_elem_gen, - obj_val_gen, key_val_gen) - case _: - elem_ptr_gen = llvmlite.build_gep( - builder, elem_gen, obj_val_gen, key_val_gen) - if elem_ptr_gen is not None and elem_ptr_gen.Ty is not None: - pt_gen: llvmlite.LLVMType | t.CPtr = elem_ptr_gen.Ty.Pointee - if pt_gen is not None: - store_val_gen = HandlesExpr.coerce_to_type( - builder, rhs_val, pt_gen) - llvmlite.build_store(builder, store_val_gen, elem_ptr_gen) - setitem_done = 1 - if setitem_done == 0: - sub_vk: int = sub_asgn.value.kind() - if setitem_done == 0: - HandlesType.fatal_error(target, "subscript ptr is None") - continue - - # Attribute 赋值: obj.field = val - if tk == ast.ASTKind.Attribute: - field_ptr: llvmlite.Value | t.CPtr = HandlesExpr.get_attribute_ptr( - builder, pool, mod, target, self.Trans) - if field_ptr is not None: - # 获取字段类型,对 rhs_val 进行类型转换(如 i32 → i64) - store_val: llvmlite.Value | t.CPtr = rhs_val - if field_ptr.Ty is not None: - field_ty: llvmlite.LLVMType | t.CPtr = field_ptr.Ty.Pointee - if field_ty is not None: - store_val = HandlesExpr.coerce_to_type( - builder, rhs_val, field_ty) - llvmlite.build_store(builder, store_val, field_ptr) - else: - # 构造详细错误信息 - attr_node: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(target) - attr_name: str = "(unknown)" - obj_name: str = "(unknown)" - if attr_node is not None: - attr_name = attr_node.attr - if attr_node.value is not None and attr_node.value.kind() == ast.ASTKind.Name: - obj_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(attr_node.value) - obj_name = obj_nm.id - err_buf: t.CChar | t.CPtr = pool.alloc(256) - if err_buf is not None: - viperlib.snprintf(err_buf, 256, - "attribute ptr is None: %s.%s", - obj_name, attr_name) - HandlesType.fatal_error(target, err_buf) - else: - HandlesType.fatal_error(target, "attribute ptr is None") - continue - - # Name 赋值: var = val - if tk == ast.ASTKind.Name: - nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(target) - if nm.id is not None: - # global 变量:写入模块作用域中的全局变量 - if HT.is_global_name(self.Trans, nm.id) != 0: - mod_alloca: llvmlite.Value | t.CPtr = HandlesVar.lookup_module_var( - self.Trans.SymTab, nm.id) - if mod_alloca is not None: - target_ty: llvmlite.LLVMType | t.CPtr = None - if mod_alloca.Ty is not None: - target_ty = mod_alloca.Ty.Pointee - if target_ty is not None: - rhs_val = HandlesExpr.coerce_to_type(builder, rhs_val, target_ty) - llvmlite.build_store(builder, rhs_val, mod_alloca) - continue - - # nonlocal 变量:通过闭包 env 写入 - if HT.is_nonlocal_name(self.Trans, nm.id) != 0: - nl_ptr: llvmlite.Value | t.CPtr = HandlesNonlocal.get_nonlocal_var_ptr( - self.Trans, nm.id) - if nl_ptr is not None: - i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool) - rhs_coerced: llvmlite.Value | t.CPtr = HandlesExpr.coerce_to_type( - builder, rhs_val, i32_ty) - llvmlite.build_store(builder, rhs_coerced, nl_ptr) - continue - - # 普通局部变量 - alloca: llvmlite.Value | t.CPtr = HandlesVar.get_or_create_sym( - self.Trans.SymTab, pool, builder, nm.id, rhs_val.Ty) - if alloca is not None: - # 按 alloca 类型对值进行转换(如 double → float) - store_val: llvmlite.Value | t.CPtr = rhs_val - if alloca.Ty is not None: - alloca_ty: llvmlite.LLVMType | t.CPtr = alloca.Ty.Pointee - if alloca_ty is not None: - store_val = HandlesExpr.coerce_to_type( - builder, rhs_val, alloca_ty) - llvmlite.build_store(builder, store_val, alloca) - existing: llvmlite.Value | t.CPtr = HandlesVar.lookup_current( - self.Trans.SymTab, nm.id) - if existing is None: - new_vars += 1 - else: - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "alloca failed for %s", nm.id) - VLogger.error(fb, "ASGN") - - return new_vars - - -# ============================================================ -# NewAssignHandle - 工厂函数:分配并初始化 AssignHandle -# ============================================================ -def NewAssignHandle(pool: memhub.MemBuddy | t.CPtr, - trans: HT.Translator | t.CPtr) -> AssignHandle | t.CPtr: - h: AssignHandle | t.CPtr = pool.alloc(AssignHandle.__sizeof__()) - if h is None: - return None - string.memset(h, 0, AssignHandle.__sizeof__()) - h.Trans = trans - return h diff --git a/TransPyV/App/lib/core/Handles/HandlesAugAssign.py b/TransPyV/App/lib/core/Handles/HandlesAugAssign.py deleted file mode 100644 index 31d8400..0000000 --- a/TransPyV/App/lib/core/Handles/HandlesAugAssign.py +++ /dev/null @@ -1,315 +0,0 @@ -import t, c -from stdint import * -import ast -import llvmlite -import memhub -import stdio -import string -import viperlib -import lib.core.VLogger as VLogger -import lib.core.Handles.HandlesBase as HandlesBase -import lib.core.Handles.HandlesTranslator as HT -import lib.core.Handles.HandlesVar as HandlesVar -import lib.core.Handles.HandlesExpr as HandlesExpr -import lib.core.Handles.HandlesNonlocal as HandlesNonlocal - - -# ============================================================ -# HandlesAugAssign - 增强赋值语句处理(Mixin 继承模式) -# -# 处理 += -= *= /= %= &= |= ^= <<= >>= -# 流程: load target → apply binop → store result -# -# 支持 local/global/nonlocal 三种变量作用域 -# ============================================================ - - -@t.NoVTable -class AugAssignHandle(HandlesBase.Mixin): - """增强赋值处理器 (+=, -=, *=, etc.):继承 Mixin 获得 Trans 回指针""" - - def __init__(self, trans: HT.Translator | t.CPtr): - self.Trans = trans - - # ============================================================ - # Handle - 处理 AugAssign 语句,返回新增变量数(始终为 0) - # ============================================================ - def Handle(self, node: ast.AST | t.CPtr) -> int: - """翻译增强赋值语句 (x += 1, y -= 2, etc.)""" - if node is None: - return 0 - - aug: ast.AugAssign | t.CPtr = (ast.AugAssign | t.CPtr)(node) - if aug is None: - return 0 - - target: ast.AST | t.CPtr = aug.target - if target is None: - return 0 - - tk: int = target.kind() - - # Attribute 目标: self.field += 1 - # 流程: get_attribute_ptr → load → binop → store - if tk == ast.ASTKind.Attribute: - pool: memhub.MemBuddy | t.CPtr = self.Trans.Pool - builder: llvmlite.IRBuilder | t.CPtr = self.Trans._cur_builder - mod: llvmlite.LLVMModule | t.CPtr = self.Trans.Module - - # 1. 获取字段指针 - field_ptr: llvmlite.Value | t.CPtr = HandlesExpr.get_attribute_ptr( - builder, pool, mod, target, self.Trans) - if field_ptr is None: - VLogger.error("attribute ptr is None", "AUGASGN") - return 0 - - # 2. 确定字段类型并加载当前值 - target_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool) - if field_ptr.Ty is not None: - target_ty = field_ptr.Ty.Pointee - cur_val: llvmlite.Value | t.CPtr = llvmlite.build_load( - builder, target_ty, field_ptr) - if cur_val is None: - VLogger.error("cannot load attribute", "AUGASGN") - return 0 - - # 3. 翻译 RHS 值 - rhs_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( - builder, pool, mod, aug.value, None, 0, self.Trans) - if rhs_val is None: - VLogger.error("rhs is None", "AUGASGN") - return 0 - - # 4. 应用二元运算 - result: llvmlite.Value | t.CPtr = _apply_aug_op( - pool, builder, aug.op, cur_val, rhs_val) - if result is None: - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "binop failed for attr op=%d", aug.op) - VLogger.error(fb, "AUGASGN") - return 0 - - # 5. 类型对齐并存储 - result = HandlesExpr.coerce_to_type(builder, result, target_ty) - if result is None: - return 0 - llvmlite.build_store(builder, result, field_ptr) - return 0 - - # Subscript 目标: self.state[i] += x / arr[i] += x - # 流程: get_subscript_ptr → load → binop → store - if tk == ast.ASTKind.Subscript: - pool: memhub.MemBuddy | t.CPtr = self.Trans.Pool - builder: llvmlite.IRBuilder | t.CPtr = self.Trans._cur_builder - mod: llvmlite.LLVMModule | t.CPtr = self.Trans.Module - - # 1. 获取元素指针 - elem_ptr: llvmlite.Value | t.CPtr = HandlesExpr.get_subscript_ptr( - builder, pool, mod, target, self.Trans) - if elem_ptr is None: - VLogger.error("subscript ptr is None", "AUGASGN") - return 0 - - # 2. 确定元素类型并加载当前值 - target_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool) - if elem_ptr.Ty is not None and elem_ptr.Ty.Pointee is not None: - target_ty = elem_ptr.Ty.Pointee - cur_val: llvmlite.Value | t.CPtr = llvmlite.build_load( - builder, target_ty, elem_ptr) - if cur_val is None: - VLogger.error("cannot load subscript element", "AUGASGN") - return 0 - - # 3. 翻译 RHS 值 - rhs_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( - builder, pool, mod, aug.value, None, 0, self.Trans) - if rhs_val is None: - VLogger.error("rhs is None", "AUGASGN") - return 0 - - # 4. 应用二元运算 - result: llvmlite.Value | t.CPtr = _apply_aug_op( - pool, builder, aug.op, cur_val, rhs_val) - if result is None: - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "binop failed for sub op=%d", aug.op) - VLogger.error(fb, "AUGASGN") - return 0 - - # 5. 类型对齐并存储 - result = HandlesExpr.coerce_to_type(builder, result, target_ty) - if result is None: - return 0 - llvmlite.build_store(builder, result, elem_ptr) - return 0 - - if tk != ast.ASTKind.Name: - VLogger.error("only Name/Attribute/Subscript target supported", "AUGASGN") - return 0 - - nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(target) - if nm is None or nm.id is None: - return 0 - - pool: memhub.MemBuddy | t.CPtr = self.Trans.Pool - builder: llvmlite.IRBuilder | t.CPtr = self.Trans._cur_builder - mod: llvmlite.LLVMModule | t.CPtr = self.Trans.Module - i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool) - - # 1. 确定变量作用域类型: 0=local, 1=global, 2=nonlocal - scope_type: int = 0 - if HT.is_global_name(self.Trans, nm.id) != 0: - scope_type = 1 - elif HT.is_nonlocal_name(self.Trans, nm.id) != 0: - scope_type = 2 - - # 2. 加载当前值 - cur_val: llvmlite.Value | t.CPtr = None - target_alloca: llvmlite.Value | t.CPtr = None - target_ty: llvmlite.LLVMType | t.CPtr = i32_ty - - if scope_type == 1: - # global 变量 - target_alloca = HandlesVar.lookup_module_var( - self.Trans.SymTab, nm.id) - if target_alloca is not None: - if target_alloca.Ty is not None: - target_ty = target_alloca.Ty.Pointee - cur_val = llvmlite.build_load(builder, target_ty, target_alloca) - elif scope_type == 2: - # nonlocal 变量(通过闭包 env) - cur_val = HandlesNonlocal.load_nonlocal_var(self.Trans, nm.id) - if cur_val is not None: - target_ty = cur_val.Ty - else: - # 普通局部变量 - target_alloca = HandlesVar.lookup_var(self.Trans.SymTab, nm.id) - if target_alloca is not None: - if target_alloca.Ty is not None: - target_ty = target_alloca.Ty.Pointee - cur_val = llvmlite.build_load(builder, target_ty, target_alloca) - - if cur_val is None: - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "cannot load target %s", nm.id) - VLogger.error(fb, "AUGASGN") - return 0 - - # 3. 翻译 RHS 值 - rhs_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( - builder, pool, mod, aug.value, None, 0, self.Trans) - if rhs_val is None: - VLogger.error("rhs is None", "AUGASGN") - return 0 - - # 4. 类型对齐 + 应用二元运算 - # 注意: AugAssign 不走运算符重载(语义上需要 __iadd__ 而非 __add__) - result: llvmlite.Value | t.CPtr = _apply_aug_op( - pool, builder, aug.op, cur_val, rhs_val) - if result is None: - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "binop failed for op=%d", aug.op) - VLogger.error(fb, "AUGASGN") - return 0 - - # 5. 存储结果 - result = HandlesExpr.coerce_to_type(builder, result, target_ty) - if result is None: - return 0 - - if scope_type == 1: - # global 变量 - if target_alloca is not None: - llvmlite.build_store(builder, result, target_alloca) - elif scope_type == 2: - # nonlocal 变量 - nl_ptr: llvmlite.Value | t.CPtr = HandlesNonlocal.get_nonlocal_var_ptr( - self.Trans, nm.id) - if nl_ptr is not None: - llvmlite.build_store(builder, result, nl_ptr) - else: - # 普通局部变量 - if target_alloca is not None: - llvmlite.build_store(builder, result, target_alloca) - - return 0 - - -# ============================================================ -# _apply_aug_op - 应用增强赋值的二元运算 -# -# 支持指针算术: ptr += int / ptr -= int -# 整数运算自动类型提升 -# ============================================================ -def _apply_aug_op(pool: memhub.MemBuddy | t.CPtr, - builder: llvmlite.IRBuilder | t.CPtr, - op: int, - lhs: llvmlite.Value | t.CPtr, - rhs: llvmlite.Value | t.CPtr) -> llvmlite.Value | t.CPtr: - """应用增强赋值的二元运算(指针算术 + 整数运算)""" - lhs_bits: int = HandlesExpr.get_llvm_type_bits(lhs.Ty) - rhs_bits: int = HandlesExpr.get_llvm_type_bits(rhs.Ty) - - # 指针算术: ptr += int / ptr -= int - if lhs_bits == 0 and rhs_bits != 0: - if op == ast.OpKind.Add or op == ast.OpKind.Sub: - i64_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int64(pool) - ptr_as_int: llvmlite.Value | t.CPtr = llvmlite.build_ptrtoint(builder, lhs, i64_ty) - int_val: llvmlite.Value | t.CPtr = HandlesExpr.coerce_to_type(builder, rhs, i64_ty) - if ptr_as_int is None or int_val is None: - return None - if op == ast.OpKind.Add: - result: llvmlite.Value | t.CPtr = llvmlite.build_add(builder, ptr_as_int, int_val) - else: - result = llvmlite.build_sub(builder, ptr_as_int, int_val) - if result is None: - return None - return llvmlite.build_inttoptr(builder, result, lhs.Ty) - return None - - # 整数运算:类型提升 - if lhs_bits > rhs_bits and rhs_bits > 0: - rhs = HandlesExpr.coerce_to_type(builder, rhs, lhs.Ty) - elif rhs_bits > lhs_bits and lhs_bits > 0: - lhs = HandlesExpr.coerce_to_type(builder, lhs, rhs.Ty) - - if op == ast.OpKind.Add: - return llvmlite.build_add(builder, lhs, rhs) - elif op == ast.OpKind.Sub: - return llvmlite.build_sub(builder, lhs, rhs) - elif op == ast.OpKind.Mult: - return llvmlite.build_mul(builder, lhs, rhs) - elif op == ast.OpKind.Div: - return llvmlite.build_sdiv(builder, lhs, rhs) - elif op == ast.OpKind.FloorDiv: - return llvmlite.build_sdiv(builder, lhs, rhs) - elif op == ast.OpKind.Mod: - return llvmlite.build_srem(builder, lhs, rhs) - elif op == ast.OpKind.BitAnd: - return llvmlite.build_and(builder, lhs, rhs) - elif op == ast.OpKind.BitOr: - return llvmlite.build_or(builder, lhs, rhs) - elif op == ast.OpKind.BitXor: - return llvmlite.build_xor(builder, lhs, rhs) - elif op == ast.OpKind.LShift: - return llvmlite.build_shl(builder, lhs, rhs) - elif op == ast.OpKind.RShift: - return llvmlite.build_ashr(builder, lhs, rhs) - return None - - -# ============================================================ -# NewAugAssignHandle - 工厂函数 -# ============================================================ -def NewAugAssignHandle(pool: memhub.MemBuddy | t.CPtr, - trans: HT.Translator | t.CPtr) -> AugAssignHandle | t.CPtr: - h: AugAssignHandle | t.CPtr = pool.alloc(AugAssignHandle.__sizeof__()) - if h is None: - return None - string.memset(h, 0, AugAssignHandle.__sizeof__()) - h.Trans = trans - return h diff --git a/TransPyV/App/lib/core/Handles/HandlesBase.py b/TransPyV/App/lib/core/Handles/HandlesBase.py deleted file mode 100644 index 558c2de..0000000 --- a/TransPyV/App/lib/core/Handles/HandlesBase.py +++ /dev/null @@ -1,262 +0,0 @@ -import t, c -from stdint import * -import string -import viperlib -import memhub -import hashtable -import lib.core.Handles.HandlesTranslator as HT - - -# ============================================================ -# TypeKind - 类型种类枚举 -# -# 替代 TransPyC 中 CType.position frozenset 的元属性系统。 -# 每个 TypeInfo 通过 Kind 字段标记其种类,避免 Python ClassVar 反射。 -# ============================================================ -class TypeKind(t.CEnum): - Basic: t.State # 基本类型(int/char/float/double/bool 等) - Pointer: t.State # 指针(T*)— 指针层数由 TypeInfo.PtrCount 表达 - Struct: t.State # 结构体/类 - Union: t.State # 联合体 - Enum: t.State # 枚举 - Typedef: t.State # 类型别名 - Function: t.State # 函数指针 - Array: t.State # 数组 T[N] - Void: t.State # void - - -# ============================================================ -# TypeInfo - 类型信息结构 -# -# 设计原则(相对 TransPyC CTypeInfo 的简化): -# - POD 数据结构,无虚函数,无 Python 元特性(ClassVar/Generic/frozenset) -# - 通过 mbuddy 分配,调用方管理生命周期(参考 llvmlite Module 模式) -# - 通过 Kind 枚举代替 position frozenset -# - PtrCount 表达指针层数(0=非指针, 1=T*, 2=T**) -# - IsSigned 三态:-1=不适用(void/float), 0=unsigned, 1=signed -# -# 字段布局(8 字段): -# Kind : i32 类型种类(TypeKind 枚举值) -# Name : i8* 类型名(如 'int', 'CInt', 'MyStruct'),可能为 None -# Size : i32 位宽(0=void/未知;int=32, char=8, double=64, long long=64) -# Align : i32 对齐字节数(0=默认) -# IsSigned : i32 -1=N/A, 0=unsigned, 1=signed -# PtrCount : i32 指针层数 -# IsConst : i32 const 限定符(0/1) -# IsVolatile : i32 volatile 限定符(0/1) -# -# 注意:Size 使用位宽(bit width)而非字节数,与 LLVM IR 的 i{N} 和 -# TransPyC CType.Size 约定一致(CInt.Size=32, CChar.Size=8)。 -# ============================================================ -@t.NoVTable -class TypeInfo: - Kind: int - Name: str - Size: int - Align: int - IsSigned: int - PtrCount: int - IsConst: int - IsVolatile: int - - -# ============================================================ -# TypeRegistry - 类型注册表 -# -# 维护 name(str) → TypeInfo* 映射,基于 HashTable 实现 O(1) 查找。 -# 替代 TransPyC CTypeRegistry 的 _name_to_class dict。 -# 内置基本类型(int/char/void/...)由 InitBasicTypes 注册。 -# ============================================================ -class TypeRegistry: - _ht: hashtable.HashTable | t.CPtr - __mbuddy__: memhub.MemBuddy | t.CPtr - - def Register(self, ti: TypeInfo | t.CPtr) -> int: - """注册一个 TypeInfo。ti.Name 字段必须已设置。 - - Returns: - 1 表示成功,0 表示失败(ti 为 None 或 Name 为 None) - """ - if ti is None: - return 0 - if ti.Name is None: - return 0 - self._ht[ti.Name] = ti - return 1 - - def Lookup(self, name: str) -> TypeInfo | t.CPtr: - """按名称查找 TypeInfo。 - - Returns: - 找到返回 TypeInfo*,找不到返回 None - """ - if name is None: - return None - return self._ht[name] - - def Has(self, name: str) -> int: - """检查类型是否已注册。""" - if name is None: - return 0 - return name in self._ht - - -# ============================================================ -# NewTypeInfo - 工厂函数:分配并初始化一个 TypeInfo -# -# 默认值:Kind=Basic, IsSigned=-1, 其余=0/None -# ============================================================ -def NewTypeInfo(pool: memhub.MemBuddy | t.CPtr) -> TypeInfo | t.CPtr: - ptr: TypeInfo | t.CPtr = pool.alloc(TypeInfo.__sizeof__()) - if ptr is None: - return None - string.memset(ptr, 0, TypeInfo.__sizeof__()) - ptr.Kind = TypeKind.Basic - ptr.IsSigned = -1 - return ptr - - -# ============================================================ -# NewTypeRegistry - 工厂函数:创建类型注册表 -# ============================================================ -def NewTypeRegistry(pool: memhub.MemBuddy | t.CPtr) -> TypeRegistry | t.CPtr: - ptr: TypeRegistry | t.CPtr = pool.alloc(TypeRegistry.__sizeof__()) - if ptr is None: - return None - string.memset(ptr, 0, TypeRegistry.__sizeof__()) - ptr.__mbuddy__ = pool - ptr._ht = hashtable.HashTable(pool) - return ptr - - -# ============================================================ -# TypeToLLVM - 将 TypeInfo 转换为 LLVM IR 类型字符串 -# -# 规则: -# - Kind == Void 或 (Size==0 且 IsSigned==-1 且 PtrCount==0) → "void" -# - void 有 PtrCount > 0 → "i8" + PtrCount 个 "*" -# - IsSigned == -1 且 Size > 0 → 浮点: half/float/double/fp128 -# - IsSigned != -1 且 Size > 0 → 整数: i{Size} -# - 未知 → "i8*" -# -# Args: -# buf: 输出缓冲区(i8*) -# buf_size: 缓冲区容量 -# ti: TypeInfo 指针 -# -# Returns: -# 写入的字符数(不含 NUL),失败返回 -1 -# ============================================================ -def TypeToLLVM(buf: t.CChar | t.CPtr, buf_size: t.CSizeT, - ti: TypeInfo | t.CPtr) -> int: - if buf is None: - return -1 - if ti is None: - return -1 - if buf_size == 0: - return -1 - - # 判定 void - is_void: int = 0 - if ti.Kind == TypeKind.Void: - is_void = 1 - elif ti.Size == 0 and ti.IsSigned == -1 and ti.PtrCount == 0: - is_void = 1 - - # 写入 base 类型字符串到 buf - base_len: int = 0 - if is_void == 1: - if ti.PtrCount == 0: - # "void" - if buf_size < 5: - return -1 - string.strcpy(buf, "void") - base_len = 4 - else: - # void* → i8*(LLVM 中 void* 表示为 i8*) - if buf_size < 4: - return -1 - string.strcpy(buf, "i8") - base_len = 2 - elif ti.IsSigned == -1: - # 浮点 - if ti.Size == 16: - if buf_size < 5: - return -1 - string.strcpy(buf, "half") - base_len = 4 - elif ti.Size == 32: - if buf_size < 6: - return -1 - string.strcpy(buf, "float") - base_len = 5 - elif ti.Size == 64: - if buf_size < 7: - return -1 - string.strcpy(buf, "double") - base_len = 6 - elif ti.Size == 128: - if buf_size < 6: - return -1 - string.strcpy(buf, "fp128") - base_len = 5 - else: - # 未知浮点尺寸 → double 兜底 - if buf_size < 7: - return -1 - string.strcpy(buf, "double") - base_len = 6 - else: - # 整数: i{Size},用 snprintf 安全写入 - if ti.Size <= 0: - # 无效尺寸 → i8 兜底 - if buf_size < 4: - return -1 - string.strcpy(buf, "i8") - base_len = 2 - else: - viperlib.snprintf(buf, buf_size, "i%d", ti.Size) - base_len = string.strlen(buf) - - # 追加 PtrCount 个 "*" - if base_len + ti.PtrCount + 1 > buf_size: - return -1 - pos: int = base_len - for i in range(ti.PtrCount): - buf[pos] = '*' - pos += 1 - buf[pos] = 0 - return pos - - -# ============================================================ -# Mixin - 所有 Handle 的非多态基类(对应 TransPyC 的 BaseHandle) -# -# @t.NoVTable 继承:字段展平嵌入子类,无 vtable 开销(对应 C++ 非多态继承)。 -# 子类继承 Trans 字段 + 共享工具方法,编译器自动生成子类方法包装 -# (self bitcast 为父类指针后调用),子类可直接调用继承的方法。 -# -# 用法: -# @t.NoVTable -# class AssignHandle(Mixin): -# _CurrentClass: str -# def __init__(self, trans): -# self.InitMixin(trans) -# self._CurrentClass = None -# def Handle(self, node) -> int: -# rhs = self.Trans.ExprH.HandleValue(node.value) -# ... -# ============================================================ -@t.NoVTable -class Mixin: - """所有 Handle 的非多态基类:持有 Translator 回指针 + 共享委托方法""" - Trans: HT.Translator | t.CPtr - - def InitMixin(self, trans: HT.Translator | t.CPtr) -> int: - """初始化 Mixin 字段(子类 __init__ 中调用)""" - self.Trans = trans - return 0 - - -# 全局 mbuddy 指针 -_mbuddy: t.CVoid | t.CPtr diff --git a/TransPyV/App/lib/core/Handles/HandlesBody.py b/TransPyV/App/lib/core/Handles/HandlesBody.py deleted file mode 100644 index 714cadb..0000000 --- a/TransPyV/App/lib/core/Handles/HandlesBody.py +++ /dev/null @@ -1,230 +0,0 @@ -import t, c -from stdint import * -import ast -import llvmlite -import memhub -import string -import stdio -import viperlib -import lib.core.Handles.HandlesTranslator as HT -import lib.core.Handles.HandlesExpr as HandlesExpr -import lib.core.Handles.HandlesExprCall as HandlesExprCall -import lib.core.Handles.HandlesFunctions as HandlesFunctions -import lib.core.Handles.HandlesClassDef as HandlesClassDef - - -# ============================================================ -# HandlesBody - 语句分派(trans 单参模式,全方法调用) -# -# 所有语句类型通过 trans.XxxH.Handle(node) 分派到对应 Handle。 -# 对应 TransPyC BodyHandle.HandleBodyLlvm 的 isinstance 分派。 -# ============================================================ - - -# ============================================================ -# 语句翻译分派 -# ============================================================ -def translate_stmt(trans: HT.Translator | t.CPtr, - node: ast.AST | t.CPtr) -> int: - """翻译单条语句,返回新增的变量数""" - if node is None: - return 0 - k: int = node.kind() - - if k == ast.ASTKind.Expr: - return translate_expr_stmt(trans, node) - elif k == ast.ASTKind.Assign: - return trans.AssignH.Handle(node) - elif k == ast.ASTKind.AnnAssign: - return trans.AnnAssignH.Handle(node) - elif k == ast.ASTKind.FunctionDef: - # 嵌套函数定义:提升为顶层函数 + 创建闭包 - return HandlesFunctions.translate_nested_function_def(trans, node) - elif k == ast.ASTKind.Return: - return trans.ReturnH.Handle(node) - elif k == ast.ASTKind.If: - return trans.IfH.Handle(node) - elif k == ast.ASTKind.While: - return trans.WhileH.Handle(node) - elif k == ast.ASTKind.AugAssign: - return trans.AugAssignH.Handle(node) - elif k == ast.ASTKind.For: - return trans.ForH.Handle(node) - elif k == ast.ASTKind.ClassDef: - return HandlesClassDef.translate_class_def(trans, node) - elif k == ast.ASTKind.Import: - return trans.ImportsH.HandleImport(node) - elif k == ast.ASTKind.ImportFrom: - trans.ImportsH.HandleImportFromModule(node) - return trans.ImportsH.HandleImportFromNames(node) - elif k == ast.ASTKind.Global: - return translate_global(trans, node) - elif k == ast.ASTKind.Nonlocal: - return translate_nonlocal(trans, node) - elif k == ast.ASTKind.Pass: - return 0 - elif k == ast.ASTKind.Break: - return translate_break(trans) - elif k == ast.ASTKind.Continue: - return translate_continue(trans) - return 0 - - -# ============================================================ -# 翻译 Global 语句: global x, y -# -# 将 names 中的变量名加入 _global_names 集合 -# ============================================================ -def translate_global(trans: HT.Translator | t.CPtr, - node: ast.AST | t.CPtr) -> int: - """翻译 global 语句:记录 global 变量名""" - gn: ast.Global | t.CPtr = (ast.Global | t.CPtr)(node) - if gn is None: - return 0 - names: list[ast.AST | t.CPtr] | t.CPtr = gn.names - if names is None: - return 0 - n: t.CSizeT = names.__len__() - for i in range(n): - nm_node: ast.AST | t.CPtr = names.get(i) - if nm_node is not None and nm_node.kind() == ast.ASTKind.Name: - nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(nm_node) - if nm.id is not None: - HT.add_global_name(trans, nm.id) - return 0 - - -# ============================================================ -# 翻译 Nonlocal 语句: nonlocal x, y -# -# 将 names 中的变量名加入 _nonlocal_names 集合 -# ============================================================ -def translate_nonlocal(trans: HT.Translator | t.CPtr, - node: ast.AST | t.CPtr) -> int: - """翻译 nonlocal 语句:记录 nonlocal 变量名""" - nl: ast.Nonlocal | t.CPtr = (ast.Nonlocal | t.CPtr)(node) - if nl is None: - return 0 - names: list[ast.AST | t.CPtr] | t.CPtr = nl.names - if names is None: - return 0 - n: t.CSizeT = names.__len__() - for i in range(n): - nm_node: ast.AST | t.CPtr = names.get(i) - if nm_node is not None and nm_node.kind() == ast.ASTKind.Name: - nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(nm_node) - if nm.id is not None: - HT.add_nonlocal_name(trans, nm.id) - return 0 - - -# ============================================================ -# 翻译表达式语句 Expr(value=Call(...)) -# ============================================================ -def translate_expr_stmt(trans: HT.Translator | t.CPtr, - node: ast.AST | t.CPtr) -> int: - """翻译表达式语句(printf 调用等)""" - ex: ast.Expr | t.CPtr = (ast.Expr | t.CPtr)(node) - if ex is None: - return 0 - call_node: ast.AST | t.CPtr = ex.value - if call_node is None: - return 0 - ck: int = call_node.kind() - if ck != ast.ASTKind.Call: - return 0 - - cl: ast.Call | t.CPtr = (ast.Call | t.CPtr)(call_node) - func_node: ast.AST | t.CPtr = cl.func - if func_node is None: - return 0 - - func_name: str = HandlesExpr.get_func_name(func_node) - if func_name is None: - return 0 - - # printf / print 走特殊路径(print 映射到 printf) - if string.strcmp(func_name, "printf") == 0 or string.strcmp(func_name, "print") == 0: - trans.ExprCallH.HandlePrintfCall(cl) - else: - # 通用函数调用(返回值丢弃) - trans.ExprCallH.HandleCall(call_node) - return 0 - - -# ============================================================ -# 预扫描:为局部变量提前创建 alloca -# ============================================================ -def pre_scan_allocas(trans: HT.Translator | t.CPtr, - node: ast.AST | t.CPtr) -> int: - """预扫描语句中的 AnnAssign,提前创建 alloca - - 返回新增的变量数 - """ - if node is None: - return 0 - return trans.AnnAssignH.PreScan(node) - - -# ============================================================ -# 翻译 break 语句 -# ============================================================ -def translate_break(trans: HT.Translator | t.CPtr) -> int: - """翻译 break 语句:跳转到循环 end 块""" - builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder - func: llvmlite.Function | t.CPtr = trans._cur_func - pool: memhub.MemBuddy | t.CPtr = trans.Pool - - if builder is None or func is None: - return 0 - - # 发射 br 到 break 目标 - if trans._break_bb is not None: - if llvmlite.builder_cur_block_is_terminated(builder) == 0: - llvmlite.build_br(builder, trans._break_bb) - - # 创建死代码 BB,用于后续语句(break 后面的代码不可达) - cnt: int = trans._label_counter - trans._label_counter = cnt + 1 - name_buf: t.CChar | t.CPtr = pool.alloc(32) - viperlib.snprintf(name_buf, 32, "dead.%d", cnt) - dead_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf) - llvmlite.position_at_end(builder, dead_bb) - return 0 - - -# ============================================================ -# 翻译 continue 语句 -# ============================================================ -def translate_continue(trans: HT.Translator | t.CPtr) -> int: - """翻译 continue 语句:跳转到循环 cond/incr 块""" - builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder - func: llvmlite.Function | t.CPtr = trans._cur_func - pool: memhub.MemBuddy | t.CPtr = trans.Pool - - if builder is None or func is None: - return 0 - - # 发射 br 到 continue 目标 - if trans._continue_bb is not None: - if llvmlite.builder_cur_block_is_terminated(builder) == 0: - llvmlite.build_br(builder, trans._continue_bb) - - # 创建死代码 BB,用于后续语句 - cnt: int = trans._label_counter - trans._label_counter = cnt + 1 - name_buf: t.CChar | t.CPtr = pool.alloc(32) - viperlib.snprintf(name_buf, 32, "dead.%d", cnt) - dead_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf) - llvmlite.position_at_end(builder, dead_bb) - return 0 - - -# ============================================================ -# 获取语句类型名(调试用) -# ============================================================ -def get_stmt_kind_name(node: ast.AST | t.CPtr) -> str: - """获取语句类型名""" - if node is None: - return None - return node.type_name() diff --git a/TransPyV/App/lib/core/Handles/HandlesClassDef.py b/TransPyV/App/lib/core/Handles/HandlesClassDef.py deleted file mode 100644 index 8e41ab0..0000000 --- a/TransPyV/App/lib/core/Handles/HandlesClassDef.py +++ /dev/null @@ -1,3412 +0,0 @@ -import t, c -from stdint import * -import ast -import llvmlite -import memhub -import string -import stdio -import viperlib -import lib.core.VLogger as VLogger -import lib.core.Handles.HandlesTranslator as HT -import lib.core.Handles.HandlesType as HandlesType -import lib.core.Handles.HandlesStruct as HandlesStruct -import lib.core.Handles.HandlesVar as HandlesVar -import lib.core.Handles.HandlesEnum as HandlesEnum - - -# 枚举成员临时数组最大数量(本地常量) -ENUM_MEMBER_MAX_LOCAL: t.CDefine = 64 - -# REnum 变体表容量上限(本地常量) -RENUM_CLASS_MAX: t.CDefine = 64 - -# 作用域类型常量(本地副本,避免旧编译器跨模块 CDefine 查找 bug) -SCOPE_FUNCTION: t.CDefine = 1 -RENUM_VARIANT_PER_CLASS: t.CDefine = 32 -RENUM_FIELD_PER_VARIANT: t.CDefine = 16 - - -# ============================================================ -# HandlesClassDef - class 定义处理 -# -# 解析 class 定义,创建 LLVM StructType 并注册字段信息 -# -# 纯内存结构体(无方法)的 class 定义: -# class Point: -# x: t.CInt -# y: t.CInt -# -# 生成 LLVM 类型: { i32, i32 } -# 注册字段: x→index 0, y→index 1 -# ============================================================ - - -# ============================================================ -# _is_cenum_base — 检查 base 节点是否为 t.CEnum -# -# 支持 Name(id='CEnum') 和 Attribute(value=Name('t'), attr='CEnum') -# ============================================================ -def _is_cenum_base(base_node: ast.AST | t.CPtr) -> int: - """检查 base 节点是否为 t.CEnum,返回 1=是 / 0=否""" - if base_node is None: - return 0 - k: int = base_node.kind() - # Name('CEnum') 形式(from t import CEnum) - if k == ast.ASTKind.Name: - nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(base_node) - if nm.id is not None and string.strcmp(nm.id, "CEnum") == 0: - return 1 - return 0 - # Attribute(t.CEnum) 形式 - if k == ast.ASTKind.Attribute: - at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(base_node) - if at.attr is not None and string.strcmp(at.attr, "CEnum") == 0: - return 1 - return 0 - return 0 - - -# ============================================================ -# _is_enum_class — 检查 ClassDef 是否继承自 t.CEnum -# ============================================================ -def _is_enum_class(cd: ast.ClassDef | t.CPtr) -> int: - """检查 ClassDef 是否继承自 t.CEnum,返回 1=是 / 0=否""" - if cd is None or cd.bases is None: - return 0 - bases: list[ast.AST | t.CPtr] | t.CPtr = cd.bases - bn: t.CSizeT = bases.__len__() - if bn == 0: - return 0 - for bi in range(bn): - base_node: ast.AST | t.CPtr = bases.get(bi) - if base_node is None: - continue - if _is_cenum_base(base_node) == 1: - return 1 - return 0 - - -# ============================================================ -# _is_cunion_base — 检查 base 节点是否为 t.CUnion -# -# 支持 Name(id='CUnion') 和 Attribute(value=Name('t'), attr='CUnion') -# ============================================================ -def _is_cunion_base(base_node: ast.AST | t.CPtr) -> int: - """检查 base 节点是否为 t.CUnion,返回 1=是 / 0=否""" - if base_node is None: - return 0 - k: int = base_node.kind() - # Name('CUnion') 形式(from t import CUnion) - if k == ast.ASTKind.Name: - nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(base_node) - if nm.id is not None and string.strcmp(nm.id, "CUnion") == 0: - return 1 - return 0 - # Attribute(t.CUnion) 形式 - if k == ast.ASTKind.Attribute: - at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(base_node) - if at.attr is not None and string.strcmp(at.attr, "CUnion") == 0: - return 1 - return 0 - return 0 - - -# ============================================================ -# _is_union_class — 检查 ClassDef 是否继承自 t.CUnion -# ============================================================ -def _is_union_class(cd: ast.ClassDef | t.CPtr) -> int: - """检查 ClassDef 是否继承自 t.CUnion,返回 1=是 / 0=否""" - if cd is None or cd.bases is None: - return 0 - bases: list[ast.AST | t.CPtr] | t.CPtr = cd.bases - bn: t.CSizeT = bases.__len__() - if bn == 0: - return 0 - for bi in range(bn): - base_node: ast.AST | t.CPtr = bases.get(bi) - if base_node is None: - continue - if _is_cunion_base(base_node) == 1: - return 1 - return 0 - - -# ============================================================ -# _is_crenum_base — 检查 base 节点是否为 t.REnum -# -# 支持 Name(id='REnum') 和 Attribute(value=Name('t'), attr='REnum') -# ============================================================ -def _is_crenum_base(base_node: ast.AST | t.CPtr) -> int: - """检查 base 节点是否为 t.REnum,返回 1=是 / 0=否""" - if base_node is None: - return 0 - k: int = base_node.kind() - # Name('REnum') 形式(from t import REnum) - if k == ast.ASTKind.Name: - nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(base_node) - if nm.id is not None and string.strcmp(nm.id, "REnum") == 0: - return 1 - return 0 - # Attribute(t.REnum) 形式 - if k == ast.ASTKind.Attribute: - at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(base_node) - if at.attr is not None and string.strcmp(at.attr, "REnum") == 0: - return 1 - return 0 - return 0 - - -# ============================================================ -# _is_renum_class — 检查 ClassDef 是否继承自 t.REnum -# ============================================================ -def _is_renum_class(cd: ast.ClassDef | t.CPtr) -> int: - """检查 ClassDef 是否继承自 t.REnum,返回 1=是 / 0=否""" - if cd is None or cd.bases is None: - return 0 - bases: list[ast.AST | t.CPtr] | t.CPtr = cd.bases - bn: t.CSizeT = bases.__len__() - if bn == 0: - return 0 - for bi in range(bn): - base_node: ast.AST | t.CPtr = bases.get(bi) - if base_node is None: - continue - if _is_crenum_base(base_node) == 1: - return 1 - return 0 - - -# ============================================================ -# VTable 装饰器检测和继承关系判断 -# ============================================================ - -# 标记基类集合(非真实父类,仅作为类型标记) -_MARKER_BASES: t.CDefine = 8 -# 使用字符串比较代替集合,标记基类列表 -# Object, CVTable, Exception, CEnum, Enum, CStruct, CUnion, REnum - - -# ============================================================ -# _has_decorator — 检查 ClassDef/FunctionDef 的 decorator_list 中是否有指定装饰器 -# -# 支持 @t.Name 和 @Name 两种形式 -# 返回 1=有 / 0=无 -# ============================================================ -def _has_decorator(decorator_list: list[ast.AST | t.CPtr] | t.CPtr, - deco_name: str) -> int: - """检查 decorator_list 中是否有指定装饰器名""" - if decorator_list is None: - return 0 - dn: t.CSizeT = decorator_list.__len__() - if dn == 0: - return 0 - for di in range(dn): - deco: ast.AST | t.CPtr = decorator_list.get(di) - if deco is None: - continue - k: int = deco.kind() - # @t.NoVTable 形式(Attribute) - if k == ast.ASTKind.Attribute: - at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(deco) - if at.attr is not None and string.strcmp(at.attr, deco_name) == 0: - # 检查 value 是 Name('t') - if at.value is not None and at.value.kind() == ast.ASTKind.Name: - vn: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value) - if vn.id is not None and string.strcmp(vn.id, "t") == 0: - return 1 - return 0 - # @NoVTable 形式(Name,from t import NoVTable) - if k == ast.ASTKind.Name: - nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(deco) - if nm.id is not None and string.strcmp(nm.id, deco_name) == 0: - return 1 - return 0 - - -# ============================================================ -# _is_marker_base — 检查基类名是否为标记基类(非真实父类) -# -# 标记基类: Object, CVTable, Exception, CEnum, Enum, CStruct, CUnion, REnum -# ============================================================ -def _is_marker_base(base_name: str) -> int: - """检查基类名是否为标记基类,返回 1=是 / 0=否""" - if base_name is None: - return 0 - if string.strcmp(base_name, "Object") == 0: - return 1 - if string.strcmp(base_name, "CVTable") == 0: - return 1 - if string.strcmp(base_name, "Exception") == 0: - return 1 - if string.strcmp(base_name, "CEnum") == 0: - return 1 - if string.strcmp(base_name, "Enum") == 0: - return 1 - if string.strcmp(base_name, "CStruct") == 0: - return 1 - if string.strcmp(base_name, "CUnion") == 0: - return 1 - if string.strcmp(base_name, "REnum") == 0: - return 1 - return 0 - - -# ============================================================ -# _get_base_name — 从 base AST 节点提取基类名 -# -# 支持 Name(id), Attribute(attr), Subscript(value, slice) -# 对于 Subscript(如 GSListNode[Value]),需要 pool 拼接特化名 "GSListNode[Value]" -# ============================================================ -def _get_base_name(base_node: ast.AST | t.CPtr, - pool: memhub.MemBuddy | t.CPtr = None) -> str: - """从 base AST 节点提取基类名,返回 None=失败 - - 对于 Subscript 节点,需要 pool 分配内存拼接特化名; - pool=None 时降级返回基类名(不含类型实参) - """ - if base_node is None: - return None - k: int = base_node.kind() - # Name(id) 形式 - if k == ast.ASTKind.Name: - nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(base_node) - return nm.id - # Attribute(attr) 形式 - if k == ast.ASTKind.Attribute: - at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(base_node) - return at.attr - # Subscript(value, slice) 形式 — 如 GSListNode[Value] - if k == ast.ASTKind.Subscript: - sub: ast.Subscript | t.CPtr = (ast.Subscript | t.CPtr)(base_node) - if sub is None or sub.value is None or sub.slice is None: - return None - # 提取基类名(如 "GSListNode") - base_nm: str = _get_base_name(sub.value, pool) - if base_nm is None: - return None - # 提取类型实参名(如 "Value") - slice_k: int = sub.slice.kind() - arg_nm: str = None - if slice_k == ast.ASTKind.Name: - sl_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(sub.slice) - arg_nm = sl_nm.id - # 如果无法提取类型实参,返回基类名(降级) - if arg_nm is None: - return base_nm - # 无 pool 时返回基类名(降级,无法拼接特化名) - if pool is None: - return base_nm - # 拼接特化名 "GSListNode[Value]" - base_len: t.CSizeT = string.strlen(base_nm) - arg_len: t.CSizeT = string.strlen(arg_nm) - total_len: t.CSizeT = base_len + arg_len + 3 # "[" + arg + "]" + NUL - mangled: str = pool.alloc(total_len) - if mangled is None: - return base_nm # 降级 - mangled[0] = '\0' - string.strcat(mangled, base_nm) - string.strcat(mangled, "[") - string.strcat(mangled, arg_nm) - string.strcat(mangled, "]") - return mangled - return None - - -# ============================================================ -# _get_parent_class — 获取 ClassDef 的真实父类名(非标记基类) -# -# 遍历 bases,返回第一个非标记基类的名字,None=无真实父类 -# 支持 Name, Attribute, Subscript 三种 base 节点 -# 对于 Subscript(如 GSListNode[Value]),需要 trans.Pool 拼接特化名 -# ============================================================ -def _get_parent_class(cd: ast.ClassDef | t.CPtr, - trans: HT.Translator | t.CPtr = None) -> str: - """获取 ClassDef 的真实父类名,返回 None=无真实父类""" - if cd is None or cd.bases is None: - return None - pool: memhub.MemBuddy | t.CPtr = None - if trans is not None: - pool = trans.Pool - bases: list[ast.AST | t.CPtr] | t.CPtr = cd.bases - bn: t.CSizeT = bases.__len__() - if bn == 0: - return None - for bi in range(bn): - base_node: ast.AST | t.CPtr = bases.get(bi) - if base_node is None: - continue - bname: str = _get_base_name(base_node, pool) - if bname is not None and _is_marker_base(bname) == 0: - return bname - return None - - -# ============================================================ -# _trigger_base_specialization — 触发 base 中 Subscript 的泛型特化 -# -# 对于 class Value(GSListNode[Value]),GSListNode[Value] 是 Subscript 节点。 -# 在 translate_class_def 处理 Value 之前,需要先特化 GSListNode[Value], -# 否则 find_struct_by_module("GSListNode[Value]") 返回 None,父类字段不被继承。 -# -# 遍历 cd.bases,如果 base 是 Subscript,提取 class_name 和 type_args, -# 调用 _specialize_generic_class 触发特化。 -# ============================================================ -def _trigger_base_specialization(trans: HT.Translator | t.CPtr, - cd: ast.ClassDef | t.CPtr): - """触发 base 中 Subscript 的泛型特化(如 GSListNode[Value])""" - if trans is None or cd is None or cd.bases is None: - return - pool: memhub.MemBuddy | t.CPtr = trans.Pool - bases: list[ast.AST | t.CPtr] | t.CPtr = cd.bases - bn: t.CSizeT = bases.__len__() - if bn == 0: - return - for bi in range(bn): - base_node: ast.AST | t.CPtr = bases.get(bi) - if base_node is None: - continue - bk: int = base_node.kind() - if bk != ast.ASTKind.Subscript: - continue - sub: ast.Subscript | t.CPtr = (ast.Subscript | t.CPtr)(base_node) - if sub is None or sub.value is None or sub.slice is None: - continue - # 提取泛型类名(如 "GSListNode") - gen_class_name: str = _get_base_name(sub.value, pool) - if gen_class_name is None: - continue - # 跳过标记基类 - if _is_marker_base(gen_class_name) == 1: - continue - # 提取类型实参名(如 "Value") - slice_k: int = sub.slice.kind() - arg_nm: str = None - if slice_k == ast.ASTKind.Name: - sl_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(sub.slice) - arg_nm = sl_nm.id - if arg_nm is None: - continue - # 构建 type_args 列表 - type_args: list[str] | t.CPtr = list[str](pool, 1) - if type_args is None: - continue - type_args.append(arg_nm) - # 触发特化(_specialize_generic_class 有缓存,重复调用安全) - _specialize_generic_class(trans, gen_class_name, type_args) - - -# ============================================================ -# _has_any_func_cvtable — 检查类中是否有任何函数标记了 @t.CVTable -# -# 用于类级别未启用虚表时,检查函数级 @t.CVTable 是否触发虚表。 -# 跳过 __init__ 和 __before_init__(构造函数不进入虚表)。 -# ============================================================ -def _has_any_func_cvtable(cd: ast.ClassDef | t.CPtr) -> int: - """检查类中是否有任何函数标记了 @t.CVTable,返回 1=有 / 0=无""" - if cd is None or cd.children is None: - return 0 - children: list[ast.AST | t.CPtr] | t.CPtr = cd.children - cn: t.CSizeT = children.__len__() - for ci in range(cn): - stmt: ast.AST | t.CPtr = children.get(ci) - if stmt is None: - continue - if stmt.kind() != ast.ASTKind.FunctionDef: - continue - fd: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(stmt) - if fd is None or fd.name is None: - continue - # 跳过构造函数 - if string.strcmp(fd.name, "__init__") == 0: - continue - if string.strcmp(fd.name, "__before_init__") == 0: - continue - if string.strcmp(fd.name, "__new__") == 0: - continue - if fd.decorator_list is not None: - if _has_decorator(fd.decorator_list, "CVTable") == 1: - return 1 - return 0 - - -# ============================================================ -# _should_method_be_virtual — 判断方法是否应该进入虚表 -# -# 规则(优先级从高到低): -# 1. 函数有 @t.NoVTable → 排除(返回 0) -# 2. 函数有 @t.CVTable → 包含(返回 1) -# 3. 类有 @t.CVTable → 包含(返回 1) -# 4. 有继承关系(父类非 NoVTable)→ 包含(返回 1) -# 5. 默认 → 排除(返回 0) -# ============================================================ -def _should_method_be_virtual(cd: ast.ClassDef | t.CPtr, - fd: ast.FunctionDef | t.CPtr, - trans: HT.Translator | t.CPtr = None) -> int: - """判断方法是否应该进入虚表,返回 1=包含 / 0=排除""" - if fd is None: - return 0 - # 1. 检查函数级 @t.NoVTable(最高优先级,排除) - if fd.decorator_list is not None: - if _has_decorator(fd.decorator_list, "NoVTable") == 1: - return 0 - # 2. 检查函数级 @t.CVTable(明确包含) - if _has_decorator(fd.decorator_list, "CVTable") == 1: - return 1 - - # 3. 检查类级别 @t.CVTable - if cd is not None and cd.decorator_list is not None: - if _has_decorator(cd.decorator_list, "CVTable") == 1: - return 1 - - # 4. 检查继承关系 - parent_name: str = _get_parent_class(cd, trans) - if parent_name is not None: - # 用 SHA1 感知查找父类,规避跨模块同名找错 - is_nvt: int = 0 - if trans is not None: - p_entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_module( - parent_name, trans.ModuleSha1) - if p_entry is not None: - is_nvt = p_entry.IsNoVTable - else: - is_nvt = HandlesStruct.is_novtable_by_name(parent_name) - if is_nvt != 1: - return 1 # 有继承且父类非 NoVTable - - # 5. 默认排除 - return 0 - - -# ============================================================ -# _detect_vtable_status — 检测类是否应该启用虚表 -# -# 规则: -# 1. @t.CVTable → 有虚表 -# 2. 有真实父类且非 NoVTable → 有虚表(自动启用) -# 3. @t.NoVTable → 检查函数级 @t.CVTable,有则启用 -# 4. 默认 → 检查函数级 @t.CVTable,有则启用 -# -# 返回: 1=有虚表 / 0=无虚表 -# ============================================================ -def _detect_vtable_status(cd: ast.ClassDef | t.CPtr, - trans: HT.Translator | t.CPtr = None) -> int: - """检测类是否应该启用虚表""" - if cd is None: - return 0 - - # 检查类装饰器 - if cd.decorator_list is not None: - # @t.CVTable 优先级最高,直接启用 - if _has_decorator(cd.decorator_list, "CVTable") == 1: - return 1 - # @t.NoVTable:类级别禁用,但检查函数级 @t.CVTable - if _has_decorator(cd.decorator_list, "NoVTable") == 1: - return _has_any_func_cvtable(cd) - - # 检查是否有真实父类(继承自动启用 CVTable) - parent_name: str = _get_parent_class(cd, trans) - if parent_name is not None: - # 用 SHA1 感知查找父类,规避跨模块同名找错 - is_nvt: int = 0 - if trans is not None: - p_entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_module( - parent_name, trans.ModuleSha1) - if p_entry is not None: - is_nvt = p_entry.IsNoVTable - else: - is_nvt = HandlesStruct.is_novtable_by_name(parent_name) - if is_nvt == 1: - # 父类是 NoVTable,检查函数级 @t.CVTable - return _has_any_func_cvtable(cd) - return 1 # 有父类且非 NoVTable,自动启用虚表 - - # 默认(无装饰器无继承),检查函数级 @t.CVTable - return _has_any_func_cvtable(cd) - - -# ============================================================ -# _resolve_enum_member_type — 解析枚举成员的类型 -# -# - t.State → 默认 i32 -# - int / t.CInt8T / t.CInt16T / t.CInt32T / t.CInt64T 等 → 对应整数类型 -# - 联合注解(t.State | t.CInt8T)递归查找实际类型 -# ============================================================ -def _resolve_enum_member_type(pool: memhub.MemBuddy | t.CPtr, - ann_node: ast.AST | t.CPtr, - imported_modules: str, - from_imports: str) -> llvmlite.LLVMType | t.CPtr: - """解析枚举成员的类型注解为 LLVM 整数类型""" - if ann_node is None: - return llvmlite.Int32(pool) - - k: int = ann_node.kind() - - # Attribute 节点: t.State / int / t.CInt8T 等 - if k == ast.ASTKind.Attribute: - at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(ann_node) - if at.attr is None: - return llvmlite.Int32(pool) - # t.State → 默认 i32 - if string.strcmp(at.attr, "State") == 0: - return llvmlite.Int32(pool) - # 其他 t.CXxx 类型 - ty: llvmlite.LLVMType | t.CPtr = HandlesType.map_t_type(pool, at.attr) - if ty is not None: - return ty - return llvmlite.Int32(pool) - - # Name 节点: from-import 形式(State / CInt) - if k == ast.ASTKind.Name: - nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(ann_node) - if nm.id is None: - return llvmlite.Int32(pool) - if string.strcmp(nm.id, "State") == 0: - return llvmlite.Int32(pool) - ty2: llvmlite.LLVMType | t.CPtr = HandlesType.map_t_type(pool, nm.id) - if ty2 is not None: - return ty2 - return llvmlite.Int32(pool) - - # BinOp 节点: t.State | t.CInt8T(递归查找实际类型) - if k == ast.ASTKind.BinOp: - bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(ann_node) - if bop.op == ast.OpKind.BitOr: - left_ty: llvmlite.LLVMType | t.CPtr = _resolve_enum_member_type( - pool, bop.left, imported_modules, from_imports) - # 跳过 t.State(i32 默认),优先返回具体类型 - left_bits: int = HandlesType.get_llvm_type_bits(left_ty) - if left_bits != 0 and not _is_state_annotation(bop.left): - return left_ty - right_ty: llvmlite.LLVMType | t.CPtr = _resolve_enum_member_type( - pool, bop.right, imported_modules, from_imports) - if right_ty is not None and not _is_state_annotation(bop.right): - return right_ty - # 两边都是 State 或无法确定,返回较宽的 - right_bits: int = HandlesType.get_llvm_type_bits(right_ty) - if left_bits >= right_bits: - return left_ty - return right_ty - return llvmlite.Int32(pool) - - return llvmlite.Int32(pool) - - -# ============================================================ -# _is_state_annotation — 检查注解节点是否为 t.State -# ============================================================ -def _is_state_annotation(node: ast.AST | t.CPtr) -> int: - """检查注解节点是否为 t.State,返回 1=是 / 0=否""" - if node is None: - return 0 - k: int = node.kind() - if k == ast.ASTKind.Attribute: - at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(node) - if at.attr is not None and string.strcmp(at.attr, "State") == 0: - return 1 - return 0 - if k == ast.ASTKind.Name: - nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(node) - if nm.id is not None and string.strcmp(nm.id, "State") == 0: - return 1 - return 0 - return 0 - - -# ============================================================ -# _extract_int_value — 从 AST 节点提取整数值 -# -# 支持 Constant(int) 和 UnaryOp(USub, Constant(int)) -# ============================================================ -def _extract_int_value(node: ast.AST | t.CPtr) -> t.CInt64T: - """从 AST 节点提取整数值,失败返回 0""" - if node is None: - return 0 - k: int = node.kind() - if k == ast.ASTKind.Constant: - cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(node) - if cn.const_kind == ast.CONST_INT: - return cn.int_val - return 0 - if k == ast.ASTKind.UnaryOp: - uo: ast.UnaryOp | t.CPtr = (ast.UnaryOp | t.CPtr)(node) - if uo.op == ast.OpKind.USub: - inner: t.CInt64T = _extract_int_value(uo.operand) - return -inner - return 0 - return 0 - - -# ============================================================ -# _translate_enum_def — 翻译枚举类定义 -# -# 遍历 class body 中的 AnnAssign,收集成员名、类型、值 -# 自动赋值:无值时从上一值+1递增(首值默认 0) -# 基准类型:所有成员类型中 Bits 最大的(t.State 视为 i32) -# ============================================================ -def _translate_enum_def(trans: HT.Translator | t.CPtr, - cd: ast.ClassDef | t.CPtr) -> int: - """翻译枚举类定义,返回 0""" - if cd is None or cd.name is None or trans is None: - return 0 - - pool: memhub.MemBuddy | t.CPtr = trans.Pool - class_name: str = cd.name - - # 已注册则跳过 - if HandlesEnum.is_enum_class(class_name) == 1: - return 0 - - children: list[ast.AST | t.CPtr] | t.CPtr = cd.children - if children is None: - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "%s has no body", class_name) - VLogger.warning(fb, "ENUM") - return 0 - - cn: t.CSizeT = children.__len__() - - # 临时数组存储成员信息 - member_names_buf: t.CSizeT | t.CPtr = pool.alloc(8 * ENUM_MEMBER_MAX_LOCAL) - member_types_buf: t.CSizeT | t.CPtr = pool.alloc(8 * ENUM_MEMBER_MAX_LOCAL) - member_values_buf: t.CInt64T | t.CPtr = pool.alloc(8 * ENUM_MEMBER_MAX_LOCAL) - if member_names_buf is None or member_types_buf is None or member_values_buf is None: - return 0 - string.memset(member_names_buf, 0, 8 * ENUM_MEMBER_MAX_LOCAL) - string.memset(member_types_buf, 0, 8 * ENUM_MEMBER_MAX_LOCAL) - string.memset(member_values_buf, 0, 8 * ENUM_MEMBER_MAX_LOCAL) - - member_count: int = 0 - next_val: t.CInt64T = 0 - - for ci in range(cn): - stmt: ast.AST | t.CPtr = children.get(ci) - if stmt is None: - continue - sk: int = stmt.kind() - - if sk == ast.ASTKind.AnnAssign: - aa: ast.AnnAssign | t.CPtr = (ast.AnnAssign | t.CPtr)(stmt) - if aa is None or aa.target is None: - continue - - # 获取成员名 - if aa.target.kind() != ast.ASTKind.Name: - continue - tgt: ast.Name | t.CPtr = (ast.Name | t.CPtr)(aa.target) - if tgt.id is None: - continue - - # 解析成员类型 - member_ty: llvmlite.LLVMType | t.CPtr = _resolve_enum_member_type( - pool, aa.annotation, trans._imported_modules, trans._from_imports) - - # 解析成员值 - has_value: int = 0 - cur_val: t.CInt64T = 0 - if aa.value is not None: - cur_val = _extract_int_value(aa.value) - has_value = 1 - else: - cur_val = next_val - - # 下一个自动值 - next_val = cur_val + 1 - - # 存储 - if member_count < ENUM_MEMBER_MAX_LOCAL: - member_names_buf[member_count] = t.CSizeT(tgt.id) - member_types_buf[member_count] = t.CSizeT(member_ty) - member_values_buf[member_count] = cur_val - member_count += 1 - - elif sk == ast.ASTKind.Assign: - # 处理 Assign 形式的枚举成员: DEBUG = 0, INFO = 1 等 - # CEnum 子类中无类型注释的赋值也视为枚举成员 - ag: ast.Assign | t.CPtr = (ast.Assign | t.CPtr)(stmt) - if ag is None or ag.targets is None: - continue - tgts: list[ast.AST | t.CPtr] | t.CPtr = ag.targets - tn: t.CSizeT = tgts.__len__() - if tn == 0: - continue - # 取第一个 target 作为成员名 - t0: ast.AST | t.CPtr = tgts.get(0) - if t0 is None or t0.kind() != ast.ASTKind.Name: - continue - tgt_a: ast.Name | t.CPtr = (ast.Name | t.CPtr)(t0) - if tgt_a.id is None: - continue - - # Assign 无类型注释,默认使用 i32 - member_ty_a: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool) - - # 解析成员值 - cur_val_a: t.CInt64T = 0 - if ag.value is not None: - cur_val_a = _extract_int_value(ag.value) - else: - cur_val_a = next_val - - # 下一个自动值 - next_val = cur_val_a + 1 - - # 存储 - if member_count < ENUM_MEMBER_MAX_LOCAL: - member_names_buf[member_count] = t.CSizeT(tgt_a.id) - member_types_buf[member_count] = t.CSizeT(member_ty_a) - member_values_buf[member_count] = cur_val_a - member_count += 1 - - if member_count == 0: - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "%s has no members", class_name) - VLogger.warning(fb, "ENUM") - return 0 - - # 确定基准类型:所有成员类型中 Bits 最大的 - base_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool) - max_bits: int = 0 - for mi in range(member_count): - ty_addr: t.CSizeT = member_types_buf[mi] - if ty_addr == 0: - continue - mty: llvmlite.LLVMType | t.CPtr = (llvmlite.LLVMType | t.CPtr)( - t.CVoid(ty_addr, t.CPtr)) - bits: int = HandlesType.get_llvm_type_bits(mty) - if bits > max_bits: - max_bits = bits - base_ty = mty - - # 注册枚举 - entry: HandlesEnum.EnumEntry | t.CPtr = HandlesEnum.register_enum( - pool, class_name, base_ty) - if entry is None: - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "failed to register %s", class_name) - VLogger.error(fb, "ENUM") - return 0 - - # 添加成员 - for mi in range(member_count): - fname_addr: t.CSizeT = member_names_buf[mi] - if fname_addr == 0: - continue - mname: str = (str | t.CPtr)(t.CVoid(fname_addr, t.CPtr)) - fty_addr2: t.CSizeT = member_types_buf[mi] - if fty_addr2 == 0: - continue - mty2: llvmlite.LLVMType | t.CPtr = (llvmlite.LLVMType | t.CPtr)( - t.CVoid(fty_addr2, t.CPtr)) - mval: t.CInt64T = member_values_buf[mi] - if mname is not None and mty2 is not None: - HandlesEnum.add_enum_member(pool, entry, mname, mval, mty2) - - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "registered %s with %d members, base_bits=%d", - class_name, member_count, max_bits) - VLogger.info(fb, "ENUM") - return 0 - - -# ============================================================ -# _get_type_size — 计算 LLVM 类型的字节大小 -# -# 用于联合体确定最大字段大小 -# ============================================================ -def _get_type_size(ty: llvmlite.LLVMType | t.CPtr) -> int: - """计算 LLVM 类型的字节大小(含对齐 padding)""" - if ty is None: - return 0 - match ty: - case llvmlite.LLVMType.Int(bits): - return (bits + 7) // 8 - case llvmlite.LLVMType.Float(bits): - return bits // 8 - case llvmlite.LLVMType.Ptr(pointee): - return 8 - case llvmlite.LLVMType.Array(elem_ty, count): - return _get_type_size(elem_ty) * count - case llvmlite.LLVMType.Struct(fields, fcount, name): - # 计算结构体大小,考虑字段对齐 padding - # 规则: 每个字段的对齐 = 该字段类型的自然对齐 - # 指针/i64 → 8, i32 → 4, i16 → 2, i8 → 1 - # 结构体总大小需对齐到最大字段对齐的倍数 - total: int = 0 - max_align: int = 1 - cur: llvmlite.ParamNode | t.CPtr = fields - i: int = 0 - while cur is not None and i < fcount: - if cur.Ty is not None: - fty: llvmlite.LLVMType | t.CPtr = (llvmlite.LLVMType | t.CPtr)(cur.Ty) - fsize: int = _get_type_size(fty) - falign: int = _get_type_align(fty) - # 对齐当前偏移到字段对齐边界 - if falign > 0: - rem: int = total % falign - if rem != 0: - total += falign - rem - total += fsize - if falign > max_align: - max_align = falign - cur = cur.Next - i += 1 - # 结构体总大小对齐到最大字段对齐的倍数 - rem2: int = total % max_align - if rem2 != 0: - total += max_align - rem2 - return total - case _: - return 8 - - -def _get_type_align(ty: llvmlite.LLVMType | t.CPtr) -> int: - """返回类型的自然对齐(字节)""" - if ty is None: - return 1 - match ty: - case llvmlite.LLVMType.Int(bits): - if bits <= 8: - return 1 - elif bits <= 16: - return 2 - elif bits <= 32: - return 4 - else: - return 8 - case llvmlite.LLVMType.Float(bits): - if bits <= 32: - return 4 - else: - return 8 - case llvmlite.LLVMType.Ptr(pointee): - return 8 - case llvmlite.LLVMType.Array(elem_ty, count): - return _get_type_align(elem_ty) - case llvmlite.LLVMType.Struct(fields, fcount, name): - # 结构体的对齐 = 最大字段对齐 - max_align: int = 1 - cur: llvmlite.ParamNode | t.CPtr = fields - i: int = 0 - while cur is not None and i < fcount: - if cur.Ty is not None: - fty: llvmlite.LLVMType | t.CPtr = (llvmlite.LLVMType | t.CPtr)(cur.Ty) - fa: int = _get_type_align(fty) - if fa > max_align: - max_align = fa - cur = cur.Next - i += 1 - return max_align - case _: - return 8 - - -# ============================================================ -# _translate_union_def — 翻译联合体定义 -# -# 联合体语法: -# class MyUnion(t.CUnion): -# a: t.CInt -# b: t.CFloat -# c: t.CInt64T -# -# 实现方式: -# - 收集所有字段类型 -# - 计算最大字段字节大小 max_size -# - LLVM 类型 = Struct([Array(Int8, max_size)]) # { [N x i8] } -# - 注册到 HandlesStruct 并标记 IsUnion=1 -# - 字段访问通过 bitcast 实现(HandlesExpr 中处理) -# ============================================================ -def _translate_union_def(trans: HT.Translator | t.CPtr, - cd: ast.ClassDef | t.CPtr) -> int: - """翻译联合体定义,返回 0""" - if cd is None or cd.name is None or trans is None: - return 0 - - pool: memhub.MemBuddy | t.CPtr = trans.Pool - class_name: str = cd.name - - # 命名空间隔离:标记为当前文件可见(必须在 existing 检查之前) - HandlesStruct.add_visible_struct(pool, class_name) - - # 检查是否已注册(用 SHA1 区分跨模块同名类) - existing: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_module( - class_name, trans.ModuleSha1) - if existing is not None: - # Phase B: 将已存在的命名结构体注册到当前模块 - if existing.Ty is not None: - llvmlite.module_add_named_type(trans.Module, pool, existing.Ty) - # SHA1 已在 register_struct 时设置,无需再补 - return 0 - - children: list[ast.AST | t.CPtr] | t.CPtr = cd.children - if children is None: - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "%s has no body", class_name) - VLogger.warning(fb, "UNION") - return 0 - - cn: t.CSizeT = children.__len__() - - # 临时数组存储字段信息 - field_names_buf: t.CSizeT | t.CPtr = pool.alloc(8 * 48) - field_types_buf: t.CSizeT | t.CPtr = pool.alloc(8 * 48) - if field_names_buf is None or field_types_buf is None: - return 0 - string.memset(field_names_buf, 0, 8 * 48) - string.memset(field_types_buf, 0, 8 * 48) - - field_count: int = 0 - max_size: int = 0 - - for ci in range(cn): - stmt: ast.AST | t.CPtr = children.get(ci) - if stmt is None: - continue - sk: int = stmt.kind() - - if sk == ast.ASTKind.AnnAssign: - aa: ast.AnnAssign | t.CPtr = (ast.AnnAssign | t.CPtr)(stmt) - if aa is None or aa.target is None: - continue - - # 获取字段名 - if aa.target.kind() != ast.ASTKind.Name: - continue - tgt: ast.Name | t.CPtr = (ast.Name | t.CPtr)(aa.target) - if tgt.id is None: - continue - - # 解析字段类型 - field_ty: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type( - pool, aa.annotation, trans._imported_modules, trans._from_imports, trans) - if field_ty is None: - field_ty = llvmlite.Int32(pool) - - # 计算字段大小,更新 max_size - fsize: int = _get_type_size(field_ty) - if fsize > max_size: - max_size = fsize - - # 存储到数组 - if field_count < 48: - field_names_buf[field_count] = t.CSizeT(tgt.id) - field_types_buf[field_count] = t.CSizeT(field_ty) - field_count += 1 - - if field_count == 0: - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "%s has no fields", class_name) - VLogger.warning(fb, "UNION") - return 0 - - if max_size < 1: - max_size = 1 - - # 创建联合体的 LLVM 类型: Struct([Array(Int8, max_size)]) - # 即 { [max_size x i8] } - i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool) - array_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Array(pool, i8_ty, max_size) - - # 构建 ParamNode 链表(单字段:字节数组) - pnode: llvmlite.ParamNode | t.CPtr = pool.alloc(llvmlite.ParamNode.__sizeof__()) - if pnode is None: - return 0 - string.memset(pnode, 0, llvmlite.ParamNode.__sizeof__()) - pnode.Ty = array_ty - - # 构造命名结构体类型名: "sha1.ClassName" 或 "ClassName" - union_type_name: str = class_name - if trans.ModuleSha1 is not None: - union_name_buf: t.CChar | t.CPtr = pool.alloc(64) - if union_name_buf is not None: - viperlib.snprintf(union_name_buf, 64, "%s.%s", trans.ModuleSha1, class_name) - union_type_name = union_name_buf - - union_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Struct(pool, pnode, 1, union_type_name) - if union_ty is None: - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "failed to create type for %s", class_name) - VLogger.error(fb, "UNION") - return 0 - - # 注册命名结构体到模块 - llvmlite.module_add_named_type(trans.Module, pool, union_ty) - - # 注册到 HandlesStruct(传递 SHA1 在注册时直接设置,避免跨模块同名找错 entry) - entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.register_struct( - pool, class_name, union_ty, trans.ModuleSha1) - if entry is None: - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "failed to register %s", class_name) - VLogger.error(fb, "UNION") - return 0 - - # 标记为当前文件可见(命名空间隔离) - HandlesStruct.add_visible_struct(pool, class_name) - - # 标记为联合体(直接用 entry,规避跨模块同名 find_struct 找错) - entry.IsUnion = 1 - - # 添加字段信息(所有字段 Index=0,因为共享偏移 0) - for fi in range(field_count): - fname_addr: t.CSizeT = field_names_buf[fi] - if fname_addr == 0: - continue - fname: str = (str | t.CPtr)(t.CVoid(fname_addr, t.CPtr)) - fty_addr2: t.CSizeT = field_types_buf[fi] - if fty_addr2 == 0: - continue - fty2: llvmlite.LLVMType | t.CPtr = (llvmlite.LLVMType | t.CPtr)( - t.CVoid(fty_addr2, t.CPtr)) - if fname is not None and fty2 is not None: - HandlesStruct.add_field(pool, entry, fname, fty2, None, None) - - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "registered %s with %d fields, max_size=%d", - class_name, field_count, max_size) - VLogger.info(fb, "UNION") - return 0 - - -# ============================================================ -# _get_annotation_field_size — 计算注解类型的字节大小 -# -# 用于 REnum 布局计算,不要求类型已注册(避免自引用死锁)。 -# 联合类型 (A | B) 按指针 8 字节处理。 -# 未知类型默认 8 字节(指针)。 -# ============================================================ -def _get_annotation_field_size(annotation: ast.AST | t.CPtr) -> int: - """计算注解类型的字节大小,用于 REnum 布局计算""" - if annotation is None: - return 8 - k: int = annotation.kind() - # 联合类型 A | B → 指针大小 8 - if k == ast.ASTKind.BinOp: - return 8 - # Name(id) 或 Attribute(attr) → 解析类型名 - type_name: str = None - if k == ast.ASTKind.Name: - nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(annotation) - if nm is not None: - type_name = nm.id - elif k == ast.ASTKind.Attribute: - at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(annotation) - if at is not None: - type_name = at.attr - if type_name is None: - return 8 - # 内置类型 - if string.strcmp(type_name, "int") == 0: - return 4 - if string.strcmp(type_name, "CInt") == 0: - return 4 - if string.strcmp(type_name, "CInt8T") == 0: - return 1 - if string.strcmp(type_name, "CInt16T") == 0: - return 2 - if string.strcmp(type_name, "CInt32T") == 0: - return 4 - if string.strcmp(type_name, "CInt64T") == 0: - return 8 - if string.strcmp(type_name, "CChar") == 0: - return 1 - if string.strcmp(type_name, "CDouble") == 0: - return 8 - if string.strcmp(type_name, "CFloat") == 0: - return 4 - if string.strcmp(type_name, "CPtr") == 0: - return 8 - if string.strcmp(type_name, "CSizeT") == 0: - return 8 - if string.strcmp(type_name, "str") == 0: - return 8 - if string.strcmp(type_name, "bytes") == 0: - return 8 - if string.strcmp(type_name, "bool") == 0: - return 4 - # 已注册的结构体类型 - struct_ty: llvmlite.LLVMType | t.CPtr = HandlesStruct.get_struct_type(type_name) - if struct_ty is not None: - sz: int = _get_type_size(struct_ty) - if sz > 0: - return sz - # 未注册类型 → 默认指针大小 8(可能是自引用或前向引用) - return 8 - - -# ============================================================ -# _translate_renum_def — 翻译 REnum 类定义 -# -# REnum 语法: -# class LLVMType(t.REnum): -# class Int: -# Bits: t.CInt -# class Ptr: -# Pointee: LLVMType | t.CPtr -# ... -# -# 内存布局: {i32 __tag, , , ...} -# 每个字段位置取所有变体在该位置的最大字段大小: -# - max_size <= 4 → i32 -# - max_size > 4 → i64(可容纳指针) -# 至少包含 {i32, i32}(tag + 最小 payload) -# -# 对应 TPC 中 HandlesClassDef._RegisterREnumMembers 的逻辑 -# ============================================================ -def _translate_renum_def(trans: HT.Translator | t.CPtr, - cd: ast.ClassDef | t.CPtr) -> int: - """翻译 REnum 类定义,返回 0""" - if cd is None or cd.name is None or trans is None: - return 0 - - pool: memhub.MemBuddy | t.CPtr = trans.Pool - class_name: str = cd.name - - # 命名空间隔离:标记为当前文件可见 - HandlesStruct.add_visible_struct(pool, class_name) - - # 检查是否已注册(用 SHA1 区分跨模块同名类) - existing: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_module( - class_name, trans.ModuleSha1) - if existing is not None: - if existing.Ty is not None: - llvmlite.module_add_named_type(trans.Module, pool, existing.Ty) - return 0 - - children: list[ast.AST | t.CPtr] | t.CPtr = cd.children - if children is None: - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "%s has no body", class_name) - VLogger.warning(fb, "RENUM") - return 0 - - cn: t.CSizeT = children.__len__() - - # 变体最多 32 个,每个变体最多 16 个字段 - # variant_field_sizes[i][j] = 变体 i 的第 j 个字段大小 - variant_field_sizes: t.CSizeT | t.CPtr = pool.alloc(8 * 48 * 16) - if variant_field_sizes is None: - return 0 - string.memset(variant_field_sizes, 0, 8 * 48 * 16) - - variant_count: int = 0 - max_field_count: int = 0 # 所有变体中最大字段数 - - for ci in range(cn): - stmt: ast.AST | t.CPtr = children.get(ci) - if stmt is None: - continue - sk: int = stmt.kind() - - if sk == ast.ASTKind.ClassDef: - # 嵌套变体类 - variant_cd: ast.ClassDef | t.CPtr = (ast.ClassDef | t.CPtr)(stmt) - if variant_cd is None or variant_cd.children is None: - variant_count += 1 - continue - variant_children: list[ast.AST | t.CPtr] | t.CPtr = variant_cd.children - vcn: t.CSizeT = variant_children.__len__() - field_idx: int = 0 - for vi in range(vcn): - vstmt: ast.AST | t.CPtr = variant_children.get(vi) - if vstmt is None: - continue - vk: int = vstmt.kind() - if vk != ast.ASTKind.AnnAssign: - continue - vaa: ast.AnnAssign | t.CPtr = (ast.AnnAssign | t.CPtr)(vstmt) - if vaa is None or vaa.target is None or vaa.annotation is None: - continue - if vaa.target.kind() != ast.ASTKind.Name: - continue - # 提取字段名 - vnm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(vaa.target) - # 计算字段大小 - fsize: int = _get_annotation_field_size(vaa.annotation) - if variant_count < 32 and field_idx < 16: - # variant_field_sizes[variant_count][field_idx] = fsize - offset: t.CSizeT = variant_count * 16 + field_idx - variant_field_sizes[offset] = t.CSizeT(fsize) - # 直接注册变体字段名别名(避免 CSizeT→str 转换问题) - if vnm is not None and vnm.id is not None: - _register_renum_field_alias(pool, class_name, vnm.id, field_idx + 1) - field_idx += 1 - if field_idx > max_field_count: - max_field_count = field_idx - variant_count += 1 - - if variant_count == 0: - fb2: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb2 is not None: - viperlib.snprintf(fb2, 1024, "%s has no variants", class_name) - VLogger.warning(fb2, "RENUM") - return 0 - - # 计算每个位置的最大字段大小 - # 位置 0 = __tag (i32, 4 字节) - # 位置 1+ = 变体字段 - total_positions: int = max_field_count + 1 # +1 for tag - if total_positions < 2: - total_positions = 2 # 至少 {i32, i32} - - position_max_sizes: t.CSizeT | t.CPtr = pool.alloc(8 * total_positions) - if position_max_sizes is None: - return 0 - string.memset(position_max_sizes, 0, 8 * total_positions) - - # 位置 0 = tag = 4 字节 - position_max_sizes[0] = t.CSizeT(4) - - # 位置 1+ = 每个位置取所有变体的最大字段大小 - for pos in range(1, total_positions): - pos_max: int = 0 - for vi in range(variant_count): - field_pos: int = pos - 1 # 变体字段从位置 0 开始 - offset2: t.CSizeT = vi * 16 + field_pos - fsize_val: t.CSizeT = variant_field_sizes[offset2] - if fsize_val > pos_max: - pos_max = fsize_val - position_max_sizes[pos] = t.CSizeT(pos_max) - - # 构建 ParamNode 链表 - i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool) - i64_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int64(pool) - - first_node: llvmlite.ParamNode | t.CPtr = None - tail_node: llvmlite.ParamNode | t.CPtr = None - - for pos in range(total_positions): - psize: int = position_max_sizes[pos] - field_ty: llvmlite.LLVMType | t.CPtr = i32_ty - if psize > 4: - field_ty = i64_ty - pnode: llvmlite.ParamNode | t.CPtr = llvmlite.new_param_node(pool, field_ty) - if pnode is None: - continue - tail_node = llvmlite.param_list_append(first_node, tail_node, pnode) - if first_node is None: - first_node = tail_node - - if first_node is None: - fb3: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb3 is not None: - viperlib.snprintf(fb3, 1024, "failed to build field list for %s", class_name) - VLogger.error(fb3, "RENUM") - return 0 - - # 构造命名结构体类型名: "sha1.ClassName" 或 "ClassName" - renum_type_name: str = class_name - if trans.ModuleSha1 is not None: - renum_name_buf: t.CChar | t.CPtr = pool.alloc(64) - if renum_name_buf is not None: - viperlib.snprintf(renum_name_buf, 64, "%s.%s", trans.ModuleSha1, class_name) - renum_type_name = renum_name_buf - - renum_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Struct( - pool, first_node, total_positions, renum_type_name) - if renum_ty is None: - fb4: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb4 is not None: - viperlib.snprintf(fb4, 1024, "failed to create type for %s", class_name) - VLogger.error(fb4, "RENUM") - return 0 - - # 注册命名结构体到模块 - llvmlite.module_add_named_type(trans.Module, pool, renum_ty) - - # 注册到 HandlesStruct - entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.register_struct( - pool, class_name, renum_ty, trans.ModuleSha1) - if entry is None: - fb5: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb5 is not None: - viperlib.snprintf(fb5, 1024, "failed to register %s", class_name) - VLogger.error(fb5, "RENUM") - return 0 - - # 修复 class_name 指针不匹配: - # 别名注册时用 class_name(= cd.name,AST 原始指针), - # 但查找时用 entry.Name(register_struct 通过 pool.alloc+strcpy 复制的副本指针)。 - # 两者是不同指针,CSizeT 指针值比较会失败。 - # 调用辅助函数将已注册别名的 class_name 统一更新为 entry.Name。 - if entry.Name is not None: - _update_renum_alias_class_ptr(t.CSizeT(class_name), t.CSizeT(entry.Name)) - - # 添加 __tag 字段(位置 0,i32) - HandlesStruct.add_field(pool, entry, "__tag", i32_ty, None, None) - - # 添加 payload 字段(位置 1+,i32 或 i64) - for pos in range(1, total_positions): - psize2: int = position_max_sizes[pos] - payload_ty: llvmlite.LLVMType | t.CPtr = i32_ty - if psize2 > 4: - payload_ty = i64_ty - field_name_buf: t.CChar | t.CPtr = pool.alloc(16) - if field_name_buf is not None: - viperlib.snprintf(field_name_buf, 16, "_p%d", pos) - HandlesStruct.add_field(pool, entry, field_name_buf, payload_ty, None, None) - - # 注册变体名到全局变体表(供 translate_call 检测 REnum 变体构造) - _register_renum_variants(pool, class_name, cd, variant_count) - - # 注册变体字段名别名已在变体遍历时直接完成(避免 CSizeT→str 转换问题) - - fb6: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb6 is not None: - viperlib.snprintf(fb6, 1024, "registered %s with %d variants, %d positions", - class_name, variant_count, total_positions) - VLogger.info(fb6, "RENUM") - return 0 - - -# ============================================================ -# REnum 变体表(全局静态分配) -# -# 存储 ClassName → [VariantName, TagValue] 映射, -# 供 translate_call 检测 ClassName.VariantName(args) 形式的变体构造调用。 -# -# 布局(所有数组使用 t.CSizeT | t.CPtr 确保 8 字节步长): -# _renum_class_names[i] = 第 i 个 REnum 类名(str 指针,以 CSizeT 存储) -# _renum_class_variant_counts[i] = 第 i 个 REnum 类的变体数量 -# _renum_variant_names[i][j] = 第 i 个类的第 j 个变体名(str 指针,以 CSizeT 存储) -# _renum_variant_tags[i][j] = 第 i 个类的第 j 个变体的 tag 值 -# ============================================================ -_renum_class_names: t.CSizeT | t.CPtr = None -_renum_class_variant_counts: t.CSizeT | t.CPtr = None -_renum_variant_names: t.CSizeT | t.CPtr = None -_renum_variant_tags: t.CSizeT | t.CPtr = None -_renum_class_count: int = 0 - - -# ============================================================ -# REnum 字段别名表(全局静态分配) -# -# 存储 (class_name, field_name) → payload_index 映射, -# 供 translate_attribute 查找 REnum 变体字段。 -# -# REnum 结构体布局为 {i32 __tag, _p1, _p2, ...}, -# 但源码用变体字段名访问(如 ty.Pointee)。 -# 此表将变体字段名映射到 payload 索引(_p1=1, _p2=2, ...)。 -# -# 布局: -# _renum_alias_class[i] = 类名(str 指针,以 CSizeT 存储) -# _renum_alias_field[i] = 字段名(str 指针,以 CSizeT 存储) -# _renum_alias_index[i] = payload 索引(CSizeT) -# ============================================================ -RENUM_ALIAS_MAX: t.CDefine = 512 -_renum_alias_class: t.CSizeT | t.CPtr = None -_renum_alias_field: t.CSizeT | t.CPtr = None -_renum_alias_index: t.CSizeT | t.CPtr = None -_renum_alias_count: int = 0 - - -# ============================================================ -# _register_renum_variants — 注册 REnum 类的变体名和 tag 值 -# -# 遍历 ClassDef 的 children,提取嵌套变体类的名称, -# 按 children 顺序分配 tag 值(0, 1, 2, ...) -# -# 参数: -# pool: 内存分配器 -# class_name: REnum 类名(如 "LLVMType") -# cd: REnum 类的 ClassDef AST 节点 -# variant_count: 变体数量(由 _translate_renum_def 预计算) -# ============================================================ -def _register_renum_variants(pool: memhub.MemBuddy | t.CPtr, - class_name: str, - cd: ast.ClassDef | t.CPtr, - variant_count: int): - """注册 REnum 类的变体名和 tag 值到全局变体表""" - global _renum_class_names, _renum_class_variant_counts - global _renum_variant_names, _renum_variant_tags, _renum_class_count - - if pool is None or class_name is None or cd is None: - return - if variant_count == 0: - return - children: list[ast.AST | t.CPtr] | t.CPtr = cd.children - if children is None: - return - - # 懒初始化表(首次注册时分配) - if _renum_class_names is None: - _renum_class_names = pool.alloc(8 * RENUM_CLASS_MAX) - _renum_class_variant_counts = pool.alloc(8 * RENUM_CLASS_MAX) - _renum_variant_names = pool.alloc(8 * RENUM_CLASS_MAX * RENUM_VARIANT_PER_CLASS) - _renum_variant_tags = pool.alloc(8 * RENUM_CLASS_MAX * RENUM_VARIANT_PER_CLASS) - if (_renum_class_names is None or _renum_class_variant_counts is None - or _renum_variant_names is None or _renum_variant_tags is None): - _renum_class_names = None - return - string.memset(_renum_class_names, 0, 8 * RENUM_CLASS_MAX) - string.memset(_renum_class_variant_counts, 0, 8 * RENUM_CLASS_MAX) - string.memset(_renum_variant_names, 0, 8 * RENUM_CLASS_MAX * RENUM_VARIANT_PER_CLASS) - string.memset(_renum_variant_tags, 0, 8 * RENUM_CLASS_MAX * RENUM_VARIANT_PER_CLASS) - _renum_class_count = 0 - - # 检查是否已注册(避免重复注册) - for i in range(_renum_class_count): - existing: str = _renum_class_names[i] - if existing is not None and string.strcmp(existing, class_name) == 0: - return - - # 表已满 - if _renum_class_count >= RENUM_CLASS_MAX: - return - - # 注册类名 - idx: int = _renum_class_count - _renum_class_names[idx] = t.CSizeT(class_name) - _renum_class_variant_counts[idx] = variant_count - - # 遍历 children,提取嵌套变体类名并注册 - cn: t.CSizeT = children.__len__() - tag: int = 0 - for ci in range(cn): - if tag >= variant_count: - break - stmt: ast.AST | t.CPtr = children.get(ci) - if stmt is None: - continue - if stmt.kind() != ast.ASTKind.ClassDef: - continue - vcd: ast.ClassDef | t.CPtr = (ast.ClassDef | t.CPtr)(stmt) - if vcd is None or vcd.name is None: - continue - name_offset: t.CSizeT = idx * RENUM_VARIANT_PER_CLASS + tag - _renum_variant_names[name_offset] = t.CSizeT(vcd.name) - _renum_variant_tags[name_offset] = tag - tag += 1 - - _renum_class_count = idx + 1 - - -# ============================================================ -# _lookup_renum_variant — 查找变体所属的 REnum 类名 -# -# 参数: -# variant_name: 变体名(如 "Int"、"Ptr") -# -# 返回: -# 成功: class_name (str) -# 失败: None -# 注: tag_value 可通过 _lookup_renum_variant_in_class(class_name, variant_name) 获取 -# ============================================================ -def _lookup_renum_variant(variant_name: str) -> str: - """查找变体名所属的 REnum 类名 - - 返回: class_name (str),或 None - """ - if variant_name is None or _renum_class_names is None: - return None - - for i in range(_renum_class_count): - vcount: int = _renum_class_variant_counts[i] - for j in range(vcount): - name_offset: t.CSizeT = i * RENUM_VARIANT_PER_CLASS + j - vname: str = _renum_variant_names[name_offset] - if vname is not None and string.strcmp(vname, variant_name) == 0: - cls_nm: str = _renum_class_names[i] - return cls_nm - return None - - -# ============================================================ -# _is_renum_class_name — 检查名称是否是已注册的 REnum 类名 -# -# 用于 translate_call 检测 ClassName.Variant(args) 形式调用时, -# 先验证 ClassName 是否是 REnum 类。 -# ============================================================ -def _is_renum_class_name(class_name: str) -> int: - """检查名称是否是已注册的 REnum 类名,返回 1=是 / 0=否""" - if class_name is None or _renum_class_names is None: - return 0 - for i in range(_renum_class_count): - existing: str = _renum_class_names[i] - if existing is not None and string.strcmp(existing, class_name) == 0: - return 1 - return 0 - - -# ============================================================ -# _lookup_renum_variant_in_class — 在指定 REnum 类中查找变体 -# -# 参数: -# class_name: REnum 类名 -# variant_name: 变体名 -# -# 返回: -# 成功: tag_value (int) -# 失败: -1 -# ============================================================ -def _lookup_renum_variant_in_class(class_name: str, variant_name: str) -> int: - """在指定 REnum 类中查找变体,返回 tag 值或 -1""" - if class_name is None or variant_name is None or _renum_class_names is None: - return -1 - for i in range(_renum_class_count): - existing: str = _renum_class_names[i] - if existing is None or string.strcmp(existing, class_name) != 0: - continue - vcount: int = _renum_class_variant_counts[i] - for j in range(vcount): - name_offset: t.CSizeT = i * RENUM_VARIANT_PER_CLASS + j - vname: str = _renum_variant_names[name_offset] - if vname is not None and string.strcmp(vname, variant_name) == 0: - return _renum_variant_tags[name_offset] - return -1 - return -1 - - -# ============================================================ -# _register_renum_field_alias — 注册 REnum 变体字段名别名 -# -# 将变体字段名(如 "Pointee")映射到 payload 索引(如 1), -# 供 translate_attribute 查找 REnum 变体字段。 -# -# 参数: -# pool: 内存分配器 -# class_name: REnum 类名(如 "LLVMType") -# field_name: 变体字段名(如 "Pointee") -# payload_idx: payload 索引(1=_p1, 2=_p2, ...) -# ============================================================ -def _register_renum_field_alias(pool: memhub.MemBuddy | t.CPtr, - class_name: str, - field_name: str, - payload_idx: int): - """注册 REnum 变体字段名别名到全局表""" - global _renum_alias_class, _renum_alias_field, _renum_alias_index - global _renum_alias_count - - if pool is None or class_name is None or field_name is None: - return - if payload_idx < 1: - return - - # 懒初始化表 - if _renum_alias_class is None: - _renum_alias_class = pool.alloc(8 * RENUM_ALIAS_MAX) - _renum_alias_field = pool.alloc(8 * RENUM_ALIAS_MAX) - _renum_alias_index = pool.alloc(8 * RENUM_ALIAS_MAX) - if (_renum_alias_class is None or _renum_alias_field is None - or _renum_alias_index is None): - _renum_alias_class = None - return - string.memset(_renum_alias_class, 0, 8 * RENUM_ALIAS_MAX) - string.memset(_renum_alias_field, 0, 8 * RENUM_ALIAS_MAX) - string.memset(_renum_alias_index, 0, 8 * RENUM_ALIAS_MAX) - _renum_alias_count = 0 - - if _renum_alias_count >= RENUM_ALIAS_MAX: - return - - # 检查是否已注册(避免重复)— 用 CSizeT 指针值比较,避免 CSizeT→str 转换问题 - cls_key: t.CSizeT = t.CSizeT(class_name) - fld_key: t.CSizeT = t.CSizeT(field_name) - for i in range(_renum_alias_count): - cls_existing: t.CSizeT = _renum_alias_class[i] - fld_existing: t.CSizeT = _renum_alias_field[i] - if cls_existing == cls_key and fld_existing == fld_key: - return - - idx: int = _renum_alias_count - _renum_alias_class[idx] = cls_key - _renum_alias_field[idx] = fld_key - _renum_alias_index[idx] = t.CSizeT(payload_idx) - _renum_alias_count = idx + 1 - - -# ============================================================ -# _update_renum_alias_class_ptr — 更新别名表中的 class_name 指针 -# -# register_struct 会通过 pool.alloc+strcpy 复制类名,导致 entry.Name -# 与原始 cd.name 是不同指针。别名注册时用 cd.name,查找时用 entry.Name, -# CSizeT 指针值比较会失败。此函数将别名表中所有匹配 old_ptr 的 class_name -# 更新为 new_ptr,确保注册和查找使用同一指针。 -# -# 参数: -# old_ptr: 旧 class_name 指针值(CSizeT(cd.name)) -# new_ptr: 新 class_name 指针值(CSizeT(entry.Name)) -# ============================================================ -def _update_renum_alias_class_ptr(old_ptr: t.CSizeT, new_ptr: t.CSizeT): - """更新别名表中的 class_name 指针,从 old_ptr 更新为 new_ptr""" - global _renum_alias_class, _renum_alias_count - - if old_ptr == new_ptr: - return - if _renum_alias_class is None: - return - for i in range(_renum_alias_count): - if _renum_alias_class[i] == old_ptr: - _renum_alias_class[i] = new_ptr - - -# ============================================================ -# _lookup_renum_field_alias — 查找 REnum 变体字段名的 payload 索引 -# -# 参数: -# class_name: REnum 类名(如 "LLVMType") -# field_name: 变体字段名(如 "Pointee") -# -# 返回: -# 成功: payload 索引(1, 2, ...) -# 失败: -1 -# ============================================================ -def _lookup_renum_field_alias(class_name: str, field_name: str) -> int: - """查找 REnum 变体字段名的 payload 索引,返回索引或 -1 - - class_name: 用 CSizeT 指针值比较(_update_renum_alias_class_ptr 已统一指针) - field_name: 用 strcmp 内容比较(注册时 vnm.id 与查找时 at.attr 是不同指针) - """ - if class_name is None or field_name is None or _renum_alias_class is None: - return -1 - cls_key: t.CSizeT = t.CSizeT(class_name) - for i in range(_renum_alias_count): - cls_existing: t.CSizeT = _renum_alias_class[i] - if cls_existing == cls_key: - # field_name 用 strcmp 内容比较(指针不同但内容相同) - fld_existing_ptr: str = (str | t.CPtr)( - t.CVoid(_renum_alias_field[i], t.CPtr)) - if fld_existing_ptr is not None and string.strcmp(fld_existing_ptr, field_name) == 0: - return _renum_alias_index[i] - return -1 - - -# ============================================================ -# translate_class_def — 翻译 class 定义 -# -# 遍历 class body 中的 AnnAssign 语句,收集字段类型 -# 创建 LLVM StructType 并注册到 HandlesStruct -# ============================================================ -# ============================================================ -# 泛型类模板存储(模块级) -# -# 泛型类 class list[T]: 不直接发射 IR,而是存储为模板, -# 等遇到 list[int](pool) 实例化时触发 _specialize_generic_class -# ============================================================ - -_generic_class_names: list[str] | t.CPtr = None -_generic_class_nodes: list[ast.ClassDef | t.CPtr] | t.CPtr = None -# 追踪每个泛型模板定义模块的 SHA1,用于特化时统一命名空间 -_generic_class_sha1s: list[str] | t.CPtr = None - - -def _is_generic_class(tp: list[str] | t.CPtr) -> int: - """检查 ClassDef 是否有类型参数(泛型类),返回 1=是 / 0=否 - - 接收 type_params 而非 cd,避免 cd.type_params 属性访问 - 因跨模块类型推断失败返回 None。 - """ - if tp is None: - return 0 - return 1 - - -def _register_generic_template(pool: memhub.MemBuddy | t.CPtr, - cd: ast.ClassDef | t.CPtr, - module_sha1: str): - """注册泛型类模板(类名 + ClassDef 节点 + 来源模块 SHA1)""" - global _generic_class_names, _generic_class_nodes, _generic_class_sha1s - if _generic_class_names is None: - _generic_class_names = list[str](pool, 8) - _generic_class_nodes = list[ast.ClassDef | t.CPtr](pool, 8) - _generic_class_sha1s = list[str](pool, 8) - # 用局部变量接收 global list,触发类型推断(避免 global 变量 __len__ 失败) - names_local: list[str] | t.CPtr = _generic_class_names - cn: t.CSizeT = names_local.__len__() - i: t.CSizeT - for i in range(cn): - nm: str = names_local.get(i) - if nm is not None and string.strcmp(nm, cd.name) == 0: - return - _generic_class_names.append(cd.name) - _generic_class_nodes.append(cd) - _generic_class_sha1s.append(module_sha1) - # 诊断日志:确认泛型模板注册 - fb_rg: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb_rg is not None: - viperlib.snprintf(fb_rg, 1024, "注册泛型模板: %s (module=%s)", cd.name, module_sha1) - VLogger.info(fb_rg, "SPEC") - - -def _find_generic_template(class_name: str) -> ast.ClassDef | t.CPtr: - """查找泛型类模板,返回 ClassDef 节点或 None""" - if _generic_class_names is None or class_name is None: - return None - # 用局部变量接收 global list,触发类型推断(避免 global 变量 __len__ 失败) - names_local: list[str] | t.CPtr = _generic_class_names - nodes_local: list[ast.ClassDef | t.CPtr] | t.CPtr = _generic_class_nodes - cn: t.CSizeT = names_local.__len__() - i: t.CSizeT - for i in range(cn): - nm: str = names_local.get(i) - if nm is not None and string.strcmp(nm, class_name) == 0: - node: ast.ClassDef | t.CPtr = nodes_local.get(i) - return node - return None - - -def _find_generic_template_sha1(class_name: str) -> str: - """查找泛型类模板的来源模块 SHA1,未找到返回 None""" - if _generic_class_names is None or class_name is None: - return None - # 用局部变量接收 global list,触发类型推断 - names_local: list[str] | t.CPtr = _generic_class_names - sha1s_local: list[str] | t.CPtr = _generic_class_sha1s - cn: t.CSizeT = names_local.__len__() - i: t.CSizeT - for i in range(cn): - nm: str = names_local.get(i) - if nm is not None and string.strcmp(nm, class_name) == 0: - sha1_val: str = sha1s_local.get(i) - return sha1_val - return None - - -def _mangle_generic_class_name(pool: memhub.MemBuddy | t.CPtr, - class_name: str, - type_args: list[str] | t.CPtr) -> str: - """生成特化类名: list + [int] -> list[int] - - 分配新缓冲区拼接,避免原地 strcat 导致缓冲区溢出 - """ - if class_name is None or type_args is None or pool is None: - return class_name - n: t.CSizeT = type_args.__len__() - if n == 0: - return class_name - # 计算总长度: class_name + "[" + arg0 + "," + arg1 + ... + "]" + NUL - total_len: t.CSizeT = string.strlen(class_name) + 2 # "[" 和 "]" - i: t.CSizeT - for i in range(n): - if i > 0: - total_len += 1 # "," - ta: str = type_args.get(i) - if ta is not None: - total_len += string.strlen(ta) - total_len += 1 # NUL - # 分配新缓冲区 - mangled: str = pool.alloc(total_len) - if mangled is None: - return class_name - mangled[0] = '\0' - string.strcat(mangled, class_name) - string.strcat(mangled, "[") - for i in range(n): - if i > 0: - string.strcat(mangled, ",") - ta: str = type_args.get(i) - if ta is not None: - string.strcat(mangled, ta) - string.strcat(mangled, "]") - return mangled - - -# ============================================================ -# 类型注解拷贝(用于泛型特化) -# -# _clone_annotation: 拷贝类型注解表达式,替换类型参数 T 为具体类型 -# _clone_arguments: 拷贝 Arguments 节点,替换 arg annotation 中的 T -# _clone_classdef_for_spec: 拷贝 ClassDef 用于泛型特化 -# ============================================================ - -def _clone_annotation(pool: memhub.MemBuddy | t.CPtr, - node: ast.AST | t.CPtr, - tp_names: list[str] | t.CPtr, - type_args: list[str] | t.CPtr) -> ast.AST | t.CPtr: - """拷贝类型注解表达式,替换类型参数 T 为具体类型名 - - tp_names: 类型参数名列表 ['T'] - type_args: 类型实参名列表 ['int'] - """ - if node is None: - return None - k: int = node.kind() - - # Name: 可能是类型参数 T - if k == ast.ASTKind.Name: - nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(node) - if nm.id is not None: - n: t.CSizeT = tp_names.__len__() if tp_names is not None else 0 - i: t.CSizeT - for i in range(n): - tpn: str = tp_names.get(i) - if tpn is not None and string.strcmp(nm.id, tpn) == 0: - ta: str = type_args.get(i) - # 类型实参可能是复合类型(如 "AST|t.CPtr"),用 _parse_type_string_ptr 解析 - # 使用 _ptr 包装避免旧编译器对 ast.AST|t.CPtr 返回类型推断为 i32 的 bug - parsed_node: ast.AST | t.CPtr = HandlesType._parse_type_string_ptr(pool, ta, nm.ctx) - return parsed_node - return ast.Name(pool, nm.id, nm.ctx) - return None - - # Attribute: t.CPtr 等 - if k == ast.ASTKind.Attribute: - at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(node) - new_value: ast.AST | t.CPtr = _clone_annotation(pool, at.value, tp_names, type_args) - return ast.Attribute(pool, new_value, at.attr, at.ctx) - - # BinOp: T | t.CPtr 等 - if k == ast.ASTKind.BinOp: - bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(node) - new_left: ast.AST | t.CPtr = _clone_annotation(pool, bop.left, tp_names, type_args) - new_right: ast.AST | t.CPtr = _clone_annotation(pool, bop.right, tp_names, type_args) - return ast.BinOp(pool, new_left, bop.op, new_right) - - # Subscript: list[int] 等 - if k == ast.ASTKind.Subscript: - sub: ast.Subscript | t.CPtr = (ast.Subscript | t.CPtr)(node) - new_value2: ast.AST | t.CPtr = _clone_annotation(pool, sub.value, tp_names, type_args) - new_slice: ast.AST | t.CPtr = _clone_annotation(pool, sub.slice, tp_names, type_args) - return ast.Subscript(pool, new_value2, new_slice, sub.ctx) - - # Tuple: (T, int) 等 - if k == ast.ASTKind.Tuple: - tup: ast.Tuple | t.CPtr = (ast.Tuple | t.CPtr)(node) - new_elts: list[ast.AST | t.CPtr] | t.CPtr = list[ast.AST | t.CPtr](pool, 8) - if tup.elts is not None: - tup_elts: list[ast.AST | t.CPtr] | t.CPtr = tup.elts - en: t.CSizeT = tup_elts.__len__() - ei: t.CSizeT - for ei in range(en): - el: ast.AST | t.CPtr = tup_elts.get(ei) - new_el: ast.AST | t.CPtr = _clone_annotation(pool, el, tp_names, type_args) - if new_el is not None: - new_elts.append(new_el) - return ast.Tuple(pool, new_elts, tup.ctx) - - # Constant: 默认值等 - if k == ast.ASTKind.Constant: - cnst: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(node) - return ast.Constant(pool, cnst.const_kind, cnst.int_val, cnst.float_val, - cnst.str_val, cnst.lineno, cnst.col_offset) - - # 其他: 直接引用(不拷贝) - return node - - -def _clone_arguments(pool: memhub.MemBuddy | t.CPtr, - args: ast.AST | t.CPtr, - tp_names: list[str] | t.CPtr, - type_args: list[str] | t.CPtr) -> ast.AST | t.CPtr: - """拷贝 Arguments 节点,替换 arg annotation 中的 T""" - if args is None: - return None - if args.kind() != ast.ASTKind.Arguments: - return args - old_args: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(args) - # 拷贝 args 列表,替换每个 Arg 的 annotation - new_arg_list: list[ast.AST | t.CPtr] | t.CPtr = list[ast.AST | t.CPtr](pool, 8) - if old_args.args is not None: - old_arg_list: list[ast.AST | t.CPtr] | t.CPtr = old_args.args - an: t.CSizeT = old_arg_list.__len__() - ai: t.CSizeT - for ai in range(an): - arg_node: ast.AST | t.CPtr = old_arg_list.get(ai) - if arg_node is None: - continue - if arg_node.kind() == ast.ASTKind.Arg: - ag: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(arg_node) - new_anno: ast.AST | t.CPtr = _clone_annotation(pool, ag.annotation, tp_names, type_args) - new_arg: ast.Arg | t.CPtr = ast.Arg(pool, ag.arg, new_anno) - new_arg_list.append(new_arg) - else: - new_arg_list.append(arg_node) - return ast.Arguments(pool, new_arg_list, old_args.vararg, old_args.kwarg, - old_args.defaults, old_args.kw_defaults) - - -def _clone_classdef_for_spec(pool: memhub.MemBuddy | t.CPtr, - cd: ast.ClassDef | t.CPtr, - spec_name: str, - tp_names: list[str] | t.CPtr, - type_args: list[str] | t.CPtr) -> ast.ClassDef | t.CPtr: - """拷贝 ClassDef 节点用于泛型特化 - - - 替换类名为 spec_name - - 清除 type_params(特化后不是泛型类) - - 拷贝 children 中的 AnnAssign 和 FunctionDef,替换类型注解中的 T - - 方法体直接引用原始节点(通过 type_map 上下文处理 T) - """ - # 创建新 ClassDef(type_params=None 表示非泛型) - new_cd: ast.ClassDef | t.CPtr = ast.ClassDef(pool, spec_name, cd.bases, cd.keywords, - cd.decorator_list, None) - # 拷贝 children - if cd.children is not None: - cd_children: list[ast.AST | t.CPtr] | t.CPtr = cd.children - cn: t.CSizeT = cd_children.__len__() - ci: t.CSizeT - for ci in range(cn): - child: ast.AST | t.CPtr = cd_children.get(ci) - if child is None: - continue - ck: int = child.kind() - - if ck == ast.ASTKind.AnnAssign: - aa: ast.AnnAssign | t.CPtr = (ast.AnnAssign | t.CPtr)(child) - new_target: ast.AST | t.CPtr = aa.target - new_anno2: ast.AST | t.CPtr = _clone_annotation(pool, aa.annotation, tp_names, type_args) - new_value3: ast.AST | t.CPtr = aa.value - new_aa: ast.AnnAssign | t.CPtr = ast.AnnAssign(pool, new_target, new_anno2, new_value3, aa.simple) - new_cd.append(new_aa) - - elif ck == ast.ASTKind.FunctionDef: - fd: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(child) - new_args2: ast.AST | t.CPtr = _clone_arguments(pool, fd.args, tp_names, type_args) - new_returns2: ast.AST | t.CPtr = _clone_annotation(pool, fd.returns, tp_names, type_args) - new_fd: ast.FunctionDef | t.CPtr = ast.FunctionDef(pool, fd.name, new_args2, - fd.decorator_list, new_returns2, 0) - # 方法体直接引用原始节点 - if fd.children is not None: - fd_children: list[ast.AST | t.CPtr] | t.CPtr = fd.children - bcn: t.CSizeT = fd_children.__len__() - bci: t.CSizeT - for bci in range(bcn): - body_stmt: ast.AST | t.CPtr = fd_children.get(bci) - if body_stmt is not None: - new_fd.append(body_stmt) - new_cd.append(new_fd) - - else: - new_cd.append(child) - - return new_cd - - -# ============================================================ -# 泛型特化缓存(模块级) -# ============================================================ - -_spec_keys: list[str] | t.CPtr = None -_spec_names: list[str] | t.CPtr = None - - -def _find_cached_spec(spec_key: str) -> str: - """查找已缓存的特化名,未找到返回 None""" - if _spec_keys is None or spec_key is None: - return None - n: t.CSizeT = _spec_keys.__len__() - i: t.CSizeT - for i in range(n): - k: str = _spec_keys.get(i) - if k is not None and string.strcmp(k, spec_key) == 0: - # 用局部变量接收 list.get() 结果,触发旧编译器 inttoptr 类型转换 - spec_nm: str = _spec_names.get(i) - return spec_nm - return None - - -def _cache_spec(pool: memhub.MemBuddy | t.CPtr, spec_key: str, spec_name: str): - """缓存特化结果""" - global _spec_keys, _spec_names - if _spec_keys is None: - _spec_keys = list[str](pool, 8) - _spec_names = list[str](pool, 8) - _spec_keys.append(spec_key) - _spec_names.append(spec_name) - - -def _specialize_generic_class(trans: HT.Translator | t.CPtr, - class_name: str, - type_args: list[str] | t.CPtr) -> str: - """特化泛型类,返回特化类名 - - 1. 查找泛型模板 - 2. 生成特化名 - 3. 检查缓存 - 4. 拷贝 ClassDef 节点(替换类型注解中的 T) - 5. 设置 type_map 上下文(用于方法体中的 T 替换) - 6. 调用 translate_class_def 翻译特化类 - 7. 返回特化名 - """ - if trans is None or class_name is None or type_args is None: - return None - - pool: memhub.MemBuddy | t.CPtr = trans.Pool - - # ============================================================ - # 诊断输出:追踪 GSListNode 特化调用路径 - # ============================================================ - if string.strcmp(class_name, "GSListNode") == 0: - VLogger.debug("=== _specialize_generic_class ===", "SPEC") - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "class=%s module=%s", class_name, trans.ModuleSha1) - VLogger.debug(fb, "SPEC") - if type_args is not None: - ta_n: t.CSizeT = type_args.__len__() - ta_i: t.CSizeT - for ta_i in range(ta_n): - ta: str = type_args.get(ta_i) - if ta is not None: - if fb is not None: - viperlib.snprintf(fb, 1024, " type_arg[%d]=%s", ta_i, ta) - VLogger.debug(fb, "SPEC") - - # 1. 查找泛型模板 - template_cd: ast.ClassDef | t.CPtr = _find_generic_template(class_name) - if template_cd is None: - if string.strcmp(class_name, "GSListNode") == 0: - VLogger.debug("template NOT FOUND, return None", "SPEC") - return None - - # 2. 生成特化名 - spec_name: str = _mangle_generic_class_name(pool, class_name, type_args) - if spec_name is None: - return None - - # 3. 检查缓存(spec_key 包含所有类型实参,避免多参数泛型缓存冲突) - # 分配新缓冲区避免原地 strcat 溢出 - sk_n: t.CSizeT = type_args.__len__() - sk_total: t.CSizeT = string.strlen(class_name) + 2 # "<" 和 ">" - sk_i: t.CSizeT - for sk_i in range(sk_n): - if sk_i > 0: - sk_total += 1 # "," - sk_ta: str = type_args.get(sk_i) - if sk_ta is not None: - sk_total += string.strlen(sk_ta) - sk_total += 1 # NUL - spec_key: str = pool.alloc(sk_total) - if spec_key is None: - return None - spec_key[0] = '\0' - string.strcat(spec_key, class_name) - string.strcat(spec_key, "<") - for sk_i in range(sk_n): - if sk_i > 0: - string.strcat(spec_key, ",") - sk_ta: str = type_args.get(sk_i) - if sk_ta is not None: - string.strcat(spec_key, sk_ta) - string.strcat(spec_key, ">") - cached: str = _find_cached_spec(spec_key) - if cached is not None: - if string.strcmp(class_name, "GSListNode") == 0: - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "CACHE HIT, return cached=%s", cached) - VLogger.debug(fb, "SPEC") - return cached - - # 4. 检查是否已注册(Phase B 重复特化) - existing: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct(spec_name) - if existing is not None: - if string.strcmp(class_name, "GSListNode") == 0: - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "EXISTING registered, return spec_name=%s field_count=%d", - spec_name, existing.FieldCount) - VLogger.debug(fb, "SPEC") - _cache_spec(pool, spec_key, spec_name) - return spec_name - - # 预注册缓存(防止递归) - _cache_spec(pool, spec_key, spec_name) - - # 5. 拷贝 ClassDef 节点 - tp_names: list[str] | t.CPtr = template_cd.type_params - spec_cd: ast.ClassDef | t.CPtr = _clone_classdef_for_spec( - pool, template_cd, spec_name, tp_names, type_args) - if spec_cd is None: - return None - - # 6. 设置 type_map 上下文(用于方法体中的 T 替换) - trans.GenericTypeParamNames = tp_names - trans.GenericTypeArgs = type_args - HandlesType.set_generic_context(tp_names, type_args) - - # 7. 翻译特化类 - # 切换 trans.ModuleSha1 为泛型模板定义模块的 SHA1, - # 使结构体类型名和方法定义名都用定义模块的 SHA1 前缀, - # 与调用端 get_struct_sha1(class_name) 查到的 SHA1 一致。 - saved_module_sha1: str = trans.ModuleSha1 - template_sha1: str = _find_generic_template_sha1(class_name) - if template_sha1 is not None: - trans.ModuleSha1 = template_sha1 - translate_class_def(trans, spec_cd) - # 恢复原始 ModuleSha1 - trans.ModuleSha1 = saved_module_sha1 - - # 8. 清除 type_map 上下文 - trans.GenericTypeParamNames = None - trans.GenericTypeArgs = None - HandlesType.clear_generic_context() - - # 诊断输出:检查特化结果 - if string.strcmp(class_name, "GSListNode") == 0: - result_entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct(spec_name) - if result_entry is not None: - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "DONE spec_name=%s field_count=%d", - spec_name, result_entry.FieldCount) - VLogger.debug(fb, "SPEC") - # 打印每个字段的类型信息 - ri: int - for ri in range(result_entry.FieldCount): - rfe: HandlesStruct.FieldEntry | t.CPtr = HandlesStruct._get_field_entry( - result_entry, ri) - if rfe is not None: - rfn: str = HandlesStruct.get_field_name_ptr(rfe) - rft: llvmlite.LLVMType | t.CPtr = HandlesStruct.get_field_type_ptr(rfe) - if fb is not None: - viperlib.snprintf(fb, 1024, " field[%d] name=%s type=%d", - ri, rfn if rfn is not None else "(null)", - t.CSizeT(rft) if rft is not None else 0) - VLogger.debug(fb, "SPEC") - else: - VLogger.debug("DONE but result NOT FOUND in struct table!", "SPEC") - - return spec_name - - -def translate_class_def(trans: HT.Translator | t.CPtr, - node: ast.AST | t.CPtr) -> int: - """翻译 class 定义,返回 0""" - if node is None or trans is None: - return 0 - - cd: ast.ClassDef | t.CPtr = (ast.ClassDef | t.CPtr)(node) - if cd is None or cd.name is None: - return 0 - - pool: memhub.MemBuddy | t.CPtr = trans.Pool - class_name: str = cd.name - - # 命名空间隔离:标记为当前文件可见(必须在 existing 检查之前, - # 因为 Phase B 时结构体已注册会提前 return,否则永远无法标记本地类) - HandlesStruct.add_visible_struct(pool, class_name) - - # 枚举类:交给 HandlesEnum 处理 - if _is_enum_class(cd) == 1: - return _translate_enum_def(trans, cd) - - # 联合体类:交给联合体处理 - if _is_union_class(cd) == 1: - return _translate_union_def(trans, cd) - - # REnum 类:交给 REnum 处理({i32 tag, max_payload} 布局) - if _is_renum_class(cd) == 1: - return _translate_renum_def(trans, cd) - - # 泛型类:存储为模板,不发射 IR(等实例化时特化) - # 用局部变量接收 cd.type_params,触发类型推断 - tp_val: list[str] | t.CPtr = cd.type_params - if _is_generic_class(tp_val) == 1: - _register_generic_template(pool, cd, trans.ModuleSha1) - return 0 - - # 检查是否已注册(用 SHA1 区分跨模块同名类) - existing: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_module( - class_name, trans.ModuleSha1) - if existing is not None: - # 结构体已注册(Phase A-pre 多遍扫描或 Phase B 重新翻译),但仍需在当前模块中翻译方法 - if existing.Ty is not None: - # Phase B: 将已存在的命名结构体注册到当前模块(输出类型定义行) - llvmlite.module_add_named_type(trans.Module, pool, existing.Ty) - # Phase A-pre(declare_only=1)多遍扫描时,类已注册但不应翻译方法体 - # Phase B(declare_only=0)时全量翻译方法体 - if trans._declare_only == 1: - _translate_oop_methods(trans, cd, existing.Ty, class_name, 1) - else: - _translate_oop_methods(trans, cd, existing.Ty, class_name) - # SHA1 已在 register_struct 时设置,无需再补 - return 0 - - # ============================================================ - # 触发 base 中 Subscript 的泛型特化(如 GSListNode[Value]) - # 必须在 _detect_vtable_status 和父类字段继承之前调用, - # 否则 find_struct_by_module("GSListNode[Value]") 返回 None - # ============================================================ - _trigger_base_specialization(trans, cd) - - # ============================================================ - # VTable 检测:判断是否启用虚表 - # ============================================================ - has_vtable: int = _detect_vtable_status(cd, trans) - parent_name: str = _get_parent_class(cd, trans) - is_novtable_deco: int = 0 - if cd.decorator_list is not None: - if _has_decorator(cd.decorator_list, "NoVTable") == 1: - is_novtable_deco = 1 - - # ============================================================ - # PhaseA 预注册延迟检查:父类未注册时延迟注册当前类 - # - # 根因:AssignHandle(HandlesBase.Mixin) 有自己的字段 _CurrentClass, - # 当 Mixin 未注册时(字母序:HandlesAssign.py 在 HandlesBase.py 之前), - # field_count=1(不是0),field_count==0 静默返回不触发, - # AssignHandle 被注册为只有 _CurrentClass 字段(缺 Trans)。 - # 后续遍 existing is not None,不补字段 → attribute ptr is None: self.Trans - # - # 修复:declare_only==1 且父类未注册时,延迟注册到下一遍。 - # 多遍 PhaseA-pre 会在后续遍中重试(父类已注册后完整注册)。 - # Phase B(declare_only==0)不延迟,避免死锁。 - # ============================================================ - if trans._declare_only == 1 and parent_name is not None: - parent_check: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_module( - parent_name, trans.ModuleSha1) - if parent_check is None: - parent_check = HandlesStruct.find_struct(parent_name) - if parent_check is None: - return 0 - - # ============================================================ - # 1. 遍历 class body,收集字段信息 - # ============================================================ - # 用 CSizeT 数组存储指针值(64 位系统上 8 字节) - field_names_buf: t.CSizeT | t.CPtr = pool.alloc(8 * 48) - field_types_buf: t.CSizeT | t.CPtr = pool.alloc(8 * 48) - field_defaults_buf: t.CSizeT | t.CPtr = pool.alloc(8 * 48) - field_annot_buf: t.CSizeT | t.CPtr = pool.alloc(8 * 48) - if field_names_buf is None or field_types_buf is None or field_defaults_buf is None: - return 0 - if field_annot_buf is None: - return 0 - string.memset(field_names_buf, 0, 8 * 48) - string.memset(field_types_buf, 0, 8 * 48) - string.memset(field_defaults_buf, 0, 8 * 48) - string.memset(field_annot_buf, 0, 8 * 48) - - field_count: int = 0 - - # ============================================================ - # 1.5 继承父类字段(字段展平) - # - # 父类字段排在子类字段之前,结构体布局: - # [vtable_ptr?, parent_field1, ..., child_field1, ...] - # 跳过父类的 __vtable__ 字段(子类会有自己的 vtable 指针) - # ============================================================ - if parent_name is not None: - # 用 SHA1 感知查找父类,规避跨模块同名找错 - parent_entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_module( - parent_name, trans.ModuleSha1) - if parent_entry is None: - # 父类可能定义在另一个模块(不同 SHA1,如 HandlesBase.Mixin), - # find_struct_by_module 不回退全局查找,此处手动回退到 find_struct, - # 否则子类无法继承父类字段 → field_count==0 → __sizeof__ 失败 - parent_entry = HandlesStruct.find_struct(parent_name) - if parent_entry is not None: - pfc: int = parent_entry.FieldCount - for pfi in range(pfc): - pfe: HandlesStruct.FieldEntry | t.CPtr = HandlesStruct._get_field_entry( - parent_entry, pfi) - if pfe is None: - continue - pfn: str = HandlesStruct.get_field_name_ptr(pfe) - if pfn is None: - continue - # 跳过父类的 vtable 指针字段 - if string.strcmp(pfn, "__vtable__") == 0: - continue - if field_count < 48: - pft: llvmlite.LLVMType | t.CPtr = HandlesStruct.get_field_type_ptr(pfe) - pfd: ast.AST | t.CPtr = HandlesStruct.get_field_default_ptr(pfe) - pfa: str = HandlesStruct.get_field_annot_class_name(pfe) - field_names_buf[field_count] = t.CSizeT(pfn) - field_types_buf[field_count] = t.CSizeT(pft) - if pfd is not None: - field_defaults_buf[field_count] = t.CSizeT(pfd) - else: - field_defaults_buf[field_count] = 0 - if pfa is not None: - stored_val: t.CSizeT = t.CSizeT(pfa) - field_annot_buf[field_count] = stored_val - else: - field_annot_buf[field_count] = 0 - field_count += 1 - - children: list[ast.AST | t.CPtr] | t.CPtr = cd.children - if children is None: - return 0 - - cn: t.CSizeT = children.__len__() - for ci in range(cn): - stmt: ast.AST | t.CPtr = children.get(ci) - if stmt is None: - continue - sk: int = stmt.kind() - - if sk != ast.ASTKind.AnnAssign: continue - - # AnnAssign(target=Name(id), annotation=type, value=...) - aa: ast.AnnAssign | t.CPtr = (ast.AnnAssign | t.CPtr)(stmt) - if aa is None or aa.target is None: - continue - - # 获取字段名 - if aa.target.kind() != ast.ASTKind.Name: - continue - tgt: ast.Name | t.CPtr = (ast.Name | t.CPtr)(aa.target) - if tgt.id is None: - continue - - # 跳过编译期元数据字段(__provides__/__requires__/__require_must__) - # 这些字段只用于 with 上下文的静态可达性检查,不生成运行时代码 - # 避免类体中 list 字面量翻译失败(类体无 pool 变量上下文) - if string.strcmp(tgt.id, "__provides__") == 0: - continue - if string.strcmp(tgt.id, "__requires__") == 0: - continue - if string.strcmp(tgt.id, "__require_must__") == 0: - continue - - # 解析字段类型 - field_ty: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type( - pool, aa.annotation, trans._imported_modules, trans._from_imports, trans) - if field_ty is None: - field_ty = llvmlite.Int32(pool) - - # 存储到数组(指针转 CSizeT) - if field_count < 48: - diag_name_val: t.CSizeT = t.CSizeT(tgt.id) - field_names_buf[field_count] = diag_name_val - field_types_buf[field_count] = t.CSizeT(field_ty) - # 存储默认值 AST 指针(None=无默认值) - if aa.value is not None: - field_defaults_buf[field_count] = t.CSizeT(aa.value) - else: - field_defaults_buf[field_count] = 0 - # 提取原始类型注解的类名(联合类型简化为 Ptr(i8) 时回退查找结构体) - if aa.annotation is not None: - annot_cn: str = HandlesType.extract_class_name_from_annotation( - aa.annotation, trans._imported_modules) - if annot_cn is not None: - diag_cn_val: t.CSizeT = t.CSizeT(annot_cn) - field_annot_buf[field_count] = diag_cn_val - else: - field_annot_buf[field_count] = 0 - else: - field_annot_buf[field_count] = 0 - field_count += 1 - - if field_count == 0: - # PhaseA 预注册时,父类可能尚未注册(字母序单遍扫描), - # 导致子类无法继承父类字段 → field_count==0。 - # 静默返回,Phase2.py 的多遍 PhaseA-pre 会在后续遍中重试。 - if trans._declare_only == 1 and parent_name is not None: - return 0 - fb_cf: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb_cf is not None: - viperlib.snprintf(fb_cf, 1024, "%s has no fields", class_name) - VLogger.info(fb_cf, "CLASS") - return 0 - - # ============================================================ - # 2. 创建 LLVM StructType - # ============================================================ - # 构建 ParamNode 链表 - first_node: llvmlite.ParamNode | t.CPtr = None - prev_node: llvmlite.ParamNode | t.CPtr = None - total_field_count: int = field_count - - # 如果有虚表,首字段添加 i8* vtable 指针 - if has_vtable == 1: - i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, llvmlite.Int8(pool)) - vtable_node: llvmlite.ParamNode | t.CPtr = pool.alloc(llvmlite.ParamNode.__sizeof__()) - if vtable_node is None: - fb_vn: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb_vn is not None: - viperlib.snprintf(fb_vn, 1024, "failed to alloc vtable node for %s", class_name) - VLogger.error(fb_vn, "CLASS") - return 0 - string.memset(vtable_node, 0, llvmlite.ParamNode.__sizeof__()) - vtable_node.Ty = i8_ptr_ty - first_node = vtable_node - prev_node = vtable_node - total_field_count = field_count + 1 - - for fi in range(field_count): - fty_addr: t.CSizeT = field_types_buf[fi] - if fty_addr == 0: - continue - fty: llvmlite.LLVMType | t.CPtr = (llvmlite.LLVMType | t.CPtr)(t.CVoid(fty_addr, t.CPtr)) - - # 创建 ParamNode - pnode: llvmlite.ParamNode | t.CPtr = pool.alloc(llvmlite.ParamNode.__sizeof__()) - if pnode is None: - continue - string.memset(pnode, 0, llvmlite.ParamNode.__sizeof__()) - pnode.Ty = fty - - if first_node is None: - first_node = pnode - if prev_node is not None: - prev_node.Next = pnode - prev_node = pnode - - # 构造命名结构体类型名: "sha1.ClassName" 或 "ClassName" - type_name: str = class_name - if trans.ModuleSha1 is not None: - name_buf: t.CChar | t.CPtr = pool.alloc(64) - if name_buf is not None: - viperlib.snprintf(name_buf, 64, "%s.%s", trans.ModuleSha1, class_name) - type_name = name_buf - - # 创建 StructType(命名结构体) - struct_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Struct(pool, first_node, total_field_count, type_name) - if struct_ty is None: - fb_st: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb_st is not None: - viperlib.snprintf(fb_st, 1024, "failed to create StructType for %s", class_name) - VLogger.error(fb_st, "CLASS") - return 0 - - # 注册命名结构体到模块(输出 %"name" = type { ... } 定义行) - llvmlite.module_add_named_type(trans.Module, pool, struct_ty) - - # 扫描字段类型,为跨模块结构体引用添加 opaque 声明 - # 例如 list[int].__pool__ 引用 memhub.MemManager,需要在当前模块添加 %"sha1.MemManager" = type opaque - for fi in range(field_count): - fty_addr_op: t.CSizeT = field_types_buf[fi] - if fty_addr_op == 0: - continue - fty_op: llvmlite.LLVMType | t.CPtr = (llvmlite.LLVMType | t.CPtr)(t.CVoid(fty_addr_op, t.CPtr)) - llvmlite.module_ensure_opaque_for_type(trans.Module, pool, fty_op) - - # ============================================================ - # 3. 注册到 HandlesStruct - # ============================================================ - entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.register_struct( - pool, class_name, struct_ty, trans.ModuleSha1) - if entry is None: - fb_re: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb_re is not None: - viperlib.snprintf(fb_re, 1024, "failed to register %s", class_name) - VLogger.error(fb_re, "CLASS") - return 0 - - # 标记 VTable 状态(直接用 entry,规避跨模块同名 find_struct 找错) - if has_vtable == 1: - entry.HasVTable = 1 - if is_novtable_deco == 1: - entry.IsNoVTable = 1 - if parent_name is not None: - entry.ParentName = parent_name - - # 添加字段信息 - # 如果有虚表,先添加 __vtable__ 字段占位(索引 0),用户字段从索引 1 开始 - if has_vtable == 1: - i8_ptr_ty2: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, llvmlite.Int8(pool)) - HandlesStruct.add_field(pool, entry, "__vtable__", i8_ptr_ty2, None, None) - - for fi in range(field_count): - fname_addr: t.CSizeT = field_names_buf[fi] - if fname_addr == 0: - continue - fname: str = (str | t.CPtr)(t.CVoid(fname_addr, t.CPtr)) - fty_addr2: t.CSizeT = field_types_buf[fi] - if fty_addr2 == 0: - continue - fty2: llvmlite.LLVMType | t.CPtr = (llvmlite.LLVMType | t.CPtr)(t.CVoid(fty_addr2, t.CPtr)) - # 恢复默认值 AST 指针 - fdef_addr: t.CSizeT = field_defaults_buf[fi] - fdef: ast.AST | t.CPtr = None - if fdef_addr != 0: - fdef = (ast.AST | t.CPtr)(t.CVoid(fdef_addr, t.CPtr)) - # 恢复注解类名指针 - fannot_addr: t.CSizeT = field_annot_buf[fi] - fannot: t.CChar | t.CPtr = None - if fannot_addr != 0: - fannot = (t.CChar | t.CPtr)(t.CVoid(fannot_addr, t.CPtr)) - if fname is not None and fty2 is not None: - HandlesStruct.add_field(pool, entry, fname, fty2, fdef, fannot) - - # Phase 1a 声明模式:只注册 struct + 设置 OOP 标志,不翻译方法体 - if trans._declare_only == 1: - _translate_oop_methods(trans, cd, struct_ty, class_name, 1) - return 0 - - # ============================================================ - # 4. OOP 方法处理:扫描 FunctionDef,标记 OOP,翻译方法,生成 __before_init__ - # ============================================================ - _translate_oop_methods(trans, cd, struct_ty, class_name) - - return 0 - - -# ============================================================ -# VTable 生成 -# -# 生成 VTable 全局变量: -# @"SHA1.ClassName.vtable" = internal constant { i8*, i8*, ... } { -# i8* bitcast (ret (params)* @"SHA1.ClassName.method1" to i8*), -# ... -# } -# -# VTable 槽位顺序: class body 中 FunctionDef 的出现顺序 -# ============================================================ - -VTBL_METHOD_MAX: t.CDefine = 32 - - -# _vtable_strcat — 将 src 追加到 dst 末尾 -def _vtable_strcat(dst: t.CChar | t.CPtr, dst_size: t.CSizeT, - src: t.CChar | t.CPtr): - """将 src 追加到 dst 末尾""" - if dst is None or src is None: - return - dlen: t.CSizeT = string.strlen(dst) - slen: t.CSizeT = string.strlen(src) - remain: t.CSizeT = dst_size - dlen - if remain <= 0: - return - i: t.CSizeT = 0 - while i < slen and i + 1 < remain: - dst[dlen + i] = src[i] - i += 1 - dst[dlen + i] = '\0' - - -# _vtable_name_needs_quote — 检查 LLVM 标识符是否需要引号 -def _vtable_name_needs_quote(name: str) -> int: - """检查 LLVM 标识符是否需要引号(以数字开头或含 '.')""" - if name is None: - return 0 - if '0' <= name[0] <= '9': - return 1 - for i in name: - if i == '.': - return 1 - return 0 - - -# _format_func_type_str — 从 Function 对象生成函数类型字符串 -# -# 格式: ret_ty (param1_ty, param2_ty, ...) -# 例如: void ({i32, i32}*, i32) -def _format_func_type_str(pool: memhub.MemBuddy | t.CPtr, - buf: t.CChar | t.CPtr, buf_size: t.CSizeT, - func: llvmlite.Function | t.CPtr) -> int: - """从 Function 对象生成函数类型字符串""" - if buf is None or func is None or buf_size == 0: - return 0 - buf[0] = '\0' - - # 打印返回类型(使用访问器函数避免跨模块直接字段访问) - ret_ty: llvmlite.LLVMType | t.CPtr = llvmlite.function_get_ret_ty(func) - ret_buf: t.CChar | t.CPtr = pool.alloc(128) - if ret_buf is not None and ret_ty is not None: - ret_buf[0] = '\0' - llvmlite.TypePrint(ret_buf, 128, ret_ty, pool) - _vtable_strcat(buf, buf_size, ret_buf) - _vtable_strcat(buf, buf_size, " (") - - # 遍历参数(使用访问器函数避免跨模块直接字段访问) - cur: llvmlite.Param | t.CPtr = llvmlite.function_get_param_head(func) - first: int = 1 - param_buf: t.CChar | t.CPtr = pool.alloc(128) - while cur is not None: - if first == 0: - _vtable_strcat(buf, buf_size, ", ") - if param_buf is not None: - param_buf[0] = '\0' - param_ty: llvmlite.LLVMType | t.CPtr = llvmlite.param_get_ty(cur) - if param_ty is not None: - llvmlite.TypePrint(param_buf, 128, param_ty, pool) - _vtable_strcat(buf, buf_size, param_buf) - cur = llvmlite.param_get_next(cur) - first = 0 - _vtable_strcat(buf, buf_size, ")") - return 1 - - -# _generate_vtable — 生成 VTable 全局变量 -# -# 1. 收集 class body 中所有 FunctionDef 作为虚方法 -# 2. 构造 VTable 类型 { i8*, i8*, ... } -# 3. 构造初始化字符串 { i8* bitcast (...), ... } -# 4. 创建全局变量 @"SHA1.ClassName.vtable" -# 5. 存储虚方法名列表到 StructEntry -def _generate_vtable(trans: HT.Translator | t.CPtr, - cd: ast.ClassDef | t.CPtr, - class_name: str) -> int: - """生成 VTable 全局变量""" - if trans is None or cd is None or class_name is None: - return 0 - - # 懒导入 - import lib.core.Handles.HandlesFunctions as HandlesFunctions - import lib.core.Handles.HandlesExprCall as HandlesExprCall - - pool: memhub.MemBuddy | t.CPtr = trans.Pool - mod: llvmlite.LLVMModule | t.CPtr = trans.Module - - children: list[ast.AST | t.CPtr] | t.CPtr = cd.children - if children is None: - return 0 - cn: t.CSizeT = children.__len__() - - # 1. 收集虚方法信息 - full_names_buf: t.CSizeT | t.CPtr = pool.alloc(8 * VTBL_METHOD_MAX) - method_names_buf: t.CSizeT | t.CPtr = pool.alloc(8 * VTBL_METHOD_MAX) - # 记录每个方法的父类 SHA1(非 0=继承方法用父模块 SHA1 mangling,0=当前类方法) - method_parent_sha1s: t.CSizeT | t.CPtr = pool.alloc(8 * VTBL_METHOD_MAX) - if full_names_buf is None or method_names_buf is None or method_parent_sha1s is None: - return 0 - string.memset(full_names_buf, 0, 8 * VTBL_METHOD_MAX) - string.memset(method_names_buf, 0, 8 * VTBL_METHOD_MAX) - string.memset(method_parent_sha1s, 0, 8 * VTBL_METHOD_MAX) - - method_count: int = 0 - - # ============================================================ - # 1.5 继承父类虚方法 - # - # 父类虚方法排在子类虚方法之前,保持 vtable 槽位顺序一致。 - # 如果子类覆盖了方法,full_name 用子类的;否则用父类的。 - # 用 SHA1 感知查找,规避跨模块同名 find_struct 找错 - # ============================================================ - vt_self_entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_module( - class_name, trans.ModuleSha1) - parent_name: str = None - if vt_self_entry is not None: - parent_name = vt_self_entry.ParentName - if parent_name is not None: - # 查找父类 entry(优先同模块 SHA1 匹配) - vt_parent_entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_module( - parent_name, trans.ModuleSha1) - if vt_parent_entry is None: - # 跨模块继承: 父类在不同模块定义(SHA1 不同),回退到按类名查找 - vt_parent_entry = HandlesStruct.find_struct(parent_name) - parent_vt_count: int = 0 - if vt_parent_entry is not None: - parent_vt_count = vt_parent_entry.VTableMethodCount - if parent_vt_count > 0: - for pvi in range(parent_vt_count): - if method_count >= VTBL_METHOD_MAX: - break - pmethod_name: str = None - if vt_parent_entry is not None: - pmethod_name = HandlesStruct.get_vtable_method_name(parent_name, pvi) - if pmethod_name is None: - continue - # 检查子类是否覆盖了该方法,以及是否标记 @t.NoVTable - child_overrides: int = 0 - child_nvt: int = 0 - for ci2 in range(cn): - stmt2: ast.AST | t.CPtr = children.get(ci2) - if stmt2 is None: - continue - if stmt2.kind() != ast.ASTKind.FunctionDef: - continue - fd2: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(stmt2) - if fd2 is not None and fd2.name is not None: - if string.strcmp(fd2.name, pmethod_name) == 0: - child_overrides = 1 - # 检查子类覆盖方法是否标记 @t.NoVTable - if fd2.decorator_list is not None: - if _has_decorator(fd2.decorator_list, "NoVTable") == 1: - child_nvt = 1 - break - # 构造 full_name - # 子类覆盖且未标记 NoVTable → 用子类实现 - # 子类未覆盖 或 子类覆盖但标记 NoVTable → 用父类实现(保持 vtable 槽位) - pfname_buf: t.CChar | t.CPtr = pool.alloc(128) - if pfname_buf is not None: - if child_overrides == 1 and child_nvt == 0: - viperlib.snprintf(pfname_buf, 128, "%s.%s", class_name, pmethod_name) - else: - viperlib.snprintf(pfname_buf, 128, "%s.%s", parent_name, pmethod_name) - full_names_buf[method_count] = t.CSizeT(pfname_buf) - # 复制方法名(短名) - pmname_len: t.CSizeT = string.strlen(pmethod_name) - pmname_buf: t.CChar | t.CPtr = pool.alloc(pmname_len + 1) - if pmname_buf is not None: - string.strcpy(pmname_buf, pmethod_name) - method_names_buf[method_count] = t.CSizeT(pmname_buf) - # 记录 mangling 用的 SHA1(继承未覆盖的方法用父模块 SHA1) - if child_overrides == 1 and child_nvt == 0: - # 子类覆盖: 用当前模块 SHA1(保持 0) - method_parent_sha1s[method_count] = 0 - else: - # 继承未覆盖: 用父类模块 SHA1 - if vt_parent_entry is not None and vt_parent_entry.ModuleSha1 is not None: - method_parent_sha1s[method_count] = t.CSizeT(vt_parent_entry.ModuleSha1) - method_count += 1 - - # 2. 收集当前类的虚方法(跳过已从父类继承的) - for ci in range(cn): - stmt: ast.AST | t.CPtr = children.get(ci) - if stmt is None: - continue - if stmt.kind() != ast.ASTKind.FunctionDef: - continue - fd: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(stmt) - if fd is None or fd.name is None: - continue - if method_count >= VTBL_METHOD_MAX: - break - - mname: str = fd.name - # 跳过构造函数和特殊方法(不应放入虚表) - if string.strcmp(mname, "__init__") == 0: - continue - if string.strcmp(mname, "__before_init__") == 0: - continue - if string.strcmp(mname, "__new__") == 0: - continue - # 函数级装饰器过滤:判断方法是否应该进入虚表 - if _should_method_be_virtual(cd, fd, trans) == 0: - continue - # 检查是否已从父类继承(避免重复) - already_in_vt: int = 0 - for mi in range(method_count): - exist_addr: t.CSizeT = method_names_buf[mi] - if exist_addr != 0: - exist_name: str = (str | t.CPtr)(t.CVoid(exist_addr, t.CPtr)) - if exist_name is not None and string.strcmp(exist_name, mname) == 0: - already_in_vt = 1 - break - if already_in_vt == 1: - continue - # 构造 full_name = "ClassName.method_name" - fname_buf: t.CChar | t.CPtr = pool.alloc(128) - if fname_buf is not None: - viperlib.snprintf(fname_buf, 128, "%s.%s", class_name, mname) - full_names_buf[method_count] = t.CSizeT(fname_buf) - - # 复制方法名 - mname_len: t.CSizeT = string.strlen(mname) - mname_buf: t.CChar | t.CPtr = pool.alloc(mname_len + 1) - if mname_buf is not None: - string.strcpy(mname_buf, mname) - method_names_buf[method_count] = t.CSizeT(mname_buf) - - method_count += 1 - - if method_count == 0: - return 0 - - # 2. 构造 VTable 类型: { i8*, i8*, ..., i8* } - i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool) - i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty) - - first_node: llvmlite.ParamNode | t.CPtr = None - tail_node: llvmlite.ParamNode | t.CPtr = None - for i in range(method_count): - pnode: llvmlite.ParamNode | t.CPtr = llvmlite.new_param_node(pool, i8_ptr_ty) - if pnode is None: - continue - tail_node = llvmlite.param_list_append(first_node, tail_node, pnode) - if first_node is None: - first_node = tail_node - - vtable_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Struct(pool, first_node, method_count, None) - if vtable_ty is None: - return 0 - - # 3. 构造初始化字符串 - init_buf: t.CChar | t.CPtr = pool.alloc(4096) - if init_buf is None: - return 0 - init_buf[0] = '\0' - _vtable_strcat(init_buf, 4096, "{ ") - - for i in range(method_count): - if i > 0: - _vtable_strcat(init_buf, 4096, ", ") - - full_name_addr: t.CSizeT = full_names_buf[i] - if full_name_addr == 0: - _vtable_strcat(init_buf, 4096, "i8* null") - continue - - full_name: str = (str | t.CPtr)(t.CVoid(full_name_addr, t.CPtr)) - - # 检查是否是继承方法(method_parent_sha1s 非 0 表示用父模块 SHA1 mangling) - parent_sha1_addr: t.CSizeT = method_parent_sha1s[i] - if parent_sha1_addr != 0: - # 继承方法: 用父类模块 SHA1 做 mangling - parent_sha1: str = (str | t.CPtr)(t.CVoid(parent_sha1_addr, t.CPtr)) - mangled_name: str = HandlesFunctions._mangle_name_with_sha1(parent_sha1, full_name) - # 从全局函数表查找(跨模块函数不在当前模块表中) - func: llvmlite.Function | t.CPtr = HandlesExprCall.find_func_global(full_name) - else: - # 当前类方法: 用当前模块 SHA1 - mangled_name: str = HandlesFunctions._mangle_name(trans, full_name) - func: llvmlite.Function | t.CPtr = HandlesExprCall.find_func_in_table( - trans._funcs, trans._func_count, full_name) - # 当前模块表找不到时,回退到全局表 - if func is None: - func = HandlesExprCall.find_func_global(full_name) - - if func is None: - _vtable_strcat(init_buf, 4096, "i8* null") - continue - - # 构造函数类型字符串 - func_ty_buf: t.CChar | t.CPtr = pool.alloc(512) - if func_ty_buf is None: - _vtable_strcat(init_buf, 4096, "i8* null") - continue - _format_func_type_str(pool, func_ty_buf, 512, func) - - # 构造 bitcast 字符串: i8* bitcast (func_ty* @mangled to i8*) - _vtable_strcat(init_buf, 4096, "i8* bitcast (") - _vtable_strcat(init_buf, 4096, func_ty_buf) - _vtable_strcat(init_buf, 4096, "* @") - - if _vtable_name_needs_quote(mangled_name) != 0: - _vtable_strcat(init_buf, 4096, "\"") - _vtable_strcat(init_buf, 4096, mangled_name) - _vtable_strcat(init_buf, 4096, "\"") - else: - _vtable_strcat(init_buf, 4096, mangled_name) - _vtable_strcat(init_buf, 4096, " to i8*)") - - _vtable_strcat(init_buf, 4096, " }") - - # 4. 构造 VTable 全局变量名 - vtable_name_buf: t.CChar | t.CPtr = pool.alloc(128) - if vtable_name_buf is None: - return 0 - viperlib.snprintf(vtable_name_buf, 128, "%s.vtable", class_name) - vtable_mangled: str = HandlesFunctions._mangle_name(trans, vtable_name_buf) - - # 5. 创建全局变量 - gv: llvmlite.GlobalVariable | t.CPtr = llvmlite.new_global_variable( - pool, vtable_mangled, vtable_ty) - if gv is None: - return 0 - gv.Initializer = init_buf - gv.IsConstant = 1 - gv.Linkage = "internal" - - # 添加到模块 - llvmlite.module_add_global(mod, gv) - - # 6. 存储虚方法名列表到 StructEntry(直接用 entry,规避跨模块同名 find_struct 找错) - if vt_self_entry is not None: - vt_self_entry.VTableMethods = method_names_buf - vt_self_entry.VTableMethodCount = method_count - - return 0 - - -# ============================================================ -# OOP 方法翻译 -# -# 存在任意 FunctionDef 的 class 自动升级为 OOP 结构体。 -# 方法翻译为 SHA1.ClassName.method_name(self: Ptr(StructTy), ...) 函数。 -# self 参数直接注册为 SSA 值(不创建 alloca),使 self.field 能通过 GEP 直接访问。 -# ============================================================ - - -# ============================================================ -# _translate_oop_methods — 扫描 class body 中的方法并翻译 -# -# 遍历 ClassDef.children,对每个 FunctionDef: -# - 标记 OOP(mark_as_oop) -# - 如果是 __init__,标记 has_init -# - 翻译方法(生成 SHA1.ClassName.method_name 函数) -# 翻译完所有方法后,生成 __before_init__ 函数 -# ============================================================ -def _translate_oop_methods(trans: HT.Translator | t.CPtr, - cd: ast.ClassDef | t.CPtr, - struct_ty: llvmlite.LLVMType | t.CPtr, - class_name: str, - mark_only: int = 0) -> int: - """扫描 class body 中的方法并翻译,生成 __before_init__ - - mark_only: 0=全量翻译(默认),1=只设置 IsOOP/HasNew/HasInit 标志(不翻译方法体) - """ - if trans is None or cd is None or struct_ty is None or class_name is None: - return 0 - - children: list[ast.AST | t.CPtr] | t.CPtr = cd.children - if children is None: - return 0 - - cn: t.CSizeT = children.__len__() - has_method: int = 0 - has_init: int = 0 - has_new: int = 0 - - # 提前用类型指针定位 entry(规避跨模块同名类 find_struct 找错) - oop_entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_type(struct_ty) - - # 第一遍:检测是否有方法,标记 OOP - for ci in range(cn): - stmt: ast.AST | t.CPtr = children.get(ci) - if stmt is None: - continue - if stmt.kind() == ast.ASTKind.FunctionDef: - has_method = 1 - fd_check: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(stmt) - if fd_check is not None and fd_check.name is not None: - if string.strcmp(fd_check.name, "__init__") == 0: - has_init = 1 - if string.strcmp(fd_check.name, "__new__") == 0: - has_new = 1 - - if has_method == 0: - # 子类没有自己的方法,但可能继承了父类的虚方法 - # 用 oop_entry 直接获取 ParentName,规避 find_struct 按名查找找错 - parent_name: str = None - if oop_entry is not None: - parent_name = oop_entry.ParentName - if parent_name is not None: - parent_vt_count: int = HandlesStruct.get_vtable_method_count(parent_name) - if parent_vt_count > 0: - has_method = 1 # 标记为有方法(继承的虚方法) - if has_method == 0: - return 0 - - # 标记为 OOP 结构体 - if oop_entry is not None: - oop_entry.IsOOP = 1 - if has_init != 0: - oop_entry.HasInit = 1 - if has_new != 0: - oop_entry.HasNew = 1 - - # mark_only 模式:只设置标志,不翻译方法体 - if mark_only != 0: - return 0 - - # 第二遍:翻译每个方法 - for ci in range(cn): - stmt: ast.AST | t.CPtr = children.get(ci) - if stmt is None: - continue - if stmt.kind() == ast.ASTKind.FunctionDef: - fd: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(stmt) - if fd is not None and fd.name is not None: - _translate_method(trans, fd, struct_ty, class_name) - - # 如果有虚表,先生成 VTable 全局变量(设置 VTableMethodCount) - # 必须在 __before_init__ 之前,否则 __before_init__ 读不到 VTableMethodCount - # 用 oop_entry 直接检查,规避跨模块同名 find_struct 找错 - has_vt_flag: int = 0 - if oop_entry is not None: - has_vt_flag = oop_entry.HasVTable - if has_vt_flag == 1: - _generate_vtable(trans, cd, class_name) - - # 生成 __before_init__ 函数(零值填充 + 默认值赋值 + vtable 指针设置) - _generate_before_init(trans, struct_ty, class_name) - - return 0 - - -# ============================================================ -# _translate_method — 翻译单个方法 -# -# 生成: define @SHA1.ClassName.method_name(Ptr(StructTy) %self, ...) -# -# self 参数处理: -# - 类型 Ptr(struct_ty),直接注册为 SSA 值(不创建 alloca) -# - 使 self.field 能通过 GEP 直接访问原始结构体 -# ============================================================ -def _translate_method(trans: HT.Translator | t.CPtr, - fd: ast.FunctionDef | t.CPtr, - struct_ty: llvmlite.LLVMType | t.CPtr, - class_name: str) -> int: - """翻译单个方法,返回 0""" - if trans is None or fd is None or struct_ty is None or class_name is None: - return 0 - - # 懒导入 - import lib.core.Handles.HandlesFunctions as HandlesFunctions - import lib.core.Handles.HandlesVar as HandlesVar - import lib.core.Handles.HandlesBody as HandlesBody - import lib.core.Handles.HandlesType as HandlesType - import lib.core.Handles.HandlesExprCall as HandlesExprCall - - pool: memhub.MemBuddy | t.CPtr = trans.Pool - mod: llvmlite.LLVMModule | t.CPtr = trans.Module - imported_modules: str = trans._imported_modules - from_imports: str = trans._from_imports - funcs_ptr: HandlesExprCall.FuncEntry | t.CPtr = trans._funcs - func_count: int = trans._func_count - - i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool) - self_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, struct_ty) - - method_name: str = fd.name - - # 构建方法全名: ClassName.method_name - full_name_buf: t.CChar | t.CPtr = pool.alloc(128) - if full_name_buf is None: - return 0 - viperlib.snprintf(full_name_buf, 128, "%s.%s", class_name, method_name) - full_name: str = full_name_buf - - # SHA1 命名空间混淆 - mangled_name: str = HandlesFunctions._mangle_name(trans, full_name) - - # 推断返回类型 - ret_ty: llvmlite.LLVMType | t.CPtr = None - if fd.returns is not None: - ret_ty = HandlesType.resolve_annotation_type( - pool, fd.returns, imported_modules, from_imports, trans) - if ret_ty is None and fd.returns is not None: - if HandlesType.has_decorator_marker(fd.returns, "State") != 0: - ret_ty = llvmlite.Void(pool) - if ret_ty is None: - # __init__ 和 __before_init__ 返回 void - if string.strcmp(method_name, "__init__") == 0: - ret_ty = llvmlite.Void(pool) - # __new__ 返回 Ptr(struct_ty)(结构体指针作为存储空间) - elif string.strcmp(method_name, "__new__") == 0: - ret_ty = llvmlite.Ptr(pool, struct_ty) - else: - param_types_str: str = HandlesType.build_param_types_str(pool, fd.args) - ret_ty = HandlesType.infer_return_type( - pool, fd.children, param_types_str) - - # 创建 LLVM 函数 - func: llvmlite.Function | t.CPtr = llvmlite.create_function( - pool, mod, mangled_name, ret_ty) - if func is None: - return 0 - - # 提取默认参数信息(方法的 args[0] 是 self,不含在 param_count 中) - # 注意: 必须先把属性赋给显式类型为 list[...] | t.CPtr 的局部变量再调用 __len__(), - # 否则编译器无法识别属性返回的 list 类型,GEP base 会变成 i32 0 导致 llc 报错 - md_defaults: t.CVoid | t.CPtr = None - md_default_count: int = 0 - md_param_count: int = 0 - md_args_node: ast.Arguments | t.CPtr = fd.args - if md_args_node is not None: - md_ags: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(md_args_node) - if md_ags.args is not None: - md_alist: list[ast.AST | t.CPtr] | t.CPtr = md_ags.args - md_param_count = md_alist.__len__() - 1 - if md_ags.defaults is not None: - md_dlist: list[ast.AST | t.CPtr] | t.CPtr = md_ags.defaults - md_defaults = md_dlist - md_default_count = md_dlist.__len__() - - # 注册到函数表(用 ClassName.method_name 作为查找名,支持后缀匹配) - max_funcs: int = 256 - if HandlesExprCall.add_func_to_table(funcs_ptr, func_count, full_name, func, max_funcs, - md_defaults, md_default_count, md_param_count) == 0: - trans._func_count = func_count + 1 - - # 添加 self 参数(Ptr(struct_ty)) - llvmlite.add_param(pool, func, self_ptr_ty, "%self") - - # 添加其他参数(支持类型注解,跳过索引 0 的 self 参数) - args_node: ast.Arguments | t.CPtr = fd.args - if args_node is not None: - ags: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(args_node) - if ags.args is not None: - alist: list[ast.AST | t.CPtr] | t.CPtr = ags.args - an: t.CSizeT = alist.__len__() - for ai in range(1, an): - arg: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(alist.get(ai)) - if arg is not None and arg.arg is not None: - param_ty: llvmlite.LLVMType | t.CPtr = i32_ty - if arg.annotation is not None: - resolved: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type( - pool, arg.annotation, imported_modules, from_imports, trans) - if resolved is not None: - param_ty = resolved - pname: t.CChar | t.CPtr = pool.alloc(32) - if pname is not None: - viperlib.snprintf(pname, 32, "%%%s", arg.arg) - llvmlite.add_param(pool, func, param_ty, pname) - - # 创建 entry 块 - entry_blk: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, "entry") - if entry_blk is None: - return 0 - - # 创建方法专属 builder - func_builder: llvmlite.IRBuilder | t.CPtr = llvmlite.new_builder(pool, func) - if func_builder is None: - return 0 - llvmlite.position_at_end(func_builder, entry_blk) - - # 进入函数作用域 - HandlesVar.enter_scope(trans.SymTab, SCOPE_FUNCTION) - - # 为 self 创建 alloca 并 store(与其他参数一致) - # 修复: 之前 self 注册为 SSA 值导致 translate_name_value 错误地 load 一次 - # 将 Ptr(struct_ty) 变成 struct 值,引发变参函数 ABI 不匹配崩溃 - self_alloca: llvmlite.Value | t.CPtr = llvmlite.build_alloca(func_builder, self_ptr_ty) - if self_alloca is not None: - HandlesVar.define_var(trans.SymTab, "self", self_alloca) - # 设置 self 的类型注解类名(属性访问 lookup_field 回退查找用) - HandlesVar.set_var_annot_class_name(trans.SymTab, "self", class_name) - self_val: llvmlite.Value | t.CPtr = llvmlite.SSAValue(pool, self_ptr_ty, "%self") - llvmlite.build_store(func_builder, self_val, self_alloca) - - # 为其他参数创建 alloca 并 store(与普通函数一致,跳过索引 0 的 self 参数) - if args_node is not None: - ags2: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(args_node) - if ags2.args is not None: - alist2: list[ast.AST | t.CPtr] | t.CPtr = ags2.args - an2: t.CSizeT = alist2.__len__() - for ai2 in range(1, an2): - arg2: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(alist2.get(ai2)) - if arg2 is not None and arg2.arg is not None: - param_ty2: llvmlite.LLVMType | t.CPtr = i32_ty - if arg2.annotation is not None: - resolved2: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type( - pool, arg2.annotation, imported_modules, from_imports, trans) - if resolved2 is not None: - param_ty2 = resolved2 - alloca: llvmlite.Value | t.CPtr = llvmlite.build_alloca(func_builder, param_ty2) - if alloca is not None: - HandlesVar.define_var(trans.SymTab, arg2.arg, alloca) - # 存储原始类型注解的类名(方法调用检测时,Ptr(i8) 回退到类名查找结构体) - if arg2.annotation is not None: - cls_nm_oc: str = HandlesType.extract_class_name_from_annotation( - arg2.annotation, imported_modules) - if cls_nm_oc is not None: - HandlesVar.set_var_annot_class_name( - trans.SymTab, arg2.arg, cls_nm_oc) - pname2: t.CChar | t.CPtr = pool.alloc(32) - if pname2 is not None: - viperlib.snprintf(pname2, 32, "%%%s", arg2.arg) - param_val: llvmlite.Value | t.CPtr = llvmlite.SSAValue( - pool, param_ty2, pname2) - llvmlite.build_store(func_builder, param_val, alloca) - - # 保存模块级作用域状态 - old_func: llvmlite.Function | t.CPtr = trans._cur_func - old_builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder - old_global_count: int = trans._global_name_count - old_nonlocal_count: int = trans._nonlocal_name_count - old_env_count: int = trans._closure_env_count - - trans._cur_func = func - trans._cur_builder = func_builder - HT.clear_scope_names(trans) - - # 预扫描方法体:为局部变量提前创建 alloca - body: list[ast.AST | t.CPtr] | t.CPtr = fd.children - if body is not None: - bn: t.CSizeT = body.__len__() - for bi in range(bn): - stmt: ast.AST | t.CPtr = body.get(bi) - if stmt is not None: - HandlesBody.pre_scan_allocas(trans, stmt) - - # 翻译方法体 - if body is not None: - bn2: t.CSizeT = body.__len__() - for bi2 in range(bn2): - stmt2: ast.AST | t.CPtr = body.get(bi2) - if stmt2 is not None: - HandlesBody.translate_stmt(trans, stmt2) - - # 如果返回类型为 void,添加 ret void;否则添加隐式 ret 0 - is_void: int = 0 - if ret_ty is not None: - match ret_ty: - case llvmlite.LLVMType.Void(): - is_void = 1 - - if is_void != 0: - if llvmlite.builder_cur_block_is_terminated(func_builder) == 0: - llvmlite.build_ret_void(func_builder) - else: - last_is_return: int = 0 - if body is not None: - bn3: t.CSizeT = body.__len__() - if bn3 > 0: - last_stmt: ast.AST | t.CPtr = body.get(bn3 - 1) - if last_stmt is not None and last_stmt.kind() == ast.ASTKind.Return: - last_is_return = 1 - if last_is_return == 0: - if llvmlite.builder_cur_block_is_terminated(func_builder) == 0: - # 根据返回类型生成正确的零值返回 - _m_is_void: int = 0 - _m_is_ptr: int = 0 - if ret_ty is not None: - match ret_ty: - case llvmlite.LLVMType.Void(): - _m_is_void = 1 - case llvmlite.LLVMType.Ptr(_m_pe): - _m_is_ptr = 1 - if _m_is_void != 0: - llvmlite.build_ret_void(func_builder) - elif _m_is_ptr != 0: - _m_null_val: llvmlite.Value | t.CPtr = llvmlite.ConstNull(pool, ret_ty, "null") - llvmlite.build_ret(func_builder, _m_null_val) - else: - _m_zero_val: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, 0) - llvmlite.build_ret(func_builder, _m_zero_val) - - # 恢复模块级作用域 - HandlesVar.exit_scope(trans.SymTab) - trans._cur_func = old_func - trans._cur_builder = old_builder - trans._global_name_count = old_global_count - trans._nonlocal_name_count = old_nonlocal_count - trans._closure_env_count = old_env_count - - return 0 - - -# ============================================================ -# _generate_before_init — 生成 __before_init__ 函数 -# -# 生成: define void @SHA1.ClassName.__before_init__(Ptr(StructTy) %self) -# -# 执行: -# 1. store zeroinitializer 到 %self(零值填充) -# 2. 逐字段 store 默认值(如有) -# 3. ret void -# ============================================================ -def _generate_before_init(trans: HT.Translator | t.CPtr, - struct_ty: llvmlite.LLVMType | t.CPtr, - class_name: str) -> int: - """生成 __before_init__ 函数,返回 0""" - if trans is None or struct_ty is None or class_name is None: - return 0 - - import lib.core.Handles.HandlesFunctions as HandlesFunctions - import lib.core.Handles.HandlesVar as HandlesVar - import lib.core.Handles.HandlesExpr as HandlesExpr - import lib.core.Handles.HandlesExprCall as HandlesExprCall - - pool: memhub.MemBuddy | t.CPtr = trans.Pool - mod: llvmlite.LLVMModule | t.CPtr = trans.Module - funcs_ptr: HandlesExprCall.FuncEntry | t.CPtr = trans._funcs - func_count: int = trans._func_count - - self_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, struct_ty) - void_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Void(pool) - - # 构建函数名: ClassName.__before_init__ - full_name_buf: t.CChar | t.CPtr = pool.alloc(128) - if full_name_buf is None: - return 0 - viperlib.snprintf(full_name_buf, 128, "%s.__before_init__", class_name) - full_name: str = full_name_buf - - mangled_name: str = HandlesFunctions._mangle_name(trans, full_name) - - # 创建函数 - func: llvmlite.Function | t.CPtr = llvmlite.create_function( - pool, mod, mangled_name, void_ty) - if func is None: - return 0 - - # 注册到函数表 - max_funcs: int = 256 - if HandlesExprCall.add_func_to_table(funcs_ptr, func_count, full_name, func, max_funcs) == 0: - trans._func_count = func_count + 1 - - # 添加 self 参数 - llvmlite.add_param(pool, func, self_ptr_ty, "%self") - - # 创建 entry 块 + builder - entry_blk: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, "entry") - if entry_blk is None: - return 0 - func_builder: llvmlite.IRBuilder | t.CPtr = llvmlite.new_builder(pool, func) - if func_builder is None: - return 0 - llvmlite.position_at_end(func_builder, entry_blk) - - # 注册 self 为 SSA 值 - self_val: llvmlite.Value | t.CPtr = llvmlite.SSAValue(pool, self_ptr_ty, "%self") - - # 1. 零值填充: store zeroinitializer, Ptr(struct_ty)* %self - zero: llvmlite.Value | t.CPtr = llvmlite.ConstZero(pool, struct_ty) - if zero is not None: - llvmlite.build_store(func_builder, zero, self_val) - - # 1.5 如果有虚表,store vtable 全局地址到 __vtable__ 字段(索引 0) - # 用 find_struct_by_type 定位 entry,规避跨模块同名 find_struct 找错 - bi_entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_type(struct_ty) - bi_has_vt: int = 0 - if bi_entry is not None: - bi_has_vt = bi_entry.HasVTable - if bi_has_vt == 1: - vt_method_count: int = 0 - if bi_entry is not None: - vt_method_count = bi_entry.VTableMethodCount - if vt_method_count > 0: - # 构造 vtable 类型 { i8*, i8*, ..., i8* } - vt_i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool) - vt_i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, vt_i8_ty) - - vt_first_node: llvmlite.ParamNode | t.CPtr = None - vt_prev_node: llvmlite.ParamNode | t.CPtr = None - for vti in range(vt_method_count): - vtnode: llvmlite.ParamNode | t.CPtr = llvmlite.new_param_node(pool, vt_i8_ptr_ty) - if vtnode is None: - continue - if vt_first_node is None: - vt_first_node = vtnode - if vt_prev_node is not None: - llvmlite.paramnode_set_next(vt_prev_node, vtnode) - vt_prev_node = vtnode - - vt_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Struct(pool, vt_first_node, vt_method_count, None) - vt_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, vt_ty) - - # 构造 vtable 全局变量名 - vt_name_buf: t.CChar | t.CPtr = pool.alloc(128) - if vt_name_buf is not None: - viperlib.snprintf(vt_name_buf, 128, "%s.vtable", class_name) - vt_full_name: str = vt_name_buf - vt_mangled: str = HandlesFunctions._mangle_name(trans, vt_full_name) - - # GEP 到 __vtable__ 字段(索引 0) - vt_slot: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct( - func_builder, struct_ty, vt_i8_ptr_ty, self_val, 0) - if vt_slot is not None: - # 创建全局变量引用 Value - vt_ref: llvmlite.Value | t.CPtr = llvmlite.new_value(pool) - if vt_ref is not None: - llvmlite.value_set_ty(vt_ref, vt_ptr_ty) - llvmlite.value_set_isconst(vt_ref, 1) - # Name 格式: @"mangled" 或 @mangled - vt_ref_name: t.CChar | t.CPtr = pool.alloc(256) - if vt_ref_name is not None: - vt_ref_name[0] = '\0' - if _vtable_name_needs_quote(vt_mangled) != 0: - viperlib.snprintf(vt_ref_name, 256, "@\"%s\"", vt_mangled) - else: - viperlib.snprintf(vt_ref_name, 256, "@%s", vt_mangled) - llvmlite.value_set_name(vt_ref, vt_ref_name) - - # bitcast 到 i8* - vt_as_i8: llvmlite.Value | t.CPtr = llvmlite.build_bitcast( - func_builder, vt_ref, vt_i8_ptr_ty) - if vt_as_i8 is not None: - llvmlite.build_store(func_builder, vt_as_i8, vt_slot) - - # 2. 逐字段 store 默认值(用 bi_entry 直接访问,规避跨模块同名 find_struct 找错) - if bi_entry is not None: - for fi in range(bi_entry.FieldCount): - fe: HandlesStruct.FieldEntry | t.CPtr = HandlesStruct._get_field_entry( - bi_entry, fi) - if fe is None or fe.DefaultVal is None: - continue - # 翻译默认值表达式 - default_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( - func_builder, pool, mod, fe.DefaultVal, None, 0, trans) - if default_val is None: - continue - # GEP 到字段 - field_ptr: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct( - func_builder, struct_ty, fe.Ty, self_val, fe.Index) - if field_ptr is None: - continue - # 类型转换并 store - default_val = HandlesExpr.coerce_to_type(func_builder, default_val, fe.Ty) - llvmlite.build_store(func_builder, default_val, field_ptr) - - # 3. ret void - llvmlite.build_ret_void(func_builder) - - return 0 diff --git a/TransPyV/App/lib/core/Handles/HandlesEnum.py b/TransPyV/App/lib/core/Handles/HandlesEnum.py deleted file mode 100644 index bb4bb55..0000000 --- a/TransPyV/App/lib/core/Handles/HandlesEnum.py +++ /dev/null @@ -1,238 +0,0 @@ -import t, c -from stdint import * -import memhub -import string -import llvmlite -import stdio -import viperlib -import lib.core.VLogger as VLogger - - -# ============================================================ -# HandlesEnum - 枚举类型注册和成员查找 -# -# 管理 t.CEnum 派生类的成员信息: -# - 枚举名 → EnumEntry(基准类型 + 成员表) -# - 成员名 → EnumMember(值、类型) -# -# 使用全局数组存储,线性查找(枚举数量通常很少) -# ============================================================ - -ENUM_MAX: t.CDefine = 64 -ENUM_MEMBER_MAX: t.CDefine = 64 - - -# ============================================================ -# EnumMember - 枚举成员条目 -# ============================================================ -@t.NoVTable -class EnumMember: - Name: t.CChar | t.CPtr # 成员名(字符串) - Value: t.CInt64T # 成员的整数值 - Ty: llvmlite.LLVMType | t.CPtr # 成员的 LLVM 类型(用于混用类型场景) - - -# ============================================================ -# EnumEntry - 枚举类型条目 -# ============================================================ -@t.NoVTable -class EnumEntry: - Name: t.CChar | t.CPtr # 枚举类名 - BaseTy: llvmlite.LLVMType | t.CPtr # 基准类型(所有成员类型中最大的) - MemberCount: int # 成员数量 - Members: EnumMember | t.CPtr # 成员数组(ENUM_MEMBER_MAX 个槽位) - - -# ============================================================ -# 全局注册表(静态分配) -# ============================================================ -_enum_table: EnumEntry | t.CPtr = None -_enum_count: int = 0 - - -# ============================================================ -# init_enum_table — 初始化枚举注册表 -# ============================================================ -def init_enum_table(pool: memhub.MemBuddy | t.CPtr) -> int: - """初始化枚举注册表,返回 1 成功""" - global _enum_table - global _enum_count - - if _enum_table is not None: - return 1 - - entry_size: t.CSizeT = EnumEntry.__sizeof__() - _enum_table = pool.alloc(entry_size * ENUM_MAX) - if _enum_table is None: - return 0 - string.memset(_enum_table, 0, entry_size * ENUM_MAX) - _enum_count = 0 - return 1 - - -# ============================================================ -# _get_enum_entry — 获取第 i 个 EnumEntry 槽位 -# ============================================================ -def _get_enum_entry(i: int) -> EnumEntry | t.CPtr: - """获取第 i 个枚举条目""" - if _enum_table is None or i < 0 or i >= ENUM_MAX: - return None - entry_size: t.CSizeT = EnumEntry.__sizeof__() - addr: t.CUInt64T = t.CUInt64T(_enum_table) + i * entry_size - return (EnumEntry | t.CPtr)(t.CVoid(addr, t.CPtr)) - - -# ============================================================ -# _get_enum_member — 获取枚举中第 i 个 EnumMember 槽位 -# ============================================================ -def _get_enum_member(enum_entry: EnumEntry | t.CPtr, i: int) -> EnumMember | t.CPtr: - """获取枚举中第 i 个成员条目""" - if enum_entry is None or i < 0 or i >= ENUM_MEMBER_MAX: - return None - member_size: t.CSizeT = EnumMember.__sizeof__() - addr: t.CUInt64T = t.CUInt64T(enum_entry.Members) + i * member_size - return (EnumMember | t.CPtr)(t.CVoid(addr, t.CPtr)) - - -# ============================================================ -# register_enum — 注册枚举类型 -# -# 返回 EnumEntry 指针,可用于添加成员 -# ============================================================ -def register_enum(pool: memhub.MemBuddy | t.CPtr, - name: str, - base_ty: llvmlite.LLVMType | t.CPtr) -> EnumEntry | t.CPtr: - """注册枚举类型,返回 EnumEntry 指针""" - if init_enum_table(pool) == 0: - return None - - # 检查是否已注册 - existing: EnumEntry | t.CPtr = find_enum(name) - if existing is not None: - return existing - - if _enum_count >= ENUM_MAX: - fb_et: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb_et is not None: - viperlib.snprintf(fb_et, 1024, "table full, cannot register %s", name) - VLogger.error(fb_et, "ENUM") - return None - - entry: EnumEntry | t.CPtr = _get_enum_entry(_enum_count) - if entry is None: - return None - - # 分配成员数组 - member_size: t.CSizeT = EnumMember.__sizeof__() - entry.Members = pool.alloc(member_size * ENUM_MEMBER_MAX) - if entry.Members is None: - return None - string.memset(entry.Members, 0, member_size * ENUM_MEMBER_MAX) - - # 复制类名 - name_len: t.CSizeT = string.strlen(name) - name_buf: t.CChar | t.CPtr = pool.alloc(name_len + 1) - if name_buf is not None: - string.strcpy(name_buf, name) - entry.Name = name_buf - - entry.BaseTy = base_ty - entry.MemberCount = 0 - - _enum_count += 1 - return entry - - -# ============================================================ -# add_enum_member — 向枚举添加成员 -# ============================================================ -def add_enum_member(pool: memhub.MemBuddy | t.CPtr, - enum_entry: EnumEntry | t.CPtr, - member_name: str, - member_val: t.CInt64T, - member_ty: llvmlite.LLVMType | t.CPtr) -> int: - """向枚举添加成员,返回成员索引(-1 失败)""" - if enum_entry is None or member_name is None or member_ty is None: - return -1 - - if enum_entry.MemberCount >= ENUM_MEMBER_MAX: - fb_em: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb_em is not None: - viperlib.snprintf(fb_em, 1024, "member table full for %s", enum_entry.Name) - VLogger.error(fb_em, "ENUM") - return -1 - - idx: int = enum_entry.MemberCount - me: EnumMember | t.CPtr = _get_enum_member(enum_entry, idx) - if me is None: - return -1 - - # 复制成员名 - name_len: t.CSizeT = string.strlen(member_name) - name_buf: t.CChar | t.CPtr = pool.alloc(name_len + 1) - if name_buf is not None: - string.strcpy(name_buf, member_name) - me.Name = name_buf - - me.Value = member_val - me.Ty = member_ty - - enum_entry.MemberCount = idx + 1 - return idx - - -# ============================================================ -# find_enum — 按枚举类名查找 -# ============================================================ -def find_enum(name: str) -> EnumEntry | t.CPtr: - """按枚举类名查找,返回 EnumEntry 或 None""" - if name is None or _enum_table is None: - return None - for i in range(_enum_count): - entry: EnumEntry | t.CPtr = _get_enum_entry(i) - if entry is not None and entry.Name is not None: - if string.strcmp(entry.Name, name) == 0: - return entry - return None - - -# ============================================================ -# lookup_enum_member — 按枚举类名和成员名查找 -# ============================================================ -def lookup_enum_member(enum_name: str, - member_name: str) -> EnumMember | t.CPtr: - """按枚举类名和成员名查找,返回 EnumMember 或 None""" - if enum_name is None or member_name is None: - return None - entry: EnumEntry | t.CPtr = find_enum(enum_name) - if entry is None: - return None - for mi in range(entry.MemberCount): - me: EnumMember | t.CPtr = _get_enum_member(entry, mi) - if me is not None and me.Name is not None: - if string.strcmp(me.Name, member_name) == 0: - return me - return None - - -# ============================================================ -# is_enum_class — 检查类名是否为已注册枚举 -# ============================================================ -def is_enum_class(name: str) -> int: - """检查类名是否为已注册枚举,返回 1=是 / 0=否""" - if name is None: - return 0 - if find_enum(name) is not None: - return 1 - return 0 - - -# ============================================================ -# get_enum_base_type — 按枚举类名获取基准类型 -# ============================================================ -def get_enum_base_type(enum_name: str) -> llvmlite.LLVMType | t.CPtr: - """按枚举类名获取基准类型""" - entry: EnumEntry | t.CPtr = find_enum(enum_name) - if entry is not None: - return entry.BaseTy - return None diff --git a/TransPyV/App/lib/core/Handles/HandlesExpr.py b/TransPyV/App/lib/core/Handles/HandlesExpr.py deleted file mode 100644 index b8cff46..0000000 --- a/TransPyV/App/lib/core/Handles/HandlesExpr.py +++ /dev/null @@ -1,2970 +0,0 @@ -import t, c -from stdint import * -import ast -import memhub -import string -import llvmlite -import stdlib -import stdio -import viperlib -import w32.fileio as fileio -import lib.core.Handles.HandlesBase as HandlesBase -import lib.core.Handles.HandlesTranslator as HT -import lib.core.Handles.HandlesVar as HandlesVar -import lib.core.Handles.HandlesExprOps as HandlesExprOps -import lib.core.Handles.HandlesExprCall as HandlesExprCall -import lib.core.Handles.HandlesNonlocal as HandlesNonlocal -import lib.core.Handles.HandlesType as HandlesType -import lib.core.Handles.HandlesStruct as HandlesStruct -import lib.core.Handles.HandlesEnum as HandlesEnum -import lib.core.Handles.HandlesClassDef as HandlesClassDef -import lib.core.Handles.HandlesImports as HandlesImports -import lib.core.StubMerger as StubMerger -import lib.core.VLogger as VLogger -import lib.Projectrans.Config as Config - - -# ============================================================ -# HandlesExpr - 表达式处理(Mixin 继承模式) -# -# 工具函数保留为模块级(供外部调用),ExprHandle.HandleValue 提供 trans 接口 -# ============================================================ - - -# ============================================================ -# 从 AST 节点提取函数名 -# ============================================================ -def get_func_name(func_node: ast.AST | t.CPtr) -> str: - """从函数节点提取函数名""" - if func_node is None: - return None - k: int = func_node.kind() - if k == ast.ASTKind.Name: - nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(func_node) - return nm.id - elif k == ast.ASTKind.Attribute: - at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(func_node) - return at.attr - return None - - -# ============================================================ -# 转义 LLVM IR 字符串字面量 -# ============================================================ -def escape_llvm_string(pool: memhub.MemBuddy | t.CPtr, - src: t.CChar | t.CPtr) -> t.CChar | t.CPtr: - """将字符串转换为 LLVM IR 字符串字面量 c"...\\00" """ - if src is None: - return None - slen: t.CSizeT = string.strlen(src) - alloc_size: t.CSizeT = 4 * slen + 8 - buf: t.CChar | t.CPtr = pool.alloc(alloc_size) - if buf is None: - return None - pos: t.CSizeT = 0 - buf[pos] = 'c' - pos += 1 - buf[pos] = '"' - pos += 1 - for i in range(slen): - ch: t.CChar = src[i] - if ch == '\0': - break - if ch == '\"' or ch == '\\' or ch < 0x20: - buf[pos] = '\\' - pos += 1 - hi: int = (ch >> 4) & 0xF - lo: int = ch & 0xF - if hi < 10: - buf[pos] = '0' + hi - else: - buf[pos] = 'A' + (hi - 10) - pos += 1 - if lo < 10: - buf[pos] = '0' + lo - else: - buf[pos] = 'A' + (lo - 10) - pos += 1 - else: - buf[pos] = ch - pos += 1 - buf[pos] = '\\' - pos += 1 - buf[pos] = '0' - pos += 1 - buf[pos] = '0' - pos += 1 - buf[pos] = '"' - pos += 1 - buf[pos] = '\0' - return buf - - -# ============================================================ -# 获取 LLVM 整数类型的位宽 -# ============================================================ -def get_llvm_type_bits(ty: llvmlite.LLVMType | t.CPtr) -> int: - """获取 LLVM 整数类型的位宽,非整数类型返回 0""" - if ty is None: - return 0 - match ty: - case llvmlite.LLVMType.Int(bits): - return bits - case _: - return 0 - - -# ============================================================ -# 获取 LLVM 浮点类型的位宽 -# ============================================================ -def get_llvm_float_bits(ty: llvmlite.LLVMType | t.CPtr) -> int: - """获取 LLVM 浮点类型的位宽,非浮点类型返回 0""" - if ty is None: - return 0 - match ty: - case llvmlite.LLVMType.Float(bits): - return bits - case _: - return 0 - - -# ============================================================ -# 检查类型是否为 Ptr(独立函数,避免嵌套 match 的编译器 BUG) -# -# 嵌套 match 的 REnum 检测在宿主编译器中有 BUG:当 match 嵌套在 -# 另一个 match 的 case 块中时,内层 match 走非 REnum 路径, -# 导致 case 列表为空。提取为独立函数可规避此问题。 -# ============================================================ -def is_ptr_type(ty: llvmlite.LLVMType | t.CPtr) -> int: - """检查 ty 是否是 Ptr 类型,返回 1=是, 0=否""" - if ty is None: - return 0 - match ty: - case llvmlite.LLVMType.Ptr(pointee): - return 1 - case _: - return 0 - - -# ============================================================ -# 检查类型是否为 Array(独立函数,避免嵌套 match 的编译器 BUG) -# ============================================================ -def is_array_type(ty: llvmlite.LLVMType | t.CPtr) -> int: - """检查 ty 是否是 Array 类型,返回 1=是, 0=否""" - if ty is None: - return 0 - match ty: - case llvmlite.LLVMType.Array(_, _): - return 1 - case _: - return 0 - - -# ============================================================ -# _get_custom_struct_cls_nm - 检查类型是否为已注册的自定义结构体 -# -# 处理两种情况: -# - ty 直接是 Struct → 检查是否注册 -# - ty 是 Ptr(Struct) → 检查 pointee 是否注册 -# -# 返回类名字符串或 None。用于 subscript 操作中判断是否需要 -# 转发到 __getitem__/__setitem__ 而非生成 GEP。 -# ============================================================ -def _get_custom_struct_cls_nm(pool: memhub.MemBuddy | t.CPtr, - ty: llvmlite.LLVMType | t.CPtr) -> str: - """检查 ty 或 ty 的 pointee 是否是已注册的自定义结构体,返回类名或 None""" - if ty is None: - return None - # 直接检查 ty 是否是注册的结构体 - cls_nm_direct: str = HandlesStruct.get_class_name_by_type(pool, ty) - if cls_nm_direct is not None: - return cls_nm_direct - # 如果 ty 是 Ptr,检查 pointee - if is_ptr_type(ty) != 0: - pointee_cs: llvmlite.LLVMType | t.CPtr = ty.Pointee - if pointee_cs is not None: - return HandlesStruct.get_class_name_by_type(pool, pointee_cs) - return None - - -# ============================================================ -# _deref_if_ptr_ptr - 如果 obj_ptr 是 Ptr(Ptr(...)),load 解引用 -# -# 用于支持 X|t.CPtr 类型变量的属性访问: -# - 值类型变量 (cnt: Counter): alloca 类型是 Ptr(Struct) → 不解引用 -# - 指针类型变量 (r: Vec2|t.CPtr): alloca 类型是 Ptr(Ptr(Struct)) → load 解引用 -# -# 用 is_ptr_type 避免嵌套 match 的编译器 BUG -# ============================================================ -def _deref_if_ptr_ptr(builder: llvmlite.IRBuilder | t.CPtr, - obj_ptr: llvmlite.Value | t.CPtr) -> llvmlite.Value | t.CPtr: - """如果 obj_ptr 是 Ptr(Ptr(...)),load 解引用获取内层指针""" - if obj_ptr is None or obj_ptr.Ty is None: - return obj_ptr - if is_ptr_type(obj_ptr.Ty) == 0: - return obj_ptr - pointee: llvmlite.LLVMType | t.CPtr = obj_ptr.Ty.Pointee - if pointee is None: - return obj_ptr - if is_ptr_type(pointee) == 0: - return obj_ptr - # obj_ptr 是 Ptr(Ptr(...)),load 解引用 - loaded: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, pointee, obj_ptr) - if loaded is None: - return obj_ptr - return loaded - - -# ============================================================ -# 类型强制转换:整数 sext/trunc,浮点 fpext/fptrunc,int↔float si2fp/fp2si -# ============================================================ -def coerce_to_type(builder: llvmlite.IRBuilder | t.CPtr, - val: llvmlite.Value | t.CPtr, - target_ty: llvmlite.LLVMType | t.CPtr) -> llvmlite.Value | t.CPtr: - """将 val 强制转换为 target_ty - - 整数: sext(扩展)/ trunc(截断) - 浮点: fpext(扩展)/ fptrunc(截断) - int→float: sitofp - float→int: fptosi - """ - if val is None or target_ty is None: - return val - # 整数转换 - val_bits: int = get_llvm_type_bits(val.Ty) - target_bits: int = get_llvm_type_bits(target_ty) - # 整数 → 指针: inttoptr(必须在纯整数转换之前检查,因为 ptr 的 bits 非零会误入 sext/trunc 路径) - # 适用于: 跨模块方法返回 i64/i32(默认推断),目标变量是指针类型 - if val_bits != 0 and is_ptr_type(target_ty) != 0: - return llvmlite.build_inttoptr(builder, val, target_ty) - # 指针 → 整数: ptrtoint(当目标明确是整数而非指针时) - # 注意: target_bits == 8 时跳过 ptrtoint,走后面的 build_load 解引用首字符 - # 修复: buf[idx] = '\0' 中 '\0' 是 CONST_STR → i8* 指针, - # ptrtoint 会截断地址低 8 位(非 0),应 load 解引用取首字符 0 - if is_ptr_type(val.Ty) != 0 and target_bits != 0 and target_bits != 8 and is_ptr_type(target_ty) == 0: - return llvmlite.build_ptrtoint(builder, val, target_ty) - if val_bits != 0 and target_bits != 0: - if val_bits == target_bits: - return val - if val_bits < target_bits: - return llvmlite.build_sext(builder, val, target_ty) - return llvmlite.build_trunc(builder, val, target_ty) - # 浮点转换 - val_fbits: int = get_llvm_float_bits(val.Ty) - target_fbits: int = get_llvm_float_bits(target_ty) - if val_fbits != 0 and target_fbits != 0: - if val_fbits == target_fbits: - return val - if val_fbits < target_fbits: - return llvmlite.build_fpext(builder, val, target_ty) - return llvmlite.build_fptrunc(builder, val, target_ty) - # int → float - if val_bits != 0 and target_fbits != 0: - return llvmlite.build_si2fp(builder, val, target_ty) - # float → int - if val_fbits != 0 and target_bits != 0: - return llvmlite.build_fp2si(builder, val, target_ty) - # 指针 → 非指针值: build_load 解引用 - # 适用于: 指针 → 整数 (如 i8* → i8), 指针 → 结构体值 - # 当构造器返回 Ptr(Struct) 但目标变量是 Struct 值类型时,需要 load - # 注意:使用独立函数 is_ptr_type 检查,避免嵌套 match 的编译器 BUG - if is_ptr_type(val.Ty) != 0 and is_ptr_type(target_ty) == 0: - return llvmlite.build_load(builder, target_ty, val) - # 指针 → 指针: bitcast (如 i8* → i8** 当目标是全局变量存储指针) - if is_ptr_type(val.Ty) != 0 and is_ptr_type(target_ty) != 0: - return llvmlite.build_bitcast(builder, val, target_ty) - return val - - -# ============================================================ -# 创建全局字符串常量 -# ============================================================ -def create_global_string(builder: llvmlite.IRBuilder | t.CPtr, - pool: memhub.MemBuddy | t.CPtr, - mod: llvmlite.LLVMModule | t.CPtr, - str_val: str, - trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr: - """创建全局字符串常量并返回 i8* bitcast""" - escaped: t.CChar | t.CPtr = escape_llvm_string(pool, str_val) - if escaped is None: - return None - - slen: t.CSizeT = string.strlen(str_val) - count: int = slen + 1 - - i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool) - arr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Array(pool, i8_ty, count) - - # 使用模块级计数器(trans._label_counter)避免跨函数命名冲突 - str_idx: int = trans._label_counter - trans._label_counter += 1 - - # 字符串名加 SHA1 前缀,和函数导出规则一致,避免跨模块重名 - gv_name: t.CChar | t.CPtr = pool.alloc(48) - if gv_name is None: - return None - if trans.ModuleSha1 is not None: - viperlib.snprintf(gv_name, 48, ".str.%s.%d", trans.ModuleSha1, str_idx) - else: - viperlib.snprintf(gv_name, 48, ".str.%d", str_idx) - - gv: llvmlite.GlobalVariable | t.CPtr = llvmlite.new_global_variable(pool, gv_name, arr_ty) - if gv is None: - return None - llvmlite.module_add_global(mod, gv) - - # 去掉 private 链接,和函数一致:stub 中 declare,text 中 define - llvmlite.global_set_unnamed_addr(gv, 1) - llvmlite.global_set_constant(gv, 1) - gv.Initializer = escaped - - arr_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, arr_ty) - gv_ref_name: t.CChar | t.CPtr = pool.alloc(64) - if gv_ref_name is None: - return None - viperlib.snprintf(gv_ref_name, 64, "@%s", gv.Name) - gv_ref: llvmlite.Value | t.CPtr = llvmlite.SSAValue(pool, arr_ptr_ty, gv_ref_name) - - i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty) - - bc: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(builder, gv_ref, i8_ptr_ty) - return bc - - -# ============================================================ -# 翻译常量表达式 -# ============================================================ -def translate_constant(builder: llvmlite.IRBuilder | t.CPtr, - pool: memhub.MemBuddy | t.CPtr, - mod: llvmlite.LLVMModule | t.CPtr, - node: ast.AST | t.CPtr, - trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr: - """翻译常量(int/str/bool)""" - cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(node) - if cn is None: - return None - ck: int = cn.const_kind - if cn.const_kind == ast.CONST_INT: - # 超出 i32 范围则用 i64(避免常量创建时被截断) - iv: t.CInt64T = cn.int_val - if iv > 2147483647 or iv < -2147483648: - return llvmlite.const_int64(pool, iv) - return llvmlite.const_int32(pool, iv) - elif cn.const_kind == ast.CONST_FLOAT: - # 浮点常量默认创建为 double(64 位),赋值时由 coerce_to_type 自动 fptrunc - double_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Double(pool) - return llvmlite.ConstFloat(pool, double_ty, cn.float_val) - elif cn.const_kind == ast.CONST_CHAR: - # 单引号单字符 → i32 值(字符 ASCII 码),coerce_to_type 会 trunc 为 i8 - cv: t.CInt64T = cn.int_val - return llvmlite.const_int32(pool, cv) - elif cn.const_kind == ast.CONST_STR: - sv: str = cn.str_val - if sv is None: - return None - r: llvmlite.Value | t.CPtr = create_global_string(builder, pool, mod, sv, trans) - return r - elif cn.const_kind == ast.CONST_BOOL: - if cn.int_val != 0: - return llvmlite.const_int32(pool, 1) - return llvmlite.const_int32(pool, 0) - elif cn.const_kind == ast.CONST_NONE: - # None → i8* null(空指针常量),用于 `p is None` / `p is not None` 比较 - i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool) - if i8_ty is None: - return None - i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty) - if i8_ptr_ty is None: - return None - rv_none: llvmlite.Value | t.CPtr = llvmlite.ConstNull(pool, i8_ptr_ty, "null") - return rv_none - return None - - -# ============================================================ -# _infer_elem_type_from_value — 从 LLVM Value 推断 list 元素类型名 -# -# 用于 list 字面量 [a, b, c] 的元素类型推断 -# ============================================================ -def _infer_elem_type_from_value(pool: memhub.MemBuddy | t.CPtr, - value: llvmlite.Value | t.CPtr) -> str: - """从 LLVM Value 的类型推断 list 元素类型名""" - if value is None or value.Ty is None: - return "str" - ty: llvmlite.LLVMType | t.CPtr = value.Ty - bits: int = get_llvm_type_bits(ty) - if bits != 0: - if bits == 32: - return "int" - if bits == 64: - return "CSizeT" - if bits == 8: - return "CInt8T" - if bits == 16: - return "CInt16T" - return "int" - if is_ptr_type(ty) != 0: - return "str" - fbits: int = get_llvm_float_bits(ty) - if fbits != 0: - if fbits == 64: - return "CDouble" - if fbits == 32: - return "CFloat" - return "str" - - -# ============================================================ -# _find_pool_var — 查找上下文中的 pool 变量 -# -# 依次尝试 "pool", "_mbuddy", "mbuddy", "mb" -# ============================================================ -def _find_pool_var(trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr: - """查找上下文中的 pool 变量,返回 alloca 或 None - - 查找顺序: pool → _mbuddy → mbuddy → mb - 兜底: 若都未找到,注册外部全局 @_mbuddy (i8*) 供函数内动态 list 创建使用。 - 注意: 模块级 t.CArray 初始化不走此路径(由 _init_global_array_from_list 处理), - 此兜底仅用于函数内的动态 list 字面量(如 op=[...])。 - @_mbuddy 由入口模块(如 Phase2.py)定义并初始化,其他模块以 external 引用。 - """ - if trans is None: - return None - alloca: llvmlite.Value | t.CPtr = HandlesVar.lookup_var(trans.SymTab, "pool") - if alloca is not None: - return alloca - alloca = HandlesVar.lookup_var(trans.SymTab, "_mbuddy") - if alloca is not None: - return alloca - alloca = HandlesVar.lookup_var(trans.SymTab, "mbuddy") - if alloca is not None: - return alloca - alloca = HandlesVar.lookup_var(trans.SymTab, "mb") - if alloca is not None: - return alloca - # 兜底: 创建外部全局 @_mbuddy 引用(i8** 类型) - # 仅用于函数内动态 list 字面量,@_mbuddy 由入口模块定义并初始化 - pool: memhub.MemBuddy | t.CPtr = trans.Pool - if pool is None or trans.Module is None or trans.SymTab is None: - return None - # 先检查是否已注册到模块作用域(避免重复创建全局变量) - existing: llvmlite.Value | t.CPtr = HandlesVar.lookup_module_var(trans.SymTab, "_mbuddy") - if existing is not None: - return existing - # 创建 i8* 类型(t.CVoid | t.CPtr = i8*) - i8_ty_fb: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool) - i8_ptr_ty_fb: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty_fb) - # 创建外部全局 @_mbuddy(external linkage,无初始值) - gv_ext: llvmlite.GlobalVariable | t.CPtr = llvmlite.new_global_variable(pool, "_mbuddy", i8_ptr_ty_fb) - if gv_ext is not None: - gv_ext.Linkage = "external" - llvmlite.module_add_global(trans.Module, gv_ext) - # 创建 Value 引用(@_mbuddy, 类型为 i8**) - i8_ptr_ptr_ty_fb: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ptr_ty_fb) - ref_name_fb: t.CChar | t.CPtr = pool.alloc(16) - if ref_name_fb is not None: - string.strcpy(ref_name_fb, "@_mbuddy") - gv_ref_fb: llvmlite.Value | t.CPtr = llvmlite.SSAValue(pool, i8_ptr_ptr_ty_fb, ref_name_fb) - # 注册到模块作用域,避免重复创建 - HandlesVar.define_module_var(trans.SymTab, "_mbuddy", gv_ref_fb) - return gv_ref_fb - - -# ============================================================ -# translate_list_literal — 翻译 list 字面量 [a, b, c] -# -# 将 list 字面量翻译为 list[T](pool) 构造 + append 调用序列 -# -# Args: -# builder: IRBuilder -# pool: 编译器内存池(MemBuddy) -# mod: LLVMModule -# node: ast.List 节点 -# elem_type_name: 元素类型名(如 "str", "int"),None 表示从元素推断 -# trans: Translator 对象 -# -# Returns: -# list 对象指针(Ptr(list[T] struct)),None 失败 -# ============================================================ -def translate_list_literal(builder: llvmlite.IRBuilder | t.CPtr, - pool: memhub.MemBuddy | t.CPtr, - mod: llvmlite.LLVMModule | t.CPtr, - node: ast.AST | t.CPtr, - elem_type_name: str, - trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr: - """翻译 list 字面量 [a, b, c] → list[T](pool) + append 序列""" - if node is None or trans is None: - return None - - list_node: ast.List | t.CPtr = (ast.List | t.CPtr)(node) - if list_node is None: - return None - - elts: list[ast.AST | t.CPtr] | t.CPtr = list_node.elts - elts_count: t.CSizeT = 0 - if elts is not None: - elts_count = elts.__len__() - - # 推断元素类型 - inferred_type_name: str = elem_type_name - first_elem_val: llvmlite.Value | t.CPtr = None - if inferred_type_name is None: - inferred_type_name = "str" - if elts_count > 0: - first_elem_node: ast.AST | t.CPtr = elts.get(0) - first_elem_val = translate_value(builder, pool, mod, first_elem_node, None, 0, trans) - if first_elem_val is not None: - inferred_type_name = _infer_elem_type_from_value(pool, first_elem_val) - - # 查找 pool 变量 - pool_alloca: llvmlite.Value | t.CPtr = _find_pool_var(trans) - if pool_alloca is None: - HandlesType.fatal_error(node, "list literal requires pool variable in context") - return None - - # load pool 变量值(i8*) - i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool) - i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty) - pool_val: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, i8_ptr_ty, pool_alloca) - if pool_val is None: - return None - - # 特化 list[T] 类 - type_args: list[str] | t.CPtr = list[str](pool, 4) - type_args.append(inferred_type_name) - spec_name: str = HandlesClassDef._specialize_generic_class(trans, "list", type_args) - if spec_name is None: - HandlesType.fatal_error(node, "list literal generic specialization failed") - return None - - # 查找 struct entry - struct_entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct(spec_name) - if struct_entry is None: - HandlesType.fatal_error(node, "list literal specialized class not registered") - return None - struct_ty: llvmlite.LLVMType | t.CPtr = struct_entry.Ty - if struct_ty is None: - return None - - # alloca 临时 list 空间 - # 确保跨模块结构体的完整定义在当前模块中可用(供 alloca 分配空间) - HandlesStruct.ensure_struct_def_in_module(pool, mod, struct_ty) - tmp: llvmlite.Value | t.CPtr = llvmlite.build_alloca(builder, struct_ty) - if tmp is None: - return None - - # 存储指针:默认用 alloca,如果有 __new__ 则用 __new__ 返回的指针 - # __new__ 是可选的,仅当泛型类模板定义了 __new__ 方法时才调用 - # (与 _translate_struct_ctor/_translate_generic_ctor_call 保持一致, - # 避免为无 __new__ 的类生成过度声明) - storage_ptr: llvmlite.Value | t.CPtr = tmp - has_new_flag: int = 0 - if struct_entry is not None: - has_new_flag = struct_entry.HasNew - if has_new_flag != 0: - new_args: t.CSizeT | t.CPtr = pool.alloc(8 * 32) - if new_args is None: - return None - string.memset(new_args, 0, 8 * 32) - new_args[0] = t.CSizeT(pool_val) - new_ptr: llvmlite.Value | t.CPtr = HandlesExprCall._call_method_on_ptr( - pool, builder, mod, spec_name, "__new__", tmp, new_args, 1, trans) - if new_ptr is not None: - storage_ptr = new_ptr - - # 调用 __before_init__(storage_ptr) - HandlesExprCall._call_method_on_ptr( - pool, builder, mod, spec_name, "__before_init__", storage_ptr, None, 0, trans) - - # 调用 __init__(storage_ptr, pool_val, elem_size=0) - init_args: t.CSizeT | t.CPtr = pool.alloc(8 * 32) - if init_args is None: - return None - string.memset(init_args, 0, 8 * 32) - init_args[0] = t.CSizeT(pool_val) - elem_size_val: llvmlite.Value | t.CPtr = llvmlite.const_int64(pool, 0) - init_args[1] = t.CSizeT(elem_size_val) - HandlesExprCall._call_method_on_ptr( - pool, builder, mod, spec_name, "__init__", storage_ptr, init_args, 2, trans) - - # 对每个元素调用 append(storage_ptr, elem_val) - if elts_count > 0: - # 第一个元素可能已经翻译过 - if first_elem_val is not None: - append_args: t.CSizeT | t.CPtr = pool.alloc(8 * 32) - if append_args is not None: - string.memset(append_args, 0, 8 * 32) - append_args[0] = t.CSizeT(first_elem_val) - HandlesExprCall._call_method_on_ptr( - pool, builder, mod, spec_name, "append", storage_ptr, append_args, 1, trans) - - # 翻译剩余元素 - i: t.CSizeT = 1 - while i < elts_count: - elem_node_i: ast.AST | t.CPtr = elts.get(i) - elem_val_i: llvmlite.Value | t.CPtr = translate_value(builder, pool, mod, elem_node_i, None, 0, trans) - if elem_val_i is not None: - ap_args: t.CSizeT | t.CPtr = pool.alloc(8 * 32) - if ap_args is not None: - string.memset(ap_args, 0, 8 * 32) - ap_args[0] = t.CSizeT(elem_val_i) - HandlesExprCall._call_method_on_ptr( - pool, builder, mod, spec_name, "append", storage_ptr, ap_args, 1, trans) - i += 1 - - return storage_ptr - - -# ============================================================ -# 翻译值表达式(RHS 分派)— 模块级版本 -# ============================================================ -def translate_value(builder: llvmlite.IRBuilder | t.CPtr, - pool: memhub.MemBuddy | t.CPtr, - mod: llvmlite.LLVMModule | t.CPtr, - node: ast.AST | t.CPtr, - funcs_ptr: t.CPtr = None, - func_count: int = 0, - trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr: - """翻译值表达式为 LLVM Value""" - if node is None: - return None - k: int = node.kind() - if k == ast.ASTKind.Constant: - rv: llvmlite.Value | t.CPtr = translate_constant(builder, pool, mod, node, trans) - return rv - elif k == ast.ASTKind.Name: - return translate_name_value(builder, pool, node, trans) - elif k == ast.ASTKind.BinOp: - return HandlesExprOps.translate_binop(pool, builder, mod, node, trans) - elif k == ast.ASTKind.Call: - return HandlesExprCall.translate_call(pool, builder, mod, node, - funcs_ptr, func_count, trans) - elif k == ast.ASTKind.Compare: - return translate_compare(builder, pool, mod, node, trans) - elif k == ast.ASTKind.UnaryOp: - return translate_unaryop(builder, pool, mod, node, trans) - elif k == ast.ASTKind.BoolOp: - return translate_boolop(builder, pool, mod, node, - funcs_ptr, func_count, trans) - elif k == ast.ASTKind.Subscript: - return translate_subscript(builder, pool, mod, node, trans) - elif k == ast.ASTKind.Attribute: - return translate_attribute(builder, pool, mod, node, trans) - elif k == ast.ASTKind.List: - return translate_list_literal(builder, pool, mod, node, None, trans) - elif k == ast.ASTKind.IfExp: - return translate_ifexp(builder, pool, mod, node, trans) - return None - - -# ============================================================ -# 翻译三元表达式 IfExp(test, body, orelse) -# -# 生成: cond ? body : orelse -# then_blk: 翻译 body → br merge -# else_blk: 翻译 orelse → br merge -# merge_blk: phi [body_val, then_blk], [orelse_val, else_blk] -# ============================================================ -def translate_ifexp(builder: llvmlite.IRBuilder | t.CPtr, - pool: memhub.MemBuddy | t.CPtr, - mod: llvmlite.LLVMModule | t.CPtr, - node: ast.AST | t.CPtr, - trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr: - """翻译三元表达式 (body if test else orelse),返回 phi 结果 Value""" - if node is None or builder is None or trans is None: - return None - ie: ast.IfExp | t.CPtr = (ast.IfExp | t.CPtr)(node) - if ie is None: - return None - - func: llvmlite.Function | t.CPtr = trans._cur_func - if func is None: - return None - - # 1. 求值条件 - cond_val: llvmlite.Value | t.CPtr = translate_value( - builder, pool, mod, ie.test, None, 0, trans) - if cond_val is None: - return None - # 转换为 i1 - cond_bits: int = get_llvm_type_bits(cond_val.Ty) - if cond_bits == 1: - cond_i1: llvmlite.Value | t.CPtr = cond_val - else: - if is_ptr_type(cond_val.Ty) != 0: - # 指针类型:与 null 比较 - null_cond: llvmlite.Value | t.CPtr = llvmlite.ConstNull(pool, cond_val.Ty, "null") - cond_i1 = llvmlite.build_icmp(builder, llvmlite.ICMP_NE, cond_val, null_cond) - else: - zero: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, 0) - cond_i1 = llvmlite.build_icmp(builder, llvmlite.ICMP_NE, cond_val, zero) - - # 2. 创建三个基本块 - cnt: int = trans._label_counter - trans._label_counter = cnt + 1 - name_buf: t.CChar | t.CPtr = pool.alloc(32) - if name_buf is None: - return None - viperlib.snprintf(name_buf, 32, "ifexp.then.%d", cnt) - then_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf) - viperlib.snprintf(name_buf, 32, "ifexp.else.%d", cnt) - else_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf) - viperlib.snprintf(name_buf, 32, "ifexp.merge.%d", cnt) - merge_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf) - - if then_bb is None or else_bb is None or merge_bb is None: - return None - - # 3. 条件跳转 - llvmlite.build_cond_br(builder, cond_i1, then_bb, else_bb) - - # 4. then 分支 - llvmlite.position_at_end(builder, then_bb) - body_val: llvmlite.Value | t.CPtr = translate_value( - builder, pool, mod, ie.body, None, 0, trans) - then_blk_for_phi: llvmlite.BasicBlock | t.CPtr = trans._cur_builder.CurBlock - if body_val is None: - body_val = llvmlite.const_int32(pool, 0) - # 暂不 br,等类型对齐后再 br - - # 5. else 分支 - llvmlite.position_at_end(builder, else_bb) - orelse_val: llvmlite.Value | t.CPtr = translate_value( - builder, pool, mod, ie.orelse, None, 0, trans) - else_blk_for_phi: llvmlite.BasicBlock | t.CPtr = trans._cur_builder.CurBlock - if orelse_val is None: - orelse_val = llvmlite.const_int32(pool, 0) - # 暂不 br,等类型对齐后再 br - - # 类型对齐 (两分支类型可能不同) - # 必须在各自分支中执行 coerce_to_type,确保 merge 块中 PHI 是第一条指令 - # (否则 coerce_to_type 生成的 sext/zext/ptrtoint/inttoptr 指令在 PHI 之前,违反 LLVM 规则) - body_bits: int = get_llvm_type_bits(body_val.Ty) - orelse_bits: int = get_llvm_type_bits(orelse_val.Ty) - body_is_ptr: int = is_ptr_type(body_val.Ty) - orelse_is_ptr: int = is_ptr_type(orelse_val.Ty) - # 情况0: 一侧是指针,另一侧是整数(如 i64 vs i8* null) - # 必须优先处理,因为 Ptr 的 bits=0 会导致下面三个分支全部跳过 - # 选择 body_val.Ty 作为 phi_ty(then 分支优先),orelse_val 对齐到它 - # coerce_to_type 内部会调用 ptrtoint(指针→整数)或 inttoptr(整数→指针) - if body_is_ptr != orelse_is_ptr: - llvmlite.position_at_end(builder, else_blk_for_phi) - orelse_val = coerce_to_type(builder, orelse_val, body_val.Ty) - elif body_bits > orelse_bits and orelse_bits > 0: - # 在 else 块中转换 orelse_val - llvmlite.position_at_end(builder, else_blk_for_phi) - orelse_val = coerce_to_type(builder, orelse_val, body_val.Ty) - elif orelse_bits > body_bits and body_bits > 0: - # 回到 then 块转换 body_val - llvmlite.position_at_end(builder, then_blk_for_phi) - body_val = coerce_to_type(builder, body_val, orelse_val.Ty) - elif body_bits == orelse_bits and body_bits > 0: - # bits 相同但类型不同(如 i64 vs Ptr):null 不能用于 i64 PHI - # 此分支理论上不会触发(已被情况0覆盖),保留作为防御 - if is_ptr_type(body_val.Ty) != is_ptr_type(orelse_val.Ty): - llvmlite.position_at_end(builder, else_blk_for_phi) - orelse_val = coerce_to_type(builder, orelse_val, body_val.Ty) - - # 现在分别在 then/else 块中 br 到 merge(在类型转换之后) - llvmlite.position_at_end(builder, then_blk_for_phi) - llvmlite.build_br(builder, merge_bb) - llvmlite.position_at_end(builder, else_blk_for_phi) - llvmlite.build_br(builder, merge_bb) - - # 6. merge 块: phi(PHI 是 merge 块的第一条指令) - llvmlite.position_at_end(builder, merge_bb) - - phi_ty: llvmlite.LLVMType | t.CPtr = body_val.Ty - if phi_ty is None: - phi_ty = llvmlite.Int32(pool) - - inc1: llvmlite.PhiIncoming | t.CPtr = llvmlite.new_phi_incoming( - pool, body_val, then_blk_for_phi) - inc2: llvmlite.PhiIncoming | t.CPtr = llvmlite.new_phi_incoming( - pool, orelse_val, else_blk_for_phi) - if inc1 is None or inc2 is None: - return None - # 链表顺序: inc1 (head) -> inc2 (tail) - # 之前错误写成 inc2.Next = inc1,导致 build_phi 从 inc1 遍历时 - # inc1.Next 为 None,只输出一个 phi 条目,引发 LLVM 验证错误: - # "PHINode should have one entry for each predecessor" - inc1.Next = inc2 - return llvmlite.build_phi(builder, phi_ty, inc1, 2) - - -# ============================================================ -# 翻译比较表达式 Compare(left, ops, comparators) -# ============================================================ -def translate_compare(builder: llvmlite.IRBuilder | t.CPtr, - pool: memhub.MemBuddy | t.CPtr, - mod: llvmlite.LLVMModule | t.CPtr, - node: ast.AST | t.CPtr, - trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr: - """翻译比较表达式,返回 i1 结果""" - cmp: ast.Compare | t.CPtr = (ast.Compare | t.CPtr)(node) - if cmp is None: - return None - - ops_list: list[t.CInt] | t.CPtr = (list[t.CInt] | t.CPtr)(cmp.ops) - if ops_list is None or ops_list.__len__() == 0: - return None - op: int = ops_list.get(0) - - comparators: list[ast.AST | t.CPtr] | t.CPtr = cmp.comparators - if comparators is None or comparators.__len__() == 0: - return None - rhs: llvmlite.Value | t.CPtr = translate_value( - builder, pool, mod, comparators.get(0), None, 0, trans) - if rhs is None: - return None - - # === 比较运算符重载路径 1: lhs 是 Name 且对应结构体变量 === - # 对于值类型变量(如 cnt: Counter),用 alloca 指针尝试重载 - lhs_node: ast.AST | t.CPtr = cmp.left - if lhs_node is not None and lhs_node.kind() == ast.ASTKind.Name and trans is not None: - nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(lhs_node) - if nm is not None and nm.id is not None: - lhs_alloca: llvmlite.Value | t.CPtr = HandlesVar.lookup_var( - trans.SymTab, nm.id) - if lhs_alloca is not None: - ovl_result: llvmlite.Value | t.CPtr = HandlesExprOps.try_operator_overload( - pool, builder, mod, lhs_alloca, rhs, op, trans, 1) - if ovl_result is not None: - return ovl_result - - # 正常翻译 lhs - lhs: llvmlite.Value | t.CPtr = translate_value( - builder, pool, mod, cmp.left, None, 0, trans) - if lhs is None: - return None - - # === 比较运算符重载路径 2: lhs 是 Ptr(Struct) === - # Is/IsNot 不在 _cmpop_to_dunder 映射中,会自动返回 None 回退原生比较 - ovl_result2: llvmlite.Value | t.CPtr = HandlesExprOps.try_operator_overload( - pool, builder, mod, lhs, rhs, op, trans, 1) - if ovl_result2 is not None: - return ovl_result2 - - predicate: int = llvmlite.ICMP_SLT - if op == ast.OpKind.Lt: - predicate = llvmlite.ICMP_SLT - elif op == ast.OpKind.Le: - predicate = llvmlite.ICMP_SLE - elif op == ast.OpKind.Gt: - predicate = llvmlite.ICMP_SGT - elif op == ast.OpKind.Ge: - predicate = llvmlite.ICMP_SGE - elif op == ast.OpKind.Eq: - predicate = llvmlite.ICMP_EQ - elif op == ast.OpKind.Ne: - predicate = llvmlite.ICMP_NE - elif op == ast.OpKind.Is: - # `x is y` → 指针/值相等比较 - predicate = llvmlite.ICMP_EQ - elif op == ast.OpKind.IsNot: - # `x is not y` → 指针/值不等比较 - predicate = llvmlite.ICMP_NE - - # 隐式类型转换:当一侧是指针(i8*),另一侧是整数时, - # 从指针加载第一个字节,使两侧类型一致 - lhs_is_ptr: int = is_ptr_type(lhs.Ty) - rhs_is_ptr: int = is_ptr_type(rhs.Ty) - if lhs_is_ptr != 0 and rhs_is_ptr == 0: - i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool) - lhs = llvmlite.build_load(builder, i8_ty, lhs) - elif rhs_is_ptr != 0 and lhs_is_ptr == 0: - i8_ty2: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool) - rhs = llvmlite.build_load(builder, i8_ty2, rhs) - - # 类型对齐:icmp 要求两边类型相同,将较窄的整数 sext 到较宽的类型 - lhs_bits: int = get_llvm_type_bits(lhs.Ty) - rhs_bits: int = get_llvm_type_bits(rhs.Ty) - if lhs_bits != 0 and rhs_bits != 0 and lhs_bits != rhs_bits: - if lhs_bits < rhs_bits: - lhs = llvmlite.build_sext(builder, lhs, rhs.Ty) - else: - rhs = llvmlite.build_sext(builder, rhs, lhs.Ty) - - return llvmlite.build_icmp(builder, predicate, lhs, rhs) - - -# ============================================================ -# 翻译一元运算表达式 UnaryOp(op, operand) -# ============================================================ -def translate_unaryop(builder: llvmlite.IRBuilder | t.CPtr, - pool: memhub.MemBuddy | t.CPtr, - mod: llvmlite.LLVMModule | t.CPtr, - node: ast.AST | t.CPtr, - trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr: - """翻译一元运算(-x, +x, not x, ~x)""" - uo: ast.UnaryOp | t.CPtr = (ast.UnaryOp | t.CPtr)(node) - if uo is None: - return None - - operand: llvmlite.Value | t.CPtr = translate_value( - builder, pool, mod, uo.operand, None, 0, trans) - if operand is None: - return None - - if uo.op == ast.OpKind.USub: - # -x = 0 - x - # 根据 operand 类型选择零值常量(避免 i32 与 i64 类型不匹配) - operand_bits: int = get_llvm_type_bits(operand.Ty) - zero: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, 0) - if operand_bits == 64: - zero = llvmlite.const_int64(pool, 0) - elif operand_bits > 0 and operand_bits != 32: - # 其他位宽(i8/i16 等):用 i32 零值,operand 会被 coerce - zero = llvmlite.const_int32(pool, 0) - return llvmlite.build_sub(builder, zero, operand) - elif uo.op == ast.OpKind.UAdd: - # +x = x - return operand - elif uo.op == ast.OpKind.Not: - # not x = (x == 0/null),返回 i1 - if is_ptr_type(operand.Ty) != 0: - # 指针类型:与 null 比较 - null_op: llvmlite.Value | t.CPtr = llvmlite.ConstNull(pool, operand.Ty, "null") - return llvmlite.build_icmp(builder, llvmlite.ICMP_EQ, operand, null_op) - operand_bits_not: int = get_llvm_type_bits(operand.Ty) - zero = llvmlite.const_int32(pool, 0) - if operand_bits_not == 64: - zero = llvmlite.const_int64(pool, 0) - return llvmlite.build_icmp(builder, llvmlite.ICMP_EQ, operand, zero) - elif uo.op == ast.OpKind.Invert: - # ~x = x ^ -1 - operand_bits_inv: int = get_llvm_type_bits(operand.Ty) - neg1: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, -1) - if operand_bits_inv == 64: - neg1 = llvmlite.const_int64(pool, -1) - return llvmlite.build_xor(builder, operand, neg1) - return operand - - -# ============================================================ -# 翻译布尔运算 BoolOp(op, values) — 短路求值,返回 i1 -# -# and: a and b and c → 若 a 为假短路到 merge(返回 a 的 i1),否则求 b, -# 最后一个值直接求值并跳 merge -# or: a or b or c → 若 a 为真短路到 merge(返回 a 的 i1),否则求 b, -# 最后一个值直接求值并跳 merge -# merge 块用 phi 合并所有入边的 i1 -# ============================================================ -def translate_boolop(builder: llvmlite.IRBuilder | t.CPtr, - pool: memhub.MemBuddy | t.CPtr, - mod: llvmlite.LLVMModule | t.CPtr, - node: ast.AST | t.CPtr, - funcs_ptr: t.CPtr = None, - func_count: int = 0, - trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr: - """翻译布尔运算(and/or)的短路求值,返回 i1""" - bo: ast.BoolOp | t.CPtr = (ast.BoolOp | t.CPtr)(node) - if bo is None: - return None - - op: int = bo.op - values: list[ast.AST | t.CPtr] | t.CPtr = bo.values - if values is None: - return None - count: t.CSizeT = values.__len__() - if count == 0: - return None - if count == 1: - return translate_value(builder, pool, mod, values.get(0), - funcs_ptr, func_count, trans) - - func: llvmlite.Function | t.CPtr = builder.Func - if func is None: - return None - - # 创建 merge BB(用 builder.Counter 生成唯一标签名,position_at_end 的 - # move_to_end 保证 BB 文本顺序与控制流顺序一致,标签名用 counter 安全) - cnt: int = builder.Counter - builder.Counter = cnt + 1 - name_buf: t.CChar | t.CPtr = pool.alloc(32) - if name_buf is None: - return None - viperlib.snprintf(name_buf, 32, "bool.merge.%d", cnt) - merge_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf) - - # phi 入边链表头/尾 - phi_head: llvmlite.PhiIncoming | t.CPtr = None - phi_tail: llvmlite.PhiIncoming | t.CPtr = None - phi_count: int = count - 1 # 循环次数 - - # 对每个值(除最后一个)求值并短路 - for i in range(count - 1): - val_node: ast.AST | t.CPtr = values.get(i) - val: llvmlite.Value | t.CPtr = translate_value( - builder, pool, mod, val_node, - funcs_ptr, func_count, trans) - if val is None: - return None - - # 转为 i1(已经是 i1 的直接用,否则与 0/null 比较) - val_bits: int = get_llvm_type_bits(val.Ty) - val_i1: llvmlite.Value | t.CPtr = val - if val_bits != 1: - if is_ptr_type(val.Ty) != 0: - # 指针类型:与 null 比较(避免 i8* 与 i32 类型不匹配) - null_val: llvmlite.Value | t.CPtr = llvmlite.ConstNull(pool, val.Ty, "null") - val_i1 = llvmlite.build_icmp(builder, llvmlite.ICMP_NE, val, null_val) - else: - zero: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, 0) - val_i1 = llvmlite.build_icmp(builder, llvmlite.ICMP_NE, val, zero) - - # 创建 next BB(求值下一个值) - cnt = builder.Counter - builder.Counter = cnt + 1 - viperlib.snprintf(name_buf, 32, "bool.next.%d", cnt) - next_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf) - - # and: 短路假→merge,真→next;or: 短路真→merge,假→next - if op == ast.OpKind.And: - llvmlite.build_cond_br(builder, val_i1, next_bb, merge_bb) - else: - llvmlite.build_cond_br(builder, val_i1, merge_bb, next_bb) - - # 添加 phi 入边:(val_i1, cond_br 所在 BB) - cur_bb: llvmlite.BasicBlock | t.CPtr = builder.CurBlock - inc: llvmlite.PhiIncoming | t.CPtr = llvmlite.new_phi_incoming(pool, val_i1, cur_bb) - if phi_head is None: - phi_head = inc - phi_tail = inc - else: - phi_tail.Next = inc - phi_tail = inc - - # 定位到 next BB,求值下一个值 - llvmlite.position_at_end(builder, next_bb) - - # 最后一个值:求值后直接跳 merge - last_node: ast.AST | t.CPtr = values.get(count - 1) - last_val: llvmlite.Value | t.CPtr = translate_value( - builder, pool, mod, last_node, - funcs_ptr, func_count, trans) - if last_val is None: - return None - last_bits: int = get_llvm_type_bits(last_val.Ty) - last_i1: llvmlite.Value | t.CPtr = last_val - if last_bits != 1: - if is_ptr_type(last_val.Ty) != 0: - # 指针类型:与 null 比较(避免 i8* 与 i32 类型不匹配) - null_val2: llvmlite.Value | t.CPtr = llvmlite.ConstNull(pool, last_val.Ty, "null") - last_i1 = llvmlite.build_icmp(builder, llvmlite.ICMP_NE, last_val, null_val2) - else: - zero = llvmlite.const_int32(pool, 0) - last_i1 = llvmlite.build_icmp(builder, llvmlite.ICMP_NE, last_val, zero) - - llvmlite.build_br(builder, merge_bb) - - cur_bb = builder.CurBlock - inc = llvmlite.new_phi_incoming(pool, last_i1, cur_bb) - if phi_head is None: - phi_head = inc - else: - phi_tail.Next = inc - phi_count += 1 - - # 定位到 merge,创建 phi 合并所有入边 - llvmlite.position_at_end(builder, merge_bb) - i1_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int1(pool) - return llvmlite.build_phi(builder, i1_ty, phi_head, phi_count) - - -# ============================================================ -# _build_source_path_from_sha1 - 通过 SHA1 从存储器构建源 .py 文件路径 -# -# .pyi 文件可能未生成(Phase1 未输出 pyi),此时回退读取源 .py 文件。 -# 从 StubMerger 全局存储器查找 SHA1 对应的相对路径, -# 根据 rel_path 前缀选择基础目录: -# - rel_path 以 "lib/" 开头 → App 源文件,用 {Config.SourceDir}/{rel_path} -# - 其他 → includes 文件,用 {Config.IncludesDir}/{rel_path} -# -# Returns: -# stdlib.malloc 分配的路径字符串(调用者负责 free),None 失败 -# ============================================================ -def _build_source_path_from_sha1(sha1: str) -> str: - """通过 SHA1 从全局存储器构建源 .py 文件路径""" - if sha1 is None: - return None - if Config.IncludesDir is None: - return None - # 从 StubMerger 全局存储器获取相对路径数组 - rel_arr_ptr: bytes | t.CPtr = StubMerger.GetSha1StoreRelArrPtr() - count: int = StubMerger.GetSha1StoreCount() - if rel_arr_ptr is None or count <= 0: - return None - sha1_arr_ptr: bytes | t.CPtr = StubMerger.GetSha1StoreArrPtr() - if sha1_arr_ptr is None: - return None - # 遍历查找匹配的 SHA1 - idx_s: int = -1 - for i in range(count): - sidx: t.CSizeT = t.CSizeT(i) * 17 - cur_sha1: str = sha1_arr_ptr + sidx - if cur_sha1[0] == '\0': - continue - if string.strcmp(cur_sha1, sha1) == 0: - idx_s = i - break - if idx_s < 0: - return None - # 获取相对路径(MAX_REL_PATH_LEN=256,避免跨模块 CDefine 解析问题) - MAX_RPL: t.CSizeT = 256 - ridx: t.CSizeT = t.CSizeT(idx_s) * MAX_RPL - rel_path: str = rel_arr_ptr + ridx - if rel_path[0] == '\0': - return None - # 选择基础目录:rel_path 以 "lib/" 开头 → App 源文件(SourceDir),否则 includes 文件 - base_dir: str = Config.IncludesDir - is_app: int = 0 - if string.strlen(rel_path) >= 4: - if (rel_path[0] == 'l' and rel_path[1] == 'i' and - rel_path[2] == 'b' and rel_path[3] == '/'): - is_app = 1 - if is_app != 0 and Config.SourceDir is not None: - base_dir = Config.SourceDir - # 构建完整路径: {base_dir}/{rel_path} - base_len: t.CSizeT = string.strlen(base_dir) - rel_len: t.CSizeT = string.strlen(rel_path) - path_len: t.CSizeT = base_len + rel_len + 2 - buf: str = stdlib.malloc(path_len) - if buf is None: - return None - viperlib.snprintf(buf, path_len, "%s/%s", base_dir, rel_path) - return buf - - -# ============================================================ -# _lookup_cross_module_cdefine - 跨模块查找 CDefine 常量 -# -# 当当前模块的 CDefine 表中找不到某个 Name 时,从 from_imports -# 解析出源模块,再从该模块的 pyi 文件中解析 CDefine 常量值。 -# 找到后缓存到当前模块的 CDefine 表中,避免重复查找。 -# -# pyi 文件格式: "NAME: t.CDefine = value" -# ============================================================ -def _lookup_cross_module_cdefine(pool: memhub.MemBuddy | t.CPtr, - name: str, - from_imports: str, - imported_modules: str = None) -> int: - """跨模块查找 CDefine 常量,返回值或 -1(未找到) - - 查找顺序: - 1. from_imports 精确匹配(from X import NAME) - 2. from_imports star 回退(from X import *) - 3. imported_modules 遍历(import X):当通过 import X 导入模块时, - 模块中定义的 CDefine 常量可通过此路径找到(如方法签名默认参数引用) - """ - if name is None: - return -1 - if from_imports is None: - from_imports = "" - - # 1. 从 from_imports 查找名称对应的模块名 - # 先尝试精确匹配(allow_star_fallback=0),避免 CDefine 常量被 star import 误导 - mod_name_raw: str = HandlesImports.lookup_from_import(from_imports, name, 0) - if mod_name_raw is None: - # 精确匹配失败:尝试 star import 回退 - mod_name_raw = HandlesImports.lookup_from_import(from_imports, name, 1) - - # 2. from_imports 查找失败:直接回退到 imported_modules 遍历(步骤 9.6) - # 注意:star fallback 可能返回错误模块(如 stdint),常量实际不在其中, - # 步骤 9.6 会在该模块查找失败后继续遍历 imported_modules - if mod_name_raw is None: - # from_imports 完全没有匹配(精确和 star 都失败) - # 直接进入 imported_modules 遍历(步骤 9.6) - if imported_modules is None: - return -1 - # 跳过 from_imports 模块读取,直接走步骤 9.6 的 imported_modules 遍历 - # 设置 result_found=0 跳过步骤 3-9,直接到 9.6 - HandlesType.set_cdefine_found(0) - # 直接遍历 imported_modules - im_len: t.CSizeT = string.strlen(imported_modules) - im_ci: t.CSizeT = 0 - while im_ci < im_len: - while im_ci < im_len and imported_modules[im_ci] == ' ': - im_ci += 1 - if im_ci >= im_len: - break - im_start: t.CSizeT = im_ci - while im_ci < im_len and imported_modules[im_ci] != ' ': - im_ci += 1 - im_end: t.CSizeT = im_ci - im_nlen: t.CSizeT = im_end - im_start - if im_nlen > 0 and im_nlen < 256: - im_buf: str = pool.alloc(im_nlen + 1) - if im_buf is not None: - mk: t.CSizeT = 0 - while mk < im_nlen: - im_buf[mk] = imported_modules[im_start + mk] - mk += 1 - im_buf[im_nlen] = '\0' - sub_fi: str = pool.alloc(im_nlen + 3) - if sub_fi is not None: - sub_fi[0] = '*' - sub_fi[1] = ':' - mk2: t.CSizeT = 0 - while mk2 < im_nlen: - sub_fi[2 + mk2] = im_buf[mk2] - mk2 += 1 - sub_fi[2 + im_nlen] = '\0' - sub_val: int = _lookup_cross_module_cdefine(pool, name, sub_fi, None) - if HandlesType.is_cdefine_found() != 0: - return sub_val - return -1 - - # 2. 复制模块名到新缓冲区(lookup_from_import 返回的是内部指针) - # 截断于空格、null、或 ':'(别名格式的分隔符) - mod_len: t.CSizeT = 0 - while mod_name_raw[mod_len] != ' ' and mod_name_raw[mod_len] != '\0' and mod_name_raw[mod_len] != ':': - mod_len += 1 - mod_name_buf: str = pool.alloc(mod_len + 1) - if mod_name_buf is None: - return -1 - for mi in range(mod_len): - mod_name_buf[mi] = mod_name_raw[mi] - mod_name_buf[mod_len] = '\0' - - # 3. 去掉相对导入的前导点 - base_mod: str = mod_name_buf - while base_mod[0] == '.': - base_mod = base_mod + 1 - - # 4. 查找模块的 SHA1 - sha1: str = HandlesExprCall._lookup_module_sha1(base_mod) - if sha1 is None: - sha1 = HandlesExprCall._lookup_module_sha1_suffix(base_mod) - if sha1 is None: - return -1 - - # 5. 获取 temp_dir - temp_dir: str = HandlesType.get_temp_dir() - if temp_dir is None: - return -1 - - # 6. 构建 pyi 文件路径 - td_len: t.CSizeT = string.strlen(temp_dir) - pyi_path: str = StubMerger._sliced_path(temp_dir, td_len, sha1, "pyi") - if pyi_path is None: - return -1 - - # 7. 读取 pyi 文件;若不存在或内容过短(空 stub)则回退读取源 .py 文件 - PYI_READ_BUF_SIZE: t.CSizeT = 65536 - pyi_buf: bytes = stdlib.malloc(PYI_READ_BUF_SIZE) - if pyi_buf is None: - stdlib.free(pyi_path) - return -1 - pf: fileio.File | t.CPtr = fileio.File(pyi_path, fileio.MODE.R) - need_py_fallback: int = 0 - bytes_read: LONG = 0 - if pf.closed: - # .pyi 文件不存在:回退读取源 .py 文件 - need_py_fallback = 1 - else: - bytes_read = pf.read_all(pyi_buf, PYI_READ_BUF_SIZE) - pf.close() - # pyi 内容过短(< 10 字节)视为空 stub,回退 .py - if bytes_read < 10: - need_py_fallback = 1 - else: - if bytes_read < PYI_READ_BUF_SIZE: - pyi_buf[bytes_read] = 0 - else: - pyi_buf[PYI_READ_BUF_SIZE - 1] = 0 - stdlib.free(pyi_path) - - if need_py_fallback != 0: - # 从 SHA1 存储器查找相对路径,构建 {base_dir}/{rel_path} - src_path: str = _build_source_path_from_sha1(sha1) - if src_path is None: - # 存储器中找不到 SHA1 = 编译器 bug(Phase1/Phase2 未填充存储器) - # 报错终止,不静默返回 -1(避免后续生成错误的 @UNDEFINED 全局变量引用) - err_buf: str = pool.alloc(512) - if err_buf is not None: - viperlib.snprintf(err_buf, 512, - "跨模块 CDefine 查找失败:SHA1 %s 不在存储器中(base_mod=%s name=%s)。" - "Phase1/Phase2 未正确填充 PopulateSha1MapStore/AppendToSha1MapStore", - sha1, base_mod, name) - VLogger.error(err_buf, "XMOD-CD") - stdlib.free(pyi_buf) - return -1 - pf = fileio.File(src_path, fileio.MODE.R) - stdlib.free(src_path) - if pf.closed: - stdlib.free(pyi_buf) - return -1 - bytes_read = pf.read_all(pyi_buf, PYI_READ_BUF_SIZE) - pf.close() - if bytes_read <= 0: - stdlib.free(pyi_buf) - return -1 - if bytes_read < PYI_READ_BUF_SIZE: - pyi_buf[bytes_read] = 0 - else: - pyi_buf[PYI_READ_BUF_SIZE - 1] = 0 - - # 8. 在 pyi_buf 中查找 "name: t.CDefine = value" 行 - # 格式: NAME: t.CDefine = value - name_len: t.CSizeT = string.strlen(name) - total_len: t.CSizeT = string.strlen(pyi_buf) - pos: t.CSizeT = 0 - result_val: int = 0 - result_found: int = 0 - while pos < total_len: - # 找到行首 - line_start: t.CSizeT = pos - # 找到行尾 - while pos < total_len and pyi_buf[pos] != '\n': - pos += 1 - line_len: t.CSizeT = pos - line_start - if pos < total_len: - pos += 1 # 跳过 '\n' - - # 检查行是否以 "name:" 开头 - if line_len < name_len + 1: - continue - match_ok: int = 1 - for ki in range(name_len): - if pyi_buf[line_start + ki] != name[ki]: - match_ok = 0 - break - if match_ok == 0: - continue - if pyi_buf[line_start + name_len] != ':': - continue - - # 检查行是否包含 "t.CDefine" - # 在行中查找 "t.CDefine" - has_cdefine: int = 0 - ci: t.CSizeT = line_start + name_len + 1 - while ci + 8 <= line_start + line_len: - if (pyi_buf[ci] == 't' and pyi_buf[ci + 1] == '.' and - pyi_buf[ci + 2] == 'C' and pyi_buf[ci + 3] == 'D' and - pyi_buf[ci + 4] == 'e' and pyi_buf[ci + 5] == 'f' and - pyi_buf[ci + 6] == 'i' and pyi_buf[ci + 7] == 'n' and - pyi_buf[ci + 8] == 'e'): - has_cdefine = 1 - break - ci += 1 - if has_cdefine == 0: - continue - - # 找到 "=" 后面的值 - eq_pos: t.CSizeT = line_start + name_len + 1 - while eq_pos < line_start + line_len and pyi_buf[eq_pos] != '=': - eq_pos += 1 - if eq_pos >= line_start + line_len: - continue - eq_pos += 1 # 跳过 '=' - - # 跳过空格 - while eq_pos < line_start + line_len and pyi_buf[eq_pos] == ' ': - eq_pos += 1 - - # 检查是否是 t.CUnsignedLong(...) / t.CLong(...) / t.CInt(...) 等类型构造函数 - # 格式: t.CUnsignedLong(-11) / t.CUnsignedLong(0xFFFFFFFF) - # 如果是,跳过 "t.CXxx(" 前缀,解析括号内的值,忽略结尾 ')' - is_type_ctor: int = 0 - if eq_pos + 2 < line_start + line_len: - if pyi_buf[eq_pos] == 't' and pyi_buf[eq_pos + 1] == '.': - # 找到 '(' 的位置 - paren_pos: t.CSizeT = eq_pos + 2 - while paren_pos < line_start + line_len and pyi_buf[paren_pos] != '(': - paren_pos += 1 - if paren_pos < line_start + line_len and pyi_buf[paren_pos] == '(': - is_type_ctor = 1 - eq_pos = paren_pos + 1 # 跳过 '(' - # 跳过括号内可能的前导空格 - while eq_pos < line_start + line_len and pyi_buf[eq_pos] == ' ': - eq_pos += 1 - - # 解析整数值(支持十六进制 0x 前缀和负号) - # 负号标记 - is_neg: int = 0 - if eq_pos < line_start + line_len and pyi_buf[eq_pos] == '-': - is_neg = 1 - eq_pos += 1 - val_str_start: t.CSizeT = eq_pos - val_str_len: t.CSizeT = 0 - is_hex: int = 0 - if eq_pos + 1 < line_start + line_len: - if pyi_buf[eq_pos] == '0' and (pyi_buf[eq_pos + 1] == 'x' or pyi_buf[eq_pos + 1] == 'X'): - is_hex = 1 - val_str_len = 2 - eq_pos += 2 - while eq_pos < line_start + line_len: - ch: t.CChar = pyi_buf[eq_pos] - if is_hex == 1: - if ((ch >= '0' and ch <= '9') or - (ch >= 'a' and ch <= 'f') or - (ch >= 'A' and ch <= 'F')): - val_str_len += 1 - eq_pos += 1 - else: - break - else: - if ch >= '0' and ch <= '9': - val_str_len += 1 - eq_pos += 1 - else: - break - - if val_str_len == 0: - continue - - # 复制值字符串到新缓冲区并解析 - val_buf: str = pool.alloc(val_str_len + 1) - if val_buf is None: - continue - for vi in range(val_str_len): - val_buf[vi] = pyi_buf[val_str_start + vi] - val_buf[val_str_len] = '\0' - - if is_hex == 1: - # 手动解析十六进制(跳过 0x 前缀) - hex_result: int = 0 - hex_buf: str = val_buf + 2 # 跳过 "0x" - for hi in range(val_str_len - 2): - hc: t.CChar = hex_buf[hi] - hd: int = 0 - if hc >= '0' and hc <= '9': - hd = hc - '0' - elif hc >= 'a' and hc <= 'f': - hd = hc - 'a' + 10 - elif hc >= 'A' and hc <= 'F': - hd = hc - 'A' + 10 - else: - break - hex_result = hex_result * 16 + hd - result_val = hex_result - # 十六进制负值(如 0xFFFFFFFF)保持原样,由 32 位截断处理 - result_found = 1 - else: - result_val = string.atoi(val_buf) - # 应用负号(如 t.CUnsignedLong(-11) → -11) - if is_neg != 0: - result_val = -result_val - result_found = 1 - break - - # 9.5 如果当前模块文件中没找到,递归查找子模块 - # 处理 from .X import NAME 和 from .X import * 的情况 - # 例如 ast.__init__.py 中 from .base import CONST_INT, ... - # 需要递归查找 ast.base 子模块中的 CONST_INT: t.CDefine = 1 - if result_found == 0: - name_len_rc: t.CSizeT = string.strlen(name) - rc_pos: t.CSizeT = 0 - while rc_pos < total_len and result_found == 0: - # 找到行首 - rc_line_start: t.CSizeT = rc_pos - # 找到行尾 - while rc_pos < total_len and pyi_buf[rc_pos] != '\n': - rc_pos += 1 - rc_line_len: t.CSizeT = rc_pos - rc_line_start - if rc_pos < total_len: - rc_pos += 1 - - # 检查行是否以 "from ." 开头(相对导入子模块) - if rc_line_len < 12: - continue - if pyi_buf[rc_line_start] != 'f' or pyi_buf[rc_line_start+1] != 'r' or \ - pyi_buf[rc_line_start+2] != 'o' or pyi_buf[rc_line_start+3] != 'm' or \ - pyi_buf[rc_line_start+4] != ' ' or pyi_buf[rc_line_start+5] != '.': - continue - - # 提取子模块名(从 rc_line_start+6 开始,到空格/tab 为止) - rc_sub_start: t.CSizeT = rc_line_start + 6 - rc_sub_end: t.CSizeT = rc_sub_start - while rc_sub_end < rc_line_start + rc_line_len and \ - pyi_buf[rc_sub_end] != ' ' and pyi_buf[rc_sub_end] != '\t': - rc_sub_end += 1 - rc_sub_len: t.CSizeT = rc_sub_end - rc_sub_start - if rc_sub_len == 0: - continue - - # 检查行是否包含 "import" - rc_has_import: int = 0 - rc_ipos: t.CSizeT = rc_sub_end - while rc_ipos + 6 <= rc_line_start + rc_line_len: - if pyi_buf[rc_ipos] == 'i' and pyi_buf[rc_ipos+1] == 'm' and \ - pyi_buf[rc_ipos+2] == 'p' and pyi_buf[rc_ipos+3] == 'o' and \ - pyi_buf[rc_ipos+4] == 'r' and pyi_buf[rc_ipos+5] == 't': - rc_has_import = 1 - break - rc_ipos += 1 - if rc_has_import == 0: - continue - - # 检查 NAME 是否在导入列表中,或导入是 * - # 处理多行导入:from .X import (... NAME, ...) - # 从 "import" 之后扫描,如果有 "(" 则扫描到 ")" 为止 - rc_imp_start: t.CSizeT = rc_ipos + 6 - rc_star: int = 0 - rc_name_match: int = 0 - - # 确定扫描范围:单行或跨行(括号内) - rc_scan_end: t.CSizeT = rc_line_start + rc_line_len - rc_has_paren: int = 0 - rc_pp: t.CSizeT = rc_imp_start - while rc_pp < rc_line_start + rc_line_len: - if pyi_buf[rc_pp] == '(': - rc_has_paren = 1 - break - if pyi_buf[rc_pp] == '*': - rc_star = 1 - rc_pp += 1 - - if rc_has_paren != 0: - # 多行导入:从 "(" 之后扫描到 ")" 为止 - rc_scan_end = rc_pp + 1 - rc_paren_closed: int = 0 - rc_sp: t.CSizeT = rc_pp + 1 - while rc_sp < total_len and rc_paren_closed == 0: - if pyi_buf[rc_sp] == ')': - rc_paren_closed = 1 - rc_scan_end = rc_sp - break - rc_sp += 1 - if rc_paren_closed == 0: - rc_scan_end = total_len - - # 在 rc_imp_start 到 rc_scan_end 范围内查找 NAME 和 * - rc_cpos: t.CSizeT = rc_imp_start - while rc_cpos < rc_scan_end: - rc_ch: t.CChar = pyi_buf[rc_cpos] - if rc_ch == '*': - rc_star = 1 - # 检查 NAME 是否匹配(作为完整单词) - if rc_cpos + name_len_rc <= rc_scan_end: - rc_match: int = 1 - rc_ki: t.CSizeT - for rc_ki in range(name_len_rc): - if pyi_buf[rc_cpos + rc_ki] != name[rc_ki]: - rc_match = 0 - break - if rc_match == 1: - # 检查前字符是否是非标识符字符 - rc_before_ok: int = 0 - if rc_cpos == rc_imp_start: - rc_before_ok = 1 - else: - rc_before_ch: t.CChar = pyi_buf[rc_cpos - 1] - if rc_before_ch == ' ' or rc_before_ch == '\t' or \ - rc_before_ch == '(' or rc_before_ch == ',' or \ - rc_before_ch == '\n' or rc_before_ch == '\r': - rc_before_ok = 1 - # 检查后字符是否是非标识符字符 - rc_after_ok: int = 0 - rc_after_pos: t.CSizeT = rc_cpos + name_len_rc - if rc_after_pos >= rc_scan_end: - rc_after_ok = 1 - else: - rc_after_ch: t.CChar = pyi_buf[rc_after_pos] - if rc_after_ch == ' ' or rc_after_ch == '\t' or \ - rc_after_ch == ')' or rc_after_ch == ',' or \ - rc_after_ch == '\r' or rc_after_ch == '\n': - rc_after_ok = 1 - if rc_before_ok == 1 and rc_after_ok == 1: - rc_name_match = 1 - rc_cpos += 1 - - if rc_star == 0 and rc_name_match == 0: - continue - - # 复制子模块名到新缓冲区(pyi_buf + rc_sub_start 不是 NUL 结尾) - rc_sub_buf: str = pool.alloc(rc_sub_len + 1) - if rc_sub_buf is None: - continue - rc_si: t.CSizeT - for rc_si in range(rc_sub_len): - rc_sub_buf[rc_si] = pyi_buf[rc_sub_start + rc_si] - rc_sub_buf[rc_sub_len] = '\0' - - # 构建完整子模块名 base_mod.X - rc_full_len: t.CSizeT = string.strlen(base_mod) + 1 + rc_sub_len + 1 - rc_full_mod: str = pool.alloc(rc_full_len) - if rc_full_mod is None: - continue - viperlib.snprintf(rc_full_mod, rc_full_len, "%s.%s", base_mod, rc_sub_buf) - - # 构建临时 from_imports "name:full_mod" - rc_fi_len: t.CSizeT = name_len_rc + 1 + string.strlen(rc_full_mod) + 1 - rc_fi: str = pool.alloc(rc_fi_len) - if rc_fi is None: - continue - viperlib.snprintf(rc_fi, rc_fi_len, "%s:%s", name, rc_full_mod) - - # 递归调用查找子模块 - rc_sub_val: int = _lookup_cross_module_cdefine(pool, name, rc_fi) - if HandlesType.is_cdefine_found() != 0: - result_val = rc_sub_val - result_found = 1 - - stdlib.free(pyi_buf) - - # 9.6 from_imports star fallback 模块中未找到:回退到 imported_modules 遍历 - # 当 `from stdint import *` 导致 star fallback 返回 stdint,但目标常量 - # (如 SHARE_READ)实际在 `import w32.fileio` 导入的模块中时, - # 需要遍历 imported_modules 逐个查找 - if result_found == 0 and imported_modules is not None: - im2_len: t.CSizeT = string.strlen(imported_modules) - im2_ci: t.CSizeT = 0 - while im2_ci < im2_len and result_found == 0: - while im2_ci < im2_len and imported_modules[im2_ci] == ' ': - im2_ci += 1 - if im2_ci >= im2_len: - break - im2_start: t.CSizeT = im2_ci - while im2_ci < im2_len and imported_modules[im2_ci] != ' ': - im2_ci += 1 - im2_end: t.CSizeT = im2_ci - im2_nlen: t.CSizeT = im2_end - im2_start - if im2_nlen > 0 and im2_nlen < 256: - im2_buf: str = pool.alloc(im2_nlen + 1) - if im2_buf is not None: - mk3: t.CSizeT = 0 - while mk3 < im2_nlen: - im2_buf[mk3] = imported_modules[im2_start + mk3] - mk3 += 1 - im2_buf[im2_nlen] = '\0' - sub_fi2: str = pool.alloc(im2_nlen + 3) - if sub_fi2 is not None: - sub_fi2[0] = '*' - sub_fi2[1] = ':' - mk4: t.CSizeT = 0 - while mk4 < im2_nlen: - sub_fi2[2 + mk4] = im2_buf[mk4] - mk4 += 1 - sub_fi2[2 + im2_nlen] = '\0' - sub_val2: int = _lookup_cross_module_cdefine(pool, name, sub_fi2, None) - if HandlesType.is_cdefine_found() != 0: - result_val = sub_val2 - result_found = 1 - - # 10. 缓存到当前模块的 CDefine 表中 - if result_found != 0: - HandlesType.register_cdefine_constant(pool, name, result_val) - HandlesType.set_cdefine_found(1) - else: - HandlesType.set_cdefine_found(0) - - return result_val - - -# ============================================================ -# _is_cdefine_name_pattern - 检查名字是否符合 CDefine 命名约定 -# -# CDefine 常量(如 FOREGROUND_GREEN, STD_OUTPUT_HANDLE, SCOPE_MODULE) -# 都遵循 ALL_CAPS 约定:仅含大写字母 A-Z、数字 0-9、下划线 _, -# 且至少含一个大写字母。 -# -# Python 关键字(match, if, for)和变量名(self, pool, builder) -# 都含小写字母,不会匹配,从而避免 fail-fast 误报。 -# -# 返回: 1=符合 CDefine 命名约定, 0=不符合 -# ============================================================ -def _is_cdefine_name_pattern(name: str) -> int: - """检查名字是否符合 CDefine 命名约定(全大写+下划线+数字)""" - if name is None: - return 0 - has_upper: int = 0 - i: t.CSizeT = 0 - while name[i] != '\0': - c: t.CChar = name[i] - if c >= 'a' and c <= 'z': - return 0 - if c >= 'A' and c <= 'Z': - has_upper = 1 - i += 1 - return has_upper - - -# ============================================================ -# 翻译变量引用(Name 节点)→ load -# ============================================================ -def translate_name_value(builder: llvmlite.IRBuilder | t.CPtr, - pool: memhub.MemBuddy | t.CPtr, - node: ast.AST | t.CPtr, - trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr: - """翻译变量引用(Name 节点)→ load""" - nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(node) - if nm is None: - return None - nm_id: str = nm.id - if nm_id is None: - return None - - # CDefine 编译期常量: 直接返回整数常量值(不生成运行时代码) - # NAME: t.CDefine = value 形式定义的常量在编译期已注册到本地表 - cdef_val: int = HandlesType.lookup_cdefine_constant(nm_id) - if HandlesType.is_cdefine_found() != 0: - return llvmlite.const_int32(pool, cdef_val) - - # 本地表未找到:尝试跨模块 .pyi 查找(保证多模块查表存表一致) - # 仅对符合 CDefine 命名约定(ALL_CAPS)的名字触发跨模块查找, - # 避免对普通变量名(mb/name/ptr/pool/self 等)误触发,造成严重性能损耗 - if _is_cdefine_name_pattern(nm_id) != 0: - if trans is not None: - cdef_val = _lookup_cross_module_cdefine( - pool, nm_id, trans._from_imports, trans._imported_modules) - if HandlesType.is_cdefine_found() != 0: - return llvmlite.const_int32(pool, cdef_val) - - # global 变量:从模块作用域查找(global 声明优先级最高) - if trans is not None: - if HT.is_global_name(trans, nm_id) != 0: - mod_alloca: llvmlite.Value | t.CPtr = HandlesVar.lookup_module_var( - trans.SymTab, nm_id) - if mod_alloca is not None: - load_ty: llvmlite.LLVMType | t.CPtr = None - if mod_alloca.Ty is not None: - load_ty = mod_alloca.Ty.Pointee - if load_ty is None: - load_ty = llvmlite.Int32(pool) - return llvmlite.build_load(builder, load_ty, mod_alloca) - - # nonlocal 变量:通过闭包 env 访问 - if HT.is_nonlocal_name(trans, nm_id) != 0: - return HandlesNonlocal.load_nonlocal_var(trans, nm_id) - - # 局部变量查找(必须先于模块别名检查) - # 否则与模块同名的局部变量(如 `import t, c` 后的局部变量 c)会被误判为模块别名, - # 导致 SymTab 已注册的局部变量查找不到(rhs_val is None bug 根因) - alloca: llvmlite.Value | t.CPtr = HandlesVar.lookup_var(trans.SymTab, nm_id) - if alloca is not None: - load_ty: llvmlite.LLVMType | t.CPtr = None - if alloca.Ty is not None: - load_ty = alloca.Ty.Pointee - if load_ty is None: - load_ty = llvmlite.Int32(pool) - return llvmlite.build_load(builder, load_ty, alloca) - - # 模块别名检查:SymTab 查找失败后才检查 - # 如果 nm_id 是已导入模块名(如 win32file, fileio)且未被声明为局部变量, - # 返回 None 让上层处理(用于属性访问 win32file.CreateFileA) - if trans is not None and trans._imported_modules is not None: - if HandlesImports.is_module_imported(trans._imported_modules, nm_id) != 0: - return None - - # 所有查找路径均失败 - # fail-fast: 仅对符合 CDefine 命名约定(ALL_CAPS)的名字报错 - # 避免对 match/self/pool 等关键字和变量名误报 - # 跨模块 CDefine 查找已在上方完成,此处不重复 - if _is_cdefine_name_pattern(nm_id) != 0: - err_buf2: str = pool.alloc(256) - if err_buf2 is not None: - cur_sha1: str = "(unknown)" - if trans is not None and trans.ModuleSha1 is not None: - cur_sha1 = trans.ModuleSha1 - viperlib.snprintf(err_buf2, 256, - "[CD] FATAL: Name '%s' NOT found (CDefine local+cross + global + nonlocal + alloca + module alias) in module sha1=%s\n", - nm_id, cur_sha1) - VLogger.error(err_buf2, "CD") - return None - - -# ============================================================ -# ExprHandle - 表达式处理器(Mixin 继承模式) -# -# HandleValue 提供 trans 接口,委托到模块级 translate_value -# ============================================================ -@t.NoVTable -class ExprHandle(HandlesBase.Mixin): - """表达式处理器:继承 Mixin 获得 Trans 回指针""" - - def __init__(self, trans: HT.Translator | t.CPtr): - self.Trans = trans - - # ============================================================ - # HandleValue - 翻译值表达式为 LLVM Value - # ============================================================ - def HandleValue(self, node: ast.AST | t.CPtr) -> llvmlite.Value | t.CPtr: - """翻译值表达式,从 self.Trans 获取共享状态""" - return translate_value( - self.Trans._cur_builder, self.Trans.Pool, self.Trans.Module, - node, - self.Trans._funcs, self.Trans._func_count, self.Trans) - - -# ============================================================ -# NewExprHandle - 工厂函数 -# ============================================================ -def NewExprHandle(pool: memhub.MemBuddy | t.CPtr, - trans: HT.Translator | t.CPtr) -> ExprHandle | t.CPtr: - h: ExprHandle | t.CPtr = pool.alloc(ExprHandle.__sizeof__()) - if h is None: - return None - string.memset(h, 0, ExprHandle.__sizeof__()) - h.Trans = trans - return h - - -# ============================================================ -# list_getitem_inline — 内联生成 list[T] __getitem__ 逻辑 -# -# list 结构布局 (6 字段 × 8 字节): -# __data__(0) __count__(8) __capacity__(16) __pool__(24) __elem_size__(32) __iter_index__(40) -# 返回元素地址 (i8*),调用方根据元素类型 load 正确的值 -# ============================================================ -def list_getitem_inline(builder: llvmlite.IRBuilder | t.CPtr, - pool: memhub.MemBuddy | t.CPtr, - lm_obj: llvmlite.Value | t.CPtr, - idx_val: llvmlite.Value | t.CPtr) -> llvmlite.Value | t.CPtr: - """内联生成 list __getitem__ 逻辑,返回元素地址 (i8*)""" - if builder is None or pool is None or lm_obj is None or idx_val is None: - return None - i64_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int64(pool) - i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool) - i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty) - # 加载 __data__ (偏移 0, index 0) - g_idx0: llvmlite.Value | t.CPtr = llvmlite.const_int64(pool, 0) - g_dpp: llvmlite.Value | t.CPtr = llvmlite.build_gep(builder, i64_ty, lm_obj, g_idx0) - if g_dpp is None: - return None - g_data: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, i8_ptr_ty, g_dpp) - # 加载 __elem_size__ (偏移 32, index 4) - g_idx4: llvmlite.Value | t.CPtr = llvmlite.const_int64(pool, 4) - g_epp: llvmlite.Value | t.CPtr = llvmlite.build_gep(builder, i64_ty, lm_obj, g_idx4) - if g_epp is None: - return None - g_esize: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, i64_ty, g_epp) - if g_data is None or g_esize is None: - return None - g_idx_i64: llvmlite.Value | t.CPtr = coerce_to_type(builder, idx_val, i64_ty) - if g_idx_i64 is None: - return None - g_offset: llvmlite.Value | t.CPtr = llvmlite.build_mul(builder, g_idx_i64, g_esize) - if g_offset is None: - return None - # 返回元素地址 (i8*),不 load - return llvmlite.build_gep(builder, i8_ty, g_data, g_offset) - - -# ============================================================ -# _list_elem_type_from_name — 从 list 类型名提取元素 LLVM 类型 -# -# 类型名格式: .list[] -# 用 strstr 检查完整模式,避免子串提取 -# 支持: list[int]→i32, list[str]/list[bytes]→i8*, list[CInt]→i32 等 -# 默认: i32 -# ============================================================ -def _list_elem_type_from_name(pool: memhub.MemBuddy | t.CPtr, - struct_name: str) -> llvmlite.LLVMType | t.CPtr: - """从 list 类型名提取元素 LLVM 类型""" - if pool is None or struct_name is None: - return None - # 用 strstr 检查完整模式 - if string.strstr(struct_name, "list[int]") is not None: - return llvmlite.Int32(pool) - if string.strstr(struct_name, "list[CInt]") is not None: - return llvmlite.Int32(pool) - if string.strstr(struct_name, "list[CInt8T]") is not None: - return llvmlite.Int8(pool) - if string.strstr(struct_name, "list[CInt16T]") is not None: - return llvmlite.Int16(pool) - if string.strstr(struct_name, "list[CInt32T]") is not None: - return llvmlite.Int32(pool) - if string.strstr(struct_name, "list[CInt64T]") is not None: - return llvmlite.Int64(pool) - if string.strstr(struct_name, "list[CSizeT]") is not None: - return llvmlite.Int64(pool) - if string.strstr(struct_name, "list[CDouble]") is not None: - return llvmlite.Double(pool) - if string.strstr(struct_name, "list[CFloat]") is not None: - return llvmlite.Float(pool) - if string.strstr(struct_name, "list[CChar]") is not None: - return llvmlite.Int8(pool) - # str/bytes/CPtr/其他指针类型 → i8* - i8_ty_d: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool) - return llvmlite.Ptr(pool, i8_ty_d) - - -# ============================================================ -# list_setitem_inline — 内联生成 list[T] __setitem__ 逻辑 -# -# 直接存储 rhs_val 到元素地址 (coerce 为 i8* 后 store) -# ============================================================ -def list_setitem_inline(builder: llvmlite.IRBuilder | t.CPtr, - pool: memhub.MemBuddy | t.CPtr, - lm_obj: llvmlite.Value | t.CPtr, - idx_val: llvmlite.Value | t.CPtr, - rhs_val: llvmlite.Value | t.CPtr) -> int: - """内联生成 list __setitem__ 逻辑,返回 0""" - if builder is None or pool is None or lm_obj is None or idx_val is None or rhs_val is None: - return 0 - i64_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int64(pool) - i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool) - i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty) - # 加载 __data__ (偏移 0, index 0) - s_idx0: llvmlite.Value | t.CPtr = llvmlite.const_int64(pool, 0) - s_dpp: llvmlite.Value | t.CPtr = llvmlite.build_gep(builder, i64_ty, lm_obj, s_idx0) - if s_dpp is None: - return 0 - s_data: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, i8_ptr_ty, s_dpp) - # 加载 __elem_size__ (偏移 32, index 4) - s_idx4: llvmlite.Value | t.CPtr = llvmlite.const_int64(pool, 4) - s_epp: llvmlite.Value | t.CPtr = llvmlite.build_gep(builder, i64_ty, lm_obj, s_idx4) - if s_epp is None: - return 0 - s_esize: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, i64_ty, s_epp) - if s_data is None or s_esize is None: - return 0 - s_idx_i64: llvmlite.Value | t.CPtr = coerce_to_type(builder, idx_val, i64_ty) - if s_idx_i64 is None: - return 0 - s_offset: llvmlite.Value | t.CPtr = llvmlite.build_mul(builder, s_idx_i64, s_esize) - if s_offset is None: - return 0 - s_addr: llvmlite.Value | t.CPtr = llvmlite.build_gep(builder, i8_ty, s_data, s_offset) - if s_addr is None: - return 0 - s_val_ptr: llvmlite.Value | t.CPtr = coerce_to_type(builder, rhs_val, i8_ptr_ty) - if s_val_ptr is None: - return 0 - llvmlite.build_store(builder, s_val_ptr, s_addr) - return 0 - - -# ============================================================ -# is_list_subscript — 检查 Subscript 节点是否是 list[T] 类型 -# -# 返回 list 对象指针 (Ptr(list[T])) 或 None -# ============================================================ -def is_list_subscript(node: ast.AST | t.CPtr, - trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr: - """检查 Subscript 节点是否是 list[T] 类型,返回 list 对象指针或 None""" - if node is None or trans is None: - return None - sub: ast.Subscript | t.CPtr = (ast.Subscript | t.CPtr)(node) - if sub is None or sub.value is None: - return None - if sub.value.kind() != ast.ASTKind.Name: - return None - nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(sub.value) - if nm is None or nm.id is None: - return None - alloca: llvmlite.Value | t.CPtr = HandlesVar.lookup_var(trans.SymTab, nm.id) - if alloca is None or alloca.Ty is None: - return None - if is_ptr_type(alloca.Ty) == 0: - return None - pointee: llvmlite.LLVMType | t.CPtr = alloca.Ty.Pointee - if pointee is None: - return None - # 检查 pointee 是否是 Ptr(Struct) - inner_ty: llvmlite.LLVMType | t.CPtr = None - match pointee: - case llvmlite.LLVMType.Ptr(it): - inner_ty = it - case _: - return None - if inner_ty is None: - return None - # 检查 inner_ty 是否是 Struct 且名称包含 "list[" - struct_name: str = None - match inner_ty: - case llvmlite.LLVMType.Struct(_, _, sname): - struct_name = sname - case _: - return None - if struct_name is None: - return None - if string.strstr(struct_name, "list[") is None: - return None - # 是 list 类型: load 出 list 对象指针 - builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder - return llvmlite.build_load(builder, pointee, alloca) - - -# ============================================================ -# 翻译下标表达式 Subscript(value, slice, ctx) — ptr[i] / arr[i] -# -# 指针遍历: ptr 是指针变量,load 出指针值后 GEP + load -# 数组遍历: arr 是数组变量,用 alloca 指针做双索引 GEP [0, i] + load -# list[T]: 泛型类不注册 struct,subscript 走 __getitem__ 内联路径 -# ============================================================ -def translate_subscript(builder: llvmlite.IRBuilder | t.CPtr, - pool: memhub.MemBuddy | t.CPtr, - mod: llvmlite.LLVMModule | t.CPtr, - node: ast.AST | t.CPtr, - trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr: - """翻译下标表达式,返回加载的元素值""" - if node is None or builder is None: - return None - sub: ast.Subscript | t.CPtr = (ast.Subscript | t.CPtr)(node) - if sub is None: - return None - - # 翻译索引 - idx_val: llvmlite.Value | t.CPtr = translate_value( - builder, pool, mod, sub.slice, None, 0, trans) - if idx_val is None: - return None - - # 如果 value 是 Name,尝试从 alloca 类型推断 - if sub.value is not None and sub.value.kind() == ast.ASTKind.Name: - nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(sub.value) - if nm.id is not None and trans is not None: - alloca: llvmlite.Value | t.CPtr = HandlesVar.lookup_var(trans.SymTab, nm.id) - if alloca is not None and alloca.Ty is not None: - if is_ptr_type(alloca.Ty) != 0: - pointee: llvmlite.LLVMType | t.CPtr = alloca.Ty.Pointee - if pointee is not None: - # 不调用 pointee.kind() 避免跨模块引用 LLVMType.kind 符号 - # 单层 match(避免嵌套 match 的编译器 bug) - match pointee: - case llvmlite.LLVMType.Array(elem_ty, count): - # 数组遍历: getelementptr [N x elem_ty], ... , i32 0, i32 %idx - elem_ptr: llvmlite.Value | t.CPtr = llvmlite.build_gep_array( - builder, pointee, elem_ty, alloca, idx_val) - if elem_ptr is not None: - return llvmlite.build_load(builder, elem_ty, elem_ptr) - return None - case llvmlite.LLVMType.Ptr(inner_ty): - # 检查 inner_ty 是否是 list[T] 类型(泛型类不注册 struct) - # list 的 subscript 应该走 __getitem__ 内联路径,而非指针遍历 - list_struct_name: str = None - match inner_ty: - case llvmlite.LLVMType.Struct(_, _, lsn): - list_struct_name = lsn - case _: - pass - if list_struct_name is not None: - if string.strstr(list_struct_name, "list[") is not None: - # list[T] 类型: 内联生成 __getitem__ 逻辑 - ptr_val_list: llvmlite.Value | t.CPtr = llvmlite.build_load( - builder, pointee, alloca) - if ptr_val_list is not None: - elem_addr_list: llvmlite.Value | t.CPtr = list_getitem_inline( - builder, pool, ptr_val_list, idx_val) - if elem_addr_list is not None: - # 根据类型名提取元素类型,bitcast 后 load - elem_ty_list: llvmlite.LLVMType | t.CPtr = _list_elem_type_from_name( - pool, list_struct_name) - if elem_ty_list is not None: - elem_ptr_ty_list: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr( - pool, elem_ty_list) - casted_addr_list: llvmlite.Value | t.CPtr = llvmlite.build_bitcast( - builder, elem_addr_list, elem_ptr_ty_list) - if casted_addr_list is not None: - return llvmlite.build_load( - builder, elem_ty_list, casted_addr_list) - return None - # inner_ty 是 Ptr 说明 alloca.Ty 是三重指针 Ptr(Ptr(Ptr(...))), - # 即 X|t.CPtr 当 X 本身是指针类型 (如 T=AST|t.CPtr, T|t.CPtr=AST**)。 - # 此时 [i] 应该是指针解引用 (步长 sizeof(ptr)=8), 而非调用 - # 结构体的 __getitem__ 方法 (会错误生成 AST.__getitem__ 调用)。 - # 对比 HashTable|t.CPtr: alloca.Ty=HashTable**, inner_ty=Struct(HashTable) - # (非 Ptr), 仍走下面的方法调用转发路径。 - if is_ptr_type(inner_ty) != 0: - ptr_val_pp: llvmlite.Value | t.CPtr = llvmlite.build_load( - builder, pointee, alloca) - if ptr_val_pp is not None: - elem_ptr_pp: llvmlite.Value | t.CPtr = llvmlite.build_gep( - builder, inner_ty, ptr_val_pp, idx_val) - if elem_ptr_pp is not None: - return llvmlite.build_load(builder, inner_ty, elem_ptr_pp) - return None - # 自定义结构体 (如 HashTable|t.CPtr, JsonValue|t.CPtr): - # 优先转发到 __getitem__,避免 IsPtrElement 误判为指针遍历 - cls_nm_rd_ptr: str = _get_custom_struct_cls_nm(pool, inner_ty) - if not (cls_nm_rd_ptr is None): - obj_ptr_rd: llvmlite.Value | t.CPtr = llvmlite.build_load( - builder, pointee, alloca) - if not (obj_ptr_rd is None): - arg_vals_rd_p: t.CSizeT | t.CPtr = pool.alloc(8) - if not (arg_vals_rd_p is None): - arg_vals_rd_p[0] = t.CSizeT(idx_val) - ret_rd_p: llvmlite.Value | t.CPtr = HandlesExprCall._call_method_on_ptr( - pool, builder, mod, cls_nm_rd_ptr, "__getitem__", - obj_ptr_rd, arg_vals_rd_p, 1, trans) - if not (ret_rd_p is None): - return ret_rd_p - return None - # bytes|t.CPtr / str|t.CPtr: alloca 是 i8**, - # 直接 GEP 按 i8* 步长(8 字节),load i8* - # 仅当 inner_ty 不是自定义结构体时才走指针遍历 - if trans is not None: - ve_pe_ts: HandlesVar.VarEntry | t.CPtr = \ - HandlesVar.lookup_var_entry(trans.SymTab, nm.id) - if ve_pe_ts is not None and ve_pe_ts.IsPtrElement == 1: - elem_ptr_ts: llvmlite.Value | t.CPtr = llvmlite.build_gep( - builder, pointee, alloca, idx_val) - if elem_ptr_ts is not None: - return llvmlite.build_load(builder, pointee, elem_ptr_ts) - return None - # 普通指针遍历: 先 load 指针值,再 GEP - ptr_val: llvmlite.Value | t.CPtr = llvmlite.build_load( - builder, pointee, alloca) - if ptr_val is not None: - elem_ptr2: llvmlite.Value | t.CPtr = llvmlite.build_gep( - builder, inner_ty, ptr_val, idx_val) - if elem_ptr2 is not None: - return llvmlite.build_load(builder, inner_ty, elem_ptr2) - return None - case _: - # 自定义类(结构体类型): 转发到 __getitem__ 方法调用 - # 如 hashtable[key] → hashtable.__getitem__(key) - cls_nm_sub: str = HandlesStruct.get_class_name_by_type(pool, pointee) - if cls_nm_sub is None: - pass - if not (cls_nm_sub is None): - obj_val_sub: llvmlite.Value | t.CPtr = llvmlite.build_load( - builder, pointee, alloca) - if not (obj_val_sub is None): - arg_vals_sub: t.CSizeT | t.CPtr = pool.alloc(8) - if not (arg_vals_sub is None): - arg_vals_sub[0] = t.CSizeT(idx_val) - ret_sub: llvmlite.Value | t.CPtr = HandlesExprCall._call_method_on_ptr( - pool, builder, mod, cls_nm_sub, "__getitem__", - obj_val_sub, arg_vals_sub, 1, trans) - if not (ret_sub is None): - return ret_sub - pass - - # 通用路径:翻译 value 获取指针 - ptr_val: llvmlite.Value | t.CPtr = translate_value( - builder, pool, mod, sub.value, None, 0, trans) - if ptr_val is None or ptr_val.Ty is None: - return None - - # 检查是否是指针类型 - if is_ptr_type(ptr_val.Ty) != 0: - elem_ty2: llvmlite.LLVMType | t.CPtr = ptr_val.Ty.Pointee - if elem_ty2 is not None: - # 数组类型: 双索引 GEP + load 元素 - match elem_ty2: - case llvmlite.LLVMType.Array(arr_elem_ty2, arr_count2): - elem_ptr3: llvmlite.Value | t.CPtr = llvmlite.build_gep_array( - builder, elem_ty2, arr_elem_ty2, ptr_val, idx_val) - if elem_ptr3 is not None: - return llvmlite.build_load(builder, arr_elem_ty2, elem_ptr3) - return None - case _: - pass - # 自定义结构体 (如 self._ht[key]): 转发到 __getitem__ 方法调用 - cls_nm_rd_gen: str = _get_custom_struct_cls_nm(pool, elem_ty2) - if cls_nm_rd_gen is None: - pass - if not (cls_nm_rd_gen is None): - arg_vals_rd_g: t.CSizeT | t.CPtr = pool.alloc(8) - if not (arg_vals_rd_g is None): - arg_vals_rd_g[0] = t.CSizeT(idx_val) - ret_rd_g: llvmlite.Value | t.CPtr = HandlesExprCall._call_method_on_ptr( - pool, builder, mod, cls_nm_rd_gen, "__getitem__", - ptr_val, arg_vals_rd_g, 1, trans) - if not (ret_rd_g is None): - return ret_rd_g - return None - # 指针类型: 单索引 GEP + load - elem_ptr4: llvmlite.Value | t.CPtr = llvmlite.build_gep( - builder, elem_ty2, ptr_val, idx_val) - if elem_ptr4 is not None: - return llvmlite.build_load(builder, elem_ty2, elem_ptr4) - return None - - -# ============================================================ -# find_global_in_module - 在模块全局变量链表中按名称查找 -# -# 查找策略: -# 1. 精确匹配 (如 "_mbuddy" 匹配 @_mbuddy) -# 2. 后缀匹配 (如 "_mbuddy" 匹配 @"sha1._mbuddy") -# ============================================================ -def find_global_in_module(mod: llvmlite.LLVMModule | t.CPtr, - name: str) -> llvmlite.GlobalVariable | t.CPtr: - """在模块全局变量链表中按名称查找全局变量""" - if mod is None or name is None: - return None - name_len: t.CSizeT = string.strlen(name) - cur: llvmlite.GlobalVariable | t.CPtr = mod.GlobalHead - # 第一遍: 精确匹配 - while cur is not None: - if cur.Name is not None: - if string.strcmp(cur.Name, name) == 0: - return cur - cur = cur.Next - # 第二遍: 后缀匹配 (.name) - cur = mod.GlobalHead - while cur is not None: - if cur.Name is not None: - cur_len: t.CSizeT = string.strlen(cur.Name) - if cur_len > name_len + 1: - suffix_start: t.CSizeT = cur_len - name_len - if cur.Name[suffix_start - 1] == '.': - match: int = 1 - for i in range(name_len): - if cur.Name[suffix_start + i] != name[i]: - match = 0 - break - if match == 1: - return cur - cur = cur.Next - return None - - -# ============================================================ -# make_global_ref - 创建全局变量引用 (@name,类型为 ty*) -# -# 用于跨模块全局变量访问: stub 未注入时,翻译阶段生成 @name 引用, -# 链接时由 stub 提供 external global 声明。 -# ============================================================ -def make_global_ref(pool: memhub.MemBuddy | t.CPtr, - name: str, - ty: llvmlite.LLVMType | t.CPtr) -> llvmlite.Value | t.CPtr: - """创建全局变量引用 (类型为 ty*,名称为 @name)""" - if name is None or ty is None: - return None - ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, ty) - ref_name: t.CChar | t.CPtr = pool.alloc(64) - if ref_name is None: - return None - viperlib.snprintf(ref_name, 64, "@%s", name) - return llvmlite.SSAValue(pool, ptr_ty, ref_name) - - -# ============================================================ -# _resolve_module_attribute_global - 解析模块属性访问的全局变量引用 -# -# 当 obj 是已导入模块名 (如 sys._mbuddy) 时: -# 1. 在当前模块全局变量链表中查找 (stub 已注入的情况) -# 2. 未找到则创建前向引用 (@attr_name, 类型为 ty 参数) -# -# 参数: -# ty_hint: 类型提示 (写路径用 rhs 类型, 读路径用 i8* 回退) -# 返回: Value 指针 (类型为 ty*),未识别为模块属性返回 None -# ============================================================ -def _is_t_type_object_name(name: str) -> int: - """检查 name 是否是 t.py 中的类型对象名(CPtr/CInt/CDouble 等) - - 这些类型对象在运行时作为全局变量 @CPtr/@CInt 等被引用, - 但 t.py 不被编译,需要在使用处生成带 null 初值的定义。 - """ - if name is None: - return 0 - # t.py 中的类型对象名(PascalCase,首字母大写) - if string.strcmp(name, "CPtr") == 0: - return 1 - if string.strcmp(name, "CInt") == 0: - return 1 - if string.strcmp(name, "CChar") == 0: - return 1 - if string.strcmp(name, "CShort") == 0: - return 1 - if string.strcmp(name, "CLong") == 0: - return 1 - if string.strcmp(name, "CLongLong") == 0: - return 1 - if string.strcmp(name, "CDouble") == 0: - return 1 - if string.strcmp(name, "CFloat") == 0: - return 1 - if string.strcmp(name, "CBool") == 0: - return 1 - if string.strcmp(name, "CVoid") == 0: - return 1 - if string.strcmp(name, "CInt8T") == 0: - return 1 - if string.strcmp(name, "CInt16T") == 0: - return 1 - if string.strcmp(name, "CInt32T") == 0: - return 1 - if string.strcmp(name, "CInt64T") == 0: - return 1 - if string.strcmp(name, "CUInt8T") == 0: - return 1 - if string.strcmp(name, "CUInt16T") == 0: - return 1 - if string.strcmp(name, "CUInt32T") == 0: - return 1 - if string.strcmp(name, "CUInt64T") == 0: - return 1 - if string.strcmp(name, "CUnsigned") == 0: - return 1 - if string.strcmp(name, "CUnsignedInt") == 0: - return 1 - if string.strcmp(name, "CUnsignedChar") == 0: - return 1 - if string.strcmp(name, "CUnsignedShort") == 0: - return 1 - if string.strcmp(name, "CUnsignedLong") == 0: - return 1 - if string.strcmp(name, "CUnsignedLongLong") == 0: - return 1 - if string.strcmp(name, "CSizeT") == 0: - return 1 - if string.strcmp(name, "CIntPtrT") == 0: - return 1 - if string.strcmp(name, "CUIntPtrT") == 0: - return 1 - if string.strcmp(name, "CPtrDiffT") == 0: - return 1 - if string.strcmp(name, "CType") == 0: - return 1 - if string.strcmp(name, "CDefine") == 0: - return 1 - if string.strcmp(name, "CStatic") == 0: - return 1 - if string.strcmp(name, "CExport") == 0: - return 1 - if string.strcmp(name, "CArray") == 0: - return 1 - if string.strcmp(name, "CTypedef") == 0: - return 1 - if string.strcmp(name, "CNoVTable") == 0: - return 1 - if string.strcmp(name, "CNeedPtr") == 0: - return 1 - if string.strcmp(name, "CAutoPtr") == 0: - return 1 - return 0 - - -def _resolve_module_attribute_global(pool: memhub.MemBuddy | t.CPtr, - mod: llvmlite.LLVMModule | t.CPtr, - trans: HT.Translator | t.CPtr, - at: ast.Attribute | t.CPtr, - ty_hint: llvmlite.LLVMType | t.CPtr) -> llvmlite.Value | t.CPtr: - """解析模块属性访问,返回全局变量引用 (用于跨模块 global 访问)""" - if at is None or at.value is None or at.attr is None: - return None - if at.value.kind() != ast.ASTKind.Name: - return None - if trans is None or trans._imported_modules is None: - return None - mod_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value) - if mod_nm.id is None: - return None - # 检查是否是已导入模块 - if HandlesImports.is_module_imported(trans._imported_modules, mod_nm.id) == 0: - return None - # 在当前模块查找全局变量 (stub 可能已注入) - gv: llvmlite.GlobalVariable | t.CPtr = find_global_in_module(mod, at.attr) - if gv is not None and gv.Ty is not None: - return make_global_ref(pool, at.attr, gv.Ty) - # 未找到: 创建 external global 声明并添加到模块 - # 否则只生成 @_argc 引用而无声明,LLVM 报 "use of undefined value '@_argc'" - use_ty: llvmlite.LLVMType | t.CPtr = ty_hint - if use_ty is None: - use_ty = llvmlite.Int8(pool) - # 确保 use_ty 中的跨模块结构体类型有 opaque 声明 - llvmlite.module_ensure_opaque_for_type(mod, pool, use_ty) - # 特殊处理: t.py 中的类型对象(CPtr/CInt/CDouble 等) - # t.py 不被编译,但这些类型对象在运行时被引用(如 va_arg(ap, t.CPtr))。 - # 创建带 null 初值的 linkonce_odr 全局变量定义,避免链接时 undefined reference。 - # LLVM 22+ 不允许 external linkage 全局变量带初值,使用 linkonce_odr 替代。 - is_t_type_obj: int = 0 - if string.strcmp(mod_nm.id, "t") == 0: - is_t_type_obj = _is_t_type_object_name(at.attr) - ext_gv: llvmlite.GlobalVariable | t.CPtr = llvmlite.new_global_variable(pool, at.attr, use_ty) - if ext_gv is not None: - if is_t_type_obj != 0: - # t.CPtr 等类型对象: 创建带 null 初值的定义(linkonce_odr) - ext_gv.Linkage = "linkonce_odr" - # i8* null 的初值文本 - null_init: bytes = pool.alloc(8) - if null_init is not None: - null_init[0] = 'n' - null_init[1] = 'u' - null_init[2] = 'l' - null_init[3] = 'l' - null_init[4] = '\0' - ext_gv.Initializer = null_init - else: - ext_gv.Initializer = None - else: - # 普通模块属性: external 声明(由其他模块提供定义) - ext_gv.Linkage = "external" - ext_gv.Initializer = None - llvmlite.module_add_global(mod, ext_gv) - return make_global_ref(pool, at.attr, use_ty) - - -# ============================================================ -# 翻译属性访问 Attribute(value, attr, ctx) — obj.field -# -# 优先级: -# 1. 枚举成员访问 (State.Idle → 常量值) -# 2. 模块属性访问 (sys._mbuddy → 加载全局变量) -# 3. 结构体字段访问 (obj.field → GEP + load) -# -# 对于 Name 类型的 obj,直接使用 alloca 指针(不 load 结构体) -# ============================================================ -def translate_attribute(builder: llvmlite.IRBuilder | t.CPtr, - pool: memhub.MemBuddy | t.CPtr, - mod: llvmlite.LLVMModule | t.CPtr, - node: ast.AST | t.CPtr, - trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr: - """翻译属性访问,返回加载的字段值""" - if node is None or builder is None: - return None - at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(node) - if at is None or at.value is None or at.attr is None: - return None - - # 枚举成员访问: EnumName.MemberName → 常量值 - # 当 value 是 Name 且 Name.id 是已注册枚举时,查找成员并返回常量 - if at.value.kind() == ast.ASTKind.Name: - enum_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value) - if enum_nm.id is not None: - if HandlesEnum.is_enum_class(enum_nm.id) == 1: - member: HandlesEnum.EnumMember | t.CPtr = HandlesEnum.lookup_enum_member( - enum_nm.id, at.attr) - if member is not None: - base_ty: llvmlite.LLVMType | t.CPtr = HandlesEnum.get_enum_base_type( - enum_nm.id) - if base_ty is not None: - # 生成数字字符串作为常量名(LLVM IR 要求常量输出数字值) - name_buf: t.CChar | t.CPtr = pool.alloc(32) - if name_buf is not None: - viperlib.snprintf(name_buf, 32, "%lld", member.Value) - return llvmlite.ConstInt(pool, base_ty, member.Value, name_buf) - return llvmlite.const_int32(pool, member.Value) - return None - - # 嵌套枚举成员访问: Module.EnumName.MemberName → 常量值 - # 当 value 是 Attribute(如 fileio.MODE)且 attr 部分是已注册枚举时 - if at.value.kind() == ast.ASTKind.Attribute: - inner_at_e: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(at.value) - if inner_at_e.value is not None and inner_at_e.value.kind() == ast.ASTKind.Name: - inner_nm_e: ast.Name | t.CPtr = (ast.Name | t.CPtr)(inner_at_e.value) - if inner_nm_e.id is not None and inner_at_e.attr is not None: - if HandlesEnum.is_enum_class(inner_at_e.attr) == 1: - member_e: HandlesEnum.EnumMember | t.CPtr = HandlesEnum.lookup_enum_member( - inner_at_e.attr, at.attr) - if member_e is not None: - base_ty_e: llvmlite.LLVMType | t.CPtr = HandlesEnum.get_enum_base_type( - inner_at_e.attr) - if base_ty_e is not None: - name_buf_e: t.CChar | t.CPtr = pool.alloc(32) - if name_buf_e is not None: - viperlib.snprintf(name_buf_e, 32, "%lld", member_e.Value) - return llvmlite.ConstInt(pool, base_ty_e, member_e.Value, name_buf_e) - return llvmlite.const_int32(pool, member_e.Value) - return None - - # 模块属性访问 (读路径): sys._mbuddy → 加载全局变量 @_mbuddy - # 当 obj 是已导入模块名且不是普通变量时,查找/创建全局变量引用并加载 - if at.value.kind() == ast.ASTKind.Name and trans is not None: - nm_ma: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value) - if nm_ma.id is not None: - # 先检查是否是普通变量 (优先级高于模块属性) - ma_is_var: llvmlite.Value | t.CPtr = HandlesVar.lookup_var( - trans.SymTab, nm_ma.id) - if ma_is_var is None: - # 先检查是否是 CDefine 编译期常量 (如 ast.CONST_INT / win32base.INVALID_HANDLE_VALUE) - # 模块属性访问的 CDefine 常量需要跨模块查找源 .py / .pyi 文件 - cdef_ma_val: int = HandlesType.lookup_cdefine_constant(at.attr) - cd_local: int = HandlesType.is_cdefine_found() - if cd_local == 0: - # 确定真实模块名:优先从 _from_imports 解析别名 - # from_imports 中条目格式 "local_name:real_module" - # 如 win32base:w32.win32base → 别名 win32base 真实模块 w32.win32base - real_mod_name: str = nm_ma.id - if trans._from_imports is not None: - resolved_mod: str = HandlesImports.lookup_from_import( - trans._from_imports, nm_ma.id, 0) - if resolved_mod is not None: - # 复制模块名到新缓冲区(截断于空格、null、或 ':') - rm_len: t.CSizeT = 0 - while resolved_mod[rm_len] != ' ' and resolved_mod[rm_len] != '\0' and resolved_mod[rm_len] != ':': - rm_len += 1 - rm_buf: str = pool.alloc(rm_len + 1) - if rm_buf is not None: - for rm_i in range(rm_len): - rm_buf[rm_i] = resolved_mod[rm_i] - rm_buf[rm_len] = '\0' - real_mod_name = rm_buf - # 即使 _from_imports 为 None(如纯 `import ast` 无 from-import), - # 也必须尝试跨模块 CDefine 查找,否则 ast.CONST_INT 会被 - # 误解析为全局变量引用 @CONST_INT(未定义符号)。 - # 构建临时 from_imports "{attr}:{real_module}" 用于跨模块查找 - if real_mod_name is not None: - ma_fi_len: t.CSizeT = string.strlen(at.attr) + string.strlen(real_mod_name) + 2 - ma_fi: str = pool.alloc(ma_fi_len) - if ma_fi is not None: - viperlib.snprintf(ma_fi, ma_fi_len, "%s:%s", at.attr, real_mod_name) - cdef_ma_val = _lookup_cross_module_cdefine(pool, at.attr, ma_fi) - if HandlesType.is_cdefine_found() != 0: - return llvmlite.const_int32(pool, cdef_ma_val) - # 检查 nm_ma.id.at.attr 是否是已导入子模块 (如 w32.win32file) - # 如果是子模块,不应创建全局变量,让嵌套属性访问路径处理 - is_submod: int = 0 - if trans._imported_modules is not None: - submod_len: t.CSizeT = string.strlen(nm_ma.id) + string.strlen(at.attr) + 2 - submod_buf: t.CChar | t.CPtr = pool.alloc(submod_len) - if submod_buf is not None: - viperlib.snprintf(submod_buf, submod_len, "%s.%s", nm_ma.id, at.attr) - if HandlesImports.is_module_imported(trans._imported_modules, submod_buf) == 1: - is_submod = 1 - # also check from_imports: at.attr 别名对应真实模块 w32.win32file - if is_submod == 0 and trans._from_imports is not None: - fi_mod_raw: str = HandlesImports.lookup_from_import( - trans._from_imports, at.attr, 0) - if fi_mod_raw is not None: - # 复制模块名到新缓冲区(截断于空格、null、或 ':') - fm_len: t.CSizeT = 0 - while fi_mod_raw[fm_len] != ' ' and fi_mod_raw[fm_len] != '\0' and fi_mod_raw[fm_len] != ':': - fm_len += 1 - fi_mod: str = pool.alloc(fm_len + 1) - if fi_mod is not None: - for fm_i in range(fm_len): - fi_mod[fm_i] = fi_mod_raw[fm_i] - fi_mod[fm_len] = '\0' - # 检查 fi_mod 是否以 "nm_ma.id." 开头 (如 w32.win32file 以 w32. 开头) - prefix_len: t.CSizeT = string.strlen(nm_ma.id) - fi_mod_len: t.CSizeT = string.strlen(fi_mod) - if fi_mod_len > prefix_len + 1: - match_prefix: int = 1 - for pi in range(prefix_len): - if fi_mod[pi] != nm_ma.id[pi]: - match_prefix = 0 - break - if match_prefix == 1 and fi_mod[prefix_len] == '.': - is_submod = 1 - if is_submod != 0: - return None # 是子模块,交给嵌套属性访问路径 - # 特殊处理: t.ASM_DESCR 不是 CDefine,是内联汇编约束命名空间 - # t.ASM_DESCR.XXX 由 HandlesExprCall 的 _asm_resolve_constraint 处理 - # 此处返回 None,让上层嵌套属性访问路径处理 - if string.strcmp(nm_ma.id, "t") == 0 and string.strcmp(at.attr, "ASM_DESCR") == 0: - return None - # CDefine 未找到且属性名符合 ALL_CAPS 约定: 报 FATAL 错误 - # 不再创建未定义的外部全局变量引用(否则 llc 报 "use of undefined value") - if _is_cdefine_name_pattern(at.attr) != 0: - err_buf_sma: str = pool.alloc(256) - if err_buf_sma is not None: - cur_sha1_sma: str = "(unknown)" - if trans is not None and trans.ModuleSha1 is not None: - cur_sha1_sma = trans.ModuleSha1 - viperlib.snprintf(err_buf_sma, 256, - "[CD] FATAL: Module attr '%s.%s' NOT found (CDefine cross-module lookup failed) in module sha1=%s\n", - nm_ma.id, at.attr, cur_sha1_sma) - VLogger.error(err_buf_sma, "CD") - return None - # 非 CDefine: 使用 i8* 作为类型提示 (模块级变量通常存储指针) - i8_ptr_hint: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, llvmlite.Int8(pool)) - mod_gv_ref: llvmlite.Value | t.CPtr = _resolve_module_attribute_global( - pool, mod, trans, at, i8_ptr_hint) - if mod_gv_ref is not None and mod_gv_ref.Ty is not None: - load_ty_mod: llvmlite.LLVMType | t.CPtr = mod_gv_ref.Ty.Pointee - if load_ty_mod is not None: - return llvmlite.build_load(builder, load_ty_mod, mod_gv_ref) - - # 嵌套模块属性访问 (w32.win32file.GENERIC_READ → 查找全局 @GENERIC_READ) - # 当 at.value 是 Attribute 且解析为已导入子模块时,查找 at.attr 作为全局常量 - if at.value.kind() == ast.ASTKind.Attribute and trans is not None: - inner_at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(at.value) - if inner_at.value is not None and inner_at.value.kind() == ast.ASTKind.Name: - inner_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(inner_at.value) - if inner_nm.id is not None and inner_at.attr is not None: - if HandlesVar.lookup_var(trans.SymTab, inner_nm.id) is None: - # 构建限定模块名: "w32.win32file" - qual_len: t.CSizeT = string.strlen(inner_nm.id) + string.strlen(inner_at.attr) + 2 - qual_buf: t.CChar | t.CPtr = pool.alloc(qual_len) - if qual_buf is not None: - viperlib.snprintf(qual_buf, qual_len, "%s.%s", inner_nm.id, inner_at.attr) - if HandlesImports.is_module_imported(trans._imported_modules, qual_buf) == 1: - # 查找全局变量 at.attr (stub 已注入的情况) - gv_nested: llvmlite.GlobalVariable | t.CPtr = find_global_in_module(mod, at.attr) - if gv_nested is not None and gv_nested.Ty is not None: - gv_ref_nested: llvmlite.Value | t.CPtr = make_global_ref( - pool, at.attr, gv_nested.Ty) - if gv_ref_nested is not None and gv_ref_nested.Ty is not None: - load_ty_nested: llvmlite.LLVMType | t.CPtr = gv_ref_nested.Ty.Pointee - if load_ty_nested is not None: - return llvmlite.build_load(builder, load_ty_nested, gv_ref_nested) - # 未找到全局: 尝试 CDefine 常量查找 - # 对于 w32.win32base.INVALID_HANDLE_VALUE 等嵌套模块属性访问, - # 先从限定模块的 .pyi 文件中查找 CDefine 常量值并内联 - cdef_val_nested: int = HandlesType.lookup_cdefine_constant(at.attr) - if HandlesType.is_cdefine_found() == 0: - # 构建临时 from_imports "attr:module" 用于跨模块查找 - tmp_fi_len: t.CSizeT = string.strlen(at.attr) + string.strlen(qual_buf) + 2 - tmp_fi: str = pool.alloc(tmp_fi_len) - if tmp_fi is not None: - viperlib.snprintf(tmp_fi, tmp_fi_len, "%s:%s", at.attr, qual_buf) - cdef_val_nested = _lookup_cross_module_cdefine(pool, at.attr, tmp_fi) - if HandlesType.is_cdefine_found() != 0: - return llvmlite.const_int32(pool, cdef_val_nested) - # CDefine 未找到: 报 FATAL 错误(不再创建未定义的全局变量引用) - # 之前此处创建 @INVALID_HANDLE_VALUE 等前向引用,但全局未定义, - # 导致 llc 报 "use of undefined value" 错误。 - # 正确做法是报错终止,让开发者修复跨模块 CDefine 查找失败的根本原因。 - if _is_cdefine_name_pattern(at.attr) != 0: - err_buf_ma: str = pool.alloc(256) - if err_buf_ma is not None: - cur_sha1_ma: str = "(unknown)" - if trans is not None and trans.ModuleSha1 is not None: - cur_sha1_ma = trans.ModuleSha1 - viperlib.snprintf(err_buf_ma, 256, - "[CD] FATAL: Nested attr '%s.%s' NOT found (CDefine cross-module lookup failed) in module sha1=%s\n", - qual_buf, at.attr, cur_sha1_ma) - VLogger.error(err_buf_ma, "CD") - return None - - # 对于 Name 类型的 obj,直接查找 alloca(不 load 结构体) - obj_ptr: llvmlite.Value | t.CPtr = None - if at.value.kind() == ast.ASTKind.Name and trans is not None: - nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value) - if nm.id is not None: - obj_ptr = HandlesVar.lookup_var(trans.SymTab, nm.id) - - # 非 Name 路径:翻译对象值(会 load) - if obj_ptr is None: - obj_ptr = translate_value(builder, pool, mod, at.value, None, 0, trans) - - if obj_ptr is None or obj_ptr.Ty is None: - return None - - # 如果 obj_ptr 是 Ptr(Ptr(Struct))(X|t.CPtr 变量的 alloca), - # load 解引用获取 Ptr(Struct) - obj_ptr = _deref_if_ptr_ptr(builder, obj_ptr) - - # 查找结构体类型信息 - # obj_ptr 类型应该是 Ptr(Struct(...)) - match obj_ptr.Ty: - case llvmlite.LLVMType.Ptr(struct_ty): - # 确保跨模块结构体的完整定义在当前模块中可用(供 getelementptr 访问字段) - HandlesStruct.ensure_struct_def_in_module(pool, mod, struct_ty) - # 查找字段索引和类型 - field_info: HandlesStruct.FieldEntry | t.CPtr = HandlesStruct.lookup_field( - struct_ty, at.attr) - # REnum 变体字段查找: lookup_field 失败时,尝试 REnum 别名 - # REnum 结构体字段名是 _p1/_p2/...,但源码用变体字段名访问(如 ty.Pointee) - if field_info is None: - renum_se: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_type( - struct_ty) - if renum_se is not None and renum_se.Name is not None: - is_rn: int = HandlesClassDef._is_renum_class_name(renum_se.Name) - if is_rn == 1: - alias_idx: int = HandlesClassDef._lookup_renum_field_alias( - renum_se.Name, at.attr) - if alias_idx >= 1: - alias_fe: HandlesStruct.FieldEntry | t.CPtr = \ - HandlesStruct._get_field_entry(renum_se, alias_idx) - if alias_fe is not None and alias_fe.Ty is not None: - alias_ptr: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct( - builder, struct_ty, alias_fe.Ty, obj_ptr, alias_idx) - if alias_ptr is not None: - return llvmlite.build_load(builder, alias_fe.Ty, alias_ptr) - # 按需过滤: struct_ty 为 i8(简化联合类型)时,通过 AnnotClassName 按类名查找 - # 传递 SHA1 以区分跨模块同名类 - if field_info is None: - if at.value.kind() == ast.ASTKind.Name and trans is not None: - nm_fb: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value) - if nm_fb.id is not None: - var_entry: HandlesVar.VarEntry | t.CPtr = HandlesVar.lookup_var_entry( - trans.SymTab, nm_fb.id) - if var_entry is not None and var_entry.AnnotClassName is not None: - cur_sha1: str = trans.ModuleSha1 - field_info = HandlesStruct.lookup_field_by_class( - var_entry.AnnotClassName, at.attr, cur_sha1) - # 按需过滤成功:bitcast obj_ptr 到 AnnotClassName 对应的结构体类型 - # 原始 struct_ty 可能是 i8(X|t.CPtr 简化为 Ptr(i8)), - # 需用实际结构体类型做 GEP,否则 GEP i8 失败 - if field_info is not None: - annot_se: HandlesStruct.StructEntry | t.CPtr = \ - HandlesStruct.find_struct(var_entry.AnnotClassName) - if annot_se is not None and annot_se.Ty is not None: - annot_ptr_ty: llvmlite.LLVMType | t.CPtr = \ - llvmlite.Ptr(pool, annot_se.Ty) - casted_ptr: llvmlite.Value | t.CPtr = \ - llvmlite.build_bitcast(builder, obj_ptr, annot_ptr_ty) - if casted_ptr is not None: - obj_ptr = casted_ptr - struct_ty = annot_se.Ty - # 按需过滤更新 struct_ty 后,需重新确保 - # 注解类型结构体定义在当前模块可用 - # (原始 struct_ty 可能是 i8,ensure 无效) - HandlesStruct.ensure_struct_def_in_module( - pool, mod, annot_se.Ty) - if field_info is not None: - field_ty: llvmlite.LLVMType | t.CPtr = field_info.Ty - # 联合体:bitcast obj_ptr 到 field_ty* 后 load - if HandlesStruct.is_union_by_type(struct_ty) == 1: - field_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, field_ty) - casted: llvmlite.Value | t.CPtr = llvmlite.build_bitcast( - builder, obj_ptr, field_ptr_ty) - if casted is not None: - return llvmlite.build_load(builder, field_ty, casted) - return None - # 普通结构体:GEP + load - field_idx: int = field_info.Index - field_ptr: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct( - builder, struct_ty, field_ty, obj_ptr, field_idx) - if field_ptr is not None: - # 数组类型字段不能 load 为 SSA value,直接返回字段指针 - # 用于后续下标访问: self.state[0] → GEP state 字段 → GEP 数组元素 - if is_array_type(field_ty) != 0: - return field_ptr - loaded_val: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, field_ty, field_ptr) - # 联合类型字段(如 Token | t.CPtr)被编译为 i8*, - # 若 AnnotClassName 指示了具体结构体类型,bitcast 为正确的结构体指针 - if loaded_val is not None and field_info.AnnotClassName is not None: - annot_struct: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct( - field_info.AnnotClassName) - if annot_struct is not None and annot_struct.Ty is not None: - annot_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, annot_struct.Ty) - return llvmlite.build_bitcast(builder, loaded_val, annot_ptr_ty) - return loaded_val - # fast-fail: 字段未找到,打印诊断信息 - if trans is not None: - diag_annot: str = None - diag_var_nm: str = None - if at.value is not None and at.value.kind() == ast.ASTKind.Name: - dnm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value) - diag_var_nm = dnm.id - if dnm.id is not None: - dve: HandlesVar.VarEntry | t.CPtr = HandlesVar.lookup_var_entry( - trans.SymTab, dnm.id) - if dve is not None: - diag_annot = dve.AnnotClassName - fb_attr: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb_attr is not None: - viperlib.snprintf(fb_attr, 1024, - "属性访问失败: .%s (var=%s annot=%s sha1=%s:%d)", - at.attr, - diag_var_nm if diag_var_nm is not None else "?", - diag_annot if diag_annot is not None else "None", - trans.ModuleSha1 if trans.ModuleSha1 is not None else "?", - at.lineno if at.lineno is not None else 0) - VLogger.error(fb_attr, "ATTR") - return None - case _: - return None - -# ============================================================ -# 获取下标表达式的元素指针(不加载值,用于赋值) -# ============================================================ -def get_subscript_ptr(builder: llvmlite.IRBuilder | t.CPtr, - pool: memhub.MemBuddy | t.CPtr, - mod: llvmlite.LLVMModule | t.CPtr, - node: ast.AST | t.CPtr, - trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr: - """获取下标表达式的元素指针(用于赋值 lhs)""" - if node is None or builder is None: - return None - sub: ast.Subscript | t.CPtr = (ast.Subscript | t.CPtr)(node) - if sub is None: - return None - - # 翻译索引 - idx_val: llvmlite.Value | t.CPtr = translate_value( - builder, pool, mod, sub.slice, None, 0, trans) - if idx_val is None: - return None - - # 如果 value 是 Name,尝试从 alloca 类型推断 - if sub.value is not None and sub.value.kind() == ast.ASTKind.Name: - nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(sub.value) - if nm.id is not None and trans is not None: - alloca: llvmlite.Value | t.CPtr = HandlesVar.lookup_var(trans.SymTab, nm.id) - if alloca is not None and alloca.Ty is not None: - if is_ptr_type(alloca.Ty) != 0: - pointee: llvmlite.LLVMType | t.CPtr = alloca.Ty.Pointee - if pointee is not None: - # 单层 match(避免嵌套 match 的编译器 bug) - match pointee: - case llvmlite.LLVMType.Array(elem_ty, count): - # 数组遍历 - return llvmlite.build_gep_array( - builder, pointee, elem_ty, alloca, idx_val) - case llvmlite.LLVMType.Ptr(inner_ty): - # inner_ty 是 Ptr 说明 alloca.Ty 是三重指针, - # 即 X|t.CPtr 当 X 本身是指针类型 (如 T=AST|t.CPtr, T|t.CPtr=AST**)。 - # 此时 [i]=val 应该是指针解引用赋值, 而非调用 __setitem__。 - if is_ptr_type(inner_ty) != 0: - ptr_val_gsp: llvmlite.Value | t.CPtr = llvmlite.build_load( - builder, pointee, alloca) - if ptr_val_gsp is not None: - return llvmlite.build_gep( - builder, inner_ty, ptr_val_gsp, idx_val) - return None - # 自定义结构体 (如 HashTable|t.CPtr, JsonValue|t.CPtr): - # 优先返回 None 触发 __setitem__ 重载, - # 避免 IsPtrElement 误判为指针遍历 - cls_nm_ptr_chk: str = _get_custom_struct_cls_nm(pool, inner_ty) - if cls_nm_ptr_chk is None: - pass - if not (cls_nm_ptr_chk is None): - return None - # bytes|t.CPtr / str|t.CPtr: alloca 是 i8**, - # 直接 GEP 按 i8* 步长(8 字节),不 load - # 仅当 inner_ty 不是自定义结构体时才走指针遍历 - if trans is not None: - ve_pe: HandlesVar.VarEntry | t.CPtr = \ - HandlesVar.lookup_var_entry(trans.SymTab, nm.id) - if ve_pe is not None and ve_pe.IsPtrElement == 1: - return llvmlite.build_gep( - builder, pointee, alloca, idx_val) - # 普通指针遍历: 先 load 指针值,再 GEP - ptr_val: llvmlite.Value | t.CPtr = llvmlite.build_load( - builder, pointee, alloca) - if ptr_val is None: - return None - gep_r: llvmlite.Value | t.CPtr = llvmlite.build_gep( - builder, inner_ty, ptr_val, idx_val) - return gep_r - case _: - # pointee 是普通标量类型 (如 i64, i32, i8): - # alloca 是 Ptr(标量), 直接 GEP 获取第 idx 个元素指针 - # 支持 arg_vals[i] = val 这类参数数组下标赋值 - return llvmlite.build_gep(builder, pointee, alloca, idx_val) - - # 通用路径 - ptr_val: llvmlite.Value | t.CPtr = translate_value( - builder, pool, mod, sub.value, None, 0, trans) - if ptr_val is None or ptr_val.Ty is None: - return None - if is_ptr_type(ptr_val.Ty) != 0: - elem_ty2: llvmlite.LLVMType | t.CPtr = ptr_val.Ty.Pointee - if elem_ty2 is not None: - # 数组类型: 双索引 GEP (getelementptr [N x ty], ptr, i32 0, i32 idx) - match elem_ty2: - case llvmlite.LLVMType.Array(arr_elem_ty, arr_count): - return llvmlite.build_gep_array( - builder, elem_ty2, arr_elem_ty, ptr_val, idx_val) - case _: - pass - # 自定义结构体 (如 self._ht[key]): 返回 None, - # 触发 HandlesAssign 的 __setitem__ 重载 - cls_nm_gen: str = _get_custom_struct_cls_nm(pool, elem_ty2) - if cls_nm_gen is None: - pass - if not (cls_nm_gen is None): - return None - # 指针类型: 单索引 GEP (getelementptr ty, ptr, idx) - return llvmlite.build_gep(builder, elem_ty2, ptr_val, idx_val) - return None - - -# ============================================================ -# 获取属性访问的字段指针(不加载值,用于赋值) -# 对于 Name 类型的 obj,直接使用 alloca 指针(不 load 结构体) -# ============================================================ -def get_attribute_ptr(builder: llvmlite.IRBuilder | t.CPtr, - pool: memhub.MemBuddy | t.CPtr, - mod: llvmlite.LLVMModule | t.CPtr, - node: ast.AST | t.CPtr, - trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr: - """获取属性访问的字段指针(用于赋值 lhs)""" - if node is None or builder is None: - return None - at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(node) - if at is None or at.value is None or at.attr is None: - return None - - # 对于 Name 类型的 obj,直接查找 alloca(不 load 结构体) - obj_ptr: llvmlite.Value | t.CPtr = None - if at.value.kind() == ast.ASTKind.Name and trans is not None: - nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value) - if nm.id is not None: - obj_ptr = HandlesVar.lookup_var(trans.SymTab, nm.id) - - # 模块属性访问 (写路径): sys._mbuddy = mb → store 到全局变量 @_mbuddy - # 当 obj 是已导入模块名且不是普通变量时,查找/创建全局变量引用 - if obj_ptr is None and at.value.kind() == ast.ASTKind.Name and trans is not None: - nm_wma: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value) - if nm_wma.id is not None: - # CDefine 常量不可写: 报 FATAL 错误,不创建未定义全局 - if _is_cdefine_name_pattern(at.attr) != 0: - err_buf_wma: str = pool.alloc(256) - if err_buf_wma is not None: - viperlib.snprintf(err_buf_wma, 256, - "[CD] FATAL: Cannot assign to CDefine constant '%s.%s'\n", - nm_wma.id, at.attr) - VLogger.error(err_buf_wma, "CD") - return None - # 使用 i8* 作为类型提示 (模块级变量通常存储指针) - i8_ptr_w: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, llvmlite.Int8(pool)) - wma_ref: llvmlite.Value | t.CPtr = _resolve_module_attribute_global( - pool, mod, trans, at, i8_ptr_w) - if wma_ref is not None: - return wma_ref - - # 非 Name 路径:翻译对象值(会 load) - if obj_ptr is None: - obj_ptr = translate_value(builder, pool, mod, at.value, None, 0, trans) - - if obj_ptr is None or obj_ptr.Ty is None: - return None - - # 如果 obj_ptr 是 Ptr(Ptr(Struct))(X|t.CPtr 变量的 alloca), - # load 解引用获取 Ptr(Struct) - obj_ptr = _deref_if_ptr_ptr(builder, obj_ptr) - - match obj_ptr.Ty: - case llvmlite.LLVMType.Ptr(struct_ty): - # 确保跨模块结构体的完整定义在当前模块中可用(供 getelementptr 访问字段) - # 与 translate_attribute 一致,避免 opaque 类型导致 GEP 报错 - HandlesStruct.ensure_struct_def_in_module(pool, mod, struct_ty) - field_info: HandlesStruct.FieldEntry | t.CPtr = HandlesStruct.lookup_field( - struct_ty, at.attr) - # 按需过滤: struct_ty 为 i8(简化联合类型)时,通过 AnnotClassName 按类名查找 - # 传递 SHA1 以区分跨模块同名类 - if field_info is None: - if at.value.kind() == ast.ASTKind.Name and trans is not None: - nm_fb: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value) - if nm_fb.id is not None: - var_entry: HandlesVar.VarEntry | t.CPtr = HandlesVar.lookup_var_entry( - trans.SymTab, nm_fb.id) - if var_entry is not None and var_entry.AnnotClassName is not None: - cur_sha1: str = None - if trans is not None: - cur_sha1 = trans.ModuleSha1 - field_info = HandlesStruct.lookup_field_by_class( - var_entry.AnnotClassName, at.attr, cur_sha1) - # 按需过滤成功:bitcast obj_ptr 到 AnnotClassName 对应的结构体类型 - # 原始 struct_ty 可能是 i8(X|t.CPtr 简化为 Ptr(i8)), - # 需用实际结构体类型做 GEP,否则 GEP i8 失败 - if field_info is not None: - annot_se: HandlesStruct.StructEntry | t.CPtr = \ - HandlesStruct.find_struct(var_entry.AnnotClassName) - if annot_se is not None and annot_se.Ty is not None: - annot_ptr_ty: llvmlite.LLVMType | t.CPtr = \ - llvmlite.Ptr(pool, annot_se.Ty) - casted_ptr: llvmlite.Value | t.CPtr = \ - llvmlite.build_bitcast(builder, obj_ptr, annot_ptr_ty) - if casted_ptr is not None: - obj_ptr = casted_ptr - struct_ty = annot_se.Ty - # 按需过滤更新 struct_ty 后,需重新确保 - # 注解类型结构体定义在当前模块可用 - HandlesStruct.ensure_struct_def_in_module( - pool, mod, annot_se.Ty) - if field_info is not None: - # 联合体:bitcast obj_ptr 到 field_ty*(字段指针用于 store) - if HandlesStruct.is_union_by_type(struct_ty) == 1: - field_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, field_info.Ty) - return llvmlite.build_bitcast(builder, obj_ptr, field_ptr_ty) - # 普通结构体:GEP 获取字段指针 - return llvmlite.build_gep_struct( - builder, struct_ty, field_info.Ty, obj_ptr, field_info.Index) - # fast-fail: 字段未找到,打印诊断信息 - if trans is not None: - diag_annot_g: str = None - diag_var_nm_g: str = None - if at.value is not None and at.value.kind() == ast.ASTKind.Name: - dnm_g: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value) - diag_var_nm_g = dnm_g.id - if dnm_g.id is not None: - dve_g: HandlesVar.VarEntry | t.CPtr = HandlesVar.lookup_var_entry( - trans.SymTab, dnm_g.id) - if dve_g is not None: - diag_annot_g = dve_g.AnnotClassName - fb_attr_g: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb_attr_g is not None: - viperlib.snprintf(fb_attr_g, 1024, - "属性写入失败: .%s (var=%s annot=%s sha1=%s:%d)", - at.attr, - diag_var_nm_g if diag_var_nm_g is not None else "?", - diag_annot_g if diag_annot_g is not None else "None", - trans.ModuleSha1 if trans.ModuleSha1 is not None else "?", - at.lineno if at.lineno is not None else 0) - VLogger.error(fb_attr_g, "ATTR") - return None - case _: - return None diff --git a/TransPyV/App/lib/core/Handles/HandlesExprCall.py b/TransPyV/App/lib/core/Handles/HandlesExprCall.py deleted file mode 100644 index 1d40c34..0000000 --- a/TransPyV/App/lib/core/Handles/HandlesExprCall.py +++ /dev/null @@ -1,5037 +0,0 @@ -import t, c -from stdint import * -import ast -import llvmlite -import memhub -import string -import stdio -import stdlib -import sys -import viperlib -import lib.core.VLogger as VLogger -import lib.core.Handles.HandlesBase as HandlesBase -import lib.core.Handles.HandlesTranslator as HT -import lib.core.Handles.HandlesExpr as HandlesExpr -import lib.core.Handles.HandlesVar as HandlesVar -import lib.core.Handles.HandlesType as HandlesType -import lib.core.Handles.HandlesStruct as HandlesStruct -import lib.core.Handles.HandlesImports as HandlesImports -import lib.core.Handles.HandlesClassDef as HandlesClassDef - -# ============================================================ -# 全局模块 SHA1 映射(module_name → SHA1) -# -# 翻译时用于跨模块函数调用名混淆: -# string.strchr(...) → call @{sha1_of_string}.strchr(...) -# -# 通过 set_module_sha1_map 设置,_lookup_module_sha1 查询 -# ============================================================ -_g_sha1_arr: bytes = None -_g_mod_arr: bytes = None -_g_sha1_count: int = 0 - -def set_module_sha1_map(sha1_arr: bytes, mod_arr: bytes, count: int) -> int: - """设置全局模块 SHA1 映射""" - global _g_sha1_arr - global _g_mod_arr - global _g_sha1_count - _g_sha1_arr = sha1_arr - _g_mod_arr = mod_arr - _g_sha1_count = count - return 0 - -def _lookup_module_sha1(mod_name: str) -> str: - """查找模块名对应的 SHA1,找不到返回 None""" - if mod_name is None: - return None - if _g_sha1_arr is None or _g_mod_arr is None: - return None - if _g_sha1_count <= 0: - return None - for i in range(_g_sha1_count): - idx: t.CSizeT = t.CSizeT(i) * 64 - if string.strcmp(_g_mod_arr + idx, mod_name) == 0: - sidx: t.CSizeT = t.CSizeT(i) * 17 - return _g_sha1_arr + sidx - return None - -def _lookup_module_sha1_suffix(mod_suffix: str) -> str: - """后缀匹配查找模块 SHA1,如 mod_suffix="__types" 匹配 "llvmlite.__types" - - 用于 from .X import Y 的相对导入:impf.module 是 ".X"(带前导点), - 去掉前导点后为 "X",SHA1 映射表中键是 "pkg.X",需要后缀匹配。 - """ - if mod_suffix is None: - return None - if _g_sha1_arr is None or _g_mod_arr is None: - return None - if _g_sha1_count <= 0: - return None - suffix_len: t.CSizeT = string.strlen(mod_suffix) - if suffix_len == 0: - return None - for i in range(_g_sha1_count): - idx: t.CSizeT = t.CSizeT(i) * 64 - mod_name: str = _g_mod_arr + idx - mod_len: t.CSizeT = string.strlen(mod_name) - if mod_len == 0: - continue - # 精确匹配 - if mod_len == suffix_len: - if string.strcmp(mod_name, mod_suffix) == 0: - sidx: t.CSizeT = t.CSizeT(i) * 17 - return _g_sha1_arr + sidx - # 后缀匹配:mod_name 以 "." + mod_suffix 结尾 - if mod_len > suffix_len: - if mod_name[mod_len - suffix_len - 1] == '.': - cmp_start: str = mod_name + mod_len - suffix_len - if string.strcmp(cmp_start, mod_suffix) == 0: - sidx2: t.CSizeT = t.CSizeT(i) * 17 - return _g_sha1_arr + sidx2 - # 反向后缀匹配:mod_suffix 以 "." + mod_name 结尾 - # 用于 from_imports 存完整路径(如 lib.core.Handles.HandlesTranslator) - # 而 mod_arr 只存文件名(如 HandlesTranslator)的情况: - # import X as Y 的别名 Y 经 from_imports 查到完整路径, - # 需反向匹配 mod_arr 中的文件名才能找到 SHA1 - if suffix_len > mod_len: - if mod_suffix[suffix_len - mod_len - 1] == '.': - cmp_start_rev: str = mod_suffix + suffix_len - mod_len - if string.strcmp(cmp_start_rev, mod_name) == 0: - sidx_rev: t.CSizeT = t.CSizeT(i) * 17 - return _g_sha1_arr + sidx_rev - return None - -# ============================================================ -# 全局 CExport 函数表(module_sha1 + func_name) -# -# t.CExport 函数定义时不加 SHA1 前缀(如 @strlen), -# 跨模块调用时需要查表确认目标函数是否是 CExport 函数。 -# 若是,使用裸名调用(@strlen);否则使用 @{sha1}.func。 -# 必须包含模块 SHA1 记录,避免同名跨模块函数冲突 -# (一个模块有 CExport 的 strlen→@strlen,另一个没有→@{sha1}.strlen)。 -# ============================================================ -_g_cexport_sha1_arr: bytes = None -_g_cexport_func_arr: bytes = None -_g_cexport_count: int = 0 -_CEXPORT_MAX: t.CDefine = 256 - -def register_cexport_func(sha1: str, func_name: str) -> int: - """注册 CExport 函数到全局表(sha1+func_name 二元组)""" - global _g_cexport_sha1_arr - global _g_cexport_func_arr - global _g_cexport_count - if sha1 is None or func_name is None: - return 0 - if _g_cexport_sha1_arr is None: - _g_cexport_sha1_arr = stdlib.malloc(_CEXPORT_MAX * 17) - _g_cexport_func_arr = stdlib.malloc(_CEXPORT_MAX * 64) - if _g_cexport_sha1_arr is None or _g_cexport_func_arr is None: - return 0 - string.memset(_g_cexport_sha1_arr, 0, _CEXPORT_MAX * 17) - string.memset(_g_cexport_func_arr, 0, _CEXPORT_MAX * 64) - if _g_cexport_count < _CEXPORT_MAX: - idx: t.CSizeT = t.CSizeT(_g_cexport_count) * 17 - string.strcpy(_g_cexport_sha1_arr + idx, sha1) - idx2: t.CSizeT = t.CSizeT(_g_cexport_count) * 64 - string.strcpy(_g_cexport_func_arr + idx2, func_name) - _g_cexport_count += 1 - return 1 - return 0 - -def is_cexport_func(sha1: str, func_name: str) -> int: - """检查 (sha1, func_name) 是否是 CExport 函数""" - if sha1 is None or func_name is None: - return 0 - if _g_cexport_sha1_arr is None: - return 0 - for i in range(_g_cexport_count): - idx: t.CSizeT = t.CSizeT(i) * 17 - if string.strcmp(_g_cexport_sha1_arr + idx, sha1) == 0: - idx2: t.CSizeT = t.CSizeT(i) * 64 - if string.strcmp(_g_cexport_func_arr + idx2, func_name) == 0: - return 1 - return 0 - -# ============================================================ -# _lookup_mod_sha1 - 从 from_imports 查找类所属模块的 SHA1 -# -# lookup_from_import 返回指向 from_imports 内部的指针,不是 null 终止 -# (如 "namespace_defs Gadget:namespace_defs ...")。此函数手动截断 -# 模块名,复制到新缓冲区,再查找 SHA1(精确+后缀匹配)。 -# ============================================================ -def _lookup_mod_sha1(pool: memhub.MemBuddy | t.CPtr, - from_imports: str, class_name: str, - allow_star_fallback: int = 1) -> str: - """从 from_imports 查找类所属模块的 SHA1,返回 None=未找到 - - allow_star_fallback: 传 0 禁用 star import 回退(用于明确模块名/函数名查找) - """ - mod_name_raw: str = HandlesImports.lookup_from_import( - from_imports, class_name, allow_star_fallback) - if mod_name_raw is None: - return None - # 手动找到模块名结束位置(空格、null、或 ':' 别名分隔符),复制到新缓冲区 - mod_len: t.CSizeT = 0 - while mod_name_raw[mod_len] != ' ' and mod_name_raw[mod_len] != '\0' and mod_name_raw[mod_len] != ':': - mod_len += 1 - mod_name_buf: str = pool.alloc(mod_len + 1) - if mod_name_buf is None: - return None - for mi in range(mod_len): - mod_name_buf[mi] = mod_name_raw[mi] - mod_name_buf[mod_len] = '\0' - # 去掉相对导入的前导点 - base_mod: str = mod_name_buf - while base_mod[0] == '.': - base_mod = base_mod + 1 - sha1: str = _lookup_module_sha1(base_mod) - if sha1 is None: - sha1 = _lookup_module_sha1_suffix(base_mod) - return sha1 - -# ============================================================ -# HandlesExprCall - 函数调用表达式处理(Mixin 继承模式) -# -# 工具函数和 FuncEntry 保留为模块级,ExprCallHandle 提供 trans 接口 -# ============================================================ - -# ============================================================ -# 在模块函数链表中按名称查找函数 -# ============================================================ -def find_func_in_module(mod: llvmlite.LLVMModule | t.CPtr, - name: str) -> llvmlite.Function | t.CPtr: - """在模块的函数链表中按名称查找函数 - - 查找策略: - 1. 精确匹配(如 "strlen" 匹配 @strlen,有 t.CExport 的函数) - 2. 后缀匹配(如 "atoi" 匹配 @"83210a72e829a086.atoi",无 t.CExport 的函数) - - 使用 llvmlite.function_get_name/next 访问器绕过 stub 类型限制 - (stub 类型字段不足且字段类型可能错误,直接字段访问会被静默跳过)。 - """ - if mod is None or name is None: - return None - name_len: t.CSizeT = string.strlen(name) - cur: llvmlite.Function | t.CPtr = mod.FuncHead - # 第一遍:精确匹配 - while cur is not None: - cur_name: t.CChar | t.CPtr = llvmlite.function_get_name(cur) - if cur_name is not None: - if string.strcmp(cur_name, name) == 0: - return cur - cur = llvmlite.function_get_next(cur) - # 第二遍:后缀匹配(.name) - # 不跳过 declare:方法 stub 也是 declare,需要通过后缀匹配找到 - # 调用处(translate_call 等)负责判断 IsDeclared 并决定使用裸名还是 sha1 前缀名 - cur = mod.FuncHead - while cur is not None: - cur_name2: t.CChar | t.CPtr = llvmlite.function_get_name(cur) - if cur_name2 is not None: - cur_len: t.CSizeT = string.strlen(cur_name2) - if cur_len > name_len + 1: - suffix_start: t.CSizeT = cur_len - name_len - if cur_name2[suffix_start - 1] == '.': - match: int = 1 - for i in range(name_len): - if cur_name2[suffix_start + i] != name[i]: - match = 0 - break - if match == 1: - return cur - cur = llvmlite.function_get_next(cur) - return None - -# ============================================================ -# _ensure_c_lib_declare - 为已知的 C 库函数创建 declare 声明 -# -# 对应 TPC 的 _C_LIB_FUNCS 机制。当裸名调用 memset/memmove/memcmp/ -# strcmp/strlen 等已知 C 库函数时,自动在当前模块创建 declare, -# 避免报 "裸名调用未定义且未导入" 错误。 -# memcpy 不在此处理(已有 _emit_llvm_memcpy_intrinsic 映射到 @llvm.memcpy)。 -# -# Args: -# pool: 内存池 -# mod: LLVM 模块 -# name: 函数名 -# -# Returns: -# Function 指针(已创建 declare),或 None 如果不是已知 C 库函数 -# ============================================================ -def _ensure_c_lib_declare(pool: memhub.MemBuddy | t.CPtr, - mod: llvmlite.LLVMModule | t.CPtr, - name: str) -> llvmlite.Function | t.CPtr: - """为已知的 C 库函数创建 declare 声明""" - if pool is None or mod is None or name is None: - return None - - i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool) - i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool) - i64_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int64(pool) - i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty) - - ret_ty: llvmlite.LLVMType | t.CPtr = None - params: int = 0 # 参数数量 - - if string.strcmp(name, "strlen") == 0 or string.strcmp(name, "strlength") == 0: - ret_ty = i64_ty - params = 1 - elif string.strcmp(name, "memset") == 0: - ret_ty = i8_ptr_ty - params = 3 - elif string.strcmp(name, "memcpy") == 0: - ret_ty = i8_ptr_ty - params = 3 - elif string.strcmp(name, "memmove") == 0: - ret_ty = i8_ptr_ty - params = 3 - elif string.strcmp(name, "memcmp") == 0: - ret_ty = i32_ty - params = 3 - elif string.strcmp(name, "strcmp") == 0: - ret_ty = i32_ty - params = 2 - elif string.strcmp(name, "strncmp") == 0: - ret_ty = i32_ty - params = 3 - elif string.strcmp(name, "strcpy") == 0: - ret_ty = i8_ptr_ty - params = 2 - elif string.strcmp(name, "strncpy") == 0: - ret_ty = i8_ptr_ty - params = 3 - elif string.strcmp(name, "strcat") == 0: - ret_ty = i8_ptr_ty - params = 2 - elif string.strcmp(name, "puts") == 0: - ret_ty = i32_ty - params = 1 - elif string.strcmp(name, "atoi") == 0: - ret_ty = i32_ty - params = 1 - elif string.strcmp(name, "atol") == 0: - ret_ty = i64_ty - params = 1 - elif string.strcmp(name, "abs") == 0: - ret_ty = i32_ty - params = 1 - elif string.strcmp(name, "labs") == 0: - ret_ty = i64_ty - params = 1 - else: - return None - - # 创建 declare - fn: llvmlite.Function | t.CPtr = llvmlite.create_declare(pool, mod, name, ret_ty) - if fn is None: - return None - # 添加参数 - if params == 1: - if string.strcmp(name, "abs") == 0: - llvmlite.add_param(pool, fn, i32_ty, "n") - elif string.strcmp(name, "labs") == 0: - llvmlite.add_param(pool, fn, i64_ty, "n") - else: - llvmlite.add_param(pool, fn, i8_ptr_ty, "s") - elif params == 2: - llvmlite.add_param(pool, fn, i8_ptr_ty, "dst") - llvmlite.add_param(pool, fn, i8_ptr_ty, "src") - elif params == 3: - if string.strcmp(name, "memset") == 0: - llvmlite.add_param(pool, fn, i8_ptr_ty, "dst") - llvmlite.add_param(pool, fn, i32_ty, "c") - llvmlite.add_param(pool, fn, i64_ty, "n") - else: - llvmlite.add_param(pool, fn, i8_ptr_ty, "dst") - llvmlite.add_param(pool, fn, i8_ptr_ty, "src") - llvmlite.add_param(pool, fn, i64_ty, "n") - return fn - -# ============================================================ -# _infer_external_func_ret_ty - 根据函数名推断外部函数返回类型 -# -# stubs 在翻译后才注入 IR,翻译时模块中无 stub 函数声明, -# 因此对 includes 库函数(如 string.strchr 返回 i8*)需根据 -# 函数名推断返回类型,避免指针被截断为 i32。 -# -# 覆盖 includes/string.py 所有导出函数: -# i8*: strcpy, strncpy, strchr, strrchr, strstr, memset, memset32, memcpy, memmove -# i64: strlen, atoll -# double: atof -# i8: samestr -# i32(默认): strcmp, strncmp, memcmp, strspn, atoi, split -# ============================================================ -def _infer_external_func_ret_ty(pool: memhub.MemBuddy | t.CPtr, - func_name: str) -> llvmlite.LLVMType | t.CPtr: - """根据函数名推断外部 includes 函数的返回类型 - - 支持三种函数名形式: - 1. 裸名: "parse", "strlen" - 2. 别名: "json_parse"(from X import parse as json_parse) - 3. 带 SHA1 前缀: "240a9a4157959a9f.parse"(跨模块调用 mangled name) - """ - if pool is None or func_name is None: - return llvmlite.Int32(pool) - - # 提取裸函数名:去掉 SHA1 前缀(如 "240a9a4157959a9f.parse" → "parse") - # SHA1 前缀是 16 位十六进制 + '.',检查是否有 '.' 分隔 - bare_name: str = func_name - dot_pos: str = string.strrchr(func_name, 46) # 46 = ord('.') - if dot_pos is not None: - # '.' 后的部分是裸函数名 - bare_name = dot_pos + 1 - - i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, llvmlite.Int8(pool)) - - # 返回 i8* 的函数(指针返回值,截断会导致错误) - if bare_name == "strchr" or func_name == "strchr": - return i8_ptr_ty - if bare_name == "strrchr" or func_name == "strrchr": - return i8_ptr_ty - if bare_name == "strstr" or func_name == "strstr": - return i8_ptr_ty - if bare_name == "strcpy" or func_name == "strcpy": - return i8_ptr_ty - if bare_name == "strncpy" or func_name == "strncpy": - return i8_ptr_ty - if bare_name == "memset" or func_name == "memset": - return i8_ptr_ty - if bare_name == "memset32" or func_name == "memset32": - return i8_ptr_ty - if bare_name == "memcpy" or func_name == "memcpy": - return i8_ptr_ty - if bare_name == "memmove" or func_name == "memmove": - return i8_ptr_ty - # JSON 解析函数返回 JsonValue*(指针) - # from json.__parser import parse as json_parse → 别名 json_parse 也需覆盖 - if bare_name == "parse" or func_name == "parse" or func_name == "json_parse": - return i8_ptr_ty - # MemBuddy 方法(当类型信息丢失时可能走外部函数路径) - if func_name == "alloc": - return llvmlite.Ptr(pool, llvmlite.Int8(pool)) - if func_name == "calloc": - return llvmlite.Ptr(pool, llvmlite.Int8(pool)) - if func_name == "realloc": - return llvmlite.Ptr(pool, llvmlite.Int8(pool)) - if func_name == "alloc_buf": - return llvmlite.Ptr(pool, llvmlite.Int8(pool)) - # VLogger 模块函数(跨模块调用时 stub 未注入,返回指针被截断为 i32 导致崩溃) - if func_name == "get_logger": - return llvmlite.Ptr(pool, llvmlite.Int8(pool)) - if func_name == "fmt_buf": - return llvmlite.Ptr(pool, llvmlite.Int8(pool)) - # Config 模块函数(跨模块调用时 stub 未注入,返回 i8* 被 inttoptr i32 截断导致路径损坏) - if func_name == "get_includes_binary_dir": - return llvmlite.Ptr(pool, llvmlite.Int8(pool)) - - # 返回 i64 的函数 - if func_name == "strlen": - return llvmlite.Int64(pool) - if func_name == "atoll": - return llvmlite.Int64(pool) - - # 返回 double 的函数 - if func_name == "atof": - return llvmlite.Double(pool) - - # 返回 i8 的函数 - if func_name == "samestr": - return llvmlite.Int8(pool) - - # Win32 API 返回指针(VOIDPTR/HANDLE)的函数 - # stubs 翻译时未注入,需推断返回 i8* 避免指针被截断为 i32 导致解引用崩溃 - i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, llvmlite.Int8(pool)) - if func_name == "VirtualAlloc": - return i8_ptr_ty - if func_name == "HeapAlloc": - return i8_ptr_ty - if func_name == "HeapReAlloc": - return i8_ptr_ty - if func_name == "HeapCreate": - return i8_ptr_ty - if func_name == "GetProcessHeap": - return i8_ptr_ty - if func_name == "GlobalAlloc": - return i8_ptr_ty - if func_name == "GlobalFree": - return i8_ptr_ty - if func_name == "GlobalLock": - return i8_ptr_ty - if func_name == "LocalAlloc": - return i8_ptr_ty - if func_name == "LocalFree": - return i8_ptr_ty - if func_name == "GetProcAddress": - return i8_ptr_ty - if func_name == "GetModuleHandleA": - return i8_ptr_ty - if func_name == "GetModuleHandleW": - return i8_ptr_ty - if func_name == "LoadLibraryA": - return i8_ptr_ty - if func_name == "LoadLibraryW": - return i8_ptr_ty - # Win32 Handle 返回函数(HANDLE = void* = i8*) - if func_name == "GetStdHandle": - return i8_ptr_ty - if func_name == "CreateFileA": - return i8_ptr_ty - if func_name == "CreateFileW": - return i8_ptr_ty - if func_name == "FindFirstFileA": - return i8_ptr_ty - if func_name == "FindFirstFileW": - return i8_ptr_ty - - # Win32 API 返回 i64 (SIZE_T) 的函数 - if func_name == "VirtualQuery": - return llvmlite.Int64(pool) - if func_name == "HeapSize": - return llvmlite.Int64(pool) - if func_name == "HeapCompact": - return llvmlite.Int64(pool) - if func_name == "GlobalSize": - return llvmlite.Int64(pool) - - # llvmlite build_* 函数返回类型推断 - # stubs 翻译时未注入,需推断返回类型避免指针被截断为 i32 - # 大多数 build_* 函数返回 Value*(指针),少数终止指令返回 void - if string.strncmp(func_name, "build_", 6) == 0: - # 返回 void 的 build_* 函数(终止指令和无返回值指令) - if func_name == "build_ret" or func_name == "build_ret_void" or \ - func_name == "build_store" or func_name == "build_br" or \ - func_name == "build_cond_br" or func_name == "build_unreachable" or \ - func_name == "build_switch": - return llvmlite.Void(pool) - # 其他 build_* 函数返回 Value*(指针) - return llvmlite.Ptr(pool, llvmlite.Int8(pool)) - - # llvmlite 类型工厂函数返回 LLVMType*(指针) - # Int1/Int8/Int16/Int32/Int64/Ptr/Func/Array/Struct/Void/Half/Float/Double/FP128/Label - # new_param_node/new_phi_incoming 返回 ParamNode*/PhiIncoming*(指针) - # const_int32/const_int64/ConstFloat/ConstZero/ConstNull/ConstInt 返回 Value*(指针) - # function_get_name/param_get_ty 等访问器返回指针 - if func_name == "Int1" or func_name == "Int8" or func_name == "Int16" or \ - func_name == "Int32" or func_name == "Int64" or func_name == "Ptr" or \ - func_name == "Func" or func_name == "Array" or func_name == "Struct" or \ - func_name == "Void" or func_name == "Half" or func_name == "Float" or \ - func_name == "Double" or func_name == "FP128" or func_name == "Label" or \ - func_name == "new_param_node" or func_name == "new_phi_incoming" or \ - func_name == "const_int32" or func_name == "const_int64" or \ - func_name == "ConstFloat" or func_name == "ConstZero" or \ - func_name == "ConstNull" or func_name == "ConstInt" or \ - func_name == "function_get_name" or func_name == "param_get_ty" or \ - func_name == "value_get_ty" or func_name == "value_get_next" or \ - func_name == "function_get_ret_ty" or func_name == "function_get_params" or \ - func_name == "function_get_param_head" or func_name == "param_get_next": - return llvmlite.Ptr(pool, llvmlite.Int8(pool)) - - # 默认 i32(整数):与本模块函数定义的默认返回类型一致(HandlesFunctions.py line 324) - # 已知返回指针的函数在上方显式列出(返回 i8*),已知返回 i64 的函数也显式列出 - # 避免使用 i64 导致 stub 声明(declare i64)与实际定义(define i32)类型不匹配 - # x86-64 ABI 中 i32 返回值在 rax 低 32 位,与 define i32 完全一致 - # 与 _infer_method_ret_ty 的默认策略保持一致 - return llvmlite.Int32(pool) - -# ============================================================ -# _get_external_func_param_ty - 获取外部函数第 idx 个参数的期望类型 -# -# stubs 翻译时未注入,需推断参数类型以提升字面量(如 i32→i64), -# 避免 declare(i64) 与 call(i32) 类型不匹配。 -# -# 注意:stubs 翻译时 ULONG(t.CUnsignedLong) 在 LLVM IR 中被翻译为 i64 -# (因为 LLVM 中 long 是 64 位),因此 Win32 API 中所有 ULONG/DWORD/SIZE_T -# 参数在 declare 中都是 i64。call 时必须匹配,否则类型不匹配。 -# -# 策略:对 Win32 API 函数的所有非指针参数(字面量)都提升为 i64, -# 以匹配 declare 中 ULONG 被翻译为 i64 的情况。 -# -# 指针参数(VOIDPTR/HANDLE)不在此处理,由调用点的 inttoptr 处理。 -# ============================================================ -def _get_external_func_param_ty(pool: memhub.MemBuddy | t.CPtr, - func_name: str, - param_idx: int) -> llvmlite.LLVMType | t.CPtr: - """获取外部函数第 param_idx 个参数的期望类型,None 表示用字面量原类型 - - 对 Win32 API 函数的所有非指针参数返回 i64,匹配 declare 中 - ULONG/SIZE_T 被统一翻译为 i64 的情况。 - """ - if pool is None or func_name is None: - return None - - i64_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int64(pool) - - # Win32 API 函数列表:所有非指针参数在 declare 中都是 i64 - # (因为 ULONG/DWORD/SIZE_T 在 LLVM stubs 翻译时都被映射为 i64) - win32_apis: list[str] | t.CPtr = [ - "VirtualAlloc", "VirtualFree", "VirtualProtect", "VirtualQuery", - "VirtualLock", "VirtualUnlock", - "HeapCreate", "HeapDestroy", "HeapAlloc", "HeapReAlloc", - "HeapFree", "HeapSize", "HeapValidate", "HeapCompact", - "GlobalAlloc", "GlobalFree", "GlobalLock", "GlobalUnlock", "GlobalSize", - "LocalAlloc", "LocalFree", - "GetLastError", "SetLastError", - "Sleep", "SleepEx", - "GetTickCount", "GetProcessHeap" - ] - - # list 迭代不支持,用 range + get 替代 - api_count: t.CSizeT = win32_apis.__len__() - for ai in range(api_count): - api_name: str = win32_apis.get(ai) - if api_name == func_name: - return i64_ty - - return None - -# ============================================================ -# _emit_llvm_memcpy_intrinsic — 将 memcpy 调用映射到 @llvm.memcpy 内联函数 -# -# 背景: string.memcpy 是 t.CExport 函数,跨模块调用生成 @memcpy 裸名调用。 -# 但在 monomorphization 场景下,目标模块的 deps.txt 可能不含 string, -# 导致 @memcpy 声明缺失,链接器报 undefined value。 -# -# 解决: 将 memcpy 调用映射到 LLVM 内联函数 @llvm.memcpy, -# 该内联函数在当前模块内声明,无需跨模块依赖。 -# -# @llvm.memcpy 签名: void (i8* dst, i8* src, i64 len, i1 isvolatile) -# C memcpy 签名: i8* (i8* dst, i8* src, i64 len) — 返回 dst -# -# Args: -# args_head: 参数链表头(dst, src, num),通过 Value.Next 链接 -# arg_count: 参数数量(应为 3) -# -# Returns: -# dst 值(匹配 C memcpy 语义: 返回 dest 指针) -# ============================================================ -def _emit_llvm_memcpy_intrinsic(pool: memhub.MemBuddy | t.CPtr, - builder: llvmlite.IRBuilder | t.CPtr, - mod: llvmlite.LLVMModule | t.CPtr, - dst_val: llvmlite.Value | t.CPtr, - src_val: llvmlite.Value | t.CPtr, - num_val: llvmlite.Value | t.CPtr) -> llvmlite.Value | t.CPtr: - """将 memcpy 调用映射到 @llvm.memcpy 内联函数 - - 直接接收三个 Value 参数,避免通过 Next 链表遍历(共享 alloca 对象的 - Next 字段可能被其他操作污染,导致链表断裂)。 - """ - if pool is None or builder is None or mod is None: - return None - if dst_val is None or src_val is None or num_val is None: - return None - - # 在函数顶部声明 void_ty,避免后续遮蔽 - void_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Void(pool) - - # 声明 @llvm.memcpy(如未声明) - memcpy_func: llvmlite.Function | t.CPtr = find_func_in_module(mod, "llvm.memcpy") - if memcpy_func is None: - memcpy_func = llvmlite.create_declare(pool, mod, "llvm.memcpy", void_ty) - if memcpy_func is not None: - i8_ptr_ty_d: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, llvmlite.Int8(pool)) - i64_ty_d: llvmlite.LLVMType | t.CPtr = llvmlite.Int64(pool) - i1_ty_d: llvmlite.LLVMType | t.CPtr = llvmlite.Int1(pool) - llvmlite.add_param(pool, memcpy_func, i8_ptr_ty_d, "dst") - llvmlite.add_param(pool, memcpy_func, i8_ptr_ty_d, "src") - llvmlite.add_param(pool, memcpy_func, i64_ty_d, "len") - llvmlite.add_param(pool, memcpy_func, i1_ty_d, "isvolatile") - - # 类型转换: dst, src → i8*; num → i64 - # 注意: 使用 value_get_ty 访问器获取 Ty,避免本地 Value 类型字段索引偏移 - i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, llvmlite.Int8(pool)) - i64_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int64(pool) - - # dst → i8* - dst_coerced: llvmlite.Value | t.CPtr = dst_val - dst_ty: llvmlite.LLVMType | t.CPtr = llvmlite.value_get_ty(dst_val) - if HandlesExpr.is_ptr_type(dst_ty) != 0: - dst_coerced = llvmlite.build_bitcast(builder, dst_val, i8_ptr_ty) - else: - dst_bits: int = HandlesExpr.get_llvm_type_bits(dst_ty) - if dst_bits != 0: - if dst_bits < 64: - dst_coerced = llvmlite.build_zext(builder, dst_val, i64_ty) - dst_coerced = llvmlite.build_inttoptr(builder, dst_coerced, i8_ptr_ty) - - # src → i8* - src_coerced: llvmlite.Value | t.CPtr = src_val - src_ty: llvmlite.LLVMType | t.CPtr = llvmlite.value_get_ty(src_val) - if HandlesExpr.is_ptr_type(src_ty) != 0: - src_coerced = llvmlite.build_bitcast(builder, src_val, i8_ptr_ty) - else: - src_bits: int = HandlesExpr.get_llvm_type_bits(src_ty) - if src_bits != 0: - if src_bits < 64: - src_coerced = llvmlite.build_zext(builder, src_val, i64_ty) - src_coerced = llvmlite.build_inttoptr(builder, src_coerced, i8_ptr_ty) - - # num → i64 - num_coerced: llvmlite.Value | t.CPtr = HandlesExpr.coerce_to_type(builder, num_val, i64_ty) - - if dst_coerced is None or src_coerced is None or num_coerced is None: - return None - - # 添加 i1 false 参数(isvolatile)— llvm.memcpy 需要 4 个参数 - false_val: llvmlite.Value | t.CPtr = llvmlite.ConstInt(pool, llvmlite.Int1(pool), 0, "false") - - # 使用 includes 中的访问器函数构建参数链表,避免本地 Value 类型字段索引偏移 - # (f26cd4c78b4d554c.Value 缺少 GSListNode 的 Next 字段,直接访问 .Next 会修改 .Ty) - llvmlite.value_set_next(dst_coerced, src_coerced) - llvmlite.value_set_next(src_coerced, num_coerced) - if false_val is not None: - llvmlite.value_set_next(num_coerced, false_val) - llvmlite.value_set_next(false_val, None) - else: - llvmlite.value_set_next(num_coerced, None) - - # 使用 build_call 发射 call 指令(内部用 includes Value 类型访问字段,索引正确) - # _ll_name_needs_quote 已对 llvm. 前缀豁免引号 - result: llvmlite.Value | t.CPtr = llvmlite.build_call(builder, "llvm.memcpy", dst_coerced, 4, void_ty, 0) - - # 返回 dst(匹配 C memcpy 语义: 返回 dest 指针) - return dst_coerced - -# ============================================================ -# c.Deref(ptr) — 解引用指针,load i8(字符遍历用例) -# -# 生成: %N = load i8, i8* %ptr -# 返回 i8 值 -# ============================================================ -def translate_c_deref(pool: memhub.MemBuddy | t.CPtr, - builder: llvmlite.IRBuilder | t.CPtr, - mod: llvmlite.LLVMModule | t.CPtr, - cl: ast.Call | t.CPtr, - trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr: - """c.Deref(ptr) → load i8 from ptr""" - if cl is None: - return None - cargs: list[ast.AST | t.CPtr] | t.CPtr = cl.args - if cargs is None or cargs.__len__() < 1: - return None - - ptr_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( - builder, pool, mod, cargs.get(0), None, 0, trans) - if ptr_val is None: - return None - - i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool) - return llvmlite.build_load(builder, i8_ty, ptr_val) - -# ============================================================ -# c.DerefAs(ptr, val) — 解引用写入,*ptr = val -# -# 生成: %pc = bitcast i8* %ptr to * -# store %val, * %pc -# ============================================================ -def translate_c_derefas(pool: memhub.MemBuddy | t.CPtr, - builder: llvmlite.IRBuilder | t.CPtr, - mod: llvmlite.LLVMModule | t.CPtr, - cl: ast.Call | t.CPtr, - trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr: - """c.DerefAs(ptr, val) → store val to ptr(bitcast 后 store)""" - if cl is None: - return None - cargs: list[ast.AST | t.CPtr] | t.CPtr = cl.args - if cargs is None or cargs.__len__() < 2: - return None - - ptr_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( - builder, pool, mod, cargs.get(0), None, 0, trans) - val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( - builder, pool, mod, cargs.get(1), None, 0, trans) - if ptr_val is None or val is None: - return None - - # bitcast ptr 到 val.Ty* 再 store - val_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, val.Ty) - casted_ptr: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(builder, ptr_val, val_ptr_ty) - if casted_ptr is None: - return None - llvmlite.build_store(builder, val, casted_ptr) - return val - -# ============================================================ -# c.Addr(var) — 取变量地址,返回 alloca 指针(不 load) -# -# 用于获取栈变量的可写地址,配合 c.DerefAs 使用 -# ============================================================ -def translate_c_addr(pool: memhub.MemBuddy | t.CPtr, - builder: llvmlite.IRBuilder | t.CPtr, - mod: llvmlite.LLVMModule | t.CPtr, - cl: ast.Call | t.CPtr, - trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr: - """c.Addr(var) → 返回变量的 alloca 指针(不 load)""" - if cl is None: - return None - cargs: list[ast.AST | t.CPtr] | t.CPtr = cl.args - if cargs is None or cargs.__len__() < 1: - return None - - arg0: ast.AST | t.CPtr = cargs.get(0) - if arg0 is None or arg0.kind() != ast.ASTKind.Name: - return None - - nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(arg0) - if nm.id is None: - return None - - return HandlesVar.lookup_var(trans.SymTab, nm.id) - -# ============================================================ -# c.Load(a, b) — 指针间复制: *a = *b -# -# 加载 b 指向的值,存储到 a 指向的地址。 -# 生成: %pc_src = bitcast i8* %src to * -# %loaded = load , * %pc_src -# %pc_dst = bitcast i8* %dst to * -# store %loaded, * %pc_dst -# ============================================================ -def translate_c_load(pool: memhub.MemBuddy | t.CPtr, - builder: llvmlite.IRBuilder | t.CPtr, - mod: llvmlite.LLVMModule | t.CPtr, - cl: ast.Call | t.CPtr, - trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr: - """c.Load(a, b) → *a = *b(加载 b 的值,存储到 a)""" - if cl is None: - return None - cargs: list[ast.AST | t.CPtr] | t.CPtr = cl.args - if cargs is None or cargs.__len__() < 2: - return None - - dst_ptr: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( - builder, pool, mod, cargs.get(0), None, 0, trans) - src_ptr: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( - builder, pool, mod, cargs.get(1), None, 0, trans) - if dst_ptr is None or src_ptr is None: - return None - - # 确定 pointee 类型(优先用 src 的 pointee,回退到 dst 的 pointee) - pointee: llvmlite.LLVMType | t.CPtr = None - if src_ptr.Ty is not None: - pointee = src_ptr.Ty.Pointee - if pointee is None and dst_ptr.Ty is not None: - pointee = dst_ptr.Ty.Pointee - if pointee is None: - return None - - # bitcast src 到 pointee* 并 load - target_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, pointee) - src_cast: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(builder, src_ptr, target_ptr_ty) - if src_cast is None: - return None - loaded: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, pointee, src_cast) - if loaded is None: - return None - - # bitcast dst 到 pointee* 并 store - dst_cast: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(builder, dst_ptr, target_ptr_ty) - if dst_cast is None: - return None - llvmlite.build_store(builder, loaded, dst_cast) - return loaded - -# ============================================================ -# c.Asm — 内联汇编支持 -# -# 生成: %N = call asm sideeffect "", ""() -# 或: call void asm sideeffect "", ""() -# -# 操作数按出现顺序编号 $0, $1, ...(用户需按输出在前写 f-string) -# ============================================================ - -ASM_MAX_OPERANDS: t.CDefine = 16 -ASM_TEXT_BUF_SIZE: t.CDefine = 2048 -ASM_CONST_BUF_SIZE: t.CDefine = 512 -ASM_ARGS_BUF_SIZE: t.CDefine = 512 -ASM_LINE_BUF_SIZE: t.CDefine = 4096 - -# ============================================================ -# AsmOperand - 内联汇编操作数条目 -# ============================================================ -@t.NoVTable -class AsmOperand: - """内联汇编操作数条目""" - Value: llvmlite.Value | t.CPtr # 输入值或输出 alloca - Constraint: str # 约束字符串 (如 "r", "=r") - IsOutput: int # 1=输出, 0=输入 - -# ============================================================ -# _asm_append_cstr — 将 C 字符串 src 追加到 dst 末尾 -# ============================================================ -def _asm_append_cstr(dst: t.CChar | t.CPtr, dst_size: t.CSizeT, - src: t.CChar | t.CPtr): - """将 C 字符串 src 追加到 dst 末尾""" - if dst is None or src is None: - return - dlen: t.CSizeT = string.strlen(dst) - slen: t.CSizeT = string.strlen(src) - remain: t.CSizeT = dst_size - dlen - if remain <= 0: - return - i: t.CSizeT = 0 - while i < slen and i + 1 < remain: - dst[dlen + i] = src[i] - i += 1 - dst[dlen + i] = '\0' - -# ============================================================ -# _asm_escape_for_ir — 将汇编文本转义为 LLVM IR 字符串内容 -# -# \n → \0A, " → \22, \ → \5C -# ============================================================ -def _asm_escape_for_ir(pool: memhub.MemBuddy | t.CPtr, - src: t.CChar | t.CPtr) -> t.CChar | t.CPtr: - """转义汇编文本用于 LLVM IR 字符串字面量""" - if src is None: - return None - slen: t.CSizeT = string.strlen(src) - buf: t.CChar | t.CPtr = pool.alloc(slen * 4 + 8) - if buf is None: - return None - pos: t.CSizeT = 0 - for ch in src: - if ch == '\n': - buf[pos] = '\\' - pos += 1 - buf[pos] = '0' - pos += 1 - buf[pos] = 'A' - pos += 1 - elif ch == '"': - buf[pos] = '\\' - pos += 1 - buf[pos] = '2' - pos += 1 - buf[pos] = '2' - pos += 1 - elif ch == '\\': - buf[pos] = '\\' - pos += 1 - buf[pos] = '5' - pos += 1 - buf[pos] = 'C' - pos += 1 - else: - buf[pos] = ch - pos += 1 - buf[pos] = '\0' - return buf - -# ============================================================ -# _resolve_register — 将 ASM_DESCR 属性名映射到约束字符串 -# ============================================================ -def _resolve_register(attr_name: str) -> str: - """将 t.ASM_DESCR.XXX 的属性名映射到约束字符串值""" - if attr_name is None: - return "" - - # Clobber 破坏描述符 - if attr_name == "CLOBBER_MEMORY": return "memory" - if attr_name == "CLOBBER_CC": return "cc" - if attr_name == "CLOBBER_RAX": return "rax" - if attr_name == "CLOBBER_RBX": return "rbx" - if attr_name == "CLOBBER_RCX": return "rcx" - if attr_name == "CLOBBER_RDX": return "rdx" - if attr_name == "CLOBBER_RSI": return "rsi" - if attr_name == "CLOBBER_RDI": return "rdi" - if attr_name == "CLOBBER_RBP": return "rbp" - if attr_name == "CLOBBER_RSP": return "rsp" - if attr_name == "CLOBBER_R8": return "r8" - if attr_name == "CLOBBER_R9": return "r9" - if attr_name == "CLOBBER_R10": return "r10" - if attr_name == "CLOBBER_R11": return "r11" - if attr_name == "CLOBBER_R12": return "r12" - if attr_name == "CLOBBER_R13": return "r13" - if attr_name == "CLOBBER_R14": return "r14" - if attr_name == "CLOBBER_R15": return "r15" - if attr_name == "CLOBBER_EAX": return "eax" - if attr_name == "CLOBBER_EBX": return "ebx" - if attr_name == "CLOBBER_ECX": return "ecx" - if attr_name == "CLOBBER_EDX": return "edx" - if attr_name == "CLOBBER_ESI": return "esi" - if attr_name == "CLOBBER_EDI": return "edi" - if attr_name == "CLOBBER_DX": return "dx" - if attr_name == "CLOBBER_AX": return "ax" - if attr_name == "CLOBBER_CX": return "cx" - if attr_name == "CLOBBER_SI": return "si" - if attr_name == "CLOBBER_DI": return "di" - - # Output 输出约束 - if attr_name == "OUTPUT_REG": return "=r" - if attr_name == "OUTPUT_MEM": return "=m" - if attr_name == "OUTPUT_EAX": return "=a" - if attr_name == "OUTPUT_EBX": return "=b" - if attr_name == "OUTPUT_ECX": return "=c" - if attr_name == "OUTPUT_EDX": return "=d" - if attr_name == "OUTPUT_ESI": return "=S" - if attr_name == "OUTPUT_EDI": return "=D" - if attr_name == "OUTPUT_RAX": return "=a" - if attr_name == "OUTPUT_RBX": return "=b" - if attr_name == "OUTPUT_RCX": return "=c" - if attr_name == "OUTPUT_RDX": return "=d" - if attr_name == "OUTPUT_RSI": return "=S" - if attr_name == "OUTPUT_RDI": return "=D" - - # Input/Register 输入约束 - if attr_name == "REG_ANY": return "r" - if attr_name == "REG_EAX": return "a" - if attr_name == "REG_EBX": return "b" - if attr_name == "REG_ECX": return "c" - if attr_name == "REG_EDX": return "d" - if attr_name == "REG_ESI": return "S" - if attr_name == "REG_EDI": return "D" - if attr_name == "REG_RAX": return "a" - if attr_name == "REG_RBX": return "b" - if attr_name == "REG_RCX": return "c" - if attr_name == "REG_RDX": return "d" - if attr_name == "REG_RSI": return "S" - if attr_name == "REG_RDI": return "D" - - if attr_name == "INPUT_REG": return "r" - if attr_name == "INPUT_MEM": return "m" - if attr_name == "INPUT_EAX": return "a" - if attr_name == "INPUT_EBX": return "b" - if attr_name == "INPUT_ECX": return "c" - if attr_name == "INPUT_EDX": return "d" - if attr_name == "INPUT_ESI": return "S" - if attr_name == "INPUT_EDI": return "D" - if attr_name == "INPUT_RAX": return "a" - if attr_name == "INPUT_RBX": return "b" - if attr_name == "INPUT_RCX": return "c" - if attr_name == "INPUT_RDX": return "d" - if attr_name == "INPUT_RSI": return "S" - if attr_name == "INPUT_RDI": return "D" - - return "" - -# ============================================================ -# _resolve_asm_descr — 递归解析约束表达式 -# -# 支持: -# t.ASM_DESCR.XXX → _resolve_register(XXX) -# expr | expr (BinOp BitOr) → 拼接 -# "string" (Constant) → 直接返回 -# ============================================================ -def _resolve_asm_descr(pool: memhub.MemBuddy | t.CPtr, - node: ast.AST | t.CPtr) -> str: - """递归解析约束表达式,返回约束字符串""" - if node is None: - return "" - - k: int = node.kind() - - # BinOp with BitOr: 拼接左右 - if k == ast.ASTKind.BinOp: - bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(node) - if bop.op == ast.OpKind.BitOr: - left_str: str = _resolve_asm_descr(pool, bop.left) - right_str: str = _resolve_asm_descr(pool, bop.right) - llen: t.CSizeT = string.strlen(left_str) - rlen: t.CSizeT = string.strlen(right_str) - buf: str = pool.alloc(llen + rlen + 1) - if buf is None: - return "" - string.strcpy(buf, left_str) - for i in range(rlen): - buf[llen + i] = right_str[i] - buf[llen + rlen] = '\0' - return buf - return "" - - # Attribute: t.ASM_DESCR.XXX 或 t.XXX - if k == ast.ASTKind.Attribute: - at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(node) - # t.ASM_DESCR.XXX - if at.value is not None and at.value.kind() == ast.ASTKind.Attribute: - inner: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(at.value) - if inner.value is not None and inner.value.kind() == ast.ASTKind.Name: - mod_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(inner.value) - if mod_nm.id is not None and string.strcmp(mod_nm.id, "t") == 0: - if inner.attr is not None and string.strcmp(inner.attr, "ASM_DESCR") == 0: - return _resolve_register(at.attr) - # t.XXX 简化形式 - if at.value is not None and at.value.kind() == ast.ASTKind.Name: - mod_nm2: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value) - if mod_nm2.id is not None and string.strcmp(mod_nm2.id, "t") == 0: - return _resolve_register(at.attr) - return "" - - # Constant: 字符串常量 - if k == ast.ASTKind.Constant: - cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(node) - if cn.const_kind == ast.CONST_STR: - return cn.str_val - return "" - - return "" - -# ============================================================ -# _asm_get_operand — 获取操作数数组中第 idx 个元素的指针 -# ============================================================ -def _asm_get_operand(base: AsmOperand | t.CPtr, - idx: int) -> AsmOperand | t.CPtr: - """获取操作数数组中第 idx 个元素的指针""" - entry_size: t.CSizeT = AsmOperand.__sizeof__() - entry_addr: t.CUInt64T = t.CUInt64T(base) + idx * entry_size - return (AsmOperand | t.CPtr)(t.CVoid(entry_addr, t.CPtr)) - -# ============================================================ -# _asm_is_c_call — 检查 Call 节点是否是 c.XXX 调用 -# -# 返回 attr_name(如 "AsmInp"/"AsmOut"),不是则返回 None -# ============================================================ -def _asm_is_c_call(node: ast.Call | t.CPtr) -> str: - """检查 Call 节点是否是 c.XXX 调用,返回属性名或 None""" - if node is None or node.func is None: - return None - if node.func.kind() != ast.ASTKind.Attribute: - return None - at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(node.func) - if at.value is None or at.value.kind() != ast.ASTKind.Name: - return None - mod_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value) - if mod_nm.id is None or string.strcmp(mod_nm.id, "c") != 0: - return None - return at.attr - -# ============================================================ -# _asm_add_operand — 添加操作数到数组 -# -# 返回 1 成功, 0 失败(数组已满) -# ============================================================ -def _asm_add_operand(operands: AsmOperand | t.CPtr, - count: int, - val: llvmlite.Value | t.CPtr, - constraint: str, - is_output: int) -> int: - """添加操作数到数组,返回新计数(失败返回原计数)""" - if count >= ASM_MAX_OPERANDS: - return count - op: AsmOperand | t.CPtr = _asm_get_operand(operands, count) - op.Value = val - op.Constraint = constraint - op.IsOutput = is_output - return count + 1 - -# ============================================================ -# translate_c_asm — 翻译 c.Asm 内联汇编 -# -# 语法: -# c.Asm("nop", [t.ASM_DESCR.CLOBBER_MEMORY]) -# c.Asm(f"mov rax, {c.AsmInp(val, t.ASM_DESCR.REG_ANY)}", op=[...]) -# c.Asm(f"...", out=[c.AsmOut(var, t.ASM_DESCR.OUTPUT_REG)], op=[...]) -# ============================================================ -def translate_c_asm(pool: memhub.MemBuddy | t.CPtr, - builder: llvmlite.IRBuilder | t.CPtr, - mod: llvmlite.LLVMModule | t.CPtr, - cl: ast.Call | t.CPtr, - trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr: - """翻译 c.Asm 内联汇编,返回结果 Value(无输出时返回 None)""" - if cl is None: - return None - - cargs: list[ast.AST | t.CPtr] | t.CPtr = cl.args - if cargs is None or cargs.__len__() < 1: - return None - - # 分配操作数数组 - operand_size: t.CSizeT = AsmOperand.__sizeof__() - operands: AsmOperand | t.CPtr = pool.alloc(operand_size * ASM_MAX_OPERANDS) - if operands is None: - return None - string.memset(operands, 0, operand_size * ASM_MAX_OPERANDS) - - # 分配 clobber 名数组 - clobbers: str | t.CPtr = pool.alloc(8 * ASM_MAX_OPERANDS) - if clobbers is None: - return None - string.memset(clobbers, 0, 8 * ASM_MAX_OPERANDS) - - # 分配 asm 文本缓冲区 - asm_text: t.CChar | t.CPtr = pool.alloc(ASM_TEXT_BUF_SIZE) - if asm_text is None: - return None - asm_text[0] = '\0' - - operand_count: int = 0 - clobber_count: int = 0 - fv_count: int = 0 - - # 分配 fv 索引数组(记录每个 FormattedValue 对应的操作数原始索引) - fv_orig_indices: int | t.CPtr = pool.alloc(4 * ASM_MAX_OPERANDS) - if fv_orig_indices is None: - return None - string.memset(fv_orig_indices, 0, 4 * ASM_MAX_OPERANDS) - - # ============================================================ - # 1. 解析汇编模板(JoinedStr 或 Constant)— 第一遍:收集操作数 - # 不生成 asm 文本(占位符 $N 需在重排后才能确定编号) - # ============================================================ - tmpl_node: ast.AST | t.CPtr = cargs.get(0) - if tmpl_node is not None: - tk: int = tmpl_node.kind() - - if tk == ast.ASTKind.JoinedStr: - js: ast.JoinedStr | t.CPtr = (ast.JoinedStr | t.CPtr)(tmpl_node) - jvalues: list[ast.AST | t.CPtr] | t.CPtr = js.values - if jvalues is not None: - jvlen: t.CSizeT = jvalues.__len__() - for vi in range(jvlen): - part: ast.AST | t.CPtr = jvalues.get(vi) - if part is None: - continue - pk: int = part.kind() - - if pk == ast.ASTKind.FormattedValue: - fv: ast.FormattedValue | t.CPtr = (ast.FormattedValue | t.CPtr)(part) - fexpr: ast.AST | t.CPtr = fv.value - if fexpr is None or fexpr.kind() != ast.ASTKind.Call: - continue - fcall: ast.Call | t.CPtr = (ast.Call | t.CPtr)(fexpr) - attr_nm: str = _asm_is_c_call(fcall) - if attr_nm is None: - continue - - is_out: int = 0 - if string.strcmp(attr_nm, "AsmOut") == 0: - is_out = 1 - elif string.strcmp(attr_nm, "AsmInp") == 0: - is_out = 0 - else: - continue - - fargs: list[ast.AST | t.CPtr] | t.CPtr = fcall.args - if fargs is None or fargs.__len__() < 1: - continue - - val_node: ast.AST | t.CPtr = fargs.get(0) - cons_str: str = "" - if fargs.__len__() >= 2: - cons_str = _resolve_asm_descr(pool, fargs.get(1)) - - if is_out != 0: - # 输出:获取变量 alloca - if val_node is None or val_node.kind() != ast.ASTKind.Name: - continue - nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(val_node) - if nm.id is None: - continue - alloca: llvmlite.Value | t.CPtr = HandlesVar.lookup_var(trans.SymTab, nm.id) - if alloca is None: - continue - operand_count = _asm_add_operand( - operands, operand_count, alloca, cons_str, 1) - else: - # 输入:翻译值 - ival: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( - builder, pool, mod, val_node, None, 0, trans) - if ival is None: - continue - operand_count = _asm_add_operand( - operands, operand_count, ival, cons_str, 0) - - # 记录 fv 的原始操作数索引 - if fv_count < ASM_MAX_OPERANDS: - fv_orig_indices[fv_count] = operand_count - 1 - fv_count += 1 - - # ============================================================ - # 2. 解析关键字参数 out=/inp=/op=/clobber= - # ============================================================ - keywords: list[ast.AST | t.CPtr] | t.CPtr = cl.keywords - if keywords is not None: - kwlen: t.CSizeT = keywords.__len__() - for ki in range(kwlen): - kw: ast.Keyword | t.CPtr = (ast.Keyword | t.CPtr)(keywords.get(ki)) - if kw is None or kw.arg is None or kw.value is None: - continue - kwk: int = kw.value.kind() - - if string.strcmp(kw.arg, "out") == 0: - # 输出操作数列表 - if kwk != ast.ASTKind.List: - continue - out_lst: ast.List | t.CPtr = (ast.List | t.CPtr)(kw.value) - out_elts: list[ast.AST | t.CPtr] | t.CPtr = out_lst.elts - if out_elts is None: - continue - oelen: t.CSizeT = out_elts.__len__() - for oi in range(oelen): - oelt: ast.AST | t.CPtr = out_elts.get(oi) - if oelt is None or oelt.kind() != ast.ASTKind.Call: - continue - ocall: ast.Call | t.CPtr = (ast.Call | t.CPtr)(oelt) - oattr: str = _asm_is_c_call(ocall) - if oattr is None or string.strcmp(oattr, "AsmOut") != 0: - continue - oargs: list[ast.AST | t.CPtr] | t.CPtr = ocall.args - if oargs is None or oargs.__len__() < 1: - continue - oval_node: ast.AST | t.CPtr = oargs.get(0) - ocons: str = "" - if oargs.__len__() >= 2: - ocons = _resolve_asm_descr(pool, oargs.get(1)) - if oval_node is None or oval_node.kind() != ast.ASTKind.Name: - continue - onm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(oval_node) - if onm.id is None: - continue - oalloca: llvmlite.Value | t.CPtr = HandlesVar.lookup_var(trans.SymTab, onm.id) - if oalloca is None: - continue - operand_count = _asm_add_operand( - operands, operand_count, oalloca, ocons, 1) - - elif string.strcmp(kw.arg, "inp") == 0 or string.strcmp(kw.arg, "inputs") == 0: - # 输入操作数列表 - if kwk != ast.ASTKind.List: - continue - in_lst: ast.List | t.CPtr = (ast.List | t.CPtr)(kw.value) - in_elts: list[ast.AST | t.CPtr] | t.CPtr = in_lst.elts - if in_elts is None: - continue - ielen: t.CSizeT = in_elts.__len__() - for ii in range(ielen): - ielt: ast.AST | t.CPtr = in_elts.get(ii) - if ielt is None or ielt.kind() != ast.ASTKind.Call: - continue - icall: ast.Call | t.CPtr = (ast.Call | t.CPtr)(ielt) - iattr: str = _asm_is_c_call(icall) - if iattr is None or string.strcmp(iattr, "AsmInp") != 0: - continue - iargs: list[ast.AST | t.CPtr] | t.CPtr = icall.args - if iargs is None or iargs.__len__() < 1: - continue - ival_node: ast.AST | t.CPtr = iargs.get(0) - icons: str = "" - if iargs.__len__() >= 2: - icons = _resolve_asm_descr(pool, iargs.get(1)) - ival2: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( - builder, pool, mod, ival_node, None, 0, trans) - if ival2 is None: - continue - operand_count = _asm_add_operand( - operands, operand_count, ival2, icons, 0) - - elif string.strcmp(kw.arg, "op") == 0 or string.strcmp(kw.arg, "clobber") == 0: - # 破坏列表 - if kwk != ast.ASTKind.List: - continue - cl_lst: ast.List | t.CPtr = (ast.List | t.CPtr)(kw.value) - cl_elts: list[ast.AST | t.CPtr] | t.CPtr = cl_lst.elts - if cl_elts is None: - continue - clen: t.CSizeT = cl_elts.__len__() - for ci in range(clen): - celt: ast.AST | t.CPtr = cl_elts.get(ci) - if celt is None: - continue - cstr: str = _resolve_asm_descr(pool, celt) - if cstr is None or cstr[0] == '\0': - continue - if clobber_count < ASM_MAX_OPERANDS: - cl_addr: t.CUInt64T = t.CUInt64T(clobbers) + clobber_count * 8 - cl_ptr: str | t.CPtr = (str | t.CPtr)(t.CVoid(cl_addr, t.CPtr)) - cl_ptr[0] = cstr - clobber_count += 1 - - # ============================================================ - # 3. 解析第二个位置参数作为破坏列表 - # ============================================================ - if cargs.__len__() >= 2: - pos_node: ast.AST | t.CPtr = cargs.get(1) - if pos_node is not None and pos_node.kind() == ast.ASTKind.List: - pos_lst: ast.List | t.CPtr = (ast.List | t.CPtr)(pos_node) - pos_elts: list[ast.AST | t.CPtr] | t.CPtr = pos_lst.elts - if pos_elts is not None: - plen: t.CSizeT = pos_elts.__len__() - for pi in range(plen): - pelt: ast.AST | t.CPtr = pos_elts.get(pi) - if pelt is None: - continue - pstr: str = _resolve_asm_descr(pool, pelt) - if pstr is None or pstr[0] == '\0': - continue - if clobber_count < ASM_MAX_OPERANDS: - pcl_addr: t.CUInt64T = t.CUInt64T(clobbers) + clobber_count * 8 - pcl_ptr: str | t.CPtr = (str | t.CPtr)(t.CVoid(pcl_addr, t.CPtr)) - pcl_ptr[0] = pstr - clobber_count += 1 - - # ============================================================ - # 4. 统计输出/输入数量,确定返回类型 - # ============================================================ - output_count: int = 0 - input_count: int = 0 - first_output_idx: int = -1 - for oi2 in range(operand_count): - op2: AsmOperand | t.CPtr = _asm_get_operand(operands, oi2) - if op2.IsOutput != 0: - if first_output_idx < 0: - first_output_idx = oi2 - output_count += 1 - else: - input_count += 1 - - # 确定返回类型 - ret_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Void(pool) - if output_count > 0 and first_output_idx >= 0: - out_op: AsmOperand | t.CPtr = _asm_get_operand(operands, first_output_idx) - if out_op.Value is not None and out_op.Value.Ty is not None: - # alloca 的类型是指针,Pointee 是目标类型 - if out_op.Value.Ty.Pointee is not None: - ret_ty = out_op.Value.Ty.Pointee - else: - ret_ty = llvmlite.Int32(pool) - - # 判断 void — 直接基于 output_count 判断,避免 match 类型匹配问题 - is_void: int = 1 - if output_count > 0: - is_void = 0 - - # ============================================================ - # 4.5 重排操作数:输出在前,输入在后(LLVM IR 要求) - # - # new_order[new_idx] = orig_idx — 新位置对应原索引 - # orig_to_new[orig_idx] = new_idx — 原索引映射到新位置(用于占位符编号) - # ============================================================ - new_order: int | t.CPtr = pool.alloc(4 * (operand_count + 1)) - orig_to_new: int | t.CPtr = pool.alloc(4 * (operand_count + 1)) - if new_order is None or orig_to_new is None: - return None - - new_idx: int = 0 - # 先放输出 - for oi3 in range(operand_count): - op3: AsmOperand | t.CPtr = _asm_get_operand(operands, oi3) - if op3.IsOutput != 0: - new_order[new_idx] = oi3 - new_idx += 1 - # 再放输入 - for oi4 in range(operand_count): - op4: AsmOperand | t.CPtr = _asm_get_operand(operands, oi4) - if op4.IsOutput == 0: - new_order[new_idx] = oi4 - new_idx += 1 - # 建立映射 orig -> new - for ni2 in range(operand_count): - orig_to_new[new_order[ni2]] = ni2 - - # ============================================================ - # 4.6 生成汇编文本(第二遍遍历 f-string,用重排后的索引生成占位符) - # 项目约定使用 Intel 语法,通过 IR 的 inteldialect 关键字启用 - # ============================================================ - if tmpl_node is not None: - tk2: int = tmpl_node.kind() - if tk2 == ast.ASTKind.JoinedStr: - js2: ast.JoinedStr | t.CPtr = (ast.JoinedStr | t.CPtr)(tmpl_node) - jvalues2: list[ast.AST | t.CPtr] | t.CPtr = js2.values - if jvalues2 is not None: - jvlen2: t.CSizeT = jvalues2.__len__() - fv_fi: int = 0 - for vi2 in range(jvlen2): - part2: ast.AST | t.CPtr = jvalues2.get(vi2) - if part2 is None: - continue - pk2: int = part2.kind() - if pk2 == ast.ASTKind.Constant: - cn3: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(part2) - if cn3.const_kind == ast.CONST_STR and cn3.str_val is not None: - _asm_append_cstr(asm_text, ASM_TEXT_BUF_SIZE, cn3.str_val) - elif pk2 == ast.ASTKind.FormattedValue: - if fv_fi < fv_count: - orig_idx2: int = fv_orig_indices[fv_fi] - new_idx2: int = orig_to_new[orig_idx2] - ph_buf2: t.CChar | t.CPtr = pool.alloc(16) - if ph_buf2 is not None: - viperlib.snprintf(ph_buf2, 16, "$%d", new_idx2) - _asm_append_cstr(asm_text, ASM_TEXT_BUF_SIZE, ph_buf2) - fv_fi += 1 - elif tk2 == ast.ASTKind.Constant: - cn4: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(tmpl_node) - if cn4.const_kind == ast.CONST_STR and cn4.str_val is not None: - _asm_append_cstr(asm_text, ASM_TEXT_BUF_SIZE, cn4.str_val) - - # ============================================================ - # 5. 构建约束字符串(按重排后的顺序:输出在前,输入在后) - # ============================================================ - const_buf: t.CChar | t.CPtr = pool.alloc(ASM_CONST_BUF_SIZE) - if const_buf is None: - return None - const_buf[0] = '\0' - - first_const: int = 1 - for ci2 in range(operand_count): - orig_i: int = new_order[ci2] - cop: AsmOperand | t.CPtr = _asm_get_operand(operands, orig_i) - cons_val: str = cop.Constraint - if cons_val is None: - cons_val = "r" - - if first_const == 0: - _asm_append_cstr(const_buf, ASM_CONST_BUF_SIZE, ",") - first_const = 0 - - if cop.IsOutput != 0: - # 输出约束:确保以 = 开头 - if cons_val[0] != '=': - _asm_append_cstr(const_buf, ASM_CONST_BUF_SIZE, "=") - _asm_append_cstr(const_buf, ASM_CONST_BUF_SIZE, cons_val) - else: - _asm_append_cstr(const_buf, ASM_CONST_BUF_SIZE, cons_val) - - # 追加 clobber 约束 ~{name} - for cidx in range(clobber_count): - cl_addr2: t.CUInt64T = t.CUInt64T(clobbers) + cidx * 8 - cname: str = (str | t.CPtr)(t.CVoid(cl_addr2, t.CPtr))[0] - if cname is None or cname[0] == '\0': - continue - if first_const == 0: - _asm_append_cstr(const_buf, ASM_CONST_BUF_SIZE, ",") - first_const = 0 - _asm_append_cstr(const_buf, ASM_CONST_BUF_SIZE, "~{") - _asm_append_cstr(const_buf, ASM_CONST_BUF_SIZE, cname) - _asm_append_cstr(const_buf, ASM_CONST_BUF_SIZE, "}") - - # ============================================================ - # 6. 构建参数列表文本(仅输入操作数) - # ============================================================ - args_buf: t.CChar | t.CPtr = pool.alloc(ASM_ARGS_BUF_SIZE) - if args_buf is None: - return None - args_buf[0] = '\0' - - first_arg: int = 1 - for ai3 in range(operand_count): - orig_i2: int = new_order[ai3] - aop: AsmOperand | t.CPtr = _asm_get_operand(operands, orig_i2) - if aop.IsOutput != 0: - continue - aval: llvmlite.Value | t.CPtr = aop.Value - if aval is None or aval.Ty is None or aval.Name is None: - continue - - if first_arg == 0: - _asm_append_cstr(args_buf, ASM_ARGS_BUF_SIZE, ", ") - first_arg = 0 - - # 类型文本 - ty_buf: t.CChar | t.CPtr = pool.alloc(64) - if ty_buf is not None: - ty_buf[0] = '\0' - llvmlite.TypePrint(ty_buf, 64, aval.Ty, pool) - _asm_append_cstr(args_buf, ASM_ARGS_BUF_SIZE, ty_buf) - _asm_append_cstr(args_buf, ASM_ARGS_BUF_SIZE, " ") - _asm_append_cstr(args_buf, ASM_ARGS_BUF_SIZE, aval.Name) - - # ============================================================ - # 7. 转义汇编文本 - # ============================================================ - escaped_asm: t.CChar | t.CPtr = _asm_escape_for_ir(pool, asm_text) - if escaped_asm is None: - return None - - # ============================================================ - # 8. 生成 IR 行并发射 - # ============================================================ - line: t.CChar | t.CPtr = pool.alloc(ASM_LINE_BUF_SIZE) - if line is None: - return None - line[0] = '\0' - - ssa_name: t.CChar | t.CPtr = None - if is_void == 0: - ssa_name = pool.alloc(16) - if ssa_name is not None: - viperlib.snprintf(ssa_name, 16, "%%%d", builder.Counter) - builder.Counter += 1 - - # 获取返回类型文本 - ret_ty_buf: t.CChar | t.CPtr = pool.alloc(64) - if ret_ty_buf is not None: - ret_ty_buf[0] = '\0' - llvmlite.TypePrint(ret_ty_buf, 64, ret_ty, pool) - - if is_void == 1: - viperlib.snprintf(line, ASM_LINE_BUF_SIZE, - "call %s asm sideeffect inteldialect \"%s\", \"%s\"(%s)", - ret_ty_buf, escaped_asm, const_buf, args_buf) - else: - viperlib.snprintf(line, ASM_LINE_BUF_SIZE, - "%s = call %s asm sideeffect inteldialect \"%s\", \"%s\"(%s)", - ssa_name, ret_ty_buf, escaped_asm, const_buf, args_buf) - - # 发射 IR 到当前块 - llvmlite.block_append_text(pool, builder.CurBlock, line) - - # ============================================================ - # 9. 处理输出:存储结果到输出变量 - # ============================================================ - if is_void == 0 and first_output_idx >= 0: - result_val: llvmlite.Value | t.CPtr = llvmlite.SSAValue(pool, ret_ty, ssa_name) - out_op2: AsmOperand | t.CPtr = _asm_get_operand(operands, first_output_idx) - if out_op2.Value is not None: - llvmlite.build_store(builder, result_val, out_op2.Value) - return result_val - - return None - -# ============================================================ -# c.LLVMIR — 内联 LLVM IR 支持 -# -# 语法: -# c.LLVMIR(f"add i32 {c.LInp(a)}, {c.LInp(b)}", t.CInt) -# c.LLVMIR(f"%{c.LOut(result)} = add i32 {c.LInp(a)}, {c.LInp(b)}", t.CInt) -# -# c.LInp(expr) - 输入操作数,翻译后替换为对应的 LLVM 值 -# c.LOut(expr) - 输出操作数,翻译后结果存储到该变量 -# -# 支持的指令: add/sub/mul/sdiv/udiv/srem/urem/and/or/xor/shl/lshr/ashr -# fadd/fsub/fmul/fdiv -# icmp eq/ne/sgt/sge/slt/sle/ugt/uge/ult/ule -# fcmp oeq/one/olt/ogt/ole/oge -# zext/sext/trunc/bitcast/ptrtoint/inttoptr -# load/store -# ============================================================ - -LLVMIR_MAX_OPS: t.CDefine = 16 -LLVMIR_TEMPLATE_BUF: t.CDefine = 512 - -# ============================================================ -# _llvmir_get_op — 获取第 i 个 AsmOperand 槽位 -# ============================================================ -def _llvmir_get_op(buf: AsmOperand | t.CPtr, i: int) -> AsmOperand | t.CPtr: - """获取第 i 个操作数槽位""" - entry_size: t.CSizeT = AsmOperand.__sizeof__() - entry_addr: t.CUInt64T = t.CUInt64T(buf) + i * entry_size - return (AsmOperand | t.CPtr)(t.CVoid(entry_addr, t.CPtr)) - -# ============================================================ -# _llvmir_find_op_marker — 在字符串中查找 %__OP 并返回编号 -# -# 返回 (位置, 编号),未找到返回 (None, 0) -# ============================================================ -def _llvmir_find_op_marker(s: t.CChar | t.CPtr) -> t.CPtr: - """查找 %__OP 标记,返回标记开始位置或 None""" - if s is None: - return None - return string.strstr(s, "%__OP") - -# ============================================================ -# _llvmir_parse_op_num — 从 %__OPN__ 中解析编号 N -# -# 输入: 指向 "%__OP" 的指针 -# 返回: 操作数编号 -# ============================================================ -def _llvmir_parse_op_num(marker: t.CChar | t.CPtr) -> int: - """从 %__OPN__ 标记中解析编号 N""" - if marker is None: - return -1 - # 跳过 "%__OP" (5 字符) - num_start: t.CChar | t.CPtr = marker + 5 - if num_start is None: - return -1 - # 解析数字直到 "__" - num: int = 0 - i: t.CSizeT = 0 - ch: t.CChar = num_start[0] - while '0' <= ch <= '9': - num = num * 10 + (ch - '0') - i += 1 - ch = num_start[i] - return num - -# ============================================================ -# _llvmir_match_icmp_pred — 将预测字符串转为 ICMP 常量 -# ============================================================ -def _llvmir_match_icmp_pred(pred: str) -> int: - """将 icmp 预测字符串转为常量""" - if pred is None: - return 0 - if string.strcmp(pred, "eq") == 0: - return 0 - if string.strcmp(pred, "ne") == 0: - return 1 - if string.strcmp(pred, "sgt") == 0: - return 2 - if string.strcmp(pred, "sge") == 0: - return 3 - if string.strcmp(pred, "slt") == 0: - return 4 - if string.strcmp(pred, "sle") == 0: - return 5 - if string.strcmp(pred, "ugt") == 0: - return 6 - if string.strcmp(pred, "uge") == 0: - return 7 - if string.strcmp(pred, "ult") == 0: - return 8 - if string.strcmp(pred, "ule") == 0: - return 9 - return 0 - -# ============================================================ -# _llvmir_match_fcmp_pred — 将预测字符串转为 FCMP 常量 -# ============================================================ -def _llvmir_match_fcmp_pred(pred: str) -> int: - """将 fcmp 预测字符串转为常量""" - if pred is None: - return 0 - if string.strcmp(pred, "oeq") == 0: - return 0 - if string.strcmp(pred, "ogt") == 0: - return 1 - if string.strcmp(pred, "oge") == 0: - return 2 - if string.strcmp(pred, "olt") == 0: - return 3 - if string.strcmp(pred, "ole") == 0: - return 4 - if string.strcmp(pred, "one") == 0: - return 5 - if string.strcmp(pred, "ord") == 0: - return 6 - if string.strcmp(pred, "uno") == 0: - return 7 - if string.strcmp(pred, "ueq") == 0: - return 8 - if string.strcmp(pred, "ugt") == 0: - return 9 - if string.strcmp(pred, "uge") == 0: - return 10 - if string.strcmp(pred, "ult") == 0: - return 11 - if string.strcmp(pred, "ule") == 0: - return 12 - if string.strcmp(pred, "une") == 0: - return 13 - return 0 - -# ============================================================ -# _llvmir_extract_two_ops — 从模板中提取两个操作数编号 -# -# 通过输出参数返回 op1_num 和 op2_num -# ============================================================ -def _llvmir_extract_two_ops(template: t.CChar | t.CPtr, - out_nums: int | t.CPtr) -> int: - """从模板中提取前两个 %__OP 标记的编号 - - 结果写入 out_nums[0] 和 out_nums[1] - 返回 1 成功, 0 失败 - """ - out_nums[0] = -1 - out_nums[1] = -1 - m1: t.CChar | t.CPtr = _llvmir_find_op_marker(template) - if m1 is None: - return 0 - out_nums[0] = _llvmir_parse_op_num(m1) - - # 跳过第一个标记 "%__OPN__" - next_pos: t.CChar | t.CPtr = m1 + 5 # 跳过 "%__OP" - i: t.CSizeT = 0 - while next_pos[i] >= '0' and next_pos[i] <= '9': - i += 1 - next_pos = next_pos + i + 2 - - m2: t.CChar | t.CPtr = _llvmir_find_op_marker(next_pos) - if m2 is None: - return 1 - out_nums[1] = _llvmir_parse_op_num(m2) - return 1 - -# ============================================================ -# _llvmir_resolve_op — 根据编号解析操作数值 -# ============================================================ -def _llvmir_resolve_op(op_num: int, - all_kinds: int | t.CPtr, - all_indices: int | t.CPtr, - input_ops: AsmOperand | t.CPtr, - output_targets: AsmOperand | t.CPtr) -> llvmlite.Value | t.CPtr: - """根据操作数编号解析实际 Value""" - if op_num < 0 or op_num >= LLVMIR_MAX_OPS: - return None - kind: int = all_kinds[op_num] - idx: int = all_indices[op_num] - if kind == 0: - # 输入操作数 - op: AsmOperand | t.CPtr = _llvmir_get_op(input_ops, idx) - return op.Value - else: - # 输出操作数 - op2: AsmOperand | t.CPtr = _llvmir_get_op(output_targets, idx) - return op2.Value - -# ============================================================ -# _llvmir_store_outputs — 将结果存储到输出变量 -# ============================================================ -def _llvmir_store_outputs(pool: memhub.MemBuddy | t.CPtr, - builder: llvmlite.IRBuilder | t.CPtr, - result: llvmlite.Value | t.CPtr, - output_targets: AsmOperand | t.CPtr, - output_count: int) -> llvmlite.Value | t.CPtr: - """将结果存储到所有输出变量""" - if output_count == 0: - return result - for oi in range(output_count): - op: AsmOperand | t.CPtr = _llvmir_get_op(output_targets, oi) - if op.Value is not None and result is not None: - llvmlite.build_store(builder, result, op.Value) - return result - -# ============================================================ -# translate_c_llvmir — 翻译 c.LLVMIR 内联 LLVM IR -# ============================================================ -def translate_c_llvmir(pool: memhub.MemBuddy | t.CPtr, - builder: llvmlite.IRBuilder | t.CPtr, - mod: llvmlite.LLVMModule | t.CPtr, - cl: ast.Call | t.CPtr, - trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr: - """翻译 c.LLVMIR 内联 LLVM IR,返回结果 Value""" - if cl is None: - return None - - cargs: list[ast.AST | t.CPtr] | t.CPtr = cl.args - if cargs is None or cargs.__len__() < 1: - return None - - # 分配操作数数组 - op_size: t.CSizeT = AsmOperand.__sizeof__() - input_ops: AsmOperand | t.CPtr = pool.alloc(op_size * LLVMIR_MAX_OPS) - output_targets: AsmOperand | t.CPtr = pool.alloc(op_size * LLVMIR_MAX_OPS) - if input_ops is None or output_targets is None: - return None - string.memset(input_ops, 0, op_size * LLVMIR_MAX_OPS) - string.memset(output_targets, 0, op_size * LLVMIR_MAX_OPS) - - # all_ops 映射: kinds[i]=0(inp)/1(out), indices[i]=在对应数组中的索引 - all_kinds: int | t.CPtr = pool.alloc(4 * LLVMIR_MAX_OPS) - all_indices: int | t.CPtr = pool.alloc(4 * LLVMIR_MAX_OPS) - if all_kinds is None or all_indices is None: - return None - string.memset(all_kinds, 0, 4 * LLVMIR_MAX_OPS) - string.memset(all_indices, 0, 4 * LLVMIR_MAX_OPS) - - input_count: int = 0 - output_count: int = 0 - op_seq: int = 0 - - # 分配模板缓冲区 - template: t.CChar | t.CPtr = pool.alloc(LLVMIR_TEMPLATE_BUF) - if template is None: - return None - template[0] = '\0' - - # 解析返回类型(默认 i32) - ret_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool) - if cargs.__len__() >= 2: - ret_type_node: ast.AST | t.CPtr = cargs.get(1) - if ret_type_node is not None: - resolved_ty: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type( - pool, ret_type_node, trans._imported_modules, trans._from_imports, trans) - if resolved_ty is not None: - ret_ty = resolved_ty - - # ============================================================ - # 1. 解析 IR 模板(JoinedStr 或 Constant)— 收集操作数 - # ============================================================ - first_arg: ast.AST | t.CPtr = cargs.get(0) - if first_arg is None: - return None - - tk: int = first_arg.kind() - - if tk == ast.ASTKind.JoinedStr: - js: ast.JoinedStr | t.CPtr = (ast.JoinedStr | t.CPtr)(first_arg) - jvalues: list[ast.AST | t.CPtr] | t.CPtr = js.values - if jvalues is not None: - jvlen: t.CSizeT = jvalues.__len__() - for vi in range(jvlen): - part: ast.AST | t.CPtr = jvalues.get(vi) - if part is None: - continue - pk: int = part.kind() - - if pk == ast.ASTKind.Constant: - # 字符串字面量片段 - cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(part) - if cn.str_val is not None: - _asm_append_cstr(template, LLVMIR_TEMPLATE_BUF, cn.str_val) - - elif pk == ast.ASTKind.FormattedValue: - fv: ast.FormattedValue | t.CPtr = (ast.FormattedValue | t.CPtr)(part) - fexpr: ast.AST | t.CPtr = fv.value - if fexpr is None or fexpr.kind() != ast.ASTKind.Call: - continue - fcall: ast.Call | t.CPtr = (ast.Call | t.CPtr)(fexpr) - attr_nm: str = _asm_is_c_call(fcall) - if attr_nm is None: - # 非 c.LInp/c.LOut 调用,作为普通输入处理 - ival: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( - builder, pool, mod, fexpr, None, 0, trans) - if ival is not None and input_count < LLVMIR_MAX_OPS: - op_in: AsmOperand | t.CPtr = _llvmir_get_op(input_ops, input_count) - op_in.Value = ival - all_kinds[op_seq] = 0 - all_indices[op_seq] = input_count - input_count += 1 - op_seq += 1 - # 追加占位符 - viperlib.snprintf( - template + string.strlen(template), - LLVMIR_TEMPLATE_BUF - string.strlen(template), - "%%__OP%d__", op_seq - 1) - continue - - # 处理 c.LInp / c.LOut - fargs: list[ast.AST | t.CPtr] | t.CPtr = fcall.args - if fargs is None or fargs.__len__() < 1: - continue - val_node: ast.AST | t.CPtr = fargs.get(0) - - if string.strcmp(attr_nm, "LInp") == 0: - # 输入操作数:翻译值 - inp_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( - builder, pool, mod, val_node, None, 0, trans) - if inp_val is not None and input_count < LLVMIR_MAX_OPS: - op_inp: AsmOperand | t.CPtr = _llvmir_get_op(input_ops, input_count) - op_inp.Value = inp_val - all_kinds[op_seq] = 0 - all_indices[op_seq] = input_count - input_count += 1 - op_seq += 1 - viperlib.snprintf( - template + string.strlen(template), - LLVMIR_TEMPLATE_BUF - string.strlen(template), - "%%__OP%d__", op_seq - 1) - - elif string.strcmp(attr_nm, "LOut") == 0: - # 输出操作数:获取变量 alloca - if val_node is not None and val_node.kind() == ast.ASTKind.Name: - nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(val_node) - if nm.id is not None: - alloca: llvmlite.Value | t.CPtr = HandlesVar.lookup_var(trans.SymTab, nm.id) - if alloca is not None and output_count < LLVMIR_MAX_OPS: - op_out: AsmOperand | t.CPtr = _llvmir_get_op(output_targets, output_count) - op_out.Value = alloca - all_kinds[op_seq] = 1 - all_indices[op_seq] = output_count - output_count += 1 - op_seq += 1 - viperlib.snprintf( - template + string.strlen(template), - LLVMIR_TEMPLATE_BUF - string.strlen(template), - "%%__OP%d__", op_seq - 1) - - elif tk == ast.ASTKind.Constant: - cn2: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(first_arg) - if cn2.str_val is not None: - string.strcpy(template, cn2.str_val) - - # ============================================================ - # 2. 解析模板并生成 LLVM 指令 - # ============================================================ - - # 检查是否为赋值形式: %__OPN__ = <指令> - # 如果是,去掉赋值前缀,记录输出操作数编号 - assign_out_num: int = -1 - assign_marker: t.CChar | t.CPtr = _llvmir_find_op_marker(template) - if assign_marker is not None and assign_marker == template: - # 模板以 %__OP 开头 - # 查找 "=" 号 - eq_pos: t.CChar | t.CPtr = string.strchr(template, 61) # '=' = 61 - if eq_pos is not None: - # 确认 "%__OPN__ = " 格式 - assign_out_num = _llvmir_parse_op_num(assign_marker) - # 跳过 "%__OP__ = " 到实际指令开始 - # 找到 "=" 后第一个非空格字符 - instr_start: t.CChar | t.CPtr = eq_pos + 1 - while instr_start[0] == ' ' or instr_start[0] == '\t': - instr_start += 1 - # 将剩余部分复制到新模板 - tmpl2: t.CChar | t.CPtr = pool.alloc(LLVMIR_TEMPLATE_BUF) - if tmpl2 is not None: - string.strcpy(tmpl2, instr_start) - template = tmpl2 - - # 去除前导空格 - while template[0] == ' ' or template[0] == '\t': - template += 1 - - # 提取指令关键字(第一个单词) - instr_kw: t.CChar | t.CPtr = pool.alloc(32) - if instr_kw is None: - return None - instr_kw[0] = '\0' - ki: t.CSizeT = 0 - while template[ki] != ' ' and template[ki] != '\t' and template[ki] != '\0' and ki < 31: - instr_kw[ki] = template[ki] - ki += 1 - instr_kw[ki] = '\0' - - # ============================================================ - # 二元运算: add/sub/mul/sdiv/udiv/srem/urem/and/or/xor/shl/lshr/ashr - # ============================================================ - binop_result: llvmlite.Value | t.CPtr = None - - # 提取两个操作数编号 - op_nums: int | t.CPtr = pool.alloc(8) - if op_nums is not None: - string.memset(op_nums, 0, 8) - _llvmir_extract_two_ops(template, op_nums) - op1_num: int = -1 - op2_num: int = -1 - if op_nums is not None: - op1_num = op_nums[0] - op2_num = op_nums[1] - - lhs: llvmlite.Value | t.CPtr = _llvmir_resolve_op( - op1_num, all_kinds, all_indices, input_ops, output_targets) - rhs: llvmlite.Value | t.CPtr = _llvmir_resolve_op( - op2_num, all_kinds, all_indices, input_ops, output_targets) - - if lhs is not None and rhs is not None: - if string.strcmp(instr_kw, "add") == 0: - binop_result = llvmlite.build_add(builder, lhs, rhs) - elif string.strcmp(instr_kw, "sub") == 0: - binop_result = llvmlite.build_sub(builder, lhs, rhs) - elif string.strcmp(instr_kw, "mul") == 0: - binop_result = llvmlite.build_mul(builder, lhs, rhs) - elif string.strcmp(instr_kw, "sdiv") == 0: - binop_result = llvmlite.build_sdiv(builder, lhs, rhs) - elif string.strcmp(instr_kw, "udiv") == 0: - binop_result = llvmlite.build_udiv(builder, lhs, rhs) - elif string.strcmp(instr_kw, "srem") == 0: - binop_result = llvmlite.build_srem(builder, lhs, rhs) - elif string.strcmp(instr_kw, "urem") == 0: - binop_result = llvmlite.build_urem(builder, lhs, rhs) - elif string.strcmp(instr_kw, "and") == 0: - binop_result = llvmlite.build_and(builder, lhs, rhs) - elif string.strcmp(instr_kw, "or") == 0: - binop_result = llvmlite.build_or(builder, lhs, rhs) - elif string.strcmp(instr_kw, "xor") == 0: - binop_result = llvmlite.build_xor(builder, lhs, rhs) - elif string.strcmp(instr_kw, "shl") == 0: - binop_result = llvmlite.build_shl(builder, lhs, rhs) - elif string.strcmp(instr_kw, "lshr") == 0: - binop_result = llvmlite.build_lshr(builder, lhs, rhs) - elif string.strcmp(instr_kw, "ashr") == 0: - binop_result = llvmlite.build_ashr(builder, lhs, rhs) - elif string.strcmp(instr_kw, "fadd") == 0: - binop_result = llvmlite.build_fadd(builder, lhs, rhs) - elif string.strcmp(instr_kw, "fsub") == 0: - binop_result = llvmlite.build_fsub(builder, lhs, rhs) - elif string.strcmp(instr_kw, "fmul") == 0: - binop_result = llvmlite.build_fmul(builder, lhs, rhs) - elif string.strcmp(instr_kw, "fdiv") == 0: - binop_result = llvmlite.build_fdiv(builder, lhs, rhs) - - # ============================================================ - # icmp 比较: icmp %__OP0__, %__OP1__ - # ============================================================ - if binop_result is None and string.strcmp(instr_kw, "icmp") == 0: - # 提取预测(第二个单词) - pred_start: t.CChar | t.CPtr = template + ki + 1 - while pred_start[0] == ' ' or pred_start[0] == '\t': - pred_start += 1 - pred_str: t.CChar | t.CPtr = pool.alloc(16) - if pred_str is not None: - pred_str[0] = '\0' - pi: t.CSizeT = 0 - while pred_start[pi] != ' ' and pred_start[pi] != '\t' and pred_start[pi] != '\0' and pi < 15: - pred_str[pi] = pred_start[pi] - pi += 1 - pred_str[pi] = '\0' - pred_val: int = _llvmir_match_icmp_pred(pred_str) - if lhs is not None and rhs is not None: - binop_result = llvmlite.build_icmp(builder, pred_val, lhs, rhs) - - # ============================================================ - # fcmp 比较: fcmp %__OP0__, %__OP1__ - # ============================================================ - if binop_result is None and string.strcmp(instr_kw, "fcmp") == 0: - pred_start2: t.CChar | t.CPtr = template + ki + 1 - while pred_start2[0] == ' ' or pred_start2[0] == '\t': - pred_start2 += 1 - pred_str2: t.CChar | t.CPtr = pool.alloc(16) - if pred_str2 is not None: - pred_str2[0] = '\0' - pi2: t.CSizeT = 0 - while pred_start2[pi2] != ' ' and pred_start2[pi2] != '\t' and pred_start2[pi2] != '\0' and pi2 < 15: - pred_str2[pi2] = pred_start2[pi2] - pi2 += 1 - pred_str2[pi2] = '\0' - pred_val2: int = _llvmir_match_fcmp_pred(pred_str2) - if lhs is not None and rhs is not None: - binop_result = llvmlite.build_fcmp(builder, pred_val2, lhs, rhs) - - # ============================================================ - # store 指令: store %__OP0__, %__OP1__ - # ============================================================ - if binop_result is None and string.strcmp(instr_kw, "store") == 0: - if lhs is not None and rhs is not None: - llvmlite.build_store(builder, lhs, rhs) - return None - - # ============================================================ - # load 指令: load , %__OP0__ - # ============================================================ - if binop_result is None and string.strcmp(instr_kw, "load") == 0: - if lhs is not None: - # 从指针加载,类型由 ret_ty 指定 - binop_result = llvmlite.build_load(builder, ret_ty, lhs) - - # ============================================================ - # 类型转换: zext/sext/trunc/bitcast/ptrtoint/inttoptr - # ============================================================ - if binop_result is None: - if string.strcmp(instr_kw, "zext") == 0: - if lhs is not None: - binop_result = llvmlite.build_zext(builder, lhs, ret_ty) - elif string.strcmp(instr_kw, "sext") == 0: - if lhs is not None: - binop_result = llvmlite.build_sext(builder, lhs, ret_ty) - elif string.strcmp(instr_kw, "trunc") == 0: - if lhs is not None: - binop_result = llvmlite.build_trunc(builder, lhs, ret_ty) - elif string.strcmp(instr_kw, "bitcast") == 0: - if lhs is not None: - binop_result = llvmlite.build_bitcast(builder, lhs, ret_ty) - elif string.strcmp(instr_kw, "ptrtoint") == 0: - if lhs is not None: - binop_result = llvmlite.build_ptrtoint(builder, lhs, ret_ty) - elif string.strcmp(instr_kw, "inttoptr") == 0: - if lhs is not None: - binop_result = llvmlite.build_inttoptr(builder, lhs, ret_ty) - - # ============================================================ - # 3. 处理输出 - # ============================================================ - if binop_result is not None: - # 如果有赋值形式(%__OPN__ = ...),存储到对应输出 - if assign_out_num >= 0: - target: llvmlite.Value | t.CPtr = _llvmir_resolve_op( - assign_out_num, all_kinds, all_indices, input_ops, output_targets) - if target is not None: - llvmlite.build_store(builder, binop_result, target) - - # 存储到所有输出操作数 - _llvmir_store_outputs(pool, builder, binop_result, output_targets, output_count) - return binop_result - - # 未识别的指令,返回 0 - fb_li: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb_li is not None: - viperlib.snprintf(fb_li, 1024, "unsupported instruction: %s", instr_kw) - VLogger.error(fb_li, "LLVMIR") - return None - -# ============================================================ -# _apply_struct_defaults — 应用结构体字段的默认值 -# -# 在 zeroinitializer 之后、显式参数之前调用 -# 遍历所有字段,对有默认值的字段翻译并 store -# 显式参数(位置/关键字)后续会覆盖默认值 -# ============================================================ -def _apply_struct_defaults(pool: memhub.MemBuddy | t.CPtr, - builder: llvmlite.IRBuilder | t.CPtr, - mod: llvmlite.LLVMModule | t.CPtr, - struct_ty: llvmlite.LLVMType | t.CPtr, - class_name: str, - tmp: llvmlite.Value | t.CPtr, - trans: HT.Translator | t.CPtr): - """应用结构体字段的默认值""" - # 用类型指针定位 entry,规避跨模块同名 find_struct 找错 - entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_type(struct_ty) - if entry is None: - return - for fi in range(entry.FieldCount): - fe: HandlesStruct.FieldEntry | t.CPtr = HandlesStruct._get_field_entry( - entry, fi) - if fe is None or fe.DefaultVal is None: - continue - default_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( - builder, pool, mod, fe.DefaultVal, None, 0, trans) - if default_val is None: - continue - field_ptr: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct( - builder, struct_ty, fe.Ty, tmp, fe.Index) - if field_ptr is None: - continue - default_val = HandlesExpr.coerce_to_type(builder, default_val, fe.Ty) - llvmlite.build_store(builder, default_val, field_ptr) - -# ============================================================ -# _translate_struct_ctor — 结构体构造函数 Point(10, 20) -# -# 生成: -# %tmp = alloca {i32, i32} -# store {i32, i32} zeroinitializer, {i32, i32}* %tmp -# %f0 = getelementptr {i32, i32}, {i32, i32}* %tmp, i32 0, i32 0 -# store i32 10, i32* %f0 -# %f1 = getelementptr {i32, i32}, {i32, i32}* %tmp, i32 0, i32 1 -# store i32 20, i32* %f1 -# %result = load {i32, i32}, {i32, i32}* %tmp -# ============================================================ -def _translate_struct_ctor(pool: memhub.MemBuddy | t.CPtr, - builder: llvmlite.IRBuilder | t.CPtr, - mod: llvmlite.LLVMModule | t.CPtr, - struct_ty: llvmlite.LLVMType | t.CPtr, - class_name: str, - cargs: list[ast.AST | t.CPtr] | t.CPtr, - can: t.CSizeT, - trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr: - """结构体构造函数:按字段顺序 store 参数值,返回结构体值 - - OOP 结构体:alloca → call __before_init__(ptr) → call __init__(ptr, args) 或 store 参数 → load - 普通结构体:alloca → zero + defaults → store 参数 → load - """ - # 创建临时 alloca - # 确保跨模块结构体的完整定义在当前模块中可用(供 alloca 分配空间) - HandlesStruct.ensure_struct_def_in_module(pool, mod, struct_ty) - tmp: llvmlite.Value | t.CPtr = llvmlite.build_alloca(builder, struct_ty) - if tmp is None: - return llvmlite.ConstZero(pool, struct_ty) - - # 检查是否为 OOP 结构体(用类型指针定位 entry,规避跨模块同名 find_struct 找错) - ctor_entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_type(struct_ty) - is_oop: int = 0 - if ctor_entry is not None: - is_oop = ctor_entry.IsOOP - - # 跨模块 OOP 类推断:IsOOP 可能未设置(Phase1 缓存跳过 _translate_oop_methods) - # 方案1: 检查当前模块是否有 ClassName.__init__ 的声明(stub 注入) - # 方案2: 检查全局默认参数表是否有 ClassName.__init__ 的条目(翻译时填充,更可靠) - if is_oop == 0 and class_name is not None: - init_lookup_name: t.CChar | t.CPtr = pool.alloc(128) - if init_lookup_name is not None: - viperlib.snprintf(init_lookup_name, 128, "%s.__init__", class_name) - # 方案1: 检查当前模块的函数声明 - init_found_func: llvmlite.Function | t.CPtr = find_func_in_module(mod, init_lookup_name) - if init_found_func is not None: - is_oop = 1 - if ctor_entry is not None: - ctor_entry.IsOOP = 1 - ctor_entry.HasInit = 1 - else: - # 方案2: 检查全局默认参数表(翻译时填充,不依赖 stub 注入) - init_defaults_entry: FuncDefaultsEntry | t.CPtr = find_func_defaults(init_lookup_name) - if init_defaults_entry is not None: - is_oop = 1 - if ctor_entry is not None: - ctor_entry.IsOOP = 1 - ctor_entry.HasInit = 1 - - if is_oop != 0: - # 存储指针:默认用 alloca,如果有 __new__ 则用 __new__ 返回的指针 - storage_ptr: llvmlite.Value | t.CPtr = tmp - - # 如果有 __new__,调用 __new__(tmp, args...) 获取实际存储指针 - # __new__ 签名与 __init__ 一样(self + args),返回 Ptr(struct_ty) - has_new_flag: int = 0 - if ctor_entry is not None: - has_new_flag = ctor_entry.HasNew - # 注意: __new__ 是可选的,不推断 HasNew(仅 __init__ 是 OOP 类标准方法) - if has_new_flag != 0: - new_arg_vals: t.CSizeT | t.CPtr = pool.alloc(8 * 32) - if new_arg_vals is not None: - string.memset(new_arg_vals, 0, 8 * 32) - new_arg_count: int = 0 - for nai in range(can): - new_arg_node: ast.AST | t.CPtr = cargs.get(nai) - if new_arg_node is None: - continue - new_av: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( - builder, pool, mod, new_arg_node, None, 0, trans) - if new_av is not None: - if new_arg_count < 32: - new_arg_vals[new_arg_count] = t.CSizeT(new_av) - new_arg_count += 1 - - new_ptr: llvmlite.Value | t.CPtr = _call_method_on_ptr( - pool, builder, mod, class_name, - "__new__", tmp, new_arg_vals, new_arg_count, trans) - if new_ptr is not None: - storage_ptr = new_ptr - - # OOP 结构体:调用 __before_init__ 进行零值填充和默认值赋值 - _call_method_on_ptr(pool, builder, mod, class_name, - "__before_init__", storage_ptr, None, 0, trans) - - # 如果有 __init__,调用 __init__(ptr, args...) - has_init_flag: int = 0 - if ctor_entry is not None: - has_init_flag = ctor_entry.HasInit - # 跨模块 OOP 类: HasInit 可能未设置(_translate_oop_methods 未被调用) - # 但 IsOOP=1 说明类有方法,推断 HasInit=1 - if is_oop != 0 and has_init_flag == 0: - has_init_flag = 1 - if has_init_flag != 0: - # 翻译构造函数参数 - arg_vals: t.CSizeT | t.CPtr = pool.alloc(8 * 32) - if arg_vals is not None: - string.memset(arg_vals, 0, 8 * 32) - real_arg_count: int = 0 - for ai in range(can): - arg_node: ast.AST | t.CPtr = cargs.get(ai) - if arg_node is None: - continue - av: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( - builder, pool, mod, arg_node, None, 0, trans) - if av is not None: - if real_arg_count < 32: - arg_vals[real_arg_count] = t.CSizeT(av) - real_arg_count += 1 - - _call_method_on_ptr(pool, builder, mod, class_name, - "__init__", storage_ptr, arg_vals, real_arg_count, trans) - else: - # 无 __init__:逐字段 store 参数值 - for ai in range(can): - arg: ast.AST | t.CPtr = cargs.get(ai) - if arg is None: - continue - arg_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( - builder, pool, mod, arg, None, 0, trans) - if arg_val is None: - continue - fe: HandlesStruct.FieldEntry | t.CPtr = None - if ctor_entry is not None: - fe = HandlesStruct._get_field_entry(ctor_entry, ai) - else: - fe = HandlesStruct.get_field_by_index(class_name, ai) - if fe is None: - continue - field_ptr: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct( - builder, struct_ty, fe.Ty, storage_ptr, fe.Index) - if field_ptr is None: - continue - arg_val = HandlesExpr.coerce_to_type(builder, arg_val, fe.Ty) - llvmlite.build_store(builder, arg_val, field_ptr) - - # 返回指针(而非结构体值),赋值时由 coerce_to_type 按目标类型决定是否 load - return storage_ptr - - # 普通结构体:先 store zeroinitializer 清零(确保未赋值字段为零) - zero: llvmlite.Value | t.CPtr = llvmlite.ConstZero(pool, struct_ty) - llvmlite.build_store(builder, zero, tmp) - - # 应用默认值(显式参数会覆盖默认值) - _apply_struct_defaults(pool, builder, mod, struct_ty, class_name, tmp, trans) - - # 逐字段 store 参数值(覆盖默认值) - for ai in range(can): - arg: ast.AST | t.CPtr = cargs.get(ai) - if arg is None: - continue - arg_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( - builder, pool, mod, arg, None, 0, trans) - if arg_val is None: - continue - # 获取字段信息(用 ctor_entry 规避跨模块同名 find_struct 找错) - fe: HandlesStruct.FieldEntry | t.CPtr = None - if ctor_entry is not None: - fe = HandlesStruct._get_field_entry(ctor_entry, ai) - else: - fe = HandlesStruct.get_field_by_index(class_name, ai) - if fe is None: - continue - # GEP 到字段 ai - field_ptr: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct( - builder, struct_ty, fe.Ty, tmp, fe.Index) - if field_ptr is None: - continue - # 类型转换并 store - arg_val = HandlesExpr.coerce_to_type(builder, arg_val, fe.Ty) - llvmlite.build_store(builder, arg_val, field_ptr) - - # 返回指针(而非结构体值),赋值时由 coerce_to_type 按目标类型决定是否 load - return tmp - - -# ============================================================ -# _translate_renum_construct — REnum 变体构造函数 -# -# 语法: ClassName.VariantName(args...) -# 如 LLVMType.Int(1) → 构造 LLVMType 的 Int 变体,__tag=0,_p1=1 -# -# 生成 IR: -# %tmp = alloca {i32, i32, ...} ; REnum 类型 -# store zeroinitializer, %tmp ; 清零 -# %tag_ptr = gep %tmp, 0, 0 ; __tag 字段 -# store i32 , %tag_ptr ; 写入 tag -# %p1_ptr = gep %tmp, 0, 1 ; _p1 字段 -# store , %p1_ptr ; 写入 payload[0] -# ... (更多 payload 字段) -# return %tmp ; 返回指针 -# -# 对应 TPC 的 _HandleREnumConstructLlvm -# ============================================================ -def _translate_renum_construct(pool: memhub.MemBuddy | t.CPtr, - builder: llvmlite.IRBuilder | t.CPtr, - mod: llvmlite.LLVMModule | t.CPtr, - class_name: str, - variant_name: str, - tag_value: int, - cargs: list[ast.AST | t.CPtr] | t.CPtr, - can: t.CSizeT, - trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr: - """构造 REnum 变体实例,返回指向 alloca 的指针 - - class_name: REnum 类名(如 "LLVMType") - variant_name: 变体名(如 "Int") - tag_value: 变体的 tag 值(变体在类中的索引) - cargs: 参数 AST 列表 - can: 参数数量 - """ - if pool is None or builder is None or class_name is None: - return None - - # 查找 REnum 结构体类型(用 find_struct_by_module 规避跨模块同名) - renum_entry: HandlesStruct.StructEntry | t.CPtr = None - if trans is not None: - renum_entry = HandlesStruct.find_struct_by_module(class_name, trans.ModuleSha1) - if renum_entry is None: - renum_entry = HandlesStruct.find_struct(class_name) - if renum_entry is None: - fb_re: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb_re is not None: - viperlib.snprintf(fb_re, 1024, "REnum construct: type %s not registered", class_name) - VLogger.error(fb_re, "RENUM") - return None - - renum_ty: llvmlite.LLVMType | t.CPtr = renum_entry.Ty - if renum_ty is None: - return None - - # alloca REnum 类型 - # 确保跨模块结构体的完整定义在当前模块中可用(供 alloca 分配空间) - HandlesStruct.ensure_struct_def_in_module(pool, mod, renum_ty) - tmp: llvmlite.Value | t.CPtr = llvmlite.build_alloca(builder, renum_ty) - if tmp is None: - return llvmlite.ConstZero(pool, renum_ty) - - # 清零(确保未赋值的 payload 位置为零) - zero: llvmlite.Value | t.CPtr = llvmlite.ConstZero(pool, renum_ty) - llvmlite.build_store(builder, zero, tmp) - - # 写入 __tag 字段(索引 0) - i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool) - tag_const: llvmlite.Value | t.CPtr = llvmlite.ConstInt(pool, i32_ty, tag_value, "0") - tag_field: HandlesStruct.FieldEntry | t.CPtr = HandlesStruct._get_field_entry(renum_entry, 0) - tag_field_ty: llvmlite.LLVMType | t.CPtr = i32_ty - if tag_field is not None and tag_field.Ty is not None: - tag_field_ty = tag_field.Ty - tag_ptr: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct( - builder, renum_ty, tag_field_ty, tmp, 0) - if tag_ptr is not None: - llvmlite.build_store(builder, tag_const, tag_ptr) - - # 写入 payload 字段(索引 1, 2, ... 对应 _p1, _p2, ...) - # 参数按位置顺序填充 payload,跳过 __tag(索引 0) - for ai in range(can): - arg: ast.AST | t.CPtr = cargs.get(ai) - if arg is None: - continue - arg_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( - builder, pool, mod, arg, None, 0, trans) - if arg_val is None: - continue - # payload 字段索引 = ai + 1(跳过 __tag) - payload_idx: int = ai + 1 - if payload_idx >= renum_entry.FieldCount: - break - pfe: HandlesStruct.FieldEntry | t.CPtr = HandlesStruct._get_field_entry( - renum_entry, payload_idx) - if pfe is None: - continue - payload_ptr: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct( - builder, renum_ty, pfe.Ty, tmp, payload_idx) - if payload_ptr is None: - continue - # 类型转换并 store(payload 位置可能是 i32 或 i64,按字段类型 coerce) - arg_val = HandlesExpr.coerce_to_type(builder, arg_val, pfe.Ty) - llvmlite.build_store(builder, arg_val, payload_ptr) - - # 返回指针(与 _translate_struct_ctor 一致,赋值时由 coerce_to_type 决定是否 load) - return tmp - - -# ============================================================ -# _do_virtual_call — 通过虚表间接调用虚方法 -# -# IR 模式: -# %1 = getelementptr StructTy, StructTy* %self, i32 0, i32 0 ; i8** -# %2 = load i8*, i8** %1 ; i8* (vtable ptr) -# %3 = bitcast i8* %2 to {i8*, ...}* ; vtable typed ptr -# %4 = getelementptr {i8*, ...}, {i8*, ...}* %3, i32 0, i32 N ; i8** -# %5 = load i8*, i8** %4 ; i8* (func ptr) -# %6 = bitcast i8* %5 to RetTy(Params)* ; func typed ptr -# call RetTy %6(Params %self, ...) -# -# 参数: -# args_head — 已构建好的参数链表头(self_ptr 为首节点) -# args_count — 参数总数(含 self) -# found_func — 方法对应的 Function 对象(用于推断函数签名) -# ret_ty — 返回类型 -# ============================================================ -def _do_virtual_call(pool: memhub.MemBuddy | t.CPtr, - builder: llvmlite.IRBuilder | t.CPtr, - mod: llvmlite.LLVMModule | t.CPtr, - class_name: str, - method_name: str, - self_ptr: llvmlite.Value | t.CPtr, - args_head: llvmlite.Value | t.CPtr, - args_count: int, - found_func: llvmlite.Function | t.CPtr, - ret_ty: llvmlite.LLVMType | t.CPtr) -> llvmlite.Value | t.CPtr: - """通过虚表间接调用虚方法,返回 call 结果(void 方法返回 None)""" - if pool is None or builder is None or class_name is None or method_name is None: - return None - if self_ptr is None or args_head is None: - return None - - # 1. 获取结构体类型(用 find_struct_by_type 规避跨模块同名 find_struct 找错) - vc_entry: HandlesStruct.StructEntry | t.CPtr = None - struct_ty: llvmlite.LLVMType | t.CPtr = None - if self_ptr.Ty is not None: - vc_entry = HandlesStruct.get_struct_type_from_value(self_ptr) - if vc_entry is not None: - # vc_entry 是 struct_ty(LLVMType),需要找 StructEntry - vc_entry = HandlesStruct.find_struct_by_type(vc_entry) - if vc_entry is not None: - struct_ty = vc_entry.Ty - if struct_ty is None: - struct_ty = HandlesStruct.get_struct_type(class_name) - if struct_ty is None: - return None - - # 2. 获取方法在虚表中的索引(用 entry 直接查找) - method_index: int = -1 - if vc_entry is not None and vc_entry.VTableMethods is not None: - methods_arr: t.CSizeT | t.CPtr = (t.CSizeT | t.CPtr)(t.CVoid(vc_entry.VTableMethods, t.CPtr)) - for mi in range(vc_entry.VTableMethodCount): - mname_addr: t.CSizeT = methods_arr[mi] - if mname_addr == 0: - continue - mname: str = (str | t.CPtr)(t.CVoid(mname_addr, t.CPtr)) - if mname is not None and string.strcmp(mname, method_name) == 0: - method_index = mi - break - else: - method_index = HandlesStruct.get_vtable_method_index(class_name, method_name) - if method_index < 0: - return None - - # 3. 基础类型 - i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool) - i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty) - i8_ptr_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ptr_ty) - - # 4. bitcast 到 i8** 访问 __vtable__ 字段(索引 0) - # vtable 指针总是在对象第一个字段,无需 GEP,直接 bitcast 到 i8** 即可。 - # 这样即使 struct_ty 是 opaque(跨模块未加载完整定义)也能正常工作。 - vtable_slot: llvmlite.Value | t.CPtr = llvmlite.build_bitcast( - builder, self_ptr, i8_ptr_ptr_ty) - if vtable_slot is None: - return None - - # 5. load vtable 指针 (i8*) - vtable_ptr: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, i8_ptr_ty, vtable_slot) - if vtable_ptr is None: - return None - - # 6. 构造 vtable 类型 {i8*, i8*, ...} - method_count: int = 0 - if vc_entry is not None: - method_count = vc_entry.VTableMethodCount - else: - method_count = HandlesStruct.get_vtable_method_count(class_name) - if method_count <= 0: - return None - - vt_first: llvmlite.ParamNode | t.CPtr = None - vt_prev: llvmlite.ParamNode | t.CPtr = None - for vi in range(method_count): - pn: llvmlite.ParamNode | t.CPtr = llvmlite.new_param_node(pool, i8_ptr_ty) - if pn is None: - continue - if vt_first is None: - vt_first = pn - if vt_prev is not None: - llvmlite.paramnode_set_next(vt_prev, pn) - vt_prev = pn - - vtable_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Struct(pool, vt_first, method_count, None) - if vtable_ty is None: - return None - vtable_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, vtable_ty) - - # 7. bitcast i8* 到 vtable 类型指针 - vtable_typed: llvmlite.Value | t.CPtr = llvmlite.build_bitcast( - builder, vtable_ptr, vtable_ptr_ty) - if vtable_typed is None: - return None - - # 8. GEP 到方法槽位 - func_slot: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct( - builder, vtable_ty, i8_ptr_ty, vtable_typed, method_index) - if func_slot is None: - return None - - # 9. load 函数指针 (i8*) - func_i8: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, i8_ptr_ty, func_slot) - if func_i8 is None: - return None - - # 10. 从 args_head 构造函数类型 RetTy(Param1, Param2, ...) - # 直接遍历 Value 链表提取参数类型,避免跨模块访问 found_func(stub 字段偏移问题) - fp_first: llvmlite.ParamNode | t.CPtr = None - fp_prev: llvmlite.ParamNode | t.CPtr = None - fp_count: int = 0 - cur_val: llvmlite.Value | t.CPtr = args_head - for vi in range(args_count): - if cur_val is None: - break - cur_ty: llvmlite.LLVMType | t.CPtr = llvmlite.value_get_ty(cur_val) - fpn: llvmlite.ParamNode | t.CPtr = llvmlite.new_param_node(pool, cur_ty) - if fpn is not None: - if fp_first is None: - fp_first = fpn - if fp_prev is not None: - llvmlite.paramnode_set_next(fp_prev, fpn) - fp_prev = fpn - cur_val = llvmlite.value_get_next(cur_val) - fp_count += 1 - - func_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Func(pool, ret_ty, fp_first, fp_count) - if func_ty is None: - return None - func_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, func_ty) - - # 11. bitcast i8* 到函数指针类型 - func_ptr: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(builder, func_i8, func_ptr_ty) - if func_ptr is None: - return None - - # 12. 间接调用 - return llvmlite.build_call_indirect(builder, func_ptr, args_head, args_count, ret_ty) - -# ============================================================ -# _call_method_on_ptr — 在结构体指针上调用方法 -# -# 辅助函数:构造 ClassName.method_name 调用,self 指针为首个参数 -# 如果该方法在虚表中,则走虚方法分发路径(间接调用) -# ============================================================ -def _call_method_on_ptr(pool: memhub.MemBuddy | t.CPtr, - builder: llvmlite.IRBuilder | t.CPtr, - mod: llvmlite.LLVMModule | t.CPtr, - class_name: str, - method_name: str, - self_ptr: llvmlite.Value | t.CPtr, - extra_args: t.CSizeT | t.CPtr, - extra_count: int, - trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr: - """在结构体指针上调用方法,返回 call 结果(void 方法返回 None)""" - if pool is None or builder is None or class_name is None or method_name is None: - return None - if self_ptr is None: - return None - - # 提前获取结构体 entry(用 find_struct_by_type 规避跨模块同名 find_struct 找错) - # 用于 SHA1 查找和虚表分派 - cmop_entry: HandlesStruct.StructEntry | t.CPtr = None - cmop_struct_ty: llvmlite.LLVMType | t.CPtr = HandlesStruct.get_struct_type_from_value(self_ptr) - if cmop_struct_ty is not None: - cmop_entry = HandlesStruct.find_struct_by_type(cmop_struct_ty) - if cmop_entry is None: - cmop_entry = HandlesStruct.find_struct(class_name) - # fallback: 若 cmop_struct_ty 为 None 但 entry 存在,从 entry 获取类型 - # 用于跨模块调用时 self_ptr 类型信息丢失的情况 - if cmop_struct_ty is None and cmop_entry is not None: - cmop_struct_ty = cmop_entry.Ty - - # 构造方法查找名: ClassName.method_name - lookup_name: t.CChar | t.CPtr = pool.alloc(128) - if lookup_name is None: - return None - viperlib.snprintf(lookup_name, 128, "%s.%s", class_name, method_name) - - # 查找函数(支持 SHA1 后缀匹配) - found_func: llvmlite.Function | t.CPtr = find_func_in_module(mod, lookup_name) - - # 确定调用名 - call_name: str = lookup_name - if found_func is not None: - found_name: t.CChar | t.CPtr = llvmlite.function_get_name(found_func) - if found_name is not None: - call_name = found_name - else: - # found_func 为 None(stub 未注入):用类所属模块的 SHA1 构造调用名 - # 优先从 entry 获取 SHA1(规避跨模块同名 find_struct 找错) - cls_sha1: str = None - if cmop_entry is not None: - cls_sha1 = cmop_entry.ModuleSha1 - else: - cls_sha1 = HandlesStruct.get_struct_sha1(class_name) - if cls_sha1 is None and trans is not None: - # fallback: 从 from_imports 查找类所属模块的 SHA1(含截断处理) - cls_sha1 = _lookup_mod_sha1(pool, trans._from_imports, class_name) - if cls_sha1 is None: - err_msg: t.CChar | t.CPtr = pool.alloc(256) - if err_msg is not None: - viperlib.snprintf(err_msg, 256, "类 '%s' 方法 '%s' 找不到模块 SHA1", class_name, method_name) - HandlesType.fatal_error(None, err_msg) - HandlesType.fatal_error(None, "找不到模块 SHA1") - mangled_len2: t.CSizeT = string.strlen(cls_sha1) + string.strlen(lookup_name) + 2 - mangled2: str = pool.alloc(mangled_len2) - if mangled2 is not None: - viperlib.snprintf(mangled2, mangled_len2, "%s.%s", cls_sha1, lookup_name) - call_name = mangled2 - - # 确定返回类型(__before_init__ 和 __init__ 返回 void) - void_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Void(pool) - call_ret_ty: llvmlite.LLVMType | t.CPtr = void_ty - if found_func is not None: - frt: llvmlite.LLVMType | t.CPtr = llvmlite.function_get_ret_ty(found_func) - if frt is not None: - call_ret_ty = frt - else: - # found_func 为 None(跨模块调用 stub 未注入):根据方法名推断返回类型 - # __new__ 返回 Ptr(struct_ty) - # __getitem__ 返回 Ptr(struct_ty)(自定义结构体 subscript 读取) - # 其他方法默认 void - if string.strcmp(method_name, "__new__") == 0 and cmop_struct_ty is not None: - call_ret_ty = llvmlite.Ptr(pool, cmop_struct_ty) - elif string.strcmp(method_name, "__getitem__") == 0 and cmop_struct_ty is not None: - # __getitem__ 返回对象指针 (如 JsonValue|t.CPtr, HashTable|t.CPtr) - call_ret_ty = llvmlite.Ptr(pool, cmop_struct_ty) - - # 构建参数链表: self_ptr → extra_args... - llvmlite.value_set_next(self_ptr, None) - head: llvmlite.Value | t.CPtr = self_ptr - tail: llvmlite.Value | t.CPtr = self_ptr - - if extra_args is not None and extra_count > 0: - for ei in range(extra_count): - arg_addr: t.CSizeT = extra_args[ei] - if arg_addr == 0: - continue - av: llvmlite.Value | t.CPtr = (llvmlite.Value | t.CPtr)(t.CVoid(arg_addr, t.CPtr)) - if av is not None: - llvmlite.value_set_next(av, None) - llvmlite.value_set_next(tail, av) - tail = av - - total_count: int = 1 + extra_count - - # 默认参数填充:如果调用点参数少于函数定义参数,用默认值填充缺失参数 - # 优先用函数定义的默认值,无默认值时用零值兜底 - # 查找函数的 defaults 信息 - mdf_defaults: t.CVoid | t.CPtr = None - mdf_default_count: int = 0 - mdf_param_count: int = 0 - if trans is not None and trans._funcs is not None: - mdf_entry: FuncEntry | t.CPtr = find_func_entry_in_table( - trans._funcs, trans._func_count, lookup_name) - if mdf_entry is not None: - mdf_defaults = mdf_entry.Defaults - mdf_default_count = mdf_entry.DefaultCount - mdf_param_count = mdf_entry.ParamCount - if mdf_defaults is None: - mdf_gd: FuncDefaultsEntry | t.CPtr = find_func_defaults(lookup_name) - if mdf_gd is not None: - mdf_defaults = mdf_gd.Defaults - mdf_default_count = mdf_gd.DefaultCount - mdf_param_count = mdf_gd.ParamCount - - # 计算需要填充的参数(不含 self) - # extra_count = 已提供的非 self 参数数量 - # mdf_param_count = 函数定义的非 self 参数数量 - if mdf_param_count > extra_count: - mdf_offset: int = mdf_param_count - mdf_default_count - mdf_pi: int = extra_count - while mdf_pi < mdf_param_count: - # 优先用默认值 - if mdf_defaults is not None and mdf_default_count > 0 and mdf_pi >= mdf_offset: - mdf_di: int = mdf_pi - mdf_offset - if mdf_di < mdf_default_count: - mdf_defaults_list: list[ast.AST | t.CPtr] | t.CPtr = (list[ast.AST | t.CPtr] | t.CPtr)(t.CVoid(t.CUInt64T(mdf_defaults), t.CPtr)) - mdf_node: ast.AST | t.CPtr = mdf_defaults_list.get(mdf_di) - if mdf_node is not None: - mdf_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( - builder, pool, mod, mdf_node, None, 0, trans) - if mdf_val is not None: - llvmlite.value_set_next(mdf_val, None) - llvmlite.value_set_next(tail, mdf_val) - tail = mdf_val - total_count += 1 - mdf_pi += 1 - continue - # 无默认值时用零值兜底(需要 found_func 获取参数类型) - if found_func is not None: - param_node_z: llvmlite.Param | t.CPtr = llvmlite.function_get_param_head(found_func) - skip_z: int = 0 - while skip_z <= mdf_pi and param_node_z is not None: - param_node_z = llvmlite.param_get_next(param_node_z) - skip_z += 1 - if param_node_z is not None: - zero_ty: llvmlite.LLVMType | t.CPtr = llvmlite.param_get_ty(param_node_z) - zero_val: llvmlite.Value | t.CPtr = llvmlite.ConstZero(pool, zero_ty) - if zero_val is not None: - llvmlite.value_set_next(zero_val, None) - llvmlite.value_set_next(tail, zero_val) - tail = zero_val - total_count += 1 - mdf_pi += 1 - elif found_func is not None: - # 无默认参数信息但有 found_func:用零值填充(保留原有逻辑) - param_node: llvmlite.Param | t.CPtr = llvmlite.function_get_param_head(found_func) - skip_idx: int = 0 - while skip_idx < total_count and param_node is not None: - param_node = llvmlite.param_get_next(param_node) - skip_idx += 1 - while param_node is not None: - missing_ty: llvmlite.LLVMType | t.CPtr = llvmlite.param_get_ty(param_node) - zero_val2: llvmlite.Value | t.CPtr = llvmlite.ConstZero(pool, missing_ty) - if zero_val2 is not None: - llvmlite.value_set_next(zero_val2, None) - llvmlite.value_set_next(tail, zero_val2) - tail = zero_val2 - total_count += 1 - param_node = llvmlite.param_get_next(param_node) - - # 虚方法分发:如果类有虚表且该方法在虚表中,走间接调用 - # 复用前面已获取的 cmop_entry(find_struct_by_type 规避跨模块同名找错) - if found_func is not None: - cmop_has_vt: int = 0 - cmop_method_idx: int = -1 - if cmop_entry is not None: - cmop_has_vt = cmop_entry.HasVTable - if cmop_has_vt == 1 and cmop_entry.VTableMethods is not None: - cmop_methods_arr: t.CSizeT | t.CPtr = (t.CSizeT | t.CPtr)(t.CVoid(cmop_entry.VTableMethods, t.CPtr)) - for cmop_mi in range(cmop_entry.VTableMethodCount): - cmop_mname_addr: t.CSizeT = cmop_methods_arr[cmop_mi] - if cmop_mname_addr == 0: - continue - cmop_mname: str = (str | t.CPtr)(t.CVoid(cmop_mname_addr, t.CPtr)) - if cmop_mname is not None and string.strcmp(cmop_mname, method_name) == 0: - cmop_method_idx = cmop_mi - break - if cmop_has_vt == 1 and cmop_method_idx >= 0: - return _do_virtual_call(pool, builder, mod, class_name, method_name, - self_ptr, head, total_count, found_func, call_ret_ty) - - # 跨模块调用(found_func 为 None):创建 declare 声明,避免 llc 报 undefined value - if found_func is None: - _ensure_method_declare(pool, mod, call_name, call_ret_ty, head, total_count) - - return llvmlite.build_call(builder, call_name, head, total_count, call_ret_ty, 0) - - -# ============================================================ -# _ensure_method_declare - 为跨模块方法调用创建 declare 声明 -# -# 当 found_func 为 None(stub 未注入或跨模块调用)时, -# 在当前模块中创建函数声明,避免 llc 报 undefined value。 -# ============================================================ -def _ensure_method_declare(pool: memhub.MemBuddy | t.CPtr, - mod: llvmlite.LLVMModule | t.CPtr, - call_name: str, - ret_ty: llvmlite.LLVMType | t.CPtr, - param_head: llvmlite.ParamNode | t.CPtr, - param_count: int): - """为跨模块方法调用创建 declare 声明 - - 若模块中已存在同名 declare 且参数数量较少(例如 File.__init__ 的 - stub 仅 3 个参数,而实际调用传入 4 个),则向现有 declare 追加缺失 - 参数,避免 llc 报 `argument invalid for parameter type` 之类的错误。 - 已存在的 define 不修改(其参数由定义决定)。 - """ - if pool is None or mod is None or call_name is None: - return - # 检查模块中是否已有同名函数(declare 或 define) - existing: llvmlite.Function | t.CPtr = mod.FuncHead - while existing is not None: - if existing.Name is not None: - if string.strcmp(existing.Name, call_name) == 0: - # 已存在:仅当是 declare 且参数数量不足时追加缺失参数 - if existing.IsDeclared == 1: - # 遍历现有参数链表计数(避免依赖 GSList.Count 字段的类型推断) - cur_count: int = 0 - cur_p: llvmlite.Param | t.CPtr = llvmlite.function_get_param_head(existing) - while cur_p is not None: - cur_count += 1 - cur_p = cur_p.Next - # 只追加缺失的参数(cur_count < param_count 时) - if cur_count < param_count: - # 定位到 param_head 的第 cur_count 个节点开始追加 - pnode2: llvmlite.ParamNode | t.CPtr = param_head - pi2: int = 0 - # 跳过已有的 cur_count 个参数 - while pnode2 is not None and pi2 < cur_count: - pnode2 = pnode2.Next - pi2 += 1 - # 追加剩余参数 - while pnode2 is not None and pi2 < param_count: - if pnode2.Ty is not None: - param2: llvmlite.Param | t.CPtr = llvmlite.new_param(pool, pnode2.Ty, None) - if param2 is not None: - llvmlite.function_add_param(existing, param2) - pnode2 = pnode2.Next - pi2 += 1 - return - existing = existing.Next - # 创建函数声明 - func: llvmlite.Function | t.CPtr = llvmlite.new_function(pool, call_name, ret_ty) - if func is None: - return - func.IsDeclared = 1 - # 添加参数(declare 中参数名无意义,设为 None 只输出类型) - pnode: llvmlite.ParamNode | t.CPtr = param_head - pi: int = 0 - while pnode is not None and pi < param_count: - if pnode.Ty is not None: - param: llvmlite.Param | t.CPtr = llvmlite.new_param(pool, pnode.Ty, None) - if param is not None: - llvmlite.function_add_param(func, param) - pnode = pnode.Next - pi += 1 - llvmlite.module_add_function(mod, func) - - -# ============================================================ -# _infer_method_ret_ty - 根据方法名推断返回类型 -# -# stub 未注入时,find_func_in_module 返回 None, -# 需要根据方法名推断返回类型避免指针被截断为 i32。 -# ============================================================ -def _infer_method_ret_ty(pool: memhub.MemBuddy | t.CPtr, - method_name: str) -> llvmlite.LLVMType | t.CPtr: - """根据方法名推断返回类型(stub 未注入时的回退方案)""" - if pool is None or method_name is None: - return llvmlite.Int32(pool) - - i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, llvmlite.Int8(pool)) - - # 返回 i8* 的方法(分配/返回指针) - if string.strcmp(method_name, "alloc") == 0: - return i8_ptr_ty - if string.strcmp(method_name, "calloc") == 0: - return i8_ptr_ty - if string.strcmp(method_name, "realloc") == 0: - return i8_ptr_ty - if string.strcmp(method_name, "alloc_buf") == 0: - return i8_ptr_ty - if string.strcmp(method_name, "_fl_pop") == 0: - return i8_ptr_ty - if string.strcmp(method_name, "_buddy_of") == 0: - return i8_ptr_ty - if string.strcmp(method_name, "_split_to_order") == 0: - return i8_ptr_ty - if string.strcmp(method_name, "__enter__") == 0: - return i8_ptr_ty - # 工厂方法:返回对象指针(截断会导致后续方法调用崩溃) - if string.strcmp(method_name, "parse_args") == 0: - return i8_ptr_ty - # 魔术方法:返回对象指针(如 JsonValue.__getitem__ 返回 JsonValue*) - if string.strcmp(method_name, "__getitem__") == 0: - return i8_ptr_ty - - # 返回 i8* 的方法(返回字符串/类型名/描述) - if string.strcmp(method_name, "type_name") == 0: - return i8_ptr_ty - if string.strcmp(method_name, "get_name") == 0: - return i8_ptr_ty - if string.strcmp(method_name, "get_str") == 0: - return i8_ptr_ty - if string.strcmp(method_name, "get_path") == 0: - return i8_ptr_ty - if string.strcmp(method_name, "get_buf") == 0: - return i8_ptr_ty - if string.strcmp(method_name, "to_string") == 0: - return i8_ptr_ty - if string.strcmp(method_name, "as_string") == 0: - return i8_ptr_ty - if string.strcmp(method_name, "__repr__") == 0: - return i8_ptr_ty - if string.strcmp(method_name, "__str__") == 0: - return i8_ptr_ty - # 返回 i8* 的方法(返回对象指针,如 JsonValue.get_item → JsonValue*) - if string.strcmp(method_name, "get_item") == 0: - return i8_ptr_ty - - # 返回 void 的方法 - if string.strcmp(method_name, "__before_init__") == 0: - return llvmlite.Void(pool) - if string.strcmp(method_name, "__init__") == 0: - return llvmlite.Void(pool) - if string.strcmp(method_name, "__exit__") == 0: - return llvmlite.Void(pool) - - # 默认 i32(整数):与本模块函数定义的默认返回类型一致(HandlesFunctions.py line 324) - # 已知返回指针的方法在上方显式列出(返回 i8*),已知返回 void 的方法也显式列出 - # 避免使用 i64 导致 stub 声明(declare i64)与实际定义(define i32)类型不匹配 - # x86-64 ABI 中 i32 返回值在 rax 低 32 位,与 define i32 完全一致 - # 与 _infer_external_func_ret_ty 的默认策略保持一致 - return llvmlite.Int32(pool) - -# ============================================================ -# _translate_method_call - 翻译方法调用 obj.method(args) -# -# 生成: call @SHA1.ClassName.method_name(Ptr(StructTy) %obj, args...) -# -# obj_ptr 是对象变量的 alloca(Ptr(StructTy)),作为 self 参数传入 -# ============================================================ -def _translate_method_call(pool: memhub.MemBuddy | t.CPtr, - builder: llvmlite.IRBuilder | t.CPtr, - mod: llvmlite.LLVMModule | t.CPtr, - class_name: str, - method_name: str, - obj_ptr: llvmlite.Value | t.CPtr, - cl: ast.Call | t.CPtr, - trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr: - """翻译方法调用,返回 call 结果 Value""" - if pool is None or builder is None or class_name is None or method_name is None: - return None - if obj_ptr is None or cl is None: - return None - - # 提前获取结构体 entry(用 find_struct_by_type 规避跨模块同名 find_struct 找错) - # 用于继承链遍历、SHA1 查找和虚表分派 - mc_entry: HandlesStruct.StructEntry | t.CPtr = None - mc_struct_ty: llvmlite.LLVMType | t.CPtr = HandlesStruct.get_struct_type_from_value(obj_ptr) - if mc_struct_ty is not None: - mc_entry = HandlesStruct.find_struct_by_type(mc_struct_ty) - if mc_entry is None: - mc_entry = HandlesStruct.find_struct(class_name) - - # 构造方法查找名: ClassName.method_name - lookup_name: t.CChar | t.CPtr = pool.alloc(128) - if lookup_name is None: - return None - viperlib.snprintf(lookup_name, 128, "%s.%s", class_name, method_name) - - # 查找函数(支持 SHA1 后缀匹配) - found_func: llvmlite.Function | t.CPtr = find_func_in_module(mod, lookup_name) - - # 沿继承链查找父类方法(子类未覆盖时回退到父类) - if found_func is None: - cur_parent: str = None - if mc_entry is not None: - cur_parent = mc_entry.ParentName - else: - cur_parent = HandlesStruct.get_parent_name(class_name) - while cur_parent is not None: - parent_lookup: t.CChar | t.CPtr = pool.alloc(128) - if parent_lookup is not None: - viperlib.snprintf(parent_lookup, 128, "%s.%s", cur_parent, method_name) - parent_func: llvmlite.Function | t.CPtr = find_func_in_module(mod, parent_lookup) - if parent_func is not None: - found_func = parent_func - break - # 后续父类按名查找(无 ParentSha1,只能按名回退) - cur_parent = HandlesStruct.get_parent_name(cur_parent) - - # 确定调用名 - call_name: str = lookup_name - if found_func is not None: - found_name: t.CChar | t.CPtr = llvmlite.function_get_name(found_func) - if found_name is not None: - call_name = found_name - else: - # found_func 为 None(stub 未注入):用类所属模块的 SHA1 构造调用名 - # 沿继承链查找第一个有 SHA1 的类 - cls_sha1_mc: str = None - if mc_entry is not None: - cls_sha1_mc = mc_entry.ModuleSha1 - else: - cls_sha1_mc = HandlesStruct.get_struct_sha1(class_name) - if cls_sha1_mc is None: - cur_p: str = None - if mc_entry is not None: - cur_p = mc_entry.ParentName - else: - cur_p = HandlesStruct.get_parent_name(class_name) - while cur_p is not None and cls_sha1_mc is None: - cls_sha1_mc = HandlesStruct.get_struct_sha1(cur_p) - cur_p = HandlesStruct.get_parent_name(cur_p) - if cls_sha1_mc is not None: - mangled_len_mc: t.CSizeT = string.strlen(cls_sha1_mc) + string.strlen(lookup_name) + 2 - mangled_mc: str = pool.alloc(mangled_len_mc) - if mangled_mc is not None: - viperlib.snprintf(mangled_mc, mangled_len_mc, "%s.%s", cls_sha1_mc, lookup_name) - call_name = mangled_mc - - # 确定返回类型 - i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool) - call_ret_ty: llvmlite.LLVMType | t.CPtr = i32_ty - if found_func is not None: - frt: llvmlite.LLVMType | t.CPtr = llvmlite.function_get_ret_ty(found_func) - if frt is not None: - call_ret_ty = frt - else: - # found_func 为 None(stub 未注入):根据方法名推断返回类型 - call_ret_ty = _infer_method_ret_ty(pool, method_name) - - # 翻译调用参数 - cargs: list[ast.AST | t.CPtr] | t.CPtr = cl.args - can: t.CSizeT = 0 - if cargs is not None: - can = cargs.__len__() - - # 构建参数链表: obj_ptr → arg1 → arg2 → ... - llvmlite.value_set_next(obj_ptr, None) - head: llvmlite.Value | t.CPtr = obj_ptr - tail: llvmlite.Value | t.CPtr = obj_ptr - - for ai in range(can): - arg_node: ast.AST | t.CPtr = cargs.get(ai) - if arg_node is None: - continue - arg_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( - builder, pool, mod, arg_node, None, 0, trans) - if arg_val is None: - continue - llvmlite.value_set_next(arg_val, None) - llvmlite.value_set_next(tail, arg_val) - tail = arg_val - - total_count: int = 1 + can - - # 默认参数填充:如果调用点参数少于函数定义参数,用默认值填充缺失参数 - # 查找函数的 defaults 信息 - mdf_defaults: t.CVoid | t.CPtr = None - mdf_default_count: int = 0 - mdf_param_count: int = 0 - if trans is not None and trans._funcs is not None: - mdf_entry: FuncEntry | t.CPtr = find_func_entry_in_table( - trans._funcs, trans._func_count, lookup_name) - if mdf_entry is not None: - mdf_defaults = mdf_entry.Defaults - mdf_default_count = mdf_entry.DefaultCount - mdf_param_count = mdf_entry.ParamCount - if mdf_defaults is None: - mdf_gd: FuncDefaultsEntry | t.CPtr = find_func_defaults(lookup_name) - if mdf_gd is not None: - mdf_defaults = mdf_gd.Defaults - mdf_default_count = mdf_gd.DefaultCount - mdf_param_count = mdf_gd.ParamCount - - # 计算需要填充的参数(不含 self) - # can = 已提供的非 self 参数数量 - # mdf_param_count = 函数定义的非 self 参数数量 - if mdf_param_count > can: - mdf_offset: int = mdf_param_count - mdf_default_count - mdf_pi: int = can - while mdf_pi < mdf_param_count: - # 优先用默认值 - if mdf_defaults is not None and mdf_default_count > 0 and mdf_pi >= mdf_offset: - mdf_di: int = mdf_pi - mdf_offset - if mdf_di < mdf_default_count: - mdf_defaults_list: list[ast.AST | t.CPtr] | t.CPtr = (list[ast.AST | t.CPtr] | t.CPtr)(t.CVoid(t.CUInt64T(mdf_defaults), t.CPtr)) - mdf_node: ast.AST | t.CPtr = mdf_defaults_list.get(mdf_di) - if mdf_node is not None: - mdf_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( - builder, pool, mod, mdf_node, None, 0, trans) - if mdf_val is not None: - llvmlite.value_set_next(mdf_val, None) - llvmlite.value_set_next(tail, mdf_val) - tail = mdf_val - total_count += 1 - mdf_pi += 1 - continue - # 无默认值时用零值兜底(需要 found_func 获取参数类型) - if found_func is not None: - param_node_z: llvmlite.Param | t.CPtr = llvmlite.function_get_param_head(found_func) - skip_z: int = 0 - while skip_z <= mdf_pi and param_node_z is not None: - param_node_z = llvmlite.param_get_next(param_node_z) - skip_z += 1 - if param_node_z is not None: - zero_ty: llvmlite.LLVMType | t.CPtr = llvmlite.param_get_ty(param_node_z) - zero_val: llvmlite.Value | t.CPtr = llvmlite.ConstZero(pool, zero_ty) - if zero_val is not None: - llvmlite.value_set_next(zero_val, None) - llvmlite.value_set_next(tail, zero_val) - tail = zero_val - total_count += 1 - mdf_pi += 1 - - # 虚方法分发:如果类有虚表且该方法在虚表中,走间接调用 - # (不依赖 found_func — 继承的虚方法可能没有子类实现) - # 复用前面已获取的 mc_entry(find_struct_by_type 规避跨模块同名找错) - mc_has_vt: int = 0 - mc_method_idx: int = -1 - if mc_entry is not None: - mc_has_vt = mc_entry.HasVTable - if mc_has_vt == 1 and mc_entry.VTableMethods is not None: - mc_methods_arr: t.CSizeT | t.CPtr = (t.CSizeT | t.CPtr)(t.CVoid(mc_entry.VTableMethods, t.CPtr)) - for mc_mi in range(mc_entry.VTableMethodCount): - mc_mname_addr: t.CSizeT = mc_methods_arr[mc_mi] - if mc_mname_addr == 0: - continue - mc_mname: str = (str | t.CPtr)(t.CVoid(mc_mname_addr, t.CPtr)) - if mc_mname is not None and string.strcmp(mc_mname, method_name) == 0: - mc_method_idx = mc_mi - break - if mc_has_vt == 1 and mc_method_idx >= 0: - return _do_virtual_call(pool, builder, mod, class_name, method_name, - obj_ptr, head, total_count, found_func, call_ret_ty) - - # 跨模块调用:创建 declare 声明,避免 llc 报 undefined value - _ensure_method_declare(pool, mod, call_name, call_ret_ty, head, total_count) - return llvmlite.build_call(builder, call_name, head, total_count, call_ret_ty, 0) - -# ============================================================ -# _kwarg_name_matches — 检查关键字参数名是否匹配函数参数名 -# -# 函数参数名在 LLVM IR 中带 % 前缀(如 "%a"),关键字参数名无前缀(如 "a") -# 跳过 % 前缀后逐字符比较 -# ============================================================ -def _kwarg_name_matches(kw_arg: str, - param_name: t.CChar | t.CPtr) -> int: - """检查关键字参数名 kw_arg 是否匹配参数名 param_name(跳过 % 前缀)""" - if kw_arg is None or param_name is None: - return 0 - start: t.CSizeT = 0 - if param_name[0] == '%': - start = 1 - for i, ch in enumerate(kw_arg): - c: t.CChar = param_name[start + i] - if c == '\0' or c != ch: - return 0 - if param_name[start + i + 1] != '\0': - return 0 - return 1 - -# ============================================================ -# _translate_struct_ctor_kw — 结构体构造函数(关键字参数) -# -# 支持两种语法: -# Point(x=10, y=20) — 全关键字 -# Point(10, y=20) — 混合(位置 + 关键字) -# -# 位置参数按字段索引赋值,关键字参数按字段名查找赋值 -# ============================================================ -def _translate_struct_ctor_kw(pool: memhub.MemBuddy | t.CPtr, - builder: llvmlite.IRBuilder | t.CPtr, - mod: llvmlite.LLVMModule | t.CPtr, - struct_ty: llvmlite.LLVMType | t.CPtr, - class_name: str, - cargs: list[ast.AST | t.CPtr] | t.CPtr, - can: t.CSizeT, - keywords: list[ast.AST | t.CPtr] | t.CPtr, - kw_count: t.CSizeT, - trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr: - """结构体构造函数(关键字参数版本)""" - # 创建临时 alloca - # 确保跨模块结构体的完整定义在当前模块中可用(供 alloca 分配空间) - HandlesStruct.ensure_struct_def_in_module(pool, mod, struct_ty) - tmp: llvmlite.Value | t.CPtr = llvmlite.build_alloca(builder, struct_ty) - if tmp is None: - return llvmlite.ConstZero(pool, struct_ty) - - # OOP 结构体:调用 __before_init__ 进行零值填充和默认值赋值 - # 用 find_struct_by_type 规避跨模块同名 find_struct 找错 - kw_entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_type(struct_ty) - is_oop: int = 0 - if kw_entry is not None: - is_oop = kw_entry.IsOOP - - # 跨模块 OOP 类推断:IsOOP 可能未设置(Phase1 缓存跳过 _translate_oop_methods) - # 方案1: 检查当前模块是否有 ClassName.__init__ 的声明(stub 注入) - # 方案2: 检查全局默认参数表是否有 ClassName.__init__ 的条目(翻译时填充,更可靠) - if is_oop == 0 and class_name is not None: - kw_init_lookup: t.CChar | t.CPtr = pool.alloc(128) - if kw_init_lookup is not None: - viperlib.snprintf(kw_init_lookup, 128, "%s.__init__", class_name) - # 方案1: 检查当前模块的函数声明 - kw_init_found: llvmlite.Function | t.CPtr = find_func_in_module(mod, kw_init_lookup) - if kw_init_found is not None: - is_oop = 1 - if kw_entry is not None: - kw_entry.IsOOP = 1 - kw_entry.HasInit = 1 - else: - # 方案2: 检查全局默认参数表(翻译时填充,不依赖 stub 注入) - kw_init_defaults: FuncDefaultsEntry | t.CPtr = find_func_defaults(kw_init_lookup) - if kw_init_defaults is not None: - is_oop = 1 - if kw_entry is not None: - kw_entry.IsOOP = 1 - kw_entry.HasInit = 1 - - if is_oop != 0: - _call_method_on_ptr(pool, builder, mod, class_name, - "__before_init__", tmp, None, 0, trans) - else: - # 普通结构体:store zeroinitializer + 应用默认值 - zero: llvmlite.Value | t.CPtr = llvmlite.ConstZero(pool, struct_ty) - llvmlite.build_store(builder, zero, tmp) - _apply_struct_defaults(pool, builder, mod, struct_ty, class_name, tmp, trans) - - # OOP 结构体且有 __init__:调用 __init__ 而非逐字段 store - # 关键字构造调用此前总是逐字段 store,导致 __init__ 方法体不执行 - # (如 self._args = mb.alloc(...) 不执行 → self._args 为 NULL → add_argument 崩溃) - has_init_flag: int = 0 - has_new_flag: int = 0 - if kw_entry is not None: - has_init_flag = kw_entry.HasInit - has_new_flag = kw_entry.HasNew - - # 跨模块 OOP 类: HasInit 可能未设置(_translate_oop_methods 未被调用) - # 但 IsOOP=1 说明类有方法,推断 HasInit=1(__init__ 在目标模块中存在) - # 注意: __new__ 是可选的,不推断 HasNew(仅 __init__ 是 OOP 类标准方法) - if is_oop != 0 and has_init_flag == 0: - has_init_flag = 1 - - if is_oop != 0 and has_init_flag != 0: - # 有 __init__:构建参数数组并调用 __init__ - storage_ptr: llvmlite.Value | t.CPtr = tmp - - # 如果有 __new__,调用 __new__ 获取实际存储指针 - if has_new_flag != 0: - new_arg_vals: t.CSizeT | t.CPtr = pool.alloc(8 * 32) - if new_arg_vals is not None: - string.memset(new_arg_vals, 0, 8 * 32) - new_arg_count: int = 0 - for nai in range(can): - new_arg_node: ast.AST | t.CPtr = cargs.get(nai) - if new_arg_node is None: - continue - new_av: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( - builder, pool, mod, new_arg_node, None, 0, trans) - if new_av is not None: - if new_arg_count < 32: - new_arg_vals[new_arg_count] = t.CSizeT(new_av) - new_arg_count += 1 - # 关键字参数也传递给 __new__ - for nki in range(kw_count): - nkw: ast.Keyword | t.CPtr = (ast.Keyword | t.CPtr)(keywords.get(nki)) - if nkw is None or nkw.value is None: - continue - nkw_av: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( - builder, pool, mod, nkw.value, None, 0, trans) - if nkw_av is not None: - if new_arg_count < 32: - new_arg_vals[new_arg_count] = t.CSizeT(nkw_av) - new_arg_count += 1 - new_ptr: llvmlite.Value | t.CPtr = _call_method_on_ptr( - pool, builder, mod, class_name, - "__new__", tmp, new_arg_vals, new_arg_count, trans) - if new_ptr is not None: - storage_ptr = new_ptr - - # 构建 __init__ 参数数组:位置参数按顺序 + 关键字参数追加 - init_arg_vals: t.CSizeT | t.CPtr = pool.alloc(8 * 32) - if init_arg_vals is not None: - string.memset(init_arg_vals, 0, 8 * 32) - init_arg_count: int = 0 - # 位置参数 - for ai_init in range(can): - arg_node_init: ast.AST | t.CPtr = cargs.get(ai_init) - if arg_node_init is None: - continue - av_init: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( - builder, pool, mod, arg_node_init, None, 0, trans) - if av_init is not None: - if init_arg_count < 32: - init_arg_vals[init_arg_count] = t.CSizeT(av_init) - init_arg_count += 1 - # 关键字参数(追加到末尾,按出现顺序) - for ki_init in range(kw_count): - kw_init: ast.Keyword | t.CPtr = (ast.Keyword | t.CPtr)(keywords.get(ki_init)) - if kw_init is None or kw_init.value is None: - continue - kw_av_init: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( - builder, pool, mod, kw_init.value, None, 0, trans) - if kw_av_init is not None: - if init_arg_count < 32: - init_arg_vals[init_arg_count] = t.CSizeT(kw_av_init) - init_arg_count += 1 - - # 调用 __init__(storage_ptr, *args) - _call_method_on_ptr(pool, builder, mod, class_name, - "__init__", storage_ptr, init_arg_vals, init_arg_count, trans) - - # 返回指针 - return storage_ptr - - # 无 __init__(或非 OOP):逐字段 store 参数值 - # 先处理位置参数(按字段索引,覆盖默认值) - for ai in range(can): - arg: ast.AST | t.CPtr = cargs.get(ai) - if arg is None: - continue - arg_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( - builder, pool, mod, arg, None, 0, trans) - if arg_val is None: - continue - fe: HandlesStruct.FieldEntry | t.CPtr = None - if kw_entry is not None: - fe = HandlesStruct._get_field_entry(kw_entry, ai) - else: - fe = HandlesStruct.get_field_by_index(class_name, ai) - if fe is None: - continue - field_ptr: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct( - builder, struct_ty, fe.Ty, tmp, fe.Index) - if field_ptr is None: - continue - arg_val = HandlesExpr.coerce_to_type(builder, arg_val, fe.Ty) - llvmlite.build_store(builder, arg_val, field_ptr) - - # 处理关键字参数(按字段名查找) - # SHA1 从 kw_entry 获取(规避跨模块同名 find_struct 找错) - kw_sha1: str = None - if kw_entry is not None: - kw_sha1 = kw_entry.ModuleSha1 - for ki in range(kw_count): - kw: ast.Keyword | t.CPtr = (ast.Keyword | t.CPtr)(keywords.get(ki)) - if kw is None or kw.arg is None or kw.value is None: - continue - fe: HandlesStruct.FieldEntry | t.CPtr = HandlesStruct.lookup_field_by_class( - class_name, kw.arg, kw_sha1) - if fe is None: - continue - kw_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( - builder, pool, mod, kw.value, None, 0, trans) - if kw_val is None: - continue - field_ptr: llvmlite.Value | t.CPtr = llvmlite.build_gep_struct( - builder, struct_ty, fe.Ty, tmp, fe.Index) - if field_ptr is None: - continue - kw_val = HandlesExpr.coerce_to_type(builder, kw_val, fe.Ty) - llvmlite.build_store(builder, kw_val, field_ptr) - - # 返回指针(而非结构体值),赋值时由 coerce_to_type 按目标类型决定是否 load - return tmp - -# ============================================================ -# _translate_call_with_kwargs — 带关键字参数的函数调用 -# -# 支持两种语法: -# add(b=4, a=3) — 全关键字乱序 -# greet("Hello", name="World") — 位置 + 关键字混合 -# -# 策略: 遍历 found_func.Params 链表,对每个参数: -# 1. 若位置参数仍有剩余(param_idx < can),取位置参数 -# 2. 否则按参数名匹配关键字参数 -# 3. 按参数顺序构建调用参数链表 -# ============================================================ -def _translate_call_with_kwargs(pool: memhub.MemBuddy | t.CPtr, - builder: llvmlite.IRBuilder | t.CPtr, - mod: llvmlite.LLVMModule | t.CPtr, - func_name: str, - found_func: llvmlite.Function | t.CPtr, - cargs: list[ast.AST | t.CPtr] | t.CPtr, - can: t.CSizeT, - keywords: list[ast.AST | t.CPtr] | t.CPtr, - kw_count: t.CSizeT, - trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr: - """带关键字参数的函数调用,按参数顺序构建调用链表 - - 使用 llvmlite 访问器函数绕过 stub 类型限制: - found_func.Params/RetTy/Name 和 cur_param.Name/Ty/Next 在 stub - 类型中字段不足,直接访问会被 TransPyC 静默跳过。 - """ - head: llvmlite.Value | t.CPtr = None - tail: llvmlite.Value | t.CPtr = None - actual_count: t.CSizeT = 0 - # memcpy 专用: 收集前三个 Value 的独立引用(避免共享 alloca 对象的 Next 被污染) - mc_dst1: llvmlite.Value | t.CPtr = None - mc_src1: llvmlite.Value | t.CPtr = None - mc_num1: llvmlite.Value | t.CPtr = None - - # 遍历函数参数链表(使用访问器获取 Head) - param_idx: t.CSizeT = 0 - cur_param: llvmlite.Param | t.CPtr = llvmlite.function_get_param_head(found_func) - - while cur_param is not None: - arg_val: llvmlite.Value | t.CPtr = None - if param_idx < can: - # 优先使用位置参数 - arg: ast.AST | t.CPtr = cargs.get(param_idx) - if arg is not None: - arg_val = HandlesExpr.translate_value( - builder, pool, mod, arg, None, 0, trans) - else: - # 查找匹配的关键字参数 - param_name: t.CChar | t.CPtr = llvmlite.param_get_name(cur_param) - if param_name is not None: - for ki in range(kw_count): - kw: ast.Keyword | t.CPtr = (ast.Keyword | t.CPtr)(keywords.get(ki)) - if kw is None or kw.arg is None or kw.value is None: - continue - if _kwarg_name_matches(kw.arg, param_name) == 1: - arg_val = HandlesExpr.translate_value( - builder, pool, mod, kw.value, None, 0, trans) - break - - if arg_val is not None: - # 类型转换(按参数类型,使用访问器) - param_ty: llvmlite.LLVMType | t.CPtr = llvmlite.param_get_ty(cur_param) - if param_ty is not None: - arg_val = HandlesExpr.coerce_to_type(builder, arg_val, param_ty) - arg_val.Next = None - if head is None: - head = arg_val - else: - tail.Next = arg_val - tail = arg_val - # memcpy 专用: 保存前三个参数的独立引用 - if actual_count == 0: - mc_dst1 = arg_val - elif actual_count == 1: - mc_src1 = arg_val - elif actual_count == 2: - mc_num1 = arg_val - actual_count += 1 - - param_idx += 1 - cur_param = llvmlite.param_get_next(cur_param) - - # 使用模块中的实际函数名(可能带 SHA1 前缀,使用访问器) - # declare 和 define 统一用 found_func.Name: - # - 普通函数的 declare/define 都带 SHA1 前缀(forward_declare_functions 和 stub 注入都用 mangled_name) - # - t.CExtern/t.State/t.CExport 函数的 declare/define 都用裸名 - # 旧逻辑(IsDeclared==1 时用 func_name 裸名)是错误的:stub 注入的 declare Name 已带 SHA1 前缀, - # 用裸名会导致 call @_PathToModuleName 而 define 是 @"sha1._PathToModuleName",链接报 undefined reference - call_name: str = func_name - found_name: t.CChar | t.CPtr = llvmlite.function_get_name(found_func) - if found_name is not None: - call_name = found_name - - # 返回类型(使用访问器) - call_ret_ty: llvmlite.LLVMType | t.CPtr = llvmlite.function_get_ret_ty(found_func) - if call_ret_ty is None: - call_ret_ty = _infer_external_func_ret_ty(pool, func_name) - - # memcpy → @llvm.memcpy 内联函数(避免 monomorphization 跨模块 @memcpy 声明缺失) - if func_name == "memcpy" and actual_count >= 3: - return _emit_llvm_memcpy_intrinsic(pool, builder, mod, mc_dst1, mc_src1, mc_num1) - return llvmlite.build_call(builder, call_name, head, actual_count, call_ret_ty, 0) - -# ============================================================ -# _translate_t_type_cast - 翻译 t.XXX(value) 类型转换 -# -# 当 func 是 t.XXX 形式且 XXX 是已知类型名(map_t_type 能映射)时, -# 将 value 转换为目标类型: -# - 指针 → 整数: ptrtoint (如 t.CUInt64T(ptr) → i64) -# - 整数 → 指针: inttoptr (如 t.CPtr(int_val) → i8*) -# - 整数 → 整数: trunc/zext (如 t.CInt8T(i32_val) → i8) -# - 指针 → 指针: bitcast (如 t.CPtr(ptr_val) → i8*) -# ============================================================ -def _translate_t_type_cast(pool: memhub.MemBuddy | t.CPtr, - builder: llvmlite.IRBuilder | t.CPtr, - val: llvmlite.Value | t.CPtr, - target_ty: llvmlite.LLVMType | t.CPtr) -> llvmlite.Value | t.CPtr: - """类型转换:根据参数类型和目标类型选择转换方式""" - if val is None or target_ty is None: - return None - - val_bits: int = HandlesExpr.get_llvm_type_bits(val.Ty) - target_bits: int = HandlesExpr.get_llvm_type_bits(target_ty) - - # 整数 → 整数: trunc/zext - if val_bits != 0 and target_bits != 0: - if val_bits == target_bits: - return val - elif val_bits < target_bits: - return llvmlite.build_zext(builder, val, target_ty) - else: - return llvmlite.build_trunc(builder, val, target_ty) - - # 指针 → 整数: ptrtoint - if val_bits == 0 and target_bits != 0: - return llvmlite.build_ptrtoint(builder, val, target_ty) - - # 整数 → 指针: inttoptr - if val_bits != 0 and target_bits == 0: - return llvmlite.build_inttoptr(builder, val, target_ty) - - # 指针 → 指针: bitcast - return llvmlite.build_bitcast(builder, val, target_ty) - -# ============================================================ -# 泛型实例化辅助:从 Subscript slice 提取类型实参名 -# ============================================================ -# _get_type_name_from_annotation 已移至 HandlesType.py(支持 BinOp/Attribute) -# HandlesExprCall 通过 HandlesType._get_type_name_from_annotation 调用 - -def _extract_type_args_from_slice(pool: memhub.MemBuddy | t.CPtr, - slice_node: ast.AST | t.CPtr) -> list[str] | t.CPtr: - """从 Subscript.slice 提取类型实参名列表 - - list[int] -> ["int"] - dict[str, int] -> ["str", "int"] - list[AST | t.CPtr] -> ["AST|t.CPtr"] - """ - if slice_node is None or pool is None: - return None - result: list[str] | t.CPtr = list[str](pool, 4) - k: int = slice_node.kind() - if k == ast.ASTKind.Tuple: - tp: ast.Tuple | t.CPtr = (ast.Tuple | t.CPtr)(slice_node) - elts: list[ast.AST | t.CPtr] | t.CPtr = tp.elts - if elts is not None: - n: t.CSizeT = elts.__len__() - i: t.CSizeT - for i in range(n): - elt: ast.AST | t.CPtr = elts.get(i) - tn: str = HandlesType._get_type_name_from_annotation(pool, elt) - if tn is not None: - result.append(tn) - else: - tn: str = HandlesType._get_type_name_from_annotation(pool, slice_node) - if tn is not None: - result.append(tn) - return result - -# ============================================================ -# 泛型类构造调用辅助: list[str](pool, 8) → __new__ + __before_init__ + __init__ -# -# 复用 translate_list_literal 的构造逻辑: -# 1. alloca tmp(特化类临时空间,作为 __new__ 的 self) -# 2. 翻译 cl.args 为参数指针数组 -# 3. call __new__(tmp, *args) → storage_ptr -# 4. call __before_init__(storage_ptr) -# 5. call __init__(storage_ptr, *args) -# 6. return storage_ptr -# -# 必须独立于 translate_call 的普通函数路径:spec_name 是类名不是函数名, -# 走裸名路径会被 _lookup_mod_sha1 的 star import 回退误导,用错误的 SHA1 -# 且缺少 __new__ 方法名后缀,导致链接报 undefined reference。 -# ============================================================ -def _translate_generic_ctor_call(pool: memhub.MemBuddy | t.CPtr, - builder: llvmlite.IRBuilder | t.CPtr, - mod: llvmlite.LLVMModule | t.CPtr, - spec_name: str, - cl: ast.Call | t.CPtr, - trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr: - """泛型类构造调用: list[str](pool, 8) → __new__ + __before_init__ + __init__""" - if pool is None or builder is None or mod is None or spec_name is None or cl is None: - return None - - # 查找 struct entry 获取类型 - struct_entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct(spec_name) - if struct_entry is None: - HandlesType.fatal_error(cl, "泛型类构造调用: 特化类未注册") - return None - struct_ty: llvmlite.LLVMType | t.CPtr = struct_entry.Ty - if struct_ty is None: - return None - - # 确保结构体定义在当前模块中可用(供 alloca 分配空间) - HandlesStruct.ensure_struct_def_in_module(pool, mod, struct_ty) - - # alloca tmp(self 指针) - tmp: llvmlite.Value | t.CPtr = llvmlite.build_alloca(builder, struct_ty) - if tmp is None: - return None - - # 翻译 cl.args 为参数指针数组(extra_args[i] = Value 指针) - cargs: list[ast.AST | t.CPtr] | t.CPtr = cl.args - can: t.CSizeT = 0 - if cargs is not None: - can = cargs.__len__() - - extra_args: t.CSizeT | t.CPtr = pool.alloc(8 * 32) - if extra_args is None: - return None - string.memset(extra_args, 0, 8 * 32) - - ai: t.CSizeT = 0 - while ai < can: - arg_node: ast.AST | t.CPtr = cargs.get(ai) - if arg_node is not None: - arg_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( - builder, pool, mod, arg_node, None, 0, trans) - if arg_val is not None: - extra_args[ai] = t.CSizeT(arg_val) - ai += 1 - - # 存储指针:默认用 alloca,如果有 __new__ 则用 __new__ 返回的指针 - # __new__ 是可选的,仅当泛型类模板定义了 __new__ 方法时才调用 - # (与 _translate_struct_ctor 保持一致,避免为无 __new__ 的类生成过度声明) - storage_ptr: llvmlite.Value | t.CPtr = tmp - has_new_flag: int = 0 - if struct_entry is not None: - has_new_flag = struct_entry.HasNew - if has_new_flag != 0: - new_ptr: llvmlite.Value | t.CPtr = _call_method_on_ptr( - pool, builder, mod, spec_name, "__new__", tmp, extra_args, can, trans) - if new_ptr is not None: - storage_ptr = new_ptr - - # call __before_init__(storage_ptr)(TransPyV 自动生成,零值填充) - _call_method_on_ptr( - pool, builder, mod, spec_name, "__before_init__", storage_ptr, None, 0, trans) - - # call __init__(storage_ptr, *args) - _call_method_on_ptr( - pool, builder, mod, spec_name, "__init__", storage_ptr, extra_args, can, trans) - - return storage_ptr - - -# ============================================================ -# 翻译函数调用 Call(func, args) — 模块级版本 -# ============================================================ -def translate_call(pool: memhub.MemBuddy | t.CPtr, - builder: llvmlite.IRBuilder | t.CPtr, - mod: llvmlite.LLVMModule | t.CPtr, - node: ast.AST | t.CPtr, - funcs_ptr: t.CPtr, - func_count: int, - trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr: - """翻译函数调用,返回 call 结果 Value""" - cl: ast.Call | t.CPtr = (ast.Call | t.CPtr)(node) - if cl is None: - return None - - func_name: str = HandlesExpr.get_func_name(cl.func) - if func_name is None: - # 检查是否是 list[int](pool) 形式的泛型实例化调用 - # Subscript 节点作为 Call func: 泛型类构造函数 - if cl.func is not None and cl.func.kind() == ast.ASTKind.Subscript and trans is not None: - sub_node: ast.Subscript | t.CPtr = (ast.Subscript | t.CPtr)(cl.func) - if sub_node.value is not None and sub_node.value.kind() == ast.ASTKind.Name: - gen_nm_node: ast.Name | t.CPtr = (ast.Name | t.CPtr)(sub_node.value) - gen_class_name: str = gen_nm_node.id - # 检查是否是泛型类模板 - template_cd: ast.ClassDef | t.CPtr = HandlesClassDef._find_generic_template(gen_class_name) - if template_cd is not None: - # 提取类型实参 - gen_type_args: list[str] | t.CPtr = _extract_type_args_from_slice(pool, sub_node.slice) - if gen_type_args is not None and gen_type_args.__len__() > 0: - # 特化泛型类,返回特化类名 - spec_name: str = HandlesClassDef._specialize_generic_class( - trans, gen_class_name, gen_type_args) - if spec_name is not None: - # 泛型类构造调用: list[str](pool, 8) → __new__ + __before_init__ + __init__ - # 不能直接用 spec_name 作为 func_name(会走裸名调用路径, - # 被 star import 回退误导用错误的 SHA1,且缺少 __new__ 方法名后缀) - return _translate_generic_ctor_call( - pool, builder, mod, spec_name, cl, trans) - else: - # 泛型类模板未找到:可能未 import 定义模块 - gt_err: str = pool.alloc(256) - if gt_err is not None: - viperlib.snprintf(gt_err, 256, "泛型类 '%s' 未找到模板,可能未 import 定义模块", gen_class_name) - HandlesType.fatal_error(gen_nm_node, gt_err) - HandlesType.fatal_error(gen_nm_node, "泛型类模板未找到") - if func_name is None: - # 检查是否是 (A | t.CPtr)(value) 形式的类型转换 - # BinOp 节点作为 Call func: 联合类型注解用作类型转换 - if cl.func is not None and cl.func.kind() == ast.ASTKind.BinOp and trans is not None: - binop_ty: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type( - pool, cl.func, trans._imported_modules, trans._from_imports, trans) - if binop_ty is not None: - binop_args: list[ast.AST | t.CPtr] | t.CPtr = cl.args - if binop_args is not None and binop_args.__len__() == 1: - binop_arg_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( - builder, pool, mod, binop_args.get(0), funcs_ptr, func_count, trans) - if binop_arg_val is not None: - return _translate_t_type_cast(pool, builder, binop_arg_val, binop_ty) - return None - - # 检测 c.Deref / c.DerefAs / c.Addr 等特殊调用(内联 IR,不生成 call) - if cl.func is not None and cl.func.kind() == ast.ASTKind.Attribute: - at_node: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(cl.func) - if at_node.value is not None and at_node.value.kind() == ast.ASTKind.Name: - mod_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at_node.value) - if mod_nm.id is not None and string.strcmp(mod_nm.id, "c") == 0: - if string.strcmp(func_name, "Deref") == 0: - return translate_c_deref(pool, builder, mod, cl, trans) - elif string.strcmp(func_name, "DerefAs") == 0: - return translate_c_derefas(pool, builder, mod, cl, trans) - elif string.strcmp(func_name, "Addr") == 0: - return translate_c_addr(pool, builder, mod, cl, trans) - elif string.strcmp(func_name, "Load") == 0: - return translate_c_load(pool, builder, mod, cl, trans) - elif string.strcmp(func_name, "Asm") == 0: - return translate_c_asm(pool, builder, mod, cl, trans) - elif string.strcmp(func_name, "LLVMIR") == 0: - return translate_c_llvmir(pool, builder, mod, cl, trans) - elif string.strcmp(func_name, "LInp") == 0 or string.strcmp(func_name, "LOut") == 0: - # c.LInp/c.LOut 独立调用时返回 0(仅在 c.LLVMIR 的 f-string 内有意义) - return llvmlite.ConstInt(pool, llvmlite.Int32(pool), 0, "0") - - cargs: list[ast.AST | t.CPtr] | t.CPtr = cl.args - can: t.CSizeT = 0 - if cargs is not None: - can = cargs.__len__() - - # 内置强转函数: str(x)/bytes(x) → i8*, int(x) → i32 - # 等价于 (t.CChar | t.CPtr)(x) / (t.CInt32T)(x) - # 单参数:str(val) → bitcast val to i8* - # int(val) → trunc/sext val to i32 - if func_name is not None and can == 1: - if string.strcmp(func_name, "str") == 0 or string.strcmp(func_name, "bytes") == 0: - # str(x) / bytes(x) → i8* (bitcast) - cast_arg: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( - builder, pool, mod, cargs.get(0), funcs_ptr, func_count, trans) - if cast_arg is not None: - i8_ptr_ty_builtin: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, llvmlite.Int8(pool)) - return _translate_t_type_cast(pool, builder, cast_arg, i8_ptr_ty_builtin) - return None - elif string.strcmp(func_name, "int") == 0: - # int(x) → i32 - cast_arg_int: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( - builder, pool, mod, cargs.get(0), funcs_ptr, func_count, trans) - if cast_arg_int is not None: - i32_ty_builtin: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool) - return _translate_t_type_cast(pool, builder, cast_arg_int, i32_ty_builtin) - return None - - # 检测 t.XXX 类型转换: t.CUInt64T(ptr), t.CPtr(val), t.CInt(val) 等 - # 当 func 是 t.XXX 形式且 XXX 是已知类型名时,当作类型转换处理(而非函数调用) - # 支持: - # 单参数: t.CInt(val) → 目标类型 = map_t_type(func_name) - # 双参数: t.CInt(val, t.CPtr) → 目标类型 = Ptr(map_t_type(func_name)) - # t 是内部库,一旦确认为类型转换,绝不跌落到跨模块调用 FATAL 路径 - if cl.func is not None and cl.func.kind() == ast.ASTKind.Attribute: - tc_at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(cl.func) - if tc_at.value is not None and tc_at.value.kind() == ast.ASTKind.Name: - tc_mod_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(tc_at.value) - if tc_mod_nm.id is not None and string.strcmp(tc_mod_nm.id, "t") == 0: - target_ty: llvmlite.LLVMType | t.CPtr = HandlesType.map_t_type(pool, func_name) - if target_ty is not None: - tc_effective_can: t.CSizeT = can - # 双参数形式: t.CInt(val, t.CPtr) → Ptr(target_ty) - # 注意: void* 在 LLVM 中非法,CVoid* 应表示为 i8* - if can == 2: - tc_arg2_node: ast.AST | t.CPtr = cargs.get(1) - if tc_arg2_node is not None and tc_arg2_node.kind() == ast.ASTKind.Attribute: - tc_arg2_at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(tc_arg2_node) - if tc_arg2_at.attr is not None and string.strcmp(tc_arg2_at.attr, "CPtr") == 0: - if tc_arg2_at.value is not None and tc_arg2_at.value.kind() == ast.ASTKind.Name: - tc_arg2_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(tc_arg2_at.value) - if tc_arg2_nm.id is not None and string.strcmp(tc_arg2_nm.id, "t") == 0: - # CVoid* → i8*(LLVM 中 void* 表示为 i8*) - match target_ty: - case llvmlite.LLVMType.Void(): - target_ty = llvmlite.Int8(pool) - case _: - pass - target_ty = llvmlite.Ptr(pool, target_ty) - tc_effective_can = 1 - if tc_effective_can == 1: - tc_arg_node: ast.AST | t.CPtr = cargs.get(0) - if tc_arg_node is not None: - tc_arg_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( - builder, pool, mod, tc_arg_node, None, 0, trans) - if tc_arg_val is not None: - return _translate_t_type_cast(pool, builder, tc_arg_val, target_ty) - # t.XXX 类型转换已确认但不满足参数条件:返回 None,不跌落到跨模块 FATAL - return None - - # 检测 ClassName.__sizeof__() — 返回结构体大小常量(i64) - # __sizeof__ 是内置方法,不走跨模块调用路径 - # 支持: Argument.__sizeof__() 和 w32.win32file.WIN32_FIND_DATAA.__sizeof__() - if cl.func is not None and cl.func.kind() == ast.ASTKind.Attribute: - sz_at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(cl.func) - if sz_at.attr is not None and string.strcmp(sz_at.attr, "__sizeof__") == 0: - if sz_at.value is not None and can == 0: - sz_cls_name: str = None - sz_vk: int = sz_at.value.kind() - if sz_vk == ast.ASTKind.Name: - sz_cls_nm2: ast.Name | t.CPtr = (ast.Name | t.CPtr)(sz_at.value) - sz_cls_name = sz_cls_nm2.id - elif sz_vk == ast.ASTKind.Attribute: - sz_inner_at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(sz_at.value) - sz_cls_name = sz_inner_at.attr - if sz_cls_name is not None: - # 泛型类型参数 T 替换: T.__sizeof__() → int.__sizeof__() - sz_cls_name = HandlesType.resolve_generic_type_name(sz_cls_name) - # 去除模块前缀: Viper 解析器将 t.CInt 解析为 Name(id="t.CInt") - # 而非 Attribute(value=Name("t"), attr="CInt"),需要手动提取最后的类名分量 - # "t.CInt" → "CInt", "w32.win32file.WIN32_FIND_DATAA" → "WIN32_FIND_DATAA" - dot_pos: str = string.strrchr(sz_cls_name, '.') - if dot_pos is not None: - sz_cls_name = dot_pos + 1 - # 联合类型(如 AST|t.CPtr)按指针大小处理(8 字节) - # 联合类型在 TPV 中表示指针,可以指向多种类型 - # 对应 TPC 中对 BinOp/BitOr 联合类型的特殊处理 - if string.strstr(sz_cls_name, "|") is not None: - return llvmlite.const_int64(pool, 8) - # 内置类型 sizeof(int=4, str/bytes=8 指针, double=8 等) - sz_builtin: int = -1 - if string.strcmp(sz_cls_name, "int") == 0: - sz_builtin = 4 - elif string.strcmp(sz_cls_name, "str") == 0: - sz_builtin = 8 - elif string.strcmp(sz_cls_name, "bytes") == 0: - sz_builtin = 8 - elif string.strcmp(sz_cls_name, "CInt") == 0: - sz_builtin = 4 - elif string.strcmp(sz_cls_name, "CInt8T") == 0: - sz_builtin = 1 - elif string.strcmp(sz_cls_name, "CInt16T") == 0: - sz_builtin = 2 - elif string.strcmp(sz_cls_name, "CInt32T") == 0: - sz_builtin = 4 - elif string.strcmp(sz_cls_name, "CInt64T") == 0: - sz_builtin = 8 - elif string.strcmp(sz_cls_name, "CChar") == 0: - sz_builtin = 1 - elif string.strcmp(sz_cls_name, "CDouble") == 0: - sz_builtin = 8 - elif string.strcmp(sz_cls_name, "CFloat") == 0: - sz_builtin = 4 - elif string.strcmp(sz_cls_name, "CPtr") == 0: - sz_builtin = 8 - elif string.strcmp(sz_cls_name, "CSizeT") == 0: - sz_builtin = 8 - if sz_builtin >= 0: - # 注意: 必须用 const_int64 而非 ConstInt(...,"0") - # ConstInt 的 name 参数是 IR 文本表示,ValuePrint 输出时使用 Name 而非 IntVal - # 硬编码 "0" 会导致 IR 输出 i64 0 而非实际值 - return llvmlite.const_int64(pool, sz_builtin) - sz_struct_ty: llvmlite.LLVMType | t.CPtr = HandlesStruct.get_struct_type( - sz_cls_name) - if sz_struct_ty is not None: - sz_val: int = HandlesClassDef._get_type_size(sz_struct_ty) - if sz_val > 0: - return llvmlite.const_int64(pool, sz_val) - # 类型已注册但大小为 0(opaque struct 或字段链表未填充):报错终止 - fb_sz1: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb_sz1 is not None: - viperlib.snprintf(fb_sz1, 1024, - "类型 '%s' 已注册但大小为 0(字段链表未填充),立即终止编译", - sz_cls_name) - VLogger.critical(fb_sz1, "__sizeof__") - sys.exit(1) - # 类型未注册:报错终止,不静默返回 0(会导致 malloc(0)/alloc(0) 堆溢出) - fb_sz2: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb_sz2 is not None: - viperlib.snprintf(fb_sz2, 1024, - "类型 '%s' 未在结构体表中注册,无法计算大小,立即终止编译", - sz_cls_name) - VLogger.critical(fb_sz2, "__sizeof__") - sys.exit(1) - - # 检测 obj.__len__() — 返回 list 对象的 __count__ 字段(偏移 8,i64) - # __len__ 是 list[T] 的内置方法,list 是泛型类不注册 struct - # 注意: 必须用 translate_value 而非 translate_name_value,因为 len_at.value - # 可能是 Attribute 节点(如 md_ags.args),translate_name_value 只处理 Name 节点, - # 对 Attribute 会错误返回 i32 0,导致 GEP base 不是指针(base of getelementptr must be a pointer) - if cl.func is not None and cl.func.kind() == ast.ASTKind.Attribute: - len_at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(cl.func) - if len_at.attr is not None and string.strcmp(len_at.attr, "__len__") == 0: - if len_at.value is not None and can == 0: - obj_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( - builder, pool, mod, len_at.value, funcs_ptr, func_count, trans) - if obj_val is not None and obj_val.Ty is not None: - # 防御性类型检查: obj_val 必须是指针类型才能做 GEP - # 如果 translate_value 返回 i32 (如 CDefine 常量被误解析、 - # 模块属性前向引用回退为 i32),GEP base 会是 i32 而非指针, - # 导致 llc 报错 "base of getelementptr must be a pointer" - if HandlesExpr.is_ptr_type(obj_val.Ty) == 0: - return llvmlite.const_int64(pool, 0) - i64_ty_len: llvmlite.LLVMType | t.CPtr = llvmlite.Int64(pool) - # 注意: 必须用 const_int64 而非 ConstInt(...,"0") - # ConstInt 的 name 参数 "0" 会被当作 IR 文本值输出 i64 0 - # 导致 GEP 索引为 0(访问 __data__)而非 1(访问 __count__) - idx_one: llvmlite.Value | t.CPtr = llvmlite.const_int64(pool, 1) - count_ptr: llvmlite.Value | t.CPtr = llvmlite.build_gep( - builder, i64_ty_len, obj_val, idx_one) - if count_ptr is not None: - return llvmlite.build_load(builder, i64_ty_len, count_ptr) - - # 检测 len() 内置函数调用 — 转换为 strlen 调用 - # len(s) 对 str 类型调用 strlen,返回 i64 - if cl.func is not None and cl.func.kind() == ast.ASTKind.Name: - if func_name is not None and string.strcmp(func_name, "len") == 0: - if can == 1: - len_arg_node: ast.AST | t.CPtr = cargs.get(0) - if len_arg_node is not None: - len_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( - builder, pool, mod, len_arg_node, None, 0, trans) - if len_val is not None: - # 确保 strlen 在模块中有声明 - strlen_fn: llvmlite.Function | t.CPtr = find_func_in_module(mod, "strlen") - if strlen_fn is None: - i64_ty_ln: llvmlite.LLVMType | t.CPtr = llvmlite.Int64(pool) - i8_ptr_ty_ln: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, llvmlite.Int8(pool)) - strlen_fn = llvmlite.create_declare(pool, mod, "strlen", i64_ty_ln) - if strlen_fn is not None: - llvmlite.add_param(pool, strlen_fn, i8_ptr_ty_ln, "s") - # 参数类型转换为 i8* - i8_ptr_ty_ln2: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, llvmlite.Int8(pool)) - len_arg_ty: llvmlite.LLVMType | t.CPtr = llvmlite.value_get_ty(len_val) - len_coerced: llvmlite.Value | t.CPtr = len_val - if HandlesExpr.is_ptr_type(len_arg_ty) != 0: - len_coerced = llvmlite.build_bitcast(builder, len_val, i8_ptr_ty_ln2) - # 构建单参数链表并调用 strlen - len_coerced.Next = None - i64_ty_ln2: llvmlite.LLVMType | t.CPtr = llvmlite.Int64(pool) - return llvmlite.build_call(builder, "strlen", len_coerced, 1, i64_ty_ln2, 0) - - # 检测方法调用: obj.method(args) - # 当 cl.func 是 Attribute 且 obj 是已注册的结构体变量时,翻译为方法调用 - if cl.func is not None and cl.func.kind() == ast.ASTKind.Attribute: - method_at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(cl.func) - if method_at is not None and method_at.value is not None: - if method_at.value.kind() == ast.ASTKind.Name and trans is not None: - method_obj_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(method_at.value) - if method_obj_nm.id is not None: - # 查找对象变量 - obj_var: llvmlite.Value | t.CPtr = HandlesVar.lookup_var( - trans.SymTab, method_obj_nm.id) - if obj_var is not None and obj_var.Ty is not None: - # 检查是否为 Ptr(Struct(...))(结构体值变量) - # 或 Ptr(Ptr(Struct(...)))(指针变量,需 load) - match obj_var.Ty: - case llvmlite.LLVMType.Ptr(obj_struct_ty): - class_nm: str = HandlesStruct.get_class_name_by_type( - pool, obj_struct_ty) - if class_nm is not None: - return _translate_method_call( - pool, builder, mod, class_nm, func_name, - obj_var, cl, trans) - # 指针变量: alloca 类型是 Ptr(Ptr(Struct)) - # load 获取实际指针 Ptr(Struct) 后再查找 - match obj_struct_ty: - case llvmlite.LLVMType.Ptr(inner_struct_ty): - inner_nm: str = HandlesStruct.get_class_name_by_type( - pool, inner_struct_ty) - if inner_nm is not None: - obj_ptr: llvmlite.Value | t.CPtr = llvmlite.build_load( - builder, obj_struct_ty, obj_var) - if obj_ptr is not None: - return _translate_method_call( - pool, builder, mod, inner_nm, func_name, - obj_ptr, cl, trans) - # AnnotClassName 回退:联合类型简化为 Ptr(i8) 时, - # 通过原始类型注解的类名查找结构体 - var_entry: HandlesVar.VarEntry | t.CPtr = HandlesVar.lookup_var_entry( - trans.SymTab, method_obj_nm.id) - if var_entry is not None and var_entry.AnnotClassName is not None: - annot_val: str = var_entry.AnnotClassName - # 解析模块限定名 "memhub.MemBuddy" → mod_nm="memhub", cls_nm="MemBuddy" - dot_ptr: t.CChar | t.CPtr = string.strrchr(annot_val, '.') - cls_nm2: str = annot_val - mod_nm2: str = None - if dot_ptr is not None: - cls_nm2 = dot_ptr + 1 - total_len_av: t.CSizeT = string.strlen(annot_val) - cls_len_av: t.CSizeT = string.strlen(cls_nm2) - mod_len2: t.CSizeT = total_len_av - cls_len_av - 1 - mod_nm2 = pool.alloc(mod_len2 + 1) - if mod_nm2 is not None: - string.strncpy(mod_nm2, annot_val, mod_len2) - mod_nm2[mod_len2] = '\0' - # 检查结构体是否已注册 - if HandlesStruct.get_struct_type(cls_nm2) is not None: - # 结构体已注册:load obj_ptr 走方法调用 - i8_ptr_ty2: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr( - pool, llvmlite.Int8(pool)) - obj_ptr2: llvmlite.Value | t.CPtr = llvmlite.build_load( - builder, i8_ptr_ty2, obj_var) - if obj_ptr2 is not None: - return _translate_method_call( - pool, builder, mod, cls_nm2, func_name, - obj_ptr2, cl, trans) - else: - # 结构体未注册(跨模块依赖未翻译): - # 用模块名查 SHA1 构造方法调用名 - sha1_fc: str = None - if mod_nm2 is not None: - sha1_fc = _lookup_module_sha1(mod_nm2) - if sha1_fc is not None: - # 构造 "{sha1}.{cls_nm2}.{func_name}" 调用名 - mlen3: t.CSizeT = string.strlen(sha1_fc) + string.strlen(cls_nm2) + string.strlen(func_name) + 3 - mangled3: str = pool.alloc(mlen3) - if mangled3 is not None: - viperlib.snprintf(mangled3, mlen3, "%s.%s.%s", sha1_fc, cls_nm2, func_name) - # load obj_ptr (self) - i8_ptr_ty3: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr( - pool, llvmlite.Int8(pool)) - obj_ptr3: llvmlite.Value | t.CPtr = llvmlite.build_load( - builder, i8_ptr_ty3, obj_var) - if obj_ptr3 is not None: - # 构建参数链表: obj_ptr3 (self) → 其他参数 - llvmlite.value_set_next(obj_ptr3, None) - head3: llvmlite.Value | t.CPtr = obj_ptr3 - tail3: llvmlite.Value | t.CPtr = obj_ptr3 - for ai3 in range(can): - arg3: ast.AST | t.CPtr = cargs.get(ai3) - if arg3 is not None: - arg_val3: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( - builder, pool, mod, arg3, None, 0, trans) - if arg_val3 is not None: - llvmlite.value_set_next(arg_val3, None) - llvmlite.value_set_next(tail3, arg_val3) - tail3 = arg_val3 - total3: int = 1 + can - ret_ty3: llvmlite.LLVMType | t.CPtr = _infer_method_ret_ty(pool, func_name) - _ensure_method_declare(pool, mod, mangled3, ret_ty3, head3, total3) - return llvmlite.build_call(builder, mangled3, head3, total3, ret_ty3, 0) - - # ============================================================ - # 检测 self.field.method() 调用 - # - # 当 method_at.value 是 Attribute(字段访问,如 self.__pool__)时, - # 翻译字段值获取对象指针,然后走方法调用路径。 - # - # 路径1: 从字段值的 LLVM 类型获取类名(字段类型为 Ptr(Struct("MemManager"))) - # 路径2: 从字段的 AnnotClassName 回退查找(字段类型被简化为 Ptr(i8) 时) - # ============================================================ - if cl.func is not None and cl.func.kind() == ast.ASTKind.Attribute: - attr_method_at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(cl.func) - if attr_method_at is not None and attr_method_at.value is not None: - if attr_method_at.value.kind() == ast.ASTKind.Attribute and trans is not None: - inner_attr: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(attr_method_at.value) - if inner_attr is not None and inner_attr.attr is not None: - # 翻译 self.__pool__ 获取字段值(已 load 的对象指针) - field_obj: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( - builder, pool, mod, attr_method_at.value, funcs_ptr, func_count, trans) - if field_obj is not None and field_obj.Ty is not None: - field_cls_nm: str = None - # 路径1: 从字段值的 LLVM 类型获取类名 - match field_obj.Ty: - case llvmlite.LLVMType.Ptr(field_struct_ty): - field_cls_nm = HandlesStruct.get_class_name_by_type( - pool, field_struct_ty) - # 路径2: 从字段注解类名回退查找 - if field_cls_nm is None: - if inner_attr.value is not None and inner_attr.value.kind() == ast.ASTKind.Name: - inner_name_node: ast.Name | t.CPtr = (ast.Name | t.CPtr)(inner_attr.value) - if inner_name_node is not None and inner_name_node.id is not None: - inner_var: llvmlite.Value | t.CPtr = HandlesVar.lookup_var( - trans.SymTab, inner_name_node.id) - if inner_var is not None and inner_var.Ty is not None: - match inner_var.Ty: - case llvmlite.LLVMType.Ptr(field_owner_struct_ty): - field_info: HandlesStruct.FieldEntry | t.CPtr = HandlesStruct.lookup_field( - field_owner_struct_ty, inner_attr.attr) - if field_info is not None: - field_annot: str = HandlesStruct.get_field_annot_class_name(field_info) - if field_annot is not None: - dot_p: t.CChar | t.CPtr = string.strrchr(field_annot, 46) - if dot_p is not None: - field_cls_nm = dot_p + 1 - else: - field_cls_nm = field_annot - if field_cls_nm is not None: - return _translate_method_call( - pool, builder, mod, field_cls_nm, func_name, - field_obj, cl, trans) - - # ============================================================ - # 检测 list 内置方法调用: lst.get(i), lst.set(i,v), lst.pop(), lst.clear(), lst.__iter__() - # list[T] 是泛型类不注册 struct,方法调用处理器(上方)无法处理, - # 需要在此特殊处理。 - # list 结构布局 (6 字段 × 8 字节): - # __data__(0) __count__(8) __capacity__(16) __pool__(24) __elem_size__(32) __iter_index__(40) - # ============================================================ - if cl.func is not None and cl.func.kind() == ast.ASTKind.Attribute: - lm_at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(cl.func) - if lm_at is not None and lm_at.attr is not None and lm_at.value is not None: - lm_name: str = lm_at.attr - # 判断是否是 list 方法名 - lm_is_list: int = 0 - if string.strcmp(lm_name, "get") == 0: lm_is_list = 1 - elif string.strcmp(lm_name, "__getitem__") == 0: lm_is_list = 1 - elif string.strcmp(lm_name, "set") == 0: lm_is_list = 1 - elif string.strcmp(lm_name, "__setitem__") == 0: lm_is_list = 1 - elif string.strcmp(lm_name, "pop") == 0: lm_is_list = 1 - elif string.strcmp(lm_name, "clear") == 0: lm_is_list = 1 - elif string.strcmp(lm_name, "__iter__") == 0: lm_is_list = 1 - elif string.strcmp(lm_name, "append") == 0: lm_is_list = 1 - - if lm_is_list == 1 and trans is not None: - # 翻译 list 对象 - lm_obj: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( - builder, pool, mod, lm_at.value, funcs_ptr, func_count, trans) - if lm_obj is not None: - # 防御性类型检查: lm_obj 必须是指针类型才能做 GEP - # translate_value 对某些 Attribute 节点(如 ast.Arguments 的属性) - # 可能返回 i32 0 (非指针),直接 GEP 会导致 - # "base of getelementptr must be a pointer" 错误 - if lm_obj.Ty is None or HandlesExpr.is_ptr_type(lm_obj.Ty) == 0: - lm_node_kind: int = lm_at.value.kind() - fb_lm: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb_lm is not None: - viperlib.snprintf(fb_lm, 1024, - "list 方法 '%s' 的目标对象非指针 (node kind=%d)," - "translate_value 类型推断失败", - lm_name, lm_node_kind) - VLogger.critical(fb_lm, "LIST-METHOD") - return None - i64_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int64(pool) - i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool) - i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty) - - # get / __getitem__: 返回 index 处的元素 - if string.strcmp(lm_name, "get") == 0 or string.strcmp(lm_name, "__getitem__") == 0: - if can >= 1: - # 加载 __data__ (偏移 0) - g_idx0: llvmlite.Value | t.CPtr = llvmlite.ConstInt(pool, i64_ty, 0, "0") - g_dpp: llvmlite.Value | t.CPtr = llvmlite.build_gep(builder, i64_ty, lm_obj, g_idx0) - g_data: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, i8_ptr_ty, g_dpp) - # 加载 __elem_size__ (偏移 32, index 4) - g_idx4: llvmlite.Value | t.CPtr = llvmlite.ConstInt(pool, i64_ty, 4, "0") - g_epp: llvmlite.Value | t.CPtr = llvmlite.build_gep(builder, i64_ty, lm_obj, g_idx4) - g_esize: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, i64_ty, g_epp) - # 翻译 index - g_idx_node: ast.AST | t.CPtr = cargs.get(0) - g_idx_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( - builder, pool, mod, g_idx_node, None, 0, trans) - if g_data is not None and g_esize is not None and g_idx_val is not None: - g_idx_i64: llvmlite.Value | t.CPtr = HandlesExpr.coerce_to_type( - builder, g_idx_val, i64_ty) - g_offset: llvmlite.Value | t.CPtr = llvmlite.build_mul(builder, g_idx_i64, g_esize) - g_addr: llvmlite.Value | t.CPtr = llvmlite.build_gep(builder, i8_ty, g_data, g_offset) - if g_addr is not None: - return llvmlite.build_load(builder, i8_ptr_ty, g_addr) - - # set / __setitem__: 设置 index 处的元素 - elif string.strcmp(lm_name, "set") == 0 or string.strcmp(lm_name, "__setitem__") == 0: - if can >= 2: - s_idx0: llvmlite.Value | t.CPtr = llvmlite.ConstInt(pool, i64_ty, 0, "0") - s_dpp: llvmlite.Value | t.CPtr = llvmlite.build_gep(builder, i64_ty, lm_obj, s_idx0) - s_data: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, i8_ptr_ty, s_dpp) - s_idx4: llvmlite.Value | t.CPtr = llvmlite.ConstInt(pool, i64_ty, 4, "0") - s_epp: llvmlite.Value | t.CPtr = llvmlite.build_gep(builder, i64_ty, lm_obj, s_idx4) - s_esize: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, i64_ty, s_epp) - s_idx_node: ast.AST | t.CPtr = cargs.get(0) - s_val_node: ast.AST | t.CPtr = cargs.get(1) - s_idx_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( - builder, pool, mod, s_idx_node, None, 0, trans) - s_val_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( - builder, pool, mod, s_val_node, None, 0, trans) - if s_data is not None and s_esize is not None and s_idx_val is not None and s_val_val is not None: - s_idx_i64: llvmlite.Value | t.CPtr = HandlesExpr.coerce_to_type( - builder, s_idx_val, i64_ty) - s_offset: llvmlite.Value | t.CPtr = llvmlite.build_mul(builder, s_idx_i64, s_esize) - s_addr: llvmlite.Value | t.CPtr = llvmlite.build_gep(builder, i8_ty, s_data, s_offset) - if s_addr is not None: - s_val_ptr: llvmlite.Value | t.CPtr = HandlesExpr.coerce_to_type( - builder, s_val_val, i8_ptr_ty) - llvmlite.build_store(builder, s_val_ptr, s_addr) - return None - - # pop: 返回最后一个元素,count-- - elif string.strcmp(lm_name, "pop") == 0: - p_idx1: llvmlite.Value | t.CPtr = llvmlite.ConstInt(pool, i64_ty, 1, "0") - p_cpp: llvmlite.Value | t.CPtr = llvmlite.build_gep(builder, i64_ty, lm_obj, p_idx1) - p_count: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, i64_ty, p_cpp) - p_nc: llvmlite.Value | t.CPtr = llvmlite.build_sub( - builder, p_count, llvmlite.ConstInt(pool, i64_ty, 1, "0")) - llvmlite.build_store(builder, p_nc, p_cpp) - p_idx0: llvmlite.Value | t.CPtr = llvmlite.ConstInt(pool, i64_ty, 0, "0") - p_dpp: llvmlite.Value | t.CPtr = llvmlite.build_gep(builder, i64_ty, lm_obj, p_idx0) - p_data: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, i8_ptr_ty, p_dpp) - p_idx4: llvmlite.Value | t.CPtr = llvmlite.ConstInt(pool, i64_ty, 4, "0") - p_epp: llvmlite.Value | t.CPtr = llvmlite.build_gep(builder, i64_ty, lm_obj, p_idx4) - p_esize: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, i64_ty, p_epp) - if p_data is not None and p_esize is not None and p_nc is not None: - p_offset: llvmlite.Value | t.CPtr = llvmlite.build_mul(builder, p_nc, p_esize) - p_addr: llvmlite.Value | t.CPtr = llvmlite.build_gep(builder, i8_ty, p_data, p_offset) - if p_addr is not None: - return llvmlite.build_load(builder, i8_ptr_ty, p_addr) - - # clear: count = 0 - elif string.strcmp(lm_name, "clear") == 0: - c_idx1: llvmlite.Value | t.CPtr = llvmlite.ConstInt(pool, i64_ty, 1, "0") - c_cpp: llvmlite.Value | t.CPtr = llvmlite.build_gep(builder, i64_ty, lm_obj, c_idx1) - llvmlite.build_store(builder, llvmlite.ConstInt(pool, i64_ty, 0, "0"), c_cpp) - return None - - # __iter__: iter_index = 0, return self - elif string.strcmp(lm_name, "__iter__") == 0: - it_idx5: llvmlite.Value | t.CPtr = llvmlite.ConstInt(pool, i64_ty, 5, "0") - it_ipp: llvmlite.Value | t.CPtr = llvmlite.build_gep(builder, i64_ty, lm_obj, it_idx5) - llvmlite.build_store(builder, llvmlite.ConstInt(pool, i64_ty, 0, "0"), it_ipp) - return lm_obj - - # append: 直接调用 list.append(self, item) - # append 需要容量检查和内存重分配,逻辑复杂,直接调用 _list.py 中的实现 - elif string.strcmp(lm_name, "append") == 0: - if can >= 1: - ap_sha1: str = _lookup_module_sha1("_list") - if ap_sha1 is not None: - ap_mlen: t.CSizeT = string.strlen(ap_sha1) + 13 - ap_mangled: str = pool.alloc(ap_mlen) - if ap_mangled is not None: - viperlib.snprintf(ap_mangled, ap_mlen, "%s.list.append", ap_sha1) - ap_item_node: ast.AST | t.CPtr = cargs.get(0) - ap_item_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( - builder, pool, mod, ap_item_node, None, 0, trans) - if ap_item_val is not None: - llvmlite.value_set_next(lm_obj, None) - llvmlite.value_set_next(ap_item_val, None) - llvmlite.value_set_next(lm_obj, ap_item_val) - ap_ret_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool) - _ensure_method_declare(pool, mod, ap_mangled, ap_ret_ty, lm_obj, 2) - return llvmlite.build_call(builder, ap_mangled, lm_obj, 2, ap_ret_ty, 0) - - # 获取关键字参数 - keywords: list[ast.AST | t.CPtr] | t.CPtr = cl.keywords - kw_count: t.CSizeT = 0 - if keywords is not None: - kw_count = keywords.__len__() - - # 检查是否是结构体构造函数: Point() / Point(10, 20) / Point(x=10, y=20) - # 命名空间隔离:严格模式下检查结构体可见性 - # - 裸名 Class(): 需要 from X import Class 或本地定义 - # - 模块限定 Module.Class(): 需要 import Module - # 用 find_struct_by_module 规避跨模块同名 find_struct 找错 - struct_ty: llvmlite.LLVMType | t.CPtr = None - gen_ctor_entry: HandlesStruct.StructEntry | t.CPtr = None - vis: int = HandlesStruct.is_struct_visible(func_name) - if vis != 0: - if trans is not None: - gen_ctor_entry = HandlesStruct.find_struct_by_module(func_name, trans.ModuleSha1) - if gen_ctor_entry is None: - gen_ctor_entry = HandlesStruct.find_struct(func_name) - if gen_ctor_entry is not None: - struct_ty = gen_ctor_entry.Ty - elif trans is not None and cl.func is not None and cl.func.kind() == ast.ASTKind.Attribute: - at_qc: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(cl.func) - if at_qc.value is not None and at_qc.value.kind() == ast.ASTKind.Name: - mod_nm_qc: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at_qc.value) - imp_ok: int = HandlesImports.is_module_imported(trans._imported_modules, mod_nm_qc.id) - if imp_ok != 0: - if trans is not None: - gen_ctor_entry = HandlesStruct.find_struct_by_module(func_name, trans.ModuleSha1) - if gen_ctor_entry is None: - gen_ctor_entry = HandlesStruct.find_struct(func_name) - if gen_ctor_entry is not None: - struct_ty = gen_ctor_entry.Ty - if struct_ty is not None: - if can == 0 and kw_count == 0: - # OOP 结构体:即使无参数也调用 __before_init__ - # 用 gen_ctor_entry 规避跨模块同名 find_struct 找错 - ctor_is_oop: int = 0 - if gen_ctor_entry is not None: - ctor_is_oop = gen_ctor_entry.IsOOP - if ctor_is_oop != 0: - return _translate_struct_ctor( - pool, builder, mod, struct_ty, func_name, cargs, 0, trans) - # 普通结构体:检查是否有默认值(用 entry 直接访问) - gen_has_defaults: int = 0 - if gen_ctor_entry is not None: - for gdi in range(gen_ctor_entry.FieldCount): - gdf: HandlesStruct.FieldEntry | t.CPtr = HandlesStruct._get_field_entry( - gen_ctor_entry, gdi) - if gdf is not None and gdf.DefaultVal is not None: - gen_has_defaults = 1 - break - else: - gen_has_defaults = HandlesStruct.struct_has_defaults(func_name) - if gen_has_defaults == 1: - # 有默认值:走构造函数路径应用默认值 - return _translate_struct_ctor( - pool, builder, mod, struct_ty, func_name, cargs, 0, trans) - # 无默认值:返回 zeroinitializer - ret: llvmlite.Value | t.CPtr = llvmlite.ConstZero(pool, struct_ty) - return ret - if kw_count > 0: - # 有关键字参数:按字段名赋值 - return _translate_struct_ctor_kw( - pool, builder, mod, struct_ty, func_name, cargs, can, - keywords, kw_count, trans) - # 仅位置参数:按字段顺序构建 - return _translate_struct_ctor( - pool, builder, mod, struct_ty, func_name, cargs, can, trans) - - # REnum 变体构造检测: ClassName.VariantName(args...) - # 如 LLVMType.Int(1) → 构造 LLVMType 的 Int 变体 - # 必须在跨模块调用查找之前,否则 ClassName 会被误判为模块名 - # 对应 TPC HandlesExprCall.py:585-644 的三条检测路径之一 - if cl.func is not None and cl.func.kind() == ast.ASTKind.Attribute: - rc_at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(cl.func) - if rc_at.value is not None and rc_at.value.kind() == ast.ASTKind.Name: - rc_cls_node: ast.Name | t.CPtr = (ast.Name | t.CPtr)(rc_at.value) - if rc_cls_node.id is not None: - rc_cls_name: str = rc_cls_node.id - # 检查 ClassName 是否是已注册的 REnum 类 - if HandlesClassDef._is_renum_class_name(rc_cls_name) != 0: - # 在该 REnum 类中查找变体名 func_name - rc_tag: int = HandlesClassDef._lookup_renum_variant_in_class( - rc_cls_name, func_name) - if rc_tag >= 0: - return _translate_renum_construct( - pool, builder, mod, rc_cls_name, func_name, - rc_tag, cargs, can, trans) - - # 查找函数:优先从函数表按裸名精确匹配(同模块函数), - # 再从模块函数链表按后缀匹配(SHA1 前缀名)。 - # stubs 在翻译后才注入,翻译时跨模块函数 found_func 通常为 None, - # 此时根据函数名推断 includes 库函数的返回类型(如 strchr 返回 i8*) - # 如果调用方未传 funcs_ptr/func_count(如 AnnAssign 路径),从 trans 获取 - actual_funcs: HandlesExprCall.FuncEntry | t.CPtr = funcs_ptr - actual_func_count: int = func_count - if actual_funcs is None and trans is not None: - actual_funcs = trans._funcs - actual_func_count = trans._func_count - found_func: llvmlite.Function | t.CPtr = find_func_in_module(mod, func_name) - # C 库函数裸名调用支持:若模块中找不到且是已知 C 库函数,自动创建 declare - # 对应 TPC 的 _C_LIB_FUNCS 机制,支持 memset/memmove/memcmp/strcmp 等裸名调用 - if found_func is None and cl.func is not None and cl.func.kind() == ast.ASTKind.Name: - found_func = _ensure_c_lib_declare(pool, mod, func_name) - # 使用访问器绕过 stub 类型限制 - found_ret_ty: llvmlite.LLVMType | t.CPtr = None - found_params: t.CPtr = None - if found_func is not None: - found_ret_ty = llvmlite.function_get_ret_ty(found_func) - found_params = llvmlite.function_get_params(found_func) - if found_ret_ty is not None: - call_ret_ty: llvmlite.LLVMType | t.CPtr = found_ret_ty - else: - call_ret_ty = _infer_external_func_ret_ty(pool, func_name) - - # 如果模块中找不到函数,检查是否是变量(闭包调用) - if found_func is None: - closure_ptr: llvmlite.Value | t.CPtr = HandlesVar.lookup_var(trans.SymTab, func_name) - if closure_ptr is not None: - return translate_closure_call(pool, builder, mod, closure_ptr, - cargs, can) - - # 翻译参数并链接 - # 有关键字参数且找到函数定义时,按参数名匹配 - if kw_count > 0 and found_func is not None and found_params is not None: - return _translate_call_with_kwargs( - pool, builder, mod, func_name, found_func, - cargs, can, keywords, kw_count, trans) - - head: llvmlite.Value | t.CPtr = None - tail: llvmlite.Value | t.CPtr = None - # memcpy 专用: 收集前三个 Value 的独立引用(避免共享 alloca 对象的 Next 被污染) - mc_dst2: llvmlite.Value | t.CPtr = None - mc_src2: llvmlite.Value | t.CPtr = None - mc_num2: llvmlite.Value | t.CPtr = None - for ai in range(can): - arg: ast.AST | t.CPtr = cargs.get(ai) - if arg is not None: - arg_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( - builder, pool, mod, arg, None, 0, trans) - if arg_val is not None: - # 参数类型提升:当 found_func 为 None(stub 未注入)时, - # 根据外部函数签名推断期望类型,提升字面量(如 i32→i64) - # 避免 declare(i64) 与 call(i32) 类型不匹配 - if found_func is None and arg_val.Ty is not None: - ext_param_ty: llvmlite.LLVMType | t.CPtr = _get_external_func_param_ty( - pool, func_name, ai) - if ext_param_ty is not None: - val_bits_ap: int = HandlesExpr.get_llvm_type_bits(arg_val.Ty) - tgt_bits_ap: int = HandlesExpr.get_llvm_type_bits(ext_param_ty) - if val_bits_ap != 0 and tgt_bits_ap != 0 and val_bits_ap != tgt_bits_ap: - if val_bits_ap == 1 and val_bits_ap < tgt_bits_ap: - arg_val = llvmlite.build_zext(builder, arg_val, ext_param_ty) - else: - arg_val = HandlesExpr.coerce_to_type(builder, arg_val, ext_param_ty) - arg_val.Next = None - if head is None: - head = arg_val - else: - tail.Next = arg_val - tail = arg_val - # memcpy 专用: 保存前三个参数的独立引用 - if ai == 0: - mc_dst2 = arg_val - elif ai == 1: - mc_src2 = arg_val - elif ai == 2: - mc_num2 = arg_val - - # 默认参数填充:当实参数量 < 形参数量时,用默认值填充缺失参数 - # defaults 数组右对齐到 args:defaults[0] 对应 args[offset],offset = param_count - default_count - if can > 0 or (can == 0 and cargs is not None): - df_defaults: t.CVoid | t.CPtr = None - df_default_count: int = 0 - df_param_count: int = 0 - # 先从当前模块函数表查找 FuncEntry - if trans is not None and trans._funcs is not None: - df_entry: FuncEntry | t.CPtr = find_func_entry_in_table( - trans._funcs, trans._func_count, func_name) - if df_entry is not None: - df_defaults = df_entry.Defaults - df_default_count = df_entry.DefaultCount - df_param_count = df_entry.ParamCount - # 如果当前模块没有,从全局默认参数表查找(跨模块) - if df_defaults is None: - gd_entry: FuncDefaultsEntry | t.CPtr = find_func_defaults(func_name) - if gd_entry is not None: - df_defaults = gd_entry.Defaults - df_default_count = gd_entry.DefaultCount - df_param_count = gd_entry.ParamCount - # 填充缺失参数 - if df_defaults is not None and df_default_count > 0 and can < df_param_count: - df_offset: int = df_param_count - df_default_count - df_di: int = 0 - while df_di < df_default_count: - df_param_idx: int = df_offset + df_di - if df_param_idx >= can: - df_defaults_list: list[ast.AST | t.CPtr] | t.CPtr = (list[ast.AST | t.CPtr] | t.CPtr)(t.CVoid(t.CUInt64T(df_defaults), t.CPtr)) - df_default_node: ast.AST | t.CPtr = df_defaults_list.get(df_di) - if df_default_node is not None: - df_arg_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( - builder, pool, mod, df_default_node, None, 0, trans) - if df_arg_val is not None: - df_arg_val.Next = None - if head is None: - head = df_arg_val - else: - tail.Next = df_arg_val - tail = df_arg_val - df_di += 1 - - # 使用模块中的实际函数名(可能带 SHA1 前缀,如 "83210a72e829a086.atoi") - # t.CExtern/t.State/t.CExport 函数不加 SHA1 前缀,使用裸名 - # declare 和 define 统一用 found_func.Name: - # - 普通函数的 declare/define 都带 SHA1 前缀(forward_declare_functions 和 stub 注入都用 mangled_name) - # - t.CExtern/t.State/t.CExport 函数的 declare/define 都用裸名 - # 旧逻辑(IsDeclared==1 时用 func_name 裸名)是错误的:stub 注入的 declare Name 已带 SHA1 前缀, - # 用裸名会导致 call @_PathToModuleName 而 define 是 @"sha1._PathToModuleName",链接报 undefined reference - call_name: str = func_name - # 原始函数名(别名导入时记录,如 from X import parse as json_parse → orig_func_name="parse") - # 用于在别名处理后重新推断返回类型,避免 _infer_external_func_ret_ty 用别名匹配失败 - orig_func_name: str = None - if found_func is not None: - found_name: t.CChar | t.CPtr = llvmlite.function_get_name(found_func) - if found_name is not None: - call_name = found_name - else: - # 跨模块函数调用:found_func 为 None 时,检查是否是模块限定调用 - # 如 string.strchr(...) → @{sha1_of_string}.strchr - if cl.func is not None and cl.func.kind() == ast.ASTKind.Attribute: - xmod_at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(cl.func) - if xmod_at.value is not None and xmod_at.value.kind() == ast.ASTKind.Name: - xmod_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(xmod_at.value) - if xmod_nm.id is not None: - mod_sha1: str = _lookup_module_sha1(xmod_nm.id) - if mod_sha1 is not None: - # 检查是否是 re-export 函数(如 ast._lexer_init 实际定义在 ast.lexer) - reexport_src: str = HandlesImports.lookup_reexport(mod_sha1, func_name) - if reexport_src is not None: - reexport_sha1: str = _lookup_module_sha1(reexport_src) - if reexport_sha1 is not None: - mod_sha1 = reexport_sha1 - # CExport 函数定义用裸名(@strlen),跨模块调用需用裸名而非 @{sha1}.func - if is_cexport_func(mod_sha1, func_name) != 0: - call_name = func_name - else: - mangled_len: t.CSizeT = string.strlen(mod_sha1) + string.strlen(func_name) + 2 - mangled: str = pool.alloc(mangled_len) - if mangled is not None: - viperlib.snprintf(mangled, mangled_len, "%s.%s", mod_sha1, func_name) - call_name = mangled - else: - # t 和 c 是内部库,豁免 SHA1 查找:使用裸名调用 - if string.strcmp(xmod_nm.id, "t") == 0 or string.strcmp(xmod_nm.id, "c") == 0: - call_name = func_name - else: - # Bug 修复: 先检查是否是已导入的模块名(如 BuildPipeline.run_pipeline) - # 如果是已导入模块但 SHA1 未注册,说明该模块未被编译(如 Phase2 未扫描到), - # 应该立即报错,而不是错误地走 from_imports 查找(会被 star import 回退误导) - is_imported_mod: int = 0 - if trans is not None and trans._imported_modules is not None: - is_imported_mod = HandlesImports.is_module_imported( - trans._imported_modules, xmod_nm.id) - if is_imported_mod != 0: - # 别名导入(import X as Y):Y 在 _imported_modules 中, - # 但 _lookup_module_sha1("Y") 精确匹配失败(mod_arr 只存文件名)。 - # 先尝试 from_imports 查找别名→完整模块名→后缀匹配 SHA1。 - # allow_star_fallback=0 避免被 star import 回退误导。 - alias_sha1: str = None - if trans is not None and trans._from_imports is not None: - alias_sha1 = _lookup_mod_sha1(pool, trans._from_imports, xmod_nm.id, 0) - if alias_sha1 is not None: - if is_cexport_func(alias_sha1, func_name) != 0: - call_name = func_name - else: - AliasMangledLen: t.CSizeT = string.strlen(alias_sha1) + string.strlen(func_name) + 2 - alias_mangled: str = pool.alloc(AliasMangledLen) - if alias_mangled is not None: - viperlib.snprintf(alias_mangled, AliasMangledLen, "%s.%s", alias_sha1, func_name) - call_name = alias_mangled - else: - # 已导入模块但 SHA1 未注册:该模块未被编译,立即报错 - err_msg_imp: t.CChar | t.CPtr = pool.alloc(256) - if err_msg_imp is not None: - viperlib.snprintf(err_msg_imp, 256, "模块 '%s' 已导入但 SHA1 未注册(该模块未被编译)", xmod_nm.id) - HandlesType.fatal_error(xmod_nm, err_msg_imp) - HandlesType.fatal_error(xmod_nm, "已导入模块 SHA1 未注册") - else: - # 检查是否是通过 from import 导入的名称(如 from .__types import LLVMType) - # LLVMType.Ptr(ty) 中 LLVMType 是类名不是模块名, - # 但 Ptr 是 __types 模块的模块级函数 - # 禁用 star import 回退:xmod_nm.id 是明确名称,不应回退到 star import 模块 - from_sha1: str = None - if trans is not None and trans._from_imports is not None: - from_sha1 = _lookup_mod_sha1(pool, trans._from_imports, xmod_nm.id, 0) - if from_sha1 is not None: - # CExport 函数定义用裸名,跨模块调用需用裸名 - if is_cexport_func(from_sha1, func_name) != 0: - call_name = func_name - else: - fmangled_len: t.CSizeT = string.strlen(from_sha1) + string.strlen(func_name) + 2 - fmangled: str = pool.alloc(fmangled_len) - if fmangled is not None: - viperlib.snprintf(fmangled, fmangled_len, "%s.%s", from_sha1, func_name) - call_name = fmangled - else: - err_msg2: t.CChar | t.CPtr = pool.alloc(256) - if err_msg2 is not None: - viperlib.snprintf(err_msg2, 256, "跨模块调用 '%s.%s' 找不到模块 SHA1", xmod_nm.id, func_name) - HandlesType.fatal_error(xmod_nm, err_msg2) - HandlesType.fatal_error(xmod_nm, "跨模块调用找不到模块 SHA1") - else: - # 裸名调用(非 Attribute):检查 from_imports - # 裸名调用允许 star import 回退:from stdint import * 导入的名称(如 BYTEPTR)需要通过 star import 查找 - if trans is not None and trans._from_imports is not None: - bare_sha1: str = _lookup_mod_sha1(pool, trans._from_imports, func_name, 1) - if bare_sha1 is not None: - # 别名处理: from X import Y as Z → 调用 Z 时需用 Y 作为源模块函数名 - # 例如 from json.__parser import parse as json_parse → 修饰为 SHA1.parse 而非 SHA1.json_parse - bare_orig: str = HandlesImports.lookup_from_import_original( - trans._from_imports, func_name) - bare_func_name: str = func_name - if bare_orig is not None: - # bare_orig 指向 from_imports 内部缓冲区,未 null 终止 - # 需复制到独立缓冲区(截断于空格或 null) - bo_len: t.CSizeT = 0 - while bare_orig[bo_len] != ' ' and bare_orig[bo_len] != '\0': - bo_len += 1 - bo_buf: str = pool.alloc(bo_len + 1) - if bo_buf is not None: - for bo_i in range(bo_len): - bo_buf[bo_i] = bare_orig[bo_i] - bo_buf[bo_len] = '\0' - bare_func_name = bo_buf - # 记录原始函数名,供后续重新推断返回类型 - # 例如 from json.__parser import parse as json_parse - # func_name="json_parse", bare_func_name="parse" - # _infer_external_func_ret_ty 用 "parse" 能正确匹配,用 "json_parse" 则返回默认 i32 - orig_func_name = bare_func_name - if is_cexport_func(bare_sha1, bare_func_name) != 0: - call_name = bare_func_name - else: - bare_mangled_len: t.CSizeT = string.strlen(bare_sha1) + string.strlen(bare_func_name) + 2 - bare_mangled: str = pool.alloc(bare_mangled_len) - if bare_mangled is not None: - viperlib.snprintf(bare_mangled, bare_mangled_len, "%s.%s", bare_sha1, bare_func_name) - call_name = bare_mangled - else: - err_msg3: t.CChar | t.CPtr = pool.alloc(256) - if err_msg3 is not None: - viperlib.snprintf(err_msg3, 256, "裸名调用 '%s' 未定义且未导入", func_name) - HandlesType.fatal_error(node, err_msg3) - HandlesType.fatal_error(node, "裸名调用未定义且未导入") - else: - err_msg4: t.CChar | t.CPtr = pool.alloc(256) - if err_msg4 is not None: - viperlib.snprintf(err_msg4, 256, "裸名调用 '%s' 未定义且未导入", func_name) - HandlesType.fatal_error(node, err_msg4) - HandlesType.fatal_error(node, "裸名调用未定义且未导入") - - # 直接调用 - # memcpy → @llvm.memcpy 内联函数(避免 monomorphization 跨模块 @memcpy 声明缺失) - if func_name == "memcpy" and can >= 3: - return _emit_llvm_memcpy_intrinsic(pool, builder, mod, mc_dst2, mc_src2, mc_num2) - # 别名导入重新推断返回类型: - # from X import parse as json_parse → func_name="json_parse" 时 _infer_external_func_ret_ty 返回默认 i32 - # 用 orig_func_name="parse" 重新推断,能正确匹配返回 i8*(JsonValue*) - # 避免指针被截断为 i32 后 inttoptr 丢失高 32 位导致崩溃 - if orig_func_name is not None and orig_func_name != func_name: - re_inferred_ty: llvmlite.LLVMType | t.CPtr = _infer_external_func_ret_ty(pool, orig_func_name) - if re_inferred_ty is not None: - call_ret_ty = re_inferred_ty - # 跨模块调用:创建 declare 声明,避免 llc 报 undefined value - _ensure_method_declare(pool, mod, call_name, call_ret_ty, head, can) - return llvmlite.build_call(builder, call_name, head, can, call_ret_ty, 0) - -# ============================================================ -# 翻译闭包调用 — 通过闭包指针间接调用 -# -# 闭包结构: {i8* fn_ptr, i8* env_ptr} (16 字节) -# 调用过程: -# 1. load closure_ptr 从变量 alloca -# 2. load fn_ptr 从 offset 0 -# 3. load env_ptr 从 offset 8 -# 4. bitcast fn_ptr to i32 (i8*)* -# 5. call i32 %fn_typed(i8* %env_ptr) -# ============================================================ -def translate_closure_call(pool: memhub.MemBuddy | t.CPtr, - builder: llvmlite.IRBuilder | t.CPtr, - mod: llvmlite.LLVMModule | t.CPtr, - closure_alloca: llvmlite.Value | t.CPtr, - cargs: list[ast.AST | t.CPtr] | t.CPtr, - can: t.CSizeT) -> llvmlite.Value | t.CPtr: - """通过闭包指针间接调用""" - if builder is None or closure_alloca is None: - return None - - i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool) - i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty) - i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool) - - # 1. 加载闭包指针 (i8*) - closure_ptr: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, i8_ptr_ty, closure_alloca) - if closure_ptr is None: - return None - - # 2. 加载 fn_ptr (offset 0): bitcast to i8**, load i8* - fn_ptr_addr: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(builder, closure_ptr, llvmlite.Ptr(pool, i8_ptr_ty)) - if fn_ptr_addr is None: - return None - fn_raw: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, i8_ptr_ty, fn_ptr_addr) - if fn_raw is None: - return None - - # 3. 加载 env_ptr (offset 8): GEP i8, closure, 8; load i8* - eight_val: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, 8) - env_addr: llvmlite.Value | t.CPtr = llvmlite.build_gep(builder, i8_ty, closure_ptr, eight_val) - if env_addr is None: - return None - env_ptr: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, i8_ptr_ty, env_addr) - if env_ptr is None: - return None - - # 4. bitcast fn_raw to i32 (i8*)* - param_node: llvmlite.ParamNode | t.CPtr = llvmlite.new_param_node(pool, i8_ptr_ty) - func_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Func(pool, i32_ty, param_node, 1) - func_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, func_ty) - fn_typed: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(builder, fn_raw, func_ptr_ty) - if fn_typed is None: - return None - - # 5. 间接调用: call i32 %fn_typed(i8* %env_ptr) - env_ptr.Next = None - return llvmlite.build_call_indirect(builder, fn_typed, env_ptr, 1, i32_ty) - -# ============================================================ -# 翻译 printf 调用 — 模块级版本 -# ============================================================ -def translate_printf_call(pool: memhub.MemBuddy | t.CPtr, - builder: llvmlite.IRBuilder | t.CPtr, - mod: llvmlite.LLVMModule | t.CPtr, - cl: ast.Call | t.CPtr, - trans: HT.Translator | t.CPtr = None): - """翻译 printf 调用(特殊处理格式字符串)""" - cargs: list[ast.AST | t.CPtr] | t.CPtr = cl.args - if cargs is None: - return - can: t.CSizeT = cargs.__len__() - if can == 0: - return - - arg0: ast.AST | t.CPtr = cargs.get(0) - if arg0 is None: - return - - fmt_str: str = None - arg0_kind: int = arg0.kind() - if arg0_kind == ast.ASTKind.Constant: - cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(arg0) - if cn.const_kind == ast.CONST_STR: - fmt_str = cn.str_val - - if fmt_str is None: - return - - fmt_ptr: llvmlite.Value | t.CPtr = HandlesExpr.create_global_string( - builder, pool, mod, fmt_str, trans) - if fmt_ptr is None: - return - - i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool) - - # 翻译额外参数并链接 - prev: llvmlite.Value | t.CPtr = fmt_ptr - for ai in range(1, can): - arg: ast.AST | t.CPtr = cargs.get(ai) - if arg is not None: - arg_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( - builder, pool, mod, arg, None, 0, trans) - if arg_val is not None: - # C ABI integer promotion: i8/i16 → i32(printf 变参函数要求) - arg_bits: int = HandlesExpr.get_llvm_type_bits(arg_val.Ty) - if arg_bits != 0 and arg_bits < 32: - arg_val = HandlesExpr.coerce_to_type(builder, arg_val, i32_ty) - # C ABI float promotion: float → double(printf 变参函数要求) - arg_fbits: int = HandlesExpr.get_llvm_float_bits(arg_val.Ty) - if arg_fbits != 0 and arg_fbits < 64: - double_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Double(pool) - arg_val = HandlesExpr.coerce_to_type(builder, arg_val, double_ty) - arg_val.Next = None - prev.Next = arg_val - prev = arg_val - prev.Next = None - - # is_variadic=1: 生成带显式函数类型签名的 call(如 call i32 (i8*, ...) @printf), - # 让 llc 识别为 variadic 调用,生成正确的 Win64 ABI 代码(浮点参数同时传 XMM 和整数寄存器) - llvmlite.build_call(builder, "printf", fmt_ptr, can, i32_ty, 1) - -# ============================================================ -# FuncEntry 结构体(用于函数表) -# ============================================================ -@t.NoVTable -class FuncEntry: - """函数表条目""" - Name: str - Func: llvmlite.Function | t.CPtr - Defaults: t.CVoid | t.CPtr # defaults 列表节点指针 (list[AST | CPtr]),None=无默认值 - DefaultCount: int # 默认值数量 - ParamCount: int # 形参数量(不含 self) - -# ============================================================ -# 初始化函数表 -# ============================================================ -def init_func_table(pool: memhub.MemBuddy | t.CPtr, - max_count: int) -> FuncEntry | t.CPtr: - """分配并清零函数表数组""" - size: t.CSizeT = max_count * FuncEntry.__sizeof__() - funcs_ptr: FuncEntry | t.CPtr = pool.alloc(size) - if funcs_ptr is not None: - string.memset(funcs_ptr, 0, size) - return funcs_ptr - -# ============================================================ -# 查找函数 -# ============================================================ -def find_func_in_table(funcs: FuncEntry | t.CPtr, - func_count: int, - name: str) -> llvmlite.Function | t.CPtr: - """在函数表中按名称查找,返回 Function 指针或 None""" - if name is None or funcs is None: - return None - entry_size: t.CSizeT = FuncEntry.__sizeof__() - for i in range(func_count): - entry_addr: t.CUInt64T = t.CUInt64T(funcs) + i * entry_size - entry: FuncEntry | t.CPtr = (FuncEntry | t.CPtr)(t.CVoid(entry_addr, t.CPtr)) - if entry.Name is not None: - if string.strcmp(entry.Name, name) == 0: - return entry.Func - return None - -# ============================================================ -# 添加函数到函数表 -# ============================================================ -def add_func_to_table(funcs: FuncEntry | t.CPtr, - func_count: int, - name: str, - func: llvmlite.Function | t.CPtr, - max_count: int, - defaults: t.CVoid | t.CPtr = None, - default_count: int = 0, - param_count: int = 0) -> int: - """添加函数到函数表,返回 0 成功 - - Args: - defaults: ast.Arguments.defaults 列表节点指针,None=无默认值 - default_count: 默认值数量(len(defaults)) - param_count: 形参数量(不含 self,len(args.args)) - """ - if name is None or func is None or funcs is None: - return 1 - if func_count >= max_count: - return 1 - entry_size: t.CSizeT = FuncEntry.__sizeof__() - entry_addr: t.CUInt64T = t.CUInt64T(funcs) + func_count * entry_size - entry: FuncEntry | t.CPtr = (FuncEntry | t.CPtr)(t.CVoid(entry_addr, t.CPtr)) - entry.Name = name - entry.Func = func - entry.Defaults = defaults - entry.DefaultCount = default_count - entry.ParamCount = param_count - # 同时注册到全局函数表(供跨模块 vtable 初始化查找) - _register_global_func(name, func) - # 同时注册到全局默认参数表(供跨模块调用时填充默认值) - if default_count > 0: - _register_global_defaults(name, defaults, default_count, param_count) - return 0 - -# ============================================================ -# 全局函数注册表(跨模块函数查找) -# -# 所有模块翻译的函数都会注册到此表(通过 add_func_to_table 自动注册)。 -# 主要用途: vtable 初始化时查找跨模块继承方法的 Function 对象, -# 以获取函数类型信息构造 bitcast 字符串。 -# ============================================================ -GLOBAL_FUNC_MAX: t.CDefine = 8192 -_global_funcs: FuncEntry | t.CPtr = None -_global_func_count: int = 0 - -def _init_global_func_table() -> int: - """初始化全局函数表(用 stdlib.malloc 分配,生命周期=整个程序)""" - global _global_funcs - global _global_func_count - if _global_funcs is not None: - return 1 - size: t.CSizeT = GLOBAL_FUNC_MAX * FuncEntry.__sizeof__() - _global_funcs = stdlib.malloc(size) - if _global_funcs is None: - return 0 - string.memset(_global_funcs, 0, size) - _global_func_count = 0 - return 1 - -def _register_global_func(name: str, func: llvmlite.Function | t.CPtr) -> int: - """注册函数到全局表(已存在则跳过),返回 0 成功 - - 直接操作全局表,不调用 add_func_to_table,避免递归。 - """ - global _global_func_count - if name is None or func is None: - return 1 - if _init_global_func_table() == 0: - return 1 - # 已存在则跳过(避免重复) - if find_func_in_table(_global_funcs, _global_func_count, name) is not None: - return 0 - if _global_func_count >= GLOBAL_FUNC_MAX: - return 1 - # 直接写入全局表(不调用 add_func_to_table,避免递归) - entry_size: t.CSizeT = FuncEntry.__sizeof__() - entry_addr: t.CUInt64T = t.CUInt64T(_global_funcs) + _global_func_count * entry_size - entry: FuncEntry | t.CPtr = (FuncEntry | t.CPtr)(t.CVoid(entry_addr, t.CPtr)) - entry.Name = name - entry.Func = func - _global_func_count += 1 - return 0 - -def find_func_global(name: str) -> llvmlite.Function | t.CPtr: - """在全局函数表中按名称查找,返回 Function 指针或 None""" - if name is None or _global_funcs is None: - return None - return find_func_in_table(_global_funcs, _global_func_count, name) - - -# ============================================================ -# 全局默认参数注册表(跨模块默认参数填充) -# -# 独立于 _global_funcs,因为 _register_global_func 可能在 -# add_func_to_table 之前被调用(如 stub 注入),此时 defaults 还不可用。 -# ============================================================ -GLOBAL_DEFAULTS_MAX: t.CDefine = 4096 - -@t.NoVTable -class FuncDefaultsEntry: - """默认参数表条目""" - Name: str - Defaults: t.CVoid | t.CPtr # defaults 列表节点指针 (list[AST | CPtr]) - DefaultCount: int - ParamCount: int # 形参数量(不含 self) - -_global_defaults: FuncDefaultsEntry | t.CPtr = None -_global_defaults_count: int = 0 - -def _init_global_defaults_table() -> int: - """初始化全局默认参数表""" - global _global_defaults - global _global_defaults_count - if _global_defaults is not None: - return 1 - size: t.CSizeT = GLOBAL_DEFAULTS_MAX * FuncDefaultsEntry.__sizeof__() - _global_defaults = stdlib.malloc(size) - if _global_defaults is None: - return 0 - string.memset(_global_defaults, 0, size) - _global_defaults_count = 0 - return 1 - -def _register_global_defaults(name: str, - defaults: t.CVoid | t.CPtr, - default_count: int, - param_count: int) -> int: - """注册函数默认参数到全局表,返回 0 成功""" - global _global_defaults_count - if name is None or defaults is None: - return 1 - if _init_global_defaults_table() == 0: - return 1 - # 已存在则跳过 - if find_func_defaults(name) is not None: - return 0 - if _global_defaults_count >= GLOBAL_DEFAULTS_MAX: - return 1 - entry_size: t.CSizeT = FuncDefaultsEntry.__sizeof__() - entry_addr: t.CUInt64T = t.CUInt64T(_global_defaults) + _global_defaults_count * entry_size - entry: FuncDefaultsEntry | t.CPtr = (FuncDefaultsEntry | t.CPtr)(t.CVoid(entry_addr, t.CPtr)) - entry.Name = name - entry.Defaults = defaults - entry.DefaultCount = default_count - entry.ParamCount = param_count - _global_defaults_count += 1 - return 0 - -def find_func_defaults(name: str) -> FuncDefaultsEntry | t.CPtr: - """按函数名查找默认参数信息,返回 FuncDefaultsEntry 或 None""" - if name is None or _global_defaults is None: - return None - entry_size: t.CSizeT = FuncDefaultsEntry.__sizeof__() - i: int = 0 - while i < _global_defaults_count: - entry_addr: t.CUInt64T = t.CUInt64T(_global_defaults) + i * entry_size - entry: FuncDefaultsEntry | t.CPtr = (FuncDefaultsEntry | t.CPtr)(t.CVoid(entry_addr, t.CPtr)) - if entry.Name is not None: - if string.strcmp(entry.Name, name) == 0: - return entry - i += 1 - return None - -def find_func_entry_in_table(funcs: FuncEntry | t.CPtr, - func_count: int, - name: str) -> FuncEntry | t.CPtr: - """在函数表中按名称查找,返回完整 FuncEntry 或 None""" - if name is None or funcs is None: - return None - entry_size: t.CSizeT = FuncEntry.__sizeof__() - i: int = 0 - while i < func_count: - entry_addr: t.CUInt64T = t.CUInt64T(funcs) + i * entry_size - entry: FuncEntry | t.CPtr = (FuncEntry | t.CPtr)(t.CVoid(entry_addr, t.CPtr)) - if entry.Name is not None: - if string.strcmp(entry.Name, name) == 0: - return entry - i += 1 - return None - -# ============================================================ -# ExprCallHandle - 函数调用处理器(Mixin 继承模式) -# -# HandleCall / HandlePrintfCall 提供 trans 接口 -# ============================================================ -@t.NoVTable -class ExprCallHandle(HandlesBase.Mixin): - """函数调用处理器:继承 Mixin 获得 Trans 回指针""" - - def __init__(self, trans: HT.Translator | t.CPtr): - self.Trans = trans - - # ============================================================ - # HandleCall - 翻译函数调用,返回 call 结果 Value - # ============================================================ - def HandleCall(self, node: ast.AST | t.CPtr) -> llvmlite.Value | t.CPtr: - """翻译函数调用,从 self.Trans 获取共享状态""" - return translate_call( - self.Trans.Pool, self.Trans._cur_builder, self.Trans.Module, - node, - self.Trans._funcs, self.Trans._func_count, self.Trans) - - # ============================================================ - # HandlePrintfCall - 翻译 printf 调用 - # ============================================================ - def HandlePrintfCall(self, cl: ast.Call | t.CPtr): - """翻译 printf 调用,从 self.Trans 获取共享状态""" - translate_printf_call( - self.Trans.Pool, self.Trans._cur_builder, self.Trans.Module, - cl, self.Trans) - -# ============================================================ -# NewExprCallHandle - 工厂函数 -# ============================================================ -def NewExprCallHandle(pool: memhub.MemBuddy | t.CPtr, - trans: HT.Translator | t.CPtr) -> ExprCallHandle | t.CPtr: - h: ExprCallHandle | t.CPtr = pool.alloc(ExprCallHandle.__sizeof__()) - if h is None: - return None - string.memset(h, 0, ExprCallHandle.__sizeof__()) - h.Trans = trans - return h diff --git a/TransPyV/App/lib/core/Handles/HandlesExprOps.py b/TransPyV/App/lib/core/Handles/HandlesExprOps.py deleted file mode 100644 index e28216e..0000000 --- a/TransPyV/App/lib/core/Handles/HandlesExprOps.py +++ /dev/null @@ -1,289 +0,0 @@ -import t, c -from stdint import * -import ast -import llvmlite -import memhub -import string -import viperlib -import lib.core.Handles.HandlesExpr as HandlesExpr -import lib.core.Handles.HandlesVar as HandlesVar -import lib.core.Handles.HandlesTranslator as HT - - -# ============================================================ -# HandlesExprOps - 二元运算处理(模块级纯函数) -# ============================================================ - -# ============================================================ -# 运算符重载支持 -# -# 当二元/比较运算的 lhs 是结构体指针时,检查该类是否定义了 -# 对应的 dunder 方法(如 __add__、__eq__),若有则生成方法调用 -# 而非原生算术/比较指令。 -# ============================================================ - -# BinOp 运算符 → dunder 方法名 -def _binop_to_dunder(op: int) -> str: - """将 BinOp 运算符映射到 dunder 方法名,无映射时返回 None""" - if op == ast.OpKind.Add: return "__add__" - if op == ast.OpKind.Sub: return "__sub__" - if op == ast.OpKind.Mult: return "__mul__" - if op == ast.OpKind.Div: return "__div__" - if op == ast.OpKind.Mod: return "__mod__" - if op == ast.OpKind.BitAnd: return "__and__" - if op == ast.OpKind.BitOr: return "__or__" - if op == ast.OpKind.BitXor: return "__xor__" - if op == ast.OpKind.LShift: return "__lshift__" - if op == ast.OpKind.RShift: return "__rshift__" - if op == ast.OpKind.FloorDiv: return "__floordiv__" - return None - -# Compare 运算符 → dunder 方法名 -def _cmpop_to_dunder(op: int) -> str: - """将 Compare 运算符映射到 dunder 方法名,无映射时返回 None""" - if op == ast.OpKind.Eq: return "__eq__" - if op == ast.OpKind.Ne: return "__ne__" - if op == ast.OpKind.Lt: return "__lt__" - if op == ast.OpKind.Le: return "__le__" - if op == ast.OpKind.Gt: return "__gt__" - if op == ast.OpKind.Ge: return "__ge__" - return None - - -# ============================================================ -# try_operator_overload - 尝试运算符重载 -# -# 检查 lhs 是否为结构体指针,并在该类(含继承链)中查找对应的 -# dunder 方法。找到则生成方法调用 lhs.__dunder__(rhs),返回 -# 调用结果;未找到返回 None,调用方回退到原生运算。 -# -# Args: -# pool: 内存池 -# builder: IRBuilder -# mod: LLVM 模块 -# lhs: 左操作数 Value(已求值) -# rhs: 右操作数 Value(已求值) -# op: OpKind 运算符 -# trans: Translator 对象 -# is_compare: 0=BinOp, 1=Compare(决定 dunder 映射表) -# -# Returns: -# 方法调用的 Value(成功),None(未重载) -# ============================================================ -def try_operator_overload(pool: memhub.MemBuddy | t.CPtr, - builder: llvmlite.IRBuilder | t.CPtr, - mod: llvmlite.LLVMModule | t.CPtr, - lhs: llvmlite.Value | t.CPtr, - rhs: llvmlite.Value | t.CPtr, - op: int, - trans: HT.Translator | t.CPtr, - is_compare: int) -> llvmlite.Value | t.CPtr: - """尝试运算符重载:lhs 是结构体指针时调用 dunder 方法,否则返回 None""" - if lhs is None or rhs is None: - return None - - # 延迟导入避免循环依赖 - import lib.core.Handles.HandlesStruct as HandlesStruct - import lib.core.Handles.HandlesExprCall as HandlesExprCall - - # 映射运算符到 dunder 方法名 - dunder: str = None - if is_compare != 0: - dunder = _cmpop_to_dunder(op) - else: - dunder = _binop_to_dunder(op) - if dunder is None: - return None - - # 检查 lhs 是否为结构体指针 - struct_ty: llvmlite.LLVMType | t.CPtr = HandlesStruct.get_struct_type_from_value(lhs) - if struct_ty is None: - return None - - # 获取类名 - class_name: str = HandlesStruct.get_class_name_by_type(pool, struct_ty) - if class_name is None: - return None - - # 在继承链中查找 dunder 方法 - lookup_name: t.CChar | t.CPtr = pool.alloc(128) - if lookup_name is None: - return None - viperlib.snprintf(lookup_name, 128, "%s.%s", class_name, dunder) - found_func: llvmlite.Function | t.CPtr = HandlesExprCall.find_func_in_module(mod, lookup_name) - - search_class: str = class_name - if found_func is None: - cur_parent: str = HandlesStruct.get_parent_name(class_name) - while cur_parent is not None: - parent_lookup: t.CChar | t.CPtr = pool.alloc(128) - if parent_lookup is not None: - viperlib.snprintf(parent_lookup, 128, "%s.%s", cur_parent, dunder) - parent_func: llvmlite.Function | t.CPtr = HandlesExprCall.find_func_in_module(mod, parent_lookup) - if parent_func is not None: - found_func = parent_func - search_class = cur_parent - break - cur_parent = HandlesStruct.get_parent_name(cur_parent) - - # 方法不在当前模块中时,检查类(含父类)是否有 SHA1(stub 可能未注入) - # 优先用类型指针定位 entry 获取 SHA1(规避跨模块同名 find_struct 找错) - cls_sha1: str = None - op_entry: HandlesStruct.StructEntry | t.CPtr = HandlesStruct.find_struct_by_type(struct_ty) - if op_entry is not None: - cls_sha1 = op_entry.ModuleSha1 - if cls_sha1 is None: - cls_sha1 = HandlesStruct.get_struct_sha1(search_class) - if cls_sha1 is None: - cur_p: str = HandlesStruct.get_parent_name(search_class) - while cur_p is not None and cls_sha1 is None: - cls_sha1 = HandlesStruct.get_struct_sha1(cur_p) - cur_p = HandlesStruct.get_parent_name(cur_p) - - # 既无函数定义也无 SHA1 → 该类没有此 dunder 方法,返回 None 回退原生运算 - if found_func is None and cls_sha1 is None: - return None - - # 构建 extra_args 数组(仅含 rhs 一个参数) - extra_args: t.CSizeT | t.CPtr = pool.alloc(8) - if extra_args is None: - return None - extra_args[0] = t.CSizeT(rhs) - - # 调用方法: lhs.__dunder__(rhs) - return HandlesExprCall._call_method_on_ptr( - pool, builder, mod, search_class, dunder, - lhs, extra_args, 1, trans) - - -# ============================================================ -# 翻译二元运算(自动类型提升) -# ============================================================ -def translate_binop(pool: memhub.MemBuddy | t.CPtr, - builder: llvmlite.IRBuilder | t.CPtr, - mod: llvmlite.LLVMModule | t.CPtr, - node: ast.AST | t.CPtr, - trans: HT.Translator | t.CPtr = None) -> llvmlite.Value | t.CPtr: - """翻译二元运算(自动类型提升)""" - binop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(node) - if binop is None: - return None - - lhs_node: ast.AST | t.CPtr = binop.left - rhs_node: ast.AST | t.CPtr = binop.right - op: int = binop.op - - # 先翻译 rhs(只翻译一次,避免副作用重复) - rhs: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( - builder, pool, mod, rhs_node, None, 0, trans) - if rhs is None: - return None - - # === 运算符重载路径 1: lhs 是 Name 且对应结构体变量 === - # 对于值类型变量(如 cnt: Counter),translate_value 会 load 返回 Struct 值, - # 但 dunder 方法需要 Ptr(Struct) 作为 self。直接用 alloca 指针尝试重载。 - if lhs_node is not None and lhs_node.kind() == ast.ASTKind.Name and trans is not None: - nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(lhs_node) - if nm is not None and nm.id is not None: - lhs_alloca: llvmlite.Value | t.CPtr = HandlesVar.lookup_var( - trans.SymTab, nm.id) - if lhs_alloca is not None: - ovl_result: llvmlite.Value | t.CPtr = try_operator_overload( - pool, builder, mod, lhs_alloca, rhs, op, trans, 0) - if ovl_result is not None: - return ovl_result - - # 正常翻译 lhs - lhs: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( - builder, pool, mod, lhs_node, None, 0, trans) - if lhs is None: - return None - - # === 运算符重载路径 2: lhs 是 Ptr(Struct)(如 Counter|t.CPtr 变量 load 后)=== - ovl_result2: llvmlite.Value | t.CPtr = try_operator_overload( - pool, builder, mod, lhs, rhs, op, trans, 0) - if ovl_result2 is not None: - return ovl_result2 - - # 获取操作数类型信息 - lhs_bits: int = HandlesExpr.get_llvm_type_bits(lhs.Ty) - rhs_bits: int = HandlesExpr.get_llvm_type_bits(rhs.Ty) - lhs_fbits: int = HandlesExpr.get_llvm_float_bits(lhs.Ty) - rhs_fbits: int = HandlesExpr.get_llvm_float_bits(rhs.Ty) - - # 浮点运算: 任一操作数为浮点时,使用浮点指令(必须在指针算术之前检查, - # 因为 float 的 int bits 为 0,会被误认为指针) - if lhs_fbits != 0 or rhs_fbits != 0: - # 确定目标浮点类型(使用较大的位宽) - target_fbits: int = lhs_fbits - if rhs_fbits > target_fbits: - target_fbits = rhs_fbits - target_float_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Double(pool) - if target_fbits == 32: - target_float_ty = llvmlite.Float(pool) - # 将两个操作数转换为目标浮点类型(int→float via si2fp, float→float via fpext/fptrunc) - lhs = HandlesExpr.coerce_to_type(builder, lhs, target_float_ty) - rhs = HandlesExpr.coerce_to_type(builder, rhs, target_float_ty) - if op == ast.OpKind.Add: - return llvmlite.build_fadd(builder, lhs, rhs) - if op == ast.OpKind.Sub: - return llvmlite.build_fsub(builder, lhs, rhs) - if op == ast.OpKind.Mult: - return llvmlite.build_fmul(builder, lhs, rhs) - if op == ast.OpKind.Div: - return llvmlite.build_fdiv(builder, lhs, rhs) - if op == ast.OpKind.Mod: - return llvmlite.build_frem(builder, lhs, rhs) - return None - - # 指针算术: ptr + int 或 ptr - int → ptrtoint + add/sub + inttoptr - if (lhs_bits == 0 and rhs_bits != 0) or (lhs_bits != 0 and rhs_bits == 0): - if op == ast.OpKind.Add or op == ast.OpKind.Sub: - i64_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int64(pool) - if lhs_bits == 0: - # lhs 是指针,rhs 是整数 - ptr_as_int: llvmlite.Value | t.CPtr = llvmlite.build_ptrtoint(builder, lhs, i64_ty) - int_val: llvmlite.Value | t.CPtr = HandlesExpr.coerce_to_type(builder, rhs, i64_ty) - if op == ast.OpKind.Add: - result: llvmlite.Value | t.CPtr = llvmlite.build_add(builder, ptr_as_int, int_val) - else: - result = llvmlite.build_sub(builder, ptr_as_int, int_val) - return llvmlite.build_inttoptr(builder, result, lhs.Ty) - else: - # rhs 是指针,lhs 是整数(仅 Add 支持交换) - ptr_as_int = llvmlite.build_ptrtoint(builder, rhs, i64_ty) - int_val = HandlesExpr.coerce_to_type(builder, lhs, i64_ty) - if op == ast.OpKind.Add: - result = llvmlite.build_add(builder, int_val, ptr_as_int) - else: - result = llvmlite.build_sub(builder, int_val, ptr_as_int) - return llvmlite.build_inttoptr(builder, result, rhs.Ty) - - if lhs_bits > rhs_bits: - rhs = HandlesExpr.coerce_to_type(builder, rhs, lhs.Ty) - elif rhs_bits > lhs_bits: - lhs = HandlesExpr.coerce_to_type(builder, lhs, rhs.Ty) - - if op == ast.OpKind.Add: - return llvmlite.build_add(builder, lhs, rhs) - elif op == ast.OpKind.Sub: - return llvmlite.build_sub(builder, lhs, rhs) - elif op == ast.OpKind.Mult: - return llvmlite.build_mul(builder, lhs, rhs) - elif op == ast.OpKind.Div: - return llvmlite.build_sdiv(builder, lhs, rhs) - elif op == ast.OpKind.FloorDiv: - return llvmlite.build_sdiv(builder, lhs, rhs) - elif op == ast.OpKind.Mod: - return llvmlite.build_srem(builder, lhs, rhs) - elif op == ast.OpKind.BitAnd: - return llvmlite.build_and(builder, lhs, rhs) - elif op == ast.OpKind.BitOr: - return llvmlite.build_or(builder, lhs, rhs) - elif op == ast.OpKind.BitXor: - return llvmlite.build_xor(builder, lhs, rhs) - elif op == ast.OpKind.LShift: - return llvmlite.build_shl(builder, lhs, rhs) - elif op == ast.OpKind.RShift: - return llvmlite.build_ashr(builder, lhs, rhs) - return None diff --git a/TransPyV/App/lib/core/Handles/HandlesFor.py b/TransPyV/App/lib/core/Handles/HandlesFor.py deleted file mode 100644 index 214b98e..0000000 --- a/TransPyV/App/lib/core/Handles/HandlesFor.py +++ /dev/null @@ -1,398 +0,0 @@ -import t, c -from stdint import * -import ast -import llvmlite -import memhub -import string -import stdio -import viperlib -import lib.core.Handles.HandlesBase as HandlesBase -import lib.core.Handles.HandlesTranslator as HT -import lib.core.Handles.HandlesVar as HandlesVar -import lib.core.Handles.HandlesExpr as HandlesExpr -import lib.core.Handles.HandlesBody as HandlesBody -import lib.core.Handles.HandlesType as HandlesType - - -# ============================================================ -# HandlesFor - for 循环语句处理(Mixin 继承模式) -# -# 支持 for i in range(start, stop, step) 模式: -# %i = alloca i32 -# store i32 start, i32* %i -# br label %cond -# cond: -# %cur = load i32, i32* %i -# %cmp = icmp slt i32 %cur, stop -# br i1 %cmp, label %body, label %end -# body: -# ... body ... -# br label %incr -# incr: -# %cur2 = load i32, i32* %i -# %next = add i32 %cur2, step -# store i32 %next, i32* %i -# br label %cond -# end: -# ============================================================ - - -@t.NoVTable -class ForHandle(HandlesBase.Mixin): - """for 循环语句处理器:继承 Mixin 获得 Trans 回指针""" - - def __init__(self, trans: HT.Translator | t.CPtr): - self.Trans = trans - - # ============================================================ - # Handle - 处理 for 语句,返回新增变量数 - # ============================================================ - def Handle(self, node: ast.AST | t.CPtr) -> int: - """翻译 for i in range(...) 循环语句""" - if node is None: - return 0 - - trans: HT.Translator | t.CPtr = self.Trans - pool: memhub.MemBuddy | t.CPtr = trans.Pool - builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder - func: llvmlite.Function | t.CPtr = trans._cur_func - - if builder is None or func is None: - return 0 - - for_node: ast.For | t.CPtr = (ast.For | t.CPtr)(node) - - # 1. 获取循环变量名(仅支持 for i in range(...)) - target: ast.AST | t.CPtr = for_node.target - if target is None: - return 0 - if target.kind() != ast.ASTKind.Name: - return 0 - target_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(target) - var_name: str = target_nm.id - if var_name is None: - return 0 - - # 2. 解析迭代器:支持 range() 和指针迭代 - iter_node: ast.AST | t.CPtr = for_node.iter - if iter_node is None: - return 0 - - # 检查是否是 range() 调用 - is_range_iter: int = 0 - if iter_node.kind() == ast.ASTKind.Call: - call_pre: ast.Call | t.CPtr = (ast.Call | t.CPtr)(iter_node) - fn_pre: str = HandlesExpr.get_func_name(call_pre.func) - if fn_pre is not None: - if string.strcmp(fn_pre, "range") == 0: - is_range_iter = 1 - else: - err_msg: t.CChar | t.CPtr = pool.alloc(256) - if err_msg is not None: - viperlib.snprintf(err_msg, 256, "仅支持 range() 或指针迭代,got call '%s'", fn_pre) - HandlesType.fatal_error(iter_node, err_msg) - HandlesType.fatal_error(iter_node, "仅支持 range() 或指针迭代") - - # 非范围迭代:走指针迭代路径 - if is_range_iter == 0: - return self._handle_ptr_iter(for_node, var_name) - - call: ast.Call | t.CPtr = (ast.Call | t.CPtr)(iter_node) - - # 3. 解析 range 参数: range(stop) / range(start, stop) / range(start, stop, step) - args: list[ast.AST | t.CPtr] | t.CPtr = call.args - if args is None: - return 0 - arg_count: t.CSizeT = args.__len__() - - i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool) - start_val: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, 0) - stop_val: llvmlite.Value | t.CPtr = None - step_val: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, 1) - - if arg_count == 1: - stop_val = HandlesExpr.translate_value( - builder, pool, trans.Module, args.get(0), - trans._funcs, trans._func_count, trans) - elif arg_count >= 2: - start_val = HandlesExpr.translate_value( - builder, pool, trans.Module, args.get(0), - trans._funcs, trans._func_count, trans) - stop_val = HandlesExpr.translate_value( - builder, pool, trans.Module, args.get(1), - trans._funcs, trans._func_count, trans) - if arg_count >= 3: - step_val = HandlesExpr.translate_value( - builder, pool, trans.Module, args.get(2), - trans._funcs, trans._func_count, trans) - - if stop_val is None: - stop_val = llvmlite.const_int32(pool, 0) - if start_val is None: - start_val = llvmlite.const_int32(pool, 0) - if step_val is None: - step_val = llvmlite.const_int32(pool, 1) - - # 4. 创建/查找循环变量 alloca - var_alloca: llvmlite.Value | t.CPtr = HandlesVar.lookup_var( - trans.SymTab, var_name) - new_vars: int = 0 - if var_alloca is None: - var_alloca = HandlesVar._alloca_at_entry(builder, i32_ty) - if HandlesVar.define_var( - trans.SymTab, var_name, var_alloca) == 0: - new_vars = 1 - - # 获取循环变量的实际元素类型(alloca 是指针类型,需解引用 Pointee) - # 当循环变量已声明为 i64(如 t.CSizeT),使用 i64 而非硬编码 i32 - # 避免 load i32, i64* / store i32, i64* 类型不匹配 - loop_var_ty: llvmlite.LLVMType | t.CPtr = i32_ty - if var_alloca is not None and var_alloca.Ty is not None: - match var_alloca.Ty: - case llvmlite.LLVMType.Ptr(pointee_ty): - if pointee_ty is not None: - loop_var_ty = pointee_ty - loop_var_bits: int = HandlesExpr.get_llvm_type_bits(loop_var_ty) - - # 5. 存储初始值 (类型对齐: start_val 可能是 i32/i64,需对齐到 loop_var_ty) - init_val: llvmlite.Value | t.CPtr = start_val - if start_val is not None and start_val.Ty is not None: - start_bits: int = HandlesExpr.get_llvm_type_bits(start_val.Ty) - if start_bits != 0 and start_bits != loop_var_bits: - if start_bits < loop_var_bits: - init_val = llvmlite.build_sext(builder, start_val, loop_var_ty) - else: - init_val = llvmlite.build_trunc(builder, start_val, loop_var_ty) - llvmlite.build_store(builder, init_val, var_alloca) - - # 6. 创建基本块: cond / body / incr / end(使用 trans._label_counter,不与 SSA 名共享) - cnt: int = trans._label_counter - trans._label_counter = cnt + 1 - - name_buf: t.CChar | t.CPtr = pool.alloc(32) - viperlib.snprintf(name_buf, 32, "for.cond.%d", cnt) - cond_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf) - - viperlib.snprintf(name_buf, 32, "for.body.%d", cnt) - body_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf) - - viperlib.snprintf(name_buf, 32, "for.incr.%d", cnt) - incr_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf) - - viperlib.snprintf(name_buf, 32, "for.end.%d", cnt) - end_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf) - - # 7. 跳转到 cond 块 - llvmlite.build_br(builder, cond_bb) - - # 8. cond 块: load i, icmp slt i, stop, cond_br body/end - llvmlite.position_at_end(builder, cond_bb) - cur_i: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, loop_var_ty, var_alloca) - # 类型对齐: stop_val 可能是 i64 (如 range(strlen(s))),需将 cur_i 提升到 stop_val 类型 - cmp_lhs: llvmlite.Value | t.CPtr = cur_i - cmp_rhs: llvmlite.Value | t.CPtr = stop_val - if stop_val is not None and stop_val.Ty is not None: - stop_bits: int = HandlesExpr.get_llvm_type_bits(stop_val.Ty) - cur_bits: int = HandlesExpr.get_llvm_type_bits(cur_i.Ty) - if stop_bits != 0 and cur_bits != 0 and stop_bits != cur_bits: - if cur_bits < stop_bits: - cmp_lhs = llvmlite.build_sext(builder, cur_i, stop_val.Ty) - else: - cmp_rhs = llvmlite.build_trunc(builder, stop_val, loop_var_ty) - cond_i1: llvmlite.Value | t.CPtr = llvmlite.build_icmp( - builder, llvmlite.ICMP_SLT, cmp_lhs, cmp_rhs) - llvmlite.build_cond_br(builder, cond_i1, body_bb, end_bb) - - # 9. body 块: 翻译循环体,跳到 incr - llvmlite.position_at_end(builder, body_bb) - - # 保存旧循环上下文,设置 break/continue 目标 - old_break: llvmlite.BasicBlock | t.CPtr = trans._break_bb - old_continue: llvmlite.BasicBlock | t.CPtr = trans._continue_bb - trans._break_bb = end_bb - trans._continue_bb = incr_bb - - body: list[ast.AST | t.CPtr] | t.CPtr = for_node.children - if body is not None: - body_count: t.CSizeT = body.__len__() - for bi in range(body_count): - stmt: ast.AST | t.CPtr = body.get(bi) - if stmt is not None: - HandlesBody.translate_stmt(trans, stmt) - - # 恢复旧循环上下文 - trans._break_bb = old_break - trans._continue_bb = old_continue - - if llvmlite.builder_cur_block_is_terminated(builder) == 0: - llvmlite.build_br(builder, incr_bb) - - # 10. incr 块: i = i + step, 跳回 cond - llvmlite.position_at_end(builder, incr_bb) - cur_i2: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, loop_var_ty, var_alloca) - # 类型对齐: step_val 可能是 i32/i64,需对齐到 loop_var_ty 与 cur_i2 类型一致 - incr_step: llvmlite.Value | t.CPtr = step_val - if step_val is not None and step_val.Ty is not None: - step_bits: int = HandlesExpr.get_llvm_type_bits(step_val.Ty) - cur2_bits: int = HandlesExpr.get_llvm_type_bits(cur_i2.Ty) - if step_bits != 0 and cur2_bits != 0 and step_bits != cur2_bits: - if step_bits > cur2_bits: - incr_step = llvmlite.build_trunc(builder, step_val, loop_var_ty) - else: - incr_step = llvmlite.build_sext(builder, step_val, loop_var_ty) - next_i: llvmlite.Value | t.CPtr = llvmlite.build_add(builder, cur_i2, incr_step) - llvmlite.build_store(builder, next_i, var_alloca) - llvmlite.build_br(builder, cond_bb) - - # 11. 定位到 end 块 - llvmlite.position_at_end(builder, end_bb) - return new_vars - - # ============================================================ - # _handle_ptr_iter - 指针迭代: for x in ptr: - # 遍历指针,依赖隐式 index,直到解引用为空(null 终止符) - # - # 生成 IR 结构: - # %idx = alloca i32 - # store i32 0, i32* %idx - # br label %cond - # cond: - # %i = load i32, i32* %idx - # %ep = getelementptr elem_ty, ptr_ty %ptr, i32 %i - # %ev = load elem_ty, elem_ty* %ep - # %null = icmp eq elem_ty %ev, 0 - # br i1 %null, label %end, label %body - # body: - # store elem_ty %ev, elem_ty* %var - # ... 循环体 ... - # br label %incr - # incr: - # %next = add i32 %i, 1 - # store i32 %next, i32* %idx - # br label %cond - # end: - # ============================================================ - def _handle_ptr_iter(self, for_node: ast.For | t.CPtr, - var_name: str) -> int: - """指针迭代: for x in ptr: 直到解引用为空""" - trans: HT.Translator | t.CPtr = self.Trans - pool: memhub.MemBuddy | t.CPtr = trans.Pool - builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder - func: llvmlite.Function | t.CPtr = trans._cur_func - - # 翻译迭代器表达式,获取指针值 - ptr_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( - builder, pool, trans.Module, for_node.iter, - trans._funcs, trans._func_count, trans) - if ptr_val is None: - HandlesType.fatal_error(for_node, "指针迭代: 无法翻译迭代器表达式") - - # 检查是否是指针类型 - if HandlesExpr.is_ptr_type(ptr_val.Ty) == 0: - HandlesType.fatal_error(for_node, "指针迭代: 迭代器不是指针类型") - - # 获取元素类型 - elem_ty: llvmlite.LLVMType | t.CPtr = ptr_val.Ty.Pointee - if elem_ty is None: - HandlesType.fatal_error(for_node, "指针迭代: 无法获取元素类型") - - # 元素类型必须是整数(用于 icmp eq 0 检查 null 终止符) - elem_bits: int = HandlesExpr.get_llvm_type_bits(elem_ty) - if elem_bits == 0: - HandlesType.fatal_error(for_node, "指针迭代: 元素类型不是整数,无法检查 null 终止符") - - i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool) - - # 创建循环变量 alloca(存储元素值) - var_alloca: llvmlite.Value | t.CPtr = HandlesVar.lookup_var( - trans.SymTab, var_name) - new_vars: int = 0 - if var_alloca is None: - var_alloca = HandlesVar._alloca_at_entry(builder, elem_ty) - if HandlesVar.define_var( - trans.SymTab, var_name, var_alloca) == 0: - new_vars = 1 - - # 创建隐式 index 变量,初始为 0 - idx_alloca: llvmlite.Value | t.CPtr = HandlesVar._alloca_at_entry(builder, i32_ty) - llvmlite.build_store(builder, llvmlite.const_int32(pool, 0), idx_alloca) - - # 创建基本块: cond / body / incr / end - cnt: int = trans._label_counter - trans._label_counter = cnt + 1 - - name_buf: t.CChar | t.CPtr = pool.alloc(32) - viperlib.snprintf(name_buf, 32, "ptr.cond.%d", cnt) - cond_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf) - - viperlib.snprintf(name_buf, 32, "ptr.body.%d", cnt) - body_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf) - - viperlib.snprintf(name_buf, 32, "ptr.incr.%d", cnt) - incr_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf) - - viperlib.snprintf(name_buf, 32, "ptr.end.%d", cnt) - end_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf) - - # 跳转到 cond - llvmlite.build_br(builder, cond_bb) - - # cond 块: load index, GEP, load elem, icmp eq 0 - llvmlite.position_at_end(builder, cond_bb) - cur_idx: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, i32_ty, idx_alloca) - elem_ptr: llvmlite.Value | t.CPtr = llvmlite.build_gep( - builder, elem_ty, ptr_val, cur_idx) - cur_elem: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, elem_ty, elem_ptr) - null_val: llvmlite.Value | t.CPtr = llvmlite.const_int(pool, elem_bits, 0) - is_null: llvmlite.Value | t.CPtr = llvmlite.build_icmp( - builder, llvmlite.ICMP_EQ, cur_elem, null_val) - llvmlite.build_cond_br(builder, is_null, end_bb, body_bb) - - # body 块: store elem to var, 翻译循环体 - llvmlite.position_at_end(builder, body_bb) - llvmlite.build_store(builder, cur_elem, var_alloca) - - # 保存旧循环上下文,设置 break/continue 目标 - old_break: llvmlite.BasicBlock | t.CPtr = trans._break_bb - old_continue: llvmlite.BasicBlock | t.CPtr = trans._continue_bb - trans._break_bb = end_bb - trans._continue_bb = incr_bb - - body: list[ast.AST | t.CPtr] | t.CPtr = for_node.children - if body is not None: - body_count: t.CSizeT = body.__len__() - for bi in range(body_count): - stmt: ast.AST | t.CPtr = body.get(bi) - if stmt is not None: - HandlesBody.translate_stmt(trans, stmt) - - # 恢复旧循环上下文 - trans._break_bb = old_break - trans._continue_bb = old_continue - - if llvmlite.builder_cur_block_is_terminated(builder) == 0: - llvmlite.build_br(builder, incr_bb) - - # incr 块: index++, br cond - llvmlite.position_at_end(builder, incr_bb) - one_val: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, 1) - next_idx: llvmlite.Value | t.CPtr = llvmlite.build_add(builder, cur_idx, one_val) - llvmlite.build_store(builder, next_idx, idx_alloca) - llvmlite.build_br(builder, cond_bb) - - # 定位到 end 块 - llvmlite.position_at_end(builder, end_bb) - return new_vars - - -# ============================================================ -# NewForHandle - 工厂函数 -# ============================================================ -def NewForHandle(pool: memhub.MemBuddy | t.CPtr, - trans: HT.Translator | t.CPtr) -> ForHandle | t.CPtr: - h: ForHandle | t.CPtr = pool.alloc(ForHandle.__sizeof__()) - if h is None: - return None - string.memset(h, 0, ForHandle.__sizeof__()) - h.Trans = trans - return h diff --git a/TransPyV/App/lib/core/Handles/HandlesFunctions.py b/TransPyV/App/lib/core/Handles/HandlesFunctions.py deleted file mode 100644 index 96d1abd..0000000 --- a/TransPyV/App/lib/core/Handles/HandlesFunctions.py +++ /dev/null @@ -1,995 +0,0 @@ -import t, c -from stdint import * -import ast -import llvmlite -import memhub -import string -import viperlib -import stdio -import stdlib -import lib.core.VLogger as VLogger -import lib.core.Handles.HandlesTranslator as HT -import lib.core.Handles.HandlesVar as HandlesVar -import lib.core.Handles.HandlesExprCall as HandlesExprCall -import lib.core.Handles.HandlesType as HandlesType -import lib.core.Handles.HandlesExpr as HandlesExpr -import lib.core.Handles.HandlesBody as HandlesBody -import lib.core.Handles.HandlesNonlocal as HandlesNonlocal -import lib.core.Handles.HandlesImports as HandlesImports - - -# 作用域类型常量(本地副本,避免旧编译器跨模块 CDefine 查找 bug) -SCOPE_FUNCTION: t.CDefine = 1 - - -# ============================================================ -# extract_func_attrs - 从 decorator_list 提取 c.Attribute 属性 -# -# 支持 @c.Attribute(t.attr.xxx()) 和 @c.Attribute(t.attr.xxx) 形式 -# 也支持 @c.Attribute(t.attr.llvm.xxx) 形式 -# -# 返回 LLVM IR 属性字符串(如 "alwaysinline nounwind"),无属性返回 None -# ============================================================ -def extract_func_attrs(pool: memhub.MemBuddy | t.CPtr, - decorator_list: list[ast.AST | t.CPtr] | t.CPtr, - imported_modules: str) -> t.CChar | t.CPtr: - """从 decorator_list 提取 c.Attribute 属性,返回 LLVM IR 属性字符串""" - if decorator_list is None: - return None - dn: t.CSizeT = decorator_list.__len__() - if dn == 0: - return None - - attrs_buf: t.CChar | t.CPtr = pool.alloc(256) - if attrs_buf is None: - return None - attrs_buf[0] = '\0' - found_any: int = 0 - - for di in range(dn): - deco: ast.AST | t.CPtr = decorator_list.get(di) - if deco is None or deco.kind() != ast.ASTKind.Call: - continue - call_node: ast.Call | t.CPtr = (ast.Call | t.CPtr)(deco) - if call_node.func is None or call_node.func.kind() != ast.ASTKind.Attribute: - continue - - # 检测 c.Attribute - func_attr: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(call_node.func) - if func_attr.attr is None or string.strcmp(func_attr.attr, "Attribute") != 0: - continue - if func_attr.value is None or func_attr.value.kind() != ast.ASTKind.Name: - continue - c_name: ast.Name | t.CPtr = (ast.Name | t.CPtr)(func_attr.value) - if c_name.id is None or string.strcmp(c_name.id, "c") != 0: - continue - if HandlesImports.is_module_imported(imported_modules, "c") == 0: - continue - - # 遍历参数提取属性 - if call_node.args is None: - continue - args_list: list[ast.AST | t.CPtr] | t.CPtr = call_node.args - an: t.CSizeT = args_list.__len__() - for ai in range(an): - arg_node: ast.AST | t.CPtr = args_list.get(ai) - if arg_node is None: - continue - - # 提取属性名(t.attr.xxx / t.attr.xxx() / t.attr.llvm.xxx) - attr_name: str = _get_attr_name_from_node(arg_node) - if attr_name is None: - continue - - # 映射到 LLVM 属性名并追加 - if _append_llvm_attr(attrs_buf, attr_name) != 0: - found_any = 1 - # 追加成功后,如果不是最后一个属性,添加空格分隔 - # 在下一次追加前由 _append_str 处理 - - if found_any == 0: - return None - return attrs_buf - - -def _get_attr_name_from_node(node: ast.AST | t.CPtr) -> str: - """从 AST 节点提取属性名 - - 支持: - - Call(func=Attribute(...)): t.attr.always_inline() -> "always_inline" - - Attribute: t.attr.packed -> "packed" - - Attribute(t.attr.llvm.xxx): t.attr.llvm.nounwind -> "nounwind" - """ - if node is None: - return None - k: int = node.kind() - - # Call 节点: t.attr.always_inline() - if k == ast.ASTKind.Call: - call: ast.Call | t.CPtr = (ast.Call | t.CPtr)(node) - if call.func is None or call.func.kind() != ast.ASTKind.Attribute: - return None - at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(call.func) - return at.attr - - # Attribute 节点: t.attr.packed 或 t.attr.llvm.nounwind - if k == ast.ASTKind.Attribute: - at2: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(node) - return at2.attr - - return None - - -def _append_llvm_attr(attrs_buf: t.CChar | t.CPtr, attr_name: str) -> int: - """将属性名映射到 LLVM 属性名并追加到缓冲区 - - 返回 1 表示已追加,0 表示不支持该属性 - """ - if attrs_buf is None or attr_name is None: - return 0 - - # 先确定映射的 LLVM 属性名 - llvm_name: str = None - if string.strcmp(attr_name, "always_inline") == 0: - llvm_name = "alwaysinline" - elif string.strcmp(attr_name, "noinline") == 0: - llvm_name = "noinline" - elif string.strcmp(attr_name, "noreturn") == 0: - llvm_name = "noreturn" - elif string.strcmp(attr_name, "pure") == 0: - llvm_name = "readonly" - elif string.strcmp(attr_name, "const") == 0: - llvm_name = "readnone" - elif string.strcmp(attr_name, "nounwind") == 0: - llvm_name = "nounwind" - elif string.strcmp(attr_name, "noredzone") == 0: - llvm_name = "noredzone" - elif string.strcmp(attr_name, "willreturn") == 0: - llvm_name = "willreturn" - elif string.strcmp(attr_name, "mustprogress") == 0: - llvm_name = "mustprogress" - else: - # packed/aligned/section/visibility/weak 等不支持作为函数内联属性 - return 0 - - # 支持的属性:如果缓冲区非空,先追加空格分隔 - if attrs_buf[0] != '\0': - _append_str(attrs_buf, " ") - _append_str(attrs_buf, llvm_name) - return 1 - - -def _append_str(buf: t.CChar | t.CPtr, s: str) -> None: - """将字符串追加到 buf 末尾(用 strlen+strcpy 模拟 strcat)""" - if buf is None or s is None: - return - cur_len: t.CSizeT = string.strlen(buf) - string.strcpy(buf + cur_len, s) - - -# ============================================================ -# HandlesFunctions - 函数定义处理(trans 单参模式) -# -# 参考 Python 版 TransPyC FunctionHandle -# -# 函数有自己的局部作用域,通过 HandlesVar.enter_scope/exit_scope -# 管理嵌套作用域链,翻译函数体前进入函数作用域,翻译完退出。 -# ============================================================ - - -# ============================================================ -# _mangle_name - 为名称添加 SHA1 前缀 -# -# 返回 "sha1.name" 格式的混淆名。若 ModuleSha1 为 None 或名称已带 -# SHA1 前缀(16 hex + '.'),则原样返回。 -# ============================================================ -def _mangle_name(trans: HT.Translator | t.CPtr, name: str) -> str: - """为任意名称添加 SHA1 前缀(不做 main/export 检查)""" - if trans is None or name is None: - return name - if trans.ModuleSha1 is None: - return name - name_len: t.CSizeT = string.strlen(name) - # 已带 SHA1 前缀(16 hex + '.')则跳过 - if name_len > 17: - is_sha1: int = 1 - for i in range(16): - c: t.CChar = name[i] - if not (('0' <= c <= '9') or ('a' <= c <= 'f')): - is_sha1 = 0 - break - if is_sha1 != 0 and name[16] == '.': - return name - sha1: str = trans.ModuleSha1 - sha1_len: t.CSizeT = string.strlen(sha1) - mangled: str = stdlib.malloc(sha1_len + name_len + 2) - if mangled is None: - return name - string.strcpy(mangled, sha1) - mangled[sha1_len] = '.' - string.strcpy(mangled + sha1_len + 1, name) - return mangled - - -# ============================================================ -# _mangle_name_with_sha1 — 用指定 SHA1 为名称添加前缀 -# -# 用于跨模块 vtable 继承: 继承方法需要用父模块的 SHA1 做 mangling, -# 而非当前模块的 SHA1。 -# ============================================================ -def _mangle_name_with_sha1(sha1: str, name: str) -> str: - """用指定 SHA1 为名称添加前缀(不做 main/export 检查)""" - if sha1 is None or name is None: - return name - name_len: t.CSizeT = string.strlen(name) - # 已带 SHA1 前缀(16 hex + '.')则跳过 - if name_len > 17: - is_sha1: int = 1 - for i in range(16): - c2: t.CChar = name[i] - if not (('0' <= c2 <= '9') or ('a' <= c2 <= 'f')): - is_sha1 = 0 - break - if is_sha1 != 0 and name[16] == '.': - return name - sha1_len: t.CSizeT = string.strlen(sha1) - mangled: str = stdlib.malloc(sha1_len + name_len + 2) - if mangled is None: - return name - string.strcpy(mangled, sha1) - mangled[sha1_len] = '.' - string.strcpy(mangled + sha1_len + 1, name) - return mangled - - -# ============================================================ -# _mangle_func_name - 为函数名添加 SHA1 前缀(含 main/export 检查) -# -# 规则: -# - main 函数不加前缀(程序入口点) -# - has_export 非 0 时不加前缀(t.CExport 导出函数) -# - 已带 SHA1 前缀的不再加 -# - ModuleSha1 为 None 时不加前缀 -# ============================================================ -def _mangle_func_name(trans: HT.Translator | t.CPtr, name: str, - has_export: int) -> str: - """为函数名添加 SHA1 前缀(检查 main/export)""" - if trans is None or name is None: - return name - if has_export != 0: - return name - if string.strcmp(name, "main") == 0: - return name - return _mangle_name(trans, name) - - -# ============================================================ -# forward_declare_functions - 预扫描所有顶层 FunctionDef,创建前向声明 -# -# 解决同模块内前向引用问题:如 viperlib.py 中 sprintf(行15) 调用 -# vsnprintf(行41),但 vsnprintf 定义在后面。 -# -# 对每个顶层 FunctionDef: -# 1. 推断返回类型和参数类型 -# 2. 计算 mangled name(含 SHA1 前缀) -# 3. 创建 declare(IsDeclared=1) -# 4. 添加参数 -# 5. 注册到函数表 -# -# 后续 translate_function_def 会通过 find_func_in_module 找到已有的 declare, -# 复用之(清除 IsDeclared,跳过参数创建,直接添加函数体)。 -# ============================================================ -def forward_declare_functions(trans: HT.Translator | t.CPtr, - tree: ast.AST | t.CPtr) -> int: - """预扫描所有顶层 FunctionDef,创建前向声明""" - if trans is None or tree is None: - return 0 - pool: memhub.MemBuddy | t.CPtr = trans.Pool - mod: llvmlite.LLVMModule | t.CPtr = trans.Module - if pool is None or mod is None: - return 0 - - imported_modules: str = trans._imported_modules - from_imports: str = trans._from_imports - funcs_ptr: HandlesExprCall.FuncEntry | t.CPtr = trans._funcs - - i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool) - i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool) - i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty) - - ch: list[ast.AST | t.CPtr] | t.CPtr = tree.children - if ch is None: - return 0 - cn_count: t.CSizeT = ch.__len__() - - for ci in range(cn_count): - child: ast.AST | t.CPtr = ch.get(ci) - if child is None: - continue - if child.kind() != ast.ASTKind.FunctionDef: - continue - fd: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(child) - if fd is None or fd.name is None: - continue - - # 推断返回类型 - ret_ty: llvmlite.LLVMType | t.CPtr = None - if fd.returns is not None: - ret_ty = HandlesType.resolve_annotation_type( - pool, fd.returns, imported_modules, from_imports, trans) - if ret_ty is None and fd.returns is not None: - if HandlesType.has_decorator_marker(fd.returns, "State") != 0: - ret_ty = llvmlite.Void(pool) - if ret_ty is None: - ret_ty = i32_ty - - # 检测 CExtern/State/CExport - has_extern: int = 0 - has_state: int = 0 - has_export: int = 0 - if fd.returns is not None: - has_extern = HandlesType.has_decorator_marker(fd.returns, "CExtern") - has_state = HandlesType.has_decorator_marker(fd.returns, "State") - has_export = HandlesType.has_decorator_marker(fd.returns, "CExport") - is_extern_decl: int = 0 - if has_extern != 0 or has_state != 0: - is_extern_decl = 1 - - # 计算 mangled name - if has_extern != 0 or has_state != 0 or has_export != 0 or fd.name == "main": - mangled_name: str = fd.name - else: - mangled_name = _mangle_func_name(trans, fd.name, 0) - - # 如果函数已存在(如重复定义),跳过 - existing: llvmlite.Function | t.CPtr = HandlesExprCall.find_func_in_module(mod, mangled_name) - if existing is not None: - continue - - # 创建 declare - func: llvmlite.Function | t.CPtr = llvmlite.create_declare( - pool, mod, mangled_name, ret_ty) - if func is None: - continue - - # 提取默认参数信息 - # 注意: 必须先把属性赋给显式类型为 list[...] | t.CPtr 的局部变量再调用 __len__(), - # 否则编译器无法识别属性返回的 list 类型,GEP base 会变成 i32 0 导致 llc 报错 - fd_args_node: ast.Arguments | t.CPtr = fd.args - fd_defaults: t.CVoid | t.CPtr = None - fd_default_count: int = 0 - fd_param_count: int = 0 - if fd_args_node is not None: - fd_ags: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(fd_args_node) - if fd_ags.args is not None: - fd_alist: list[ast.AST | t.CPtr] | t.CPtr = fd_ags.args - fd_param_count = fd_alist.__len__() - if fd_ags.defaults is not None: - fd_dlist: list[ast.AST | t.CPtr] | t.CPtr = fd_ags.defaults - fd_defaults = fd_dlist - fd_default_count = fd_dlist.__len__() - - # 注册到函数表(用裸名 fd.name,不是 mangled_name) - max_funcs: int = 256 - cur_count: int = trans._func_count - if HandlesExprCall.add_func_to_table(funcs_ptr, cur_count, fd.name, func, max_funcs, - fd_defaults, fd_default_count, fd_param_count) == 0: - trans._func_count = cur_count + 1 - - # 注册 CExport 函数到全局表 - if (has_export != 0 or has_state != 0) and trans.ModuleSha1 is not None: - HandlesExprCall.register_cexport_func(trans.ModuleSha1, fd.name) - - # 添加参数 - args_node: ast.Arguments | t.CPtr = fd.args - if args_node is not None: - ags: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(args_node) - if ags.args is not None: - alist: list[ast.AST | t.CPtr] | t.CPtr = ags.args - an: t.CSizeT = alist.__len__() - for ai in range(an): - arg: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(alist.get(ai)) - if arg is None or arg.arg is None: - continue - # t.CVoid 表示空参:跳过 - if arg.annotation is not None: - if HandlesType._is_t_attr(arg.annotation, "CVoid", imported_modules) != 0: - continue - param_ty: llvmlite.LLVMType | t.CPtr = i32_ty - if arg.annotation is not None: - resolved: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type( - pool, arg.annotation, imported_modules, from_imports, trans) - if resolved is not None: - param_ty = resolved - pname: t.CChar | t.CPtr = pool.alloc(32) - if pname is not None: - viperlib.snprintf(pname, 32, "%%%s", arg.arg) - llvmlite.add_param(pool, func, param_ty, pname) - - return 0 - - -# ============================================================ -# 翻译函数定义 FunctionDef(name, args, body, ...) -# -# trans 单参模式:所有共享状态从 trans 获取 -# 函数局部作用域通过 enter_scope/exit_scope 管理 -# ============================================================ -def translate_function_def(trans: HT.Translator | t.CPtr, - node: ast.AST | t.CPtr) -> int: - """翻译函数定义,返回新增的变量数(通常为 0,函数定义不增加当前作用域变量)""" - fd: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(node) - if fd is None or fd.name is None: - return 0 - - pool: memhub.MemBuddy | t.CPtr = trans.Pool - mod: llvmlite.LLVMModule | t.CPtr = trans.Module - imported_modules: str = trans._imported_modules - from_imports: str = trans._from_imports - funcs_ptr: HandlesExprCall.FuncEntry | t.CPtr = trans._funcs - func_count: int = trans._func_count - - i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool) - - # 推断返回类型:优先使用返回类型注解 - ret_ty: llvmlite.LLVMType | t.CPtr = None - if fd.returns is not None: - ret_ty = HandlesType.resolve_annotation_type( - pool, fd.returns, imported_modules, from_imports, trans) - - # 如果返回类型注解纯装饰器标记(如 t.State,无实际类型),使用 void - # 注意:必须在 infer_return_type 之前检测,因为 infer_return_type 至少返回 i32 - if ret_ty is None and fd.returns is not None: - if HandlesType.has_decorator_marker(fd.returns, "State") != 0: - ret_ty = llvmlite.Void(pool) - - # 如果仍然为 None,扫描 return 语句推断(至少返回 i32) - if ret_ty is None: - param_types_str: str = HandlesType.build_param_types_str(pool, fd.args) - ret_ty = HandlesType.infer_return_type( - pool, fd.children, param_types_str) - # 检测是否为外部声明函数(t.CExtern 或 t.State) - # 语义:t.CExtern 忽略 body 体,仅生成 declare(由链接器解析符号) - # t.State = t.CExtern + t.CExport(既是声明又是导出) - # t.CExport 导出函数不加 SHA1 前缀 - # t.CExtern/t.State/t.CExport 都不加 SHA1 前缀,直接映射到 C 标准库函数名 - is_extern_decl: int = 0 - has_export: int = 0 - has_extern: int = 0 - has_state: int = 0 - if fd.returns is not None: - has_extern = HandlesType.has_decorator_marker(fd.returns, "CExtern") - has_state = HandlesType.has_decorator_marker(fd.returns, "State") - has_export = HandlesType.has_decorator_marker(fd.returns, "CExport") - # t.CExtern/t.State 忽略 body 体,仅声明(无论 body 是否为 pass) - if has_extern != 0 or has_state != 0: - is_extern_decl = 1 - - # SHA1 命名空间:t.CExtern/t.State/t.CExport 不加前缀,直接用裸名 - # (裸名映射到 C 标准库符号,带 sha1 前缀会导致 undefined reference) - # main 函数也不加前缀(程序入口点) - if has_extern != 0 or has_state != 0 or has_export != 0 or fd.name == "main": - mangled_name: str = fd.name - else: - mangled_name: str = _mangle_func_name(trans, fd.name, 0) - - # 注册 CExport 函数到全局表(供跨模块调用查表) - # t.CExport 函数定义用裸名(@strlen),跨模块调用需查表确认用裸名而非 @{sha1}.func - if (has_export != 0 or has_state != 0) and trans.ModuleSha1 is not None: - HandlesExprCall.register_cexport_func(trans.ModuleSha1, fd.name) - - if is_extern_decl != 0: - # 外部声明函数:生成 declare(仅声明,不定义) - # 先检查是否已由 forward_declare_functions 创建,避免重复 declare - existing_extern: llvmlite.Function | t.CPtr = HandlesExprCall.find_func_in_module(mod, mangled_name) - if existing_extern is not None: - # 已存在前向声明,复用之,不再重复创建 - return 0 - - func: llvmlite.Function | t.CPtr = llvmlite.create_declare( - pool, mod, mangled_name, ret_ty) - if func is None: - return 0 - - # 注册到函数表 - max_funcs_extern: int = 256 - if HandlesExprCall.add_func_to_table(funcs_ptr, func_count, fd.name, func, max_funcs_extern) == 0: - trans._func_count = func_count + 1 - - # 添加参数(支持类型注解) - args_node_extern: ast.Arguments | t.CPtr = fd.args - if args_node_extern is not None: - ags_e: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(args_node_extern) - if ags_e.args is not None: - alist_e: list[ast.AST | t.CPtr] | t.CPtr = ags_e.args - an_e: t.CSizeT = alist_e.__len__() - for ai_e in range(an_e): - arg_e: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(alist_e.get(ai_e)) - if arg_e is not None and arg_e.arg is not None: - # t.CVoid 表示空参:跳过,不添加到函数签名 - if arg_e.annotation is not None: - if HandlesType._is_t_attr(arg_e.annotation, "CVoid", imported_modules) != 0: - continue - param_ty_e: llvmlite.LLVMType | t.CPtr = i32_ty - if arg_e.annotation is not None: - resolved_e: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type( - pool, arg_e.annotation, imported_modules, from_imports, trans) - if resolved_e is not None: - param_ty_e = resolved_e - pname_e: t.CChar | t.CPtr = pool.alloc(32) - if pname_e is not None: - viperlib.snprintf(pname_e, 32, "%%%s", arg_e.arg) - llvmlite.add_param(pool, func, param_ty_e, pname_e) - - # 提取 @c.Attribute 装饰器属性并设置到函数 - func_attrs_e: t.CChar | t.CPtr = extract_func_attrs(pool, fd.decorator_list, imported_modules) - if func_attrs_e is not None: - llvmlite.function_set_attrs(func, func_attrs_e) - - return 0 - - # args_node 用于后续 alloca 创建,提前赋值 - args_node: ast.Arguments | t.CPtr = fd.args - - # 检查是否已有前向声明(由 forward_declare_functions 创建) - func: llvmlite.Function | t.CPtr = HandlesExprCall.find_func_in_module(mod, mangled_name) - if func is not None and llvmlite.function_is_declared(func) != 0: - # 复用前向声明:清除 IsDeclared 标记,转为 define - func.IsDeclared = 0 - # 装饰器属性设置(前向声明时未设置) - func_attrs_reuse: t.CChar | t.CPtr = extract_func_attrs(pool, fd.decorator_list, imported_modules) - if func_attrs_reuse is not None: - llvmlite.function_set_attrs(func, func_attrs_reuse) - else: - # 创建新的 LLVM 函数(使用 SHA1 混淆名) - func = llvmlite.create_function(pool, mod, mangled_name, ret_ty) - if func is None: - fb_cf: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb_cf is not None: - viperlib.snprintf(fb_cf, 1024, "create_function %s failed", fd.name) - VLogger.error(fb_cf, "FUNC") - return 0 - - # 提取 @c.Attribute 装饰器属性并设置到函数 - func_attrs: t.CChar | t.CPtr = extract_func_attrs(pool, fd.decorator_list, imported_modules) - if func_attrs is not None: - llvmlite.function_set_attrs(func, func_attrs) - - # 提取默认参数信息 - tfd_defaults: t.CVoid | t.CPtr = None - tfd_default_count: int = 0 - tfd_param_count: int = 0 - if args_node is not None: - tfd_ags: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(args_node) - if tfd_ags.args is not None: - tfd_alist: list[ast.AST | t.CPtr] | t.CPtr = tfd_ags.args - tfd_param_count = tfd_alist.__len__() - if tfd_ags.defaults is not None: - tfd_dlist: list[ast.AST | t.CPtr] | t.CPtr = tfd_ags.defaults - tfd_defaults = tfd_dlist - tfd_default_count = tfd_dlist.__len__() - - # 注册到函数表 - max_funcs: int = 256 - if HandlesExprCall.add_func_to_table(funcs_ptr, func_count, fd.name, func, max_funcs, - tfd_defaults, tfd_default_count, tfd_param_count) == 0: - trans._func_count = func_count + 1 - - # 添加参数(支持类型注解) - if args_node is not None: - ags: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(args_node) - if ags.args is not None: - alist: list[ast.AST | t.CPtr] | t.CPtr = ags.args - an: t.CSizeT = alist.__len__() - for ai in range(an): - arg: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(alist.get(ai)) - if arg is not None and arg.arg is not None: - # t.CVoid 表示空参:跳过,不添加到函数签名 - if arg.annotation is not None: - if HandlesType._is_t_attr(arg.annotation, "CVoid", imported_modules) != 0: - continue - param_ty: llvmlite.LLVMType | t.CPtr = i32_ty - if arg.annotation is not None: - resolved: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type( - pool, arg.annotation, imported_modules, from_imports, trans) - if resolved is not None: - param_ty = resolved - pname: t.CChar | t.CPtr = pool.alloc(32) - if pname is not None: - viperlib.snprintf(pname, 32, "%%%s", arg.arg) - llvmlite.add_param(pool, func, param_ty, pname) - # 创建 entry 块 - entry_blk: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, "entry") - if entry_blk is None: - return 0 - - # 创建函数专属 builder - func_builder: llvmlite.IRBuilder | t.CPtr = llvmlite.new_builder(pool, func) - if func_builder is None: - return 0 - llvmlite.position_at_end(func_builder, entry_blk) - - # 进入函数作用域(嵌套符号表) - HandlesVar.enter_scope(trans.SymTab, SCOPE_FUNCTION) - - # 为参数创建 alloca - if args_node is not None: - ags2: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(args_node) - if ags2.args is not None: - alist2: list[ast.AST | t.CPtr] | t.CPtr = ags2.args - an2: t.CSizeT = alist2.__len__() - for ai2 in range(an2): - arg2: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(alist2.get(ai2)) - if arg2 is not None and arg2.arg is not None: - # t.CVoid 表示空参:跳过,不创建 alloca - if arg2.annotation is not None: - if HandlesType._is_t_attr(arg2.annotation, "CVoid", imported_modules) != 0: - continue - param_ty2: llvmlite.LLVMType | t.CPtr = i32_ty - if arg2.annotation is not None: - resolved2: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type( - pool, arg2.annotation, imported_modules, from_imports, trans) - if resolved2 is not None: - param_ty2 = resolved2 - alloca: llvmlite.Value | t.CPtr = llvmlite.build_alloca(func_builder, param_ty2) - if alloca is not None: - HandlesVar.define_var(trans.SymTab, arg2.arg, alloca) - # 存储原始类型注解的类名(方法调用检测时,Ptr(i8) 回退到类名查找结构体) - if arg2.annotation is not None: - cls_nm: str = HandlesType.extract_class_name_from_annotation( - arg2.annotation, imported_modules) - if cls_nm is not None: - HandlesVar.set_var_annot_class_name( - trans.SymTab, arg2.arg, cls_nm) - pname2: t.CChar | t.CPtr = pool.alloc(32) - if pname2 is not None: - viperlib.snprintf(pname2, 32, "%%%s", arg2.arg) - param_val: llvmlite.Value | t.CPtr = llvmlite.SSAValue( - pool, param_ty2, pname2) - llvmlite.build_store(func_builder, param_val, alloca) - # 保存模块级作用域状态(仅非变量表相关) - old_func: llvmlite.Function | t.CPtr = trans._cur_func - old_builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder - old_global_count: int = trans._global_name_count - old_nonlocal_count: int = trans._nonlocal_name_count - old_env_count: int = trans._closure_env_count - - trans._cur_func = func - trans._cur_builder = func_builder - # 清空 global/nonlocal 名称集合(新函数作用域) - HT.clear_scope_names(trans) - - # 预扫描函数体:为局部变量提前创建 alloca - body: list[ast.AST | t.CPtr] | t.CPtr = fd.children - if body is not None: - bn: t.CSizeT = body.__len__() - for bi in range(bn): - stmt: ast.AST | t.CPtr = body.get(bi) - if stmt is not None: - HandlesBody.pre_scan_allocas(trans, stmt) - - # 翻译函数体 - if body is not None: - bn2: t.CSizeT = body.__len__() - for bi2 in range(bn2): - stmt2: ast.AST | t.CPtr = body.get(bi2) - if stmt2 is not None: - HandlesBody.translate_stmt(trans, stmt2) - - # 如果函数体最后一条语句不是 Return,添加隐式 ret - last_is_return: int = 0 - if body is not None: - bn3: t.CSizeT = body.__len__() - if bn3 > 0: - last_stmt: ast.AST | t.CPtr = body.get(bn3 - 1) - if last_stmt is not None and last_stmt.kind() == ast.ASTKind.Return: - last_is_return = 1 - if last_is_return == 0: - if llvmlite.builder_cur_block_is_terminated(func_builder) == 0: - # 根据返回类型生成正确的零值返回 - _is_void: int = 0 - _is_ptr: int = 0 - if ret_ty is not None: - match ret_ty: - case llvmlite.LLVMType.Void(): - _is_void = 1 - case llvmlite.LLVMType.Ptr(_pe): - _is_ptr = 1 - if _is_void != 0: - llvmlite.build_ret_void(func_builder) - elif _is_ptr != 0: - _null_val: llvmlite.Value | t.CPtr = llvmlite.ConstNull(pool, ret_ty, "null") - llvmlite.build_ret(func_builder, _null_val) - else: - _zero_val: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, 0) - llvmlite.build_ret(func_builder, _zero_val) - - # 恢复模块级作用域(退出函数作用域) - HandlesVar.exit_scope(trans.SymTab) - trans._cur_func = old_func - trans._cur_builder = old_builder - trans._global_name_count = old_global_count - trans._nonlocal_name_count = old_nonlocal_count - trans._closure_env_count = old_env_count - - return 0 - - -# ============================================================ -# translate_nested_function_def - 嵌套函数提升 + 闭包创建 -# -# 将嵌套函数提升为顶层函数 @__closure_{name}(i8* %env) -> i32, -# 在父函数中创建闭包对象 {i8* fn_ptr, i8* env_ptr} 并存储到 -# 以函数名命名的局部变量中。 -# -# 闭包结构: {i8* fn_ptr, i8* env_ptr} (16 字节, malloc 分配) -# Env 结构: {i8* ptr0, i8* ptr1, ...} (每个 nonlocal 变量 8 字节) -# ============================================================ -def translate_nested_function_def(trans: HT.Translator | t.CPtr, - node: ast.AST | t.CPtr) -> int: - """翻译嵌套函数定义:提升为顶层函数 + 创建闭包""" - fd: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(node) - if fd is None or fd.name is None: - return 0 - - pool: memhub.MemBuddy | t.CPtr = trans.Pool - mod: llvmlite.LLVMModule | t.CPtr = trans.Module - func_name: str = fd.name - - i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool) - i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool) - i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty) - - # 1. 构建提升后的函数名: __closure_{name}(加 SHA1 前缀避免跨模块冲突) - promoted_name: t.CChar | t.CPtr = pool.alloc(64) - if promoted_name is not None: - viperlib.snprintf(promoted_name, 64, "__closure_%s", func_name) - mangled_promoted: str = _mangle_name(trans, promoted_name) - - # 2. 创建提升后的函数: define i32 @__closure_{name}(i8* %env) - func: llvmlite.Function | t.CPtr = llvmlite.create_function( - pool, mod, mangled_promoted, i32_ty) - if func is None: - return 0 - llvmlite.add_param(pool, func, i8_ptr_ty, "%env") - - # 3. 创建 entry 块 + builder - entry_blk: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, "entry") - if entry_blk is None: - return 0 - func_builder: llvmlite.IRBuilder | t.CPtr = llvmlite.new_builder(pool, func) - if func_builder is None: - return 0 - llvmlite.position_at_end(func_builder, entry_blk) - - # 4. 进入嵌套函数作用域(嵌套符号表) - HandlesVar.enter_scope(trans.SymTab, SCOPE_FUNCTION) - - # 5. 创建 _env_ptr alloca 并存储 %env 参数 - env_alloca: llvmlite.Value | t.CPtr = llvmlite.build_alloca(func_builder, i8_ptr_ty) - if env_alloca is not None: - HandlesVar.define_var(trans.SymTab, "_env_ptr", env_alloca) - env_param_val: llvmlite.Value | t.CPtr = llvmlite.SSAValue(pool, i8_ptr_ty, "%env") - llvmlite.build_store(func_builder, env_param_val, env_alloca) - - # 6. 保存父函数作用域状态(仅非变量表相关) - old_func: llvmlite.Function | t.CPtr = trans._cur_func - old_builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder - old_func_name: str = trans._cur_func_name - old_global_count: int = trans._global_name_count - old_nonlocal_count: int = trans._nonlocal_name_count - old_env_count: int = trans._closure_env_count - - # 7. 切换到嵌套函数作用域 + 清空 scope names - trans._cur_func = func - trans._cur_builder = func_builder - trans._cur_func_name = func_name - HT.clear_scope_names(trans) - - # 8. 预扫描函数体:为局部变量提前创建 alloca - body: list[ast.AST | t.CPtr] | t.CPtr = fd.children - if body is not None: - bn: t.CSizeT = body.__len__() - for bi in range(bn): - stmt: ast.AST | t.CPtr = body.get(bi) - if stmt is not None: - HandlesBody.pre_scan_allocas(trans, stmt) - - # 9. 翻译函数体(Nonlocal 语句会填充 _nonlocal_names) - if body is not None: - bn2: t.CSizeT = body.__len__() - for bi2 in range(bn2): - stmt2: ast.AST | t.CPtr = body.get(bi2) - if stmt2 is not None: - HandlesBody.translate_stmt(trans, stmt2) - - # 10. 隐式 ret - last_is_return: int = 0 - if body is not None: - bn3: t.CSizeT = body.__len__() - if bn3 > 0: - last_stmt: ast.AST | t.CPtr = body.get(bn3 - 1) - if last_stmt is not None and last_stmt.kind() == ast.ASTKind.Return: - last_is_return = 1 - if last_is_return == 0: - zero_val: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, 0) - llvmlite.build_ret(func_builder, zero_val) - - # 11. 保存嵌套函数的 nonlocal 信息 - nested_nonlocal_count: int = trans._nonlocal_name_count - - # 12. 退出嵌套函数作用域,回到父函数作用域(保留 _nonlocal_names 用于 env 创建) - HandlesVar.exit_scope(trans.SymTab) - trans._cur_func = old_func - trans._cur_builder = old_builder - # NOTE: _nonlocal_names 和 _nonlocal_name_count 仍为嵌套函数的值 - - # 13. 在父函数中创建闭包对象 - parent_builder: llvmlite.IRBuilder | t.CPtr = old_builder - if parent_builder is None: - # 无 builder(模块级嵌套函数?)→ 无法创建闭包,仅恢复状态 - trans._cur_func_name = old_func_name - trans._global_name_count = old_global_count - trans._nonlocal_name_count = old_nonlocal_count - trans._closure_env_count = old_env_count - return 0 - - # 13a. 创建 env: malloc(4 * nested_nonlocal_count) — env 直接存储 i32 值 - env_ptr: llvmlite.Value | t.CPtr = None - if nested_nonlocal_count > 0: - env_size: t.CInt64T = nested_nonlocal_count * 4 - env_size_val: llvmlite.Value | t.CPtr = llvmlite.const_int64(pool, env_size) - if env_size_val is not None: - env_size_val.Next = None - env_ptr = llvmlite.build_call( - parent_builder, "malloc", env_size_val, 1, i8_ptr_ty, 0) - - # 为每个 nonlocal 变量存储值到 env - if env_ptr is not None: - i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool) - i32_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i32_ty) - for ni in range(nested_nonlocal_count): - # 从 _nonlocal_names 缓冲区读取名称 - name_addr: t.CUInt64T = t.CUInt64T(trans._nonlocal_names) + ni * 8 - nl_slot: str | t.CPtr = (t.CVoid | t.CPtr)(name_addr) - nl_name: str = nl_slot[0] - if nl_name is not None: - # 在父函数作用域中查找(Current 已回到父作用域) - var_alloca: llvmlite.Value | t.CPtr = HandlesVar.lookup_var( - trans.SymTab, nl_name) - if var_alloca is not None: - # 加载变量值 - var_ty: llvmlite.LLVMType | t.CPtr = None - if var_alloca.Ty is not None: - var_ty = var_alloca.Ty.Pointee - if var_ty is None: - var_ty = i32_ty - var_val: llvmlite.Value | t.CPtr = llvmlite.build_load( - parent_builder, var_ty, var_alloca) - if var_val is not None: - # GEP to env[ni*4] - offset_val: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, ni * 4) - slot: llvmlite.Value | t.CPtr = llvmlite.build_gep( - parent_builder, i8_ty, env_ptr, offset_val) - if slot is not None: - # bitcast to i32* and store value - slot_typed: llvmlite.Value | t.CPtr = llvmlite.build_bitcast( - parent_builder, slot, i32_ptr_ty) - if slot_typed is not None: - # 类型转换(确保 var_val 是 i32) - coerced_val: llvmlite.Value | t.CPtr = HandlesExpr.coerce_to_type( - parent_builder, var_val, i32_ty) - if coerced_val is not None: - llvmlite.build_store(parent_builder, coerced_val, slot_typed) - - # 13b. 创建闭包结构: malloc(16) - closure_size_val: llvmlite.Value | t.CPtr = llvmlite.const_int64(pool, 16) - if closure_size_val is not None: - closure_size_val.Next = None - closure_ptr: llvmlite.Value | t.CPtr = llvmlite.build_call( - parent_builder, "malloc", closure_size_val, 1, i8_ptr_ty, 0) - if closure_ptr is None: - # malloc 失败,恢复状态 - trans._cur_func_name = old_func_name - trans._global_name_count = old_global_count - trans._nonlocal_name_count = old_nonlocal_count - trans._closure_env_count = old_env_count - return 0 - - # 13c. 存储 fn_ptr 到 offset 0 - # 创建函数指针类型 i32(i8*)* - fn_param_node: llvmlite.ParamNode | t.CPtr = llvmlite.new_param_node(pool, i8_ptr_ty) - fn_func_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Func(pool, i32_ty, fn_param_node, 1) - fn_func_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, fn_func_ty) - - # 创建函数引用 Value(类型为 i32(i8*)*,使用 SHA1 混淆名) - fn_ptr_name: t.CChar | t.CPtr = pool.alloc(64) - if fn_ptr_name is not None: - # SHA1 前缀名含 '.' 需要加引号(如 @"sha1.__closure_func") - if string.strchr(mangled_promoted, '.') is not None: - viperlib.snprintf(fn_ptr_name, 64, "@\"%s\"", mangled_promoted) - else: - viperlib.snprintf(fn_ptr_name, 64, "@%s", mangled_promoted) - fn_ptr_val: llvmlite.Value | t.CPtr = llvmlite.SSAValue(pool, fn_func_ptr_ty, fn_ptr_name) - - # bitcast 函数指针到 i8*(闭包存储 i8* 类型) - fn_as_i8ptr: llvmlite.Value | t.CPtr = llvmlite.build_bitcast( - parent_builder, fn_ptr_val, i8_ptr_ty) - fn_slot: llvmlite.Value | t.CPtr = llvmlite.build_bitcast( - parent_builder, closure_ptr, llvmlite.Ptr(pool, i8_ptr_ty)) - if fn_slot is not None and fn_as_i8ptr is not None: - llvmlite.build_store(parent_builder, fn_as_i8ptr, fn_slot) - - # 13d. 存储 env_ptr 到 offset 8 - eight_val: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, 8) - env_slot_addr: llvmlite.Value | t.CPtr = llvmlite.build_gep( - parent_builder, i8_ty, closure_ptr, eight_val) - if env_slot_addr is not None: - env_slot: llvmlite.Value | t.CPtr = llvmlite.build_bitcast( - parent_builder, env_slot_addr, llvmlite.Ptr(pool, i8_ptr_ty)) - if env_slot is not None: - if env_ptr is not None: - llvmlite.build_store(parent_builder, env_ptr, env_slot) - else: - # 无 nonlocal 变量,存储 null - null_val: llvmlite.Value | t.CPtr = llvmlite.SSAValue(pool, i8_ptr_ty, "null") - llvmlite.build_store(parent_builder, null_val, env_slot) - - # 13e. 将闭包指针存储到父函数的局部变量 {func_name} - closure_alloca: llvmlite.Value | t.CPtr = llvmlite.build_alloca(parent_builder, i8_ptr_ty) - if closure_alloca is not None: - llvmlite.build_store(parent_builder, closure_ptr, closure_alloca) - HandlesVar.define_var(trans.SymTab, func_name, closure_alloca) - - # 14. 恢复 scope names - trans._cur_func_name = old_func_name - trans._global_name_count = old_global_count - trans._nonlocal_name_count = old_nonlocal_count - trans._closure_env_count = old_env_count - - return 1 - - -# ============================================================ -# 创建 LLVM 函数(简单版本,仅声明) -# ============================================================ -def create_function(pool: memhub.MemBuddy | t.CPtr, - mod: llvmlite.LLVMModule | t.CPtr, - name: str, - args_node: ast.AST | t.CPtr, - ret_ty: llvmlite.LLVMType | t.CPtr) -> llvmlite.Function | t.CPtr: - """创建 LLVM 函数并添加参数""" - if name is None or mod is None: - return None - - func: llvmlite.Function | t.CPtr = llvmlite.create_function(pool, mod, name, ret_ty) - if func is None: - return None - - if args_node is not None: - ags: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(args_node) - if ags.args is not None: - alist: list[ast.AST | t.CPtr] | t.CPtr = ags.args - an: t.CSizeT = alist.__len__() - i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool) - for ai in range(an): - arg: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(alist.get(ai)) - if arg is not None and arg.arg is not None: - # t.CVoid 表示空参:跳过 - if arg.annotation is not None: - if arg.annotation.kind() == ast.ASTKind.Attribute: - at_cf: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(arg.annotation) - if at_cf.attr is not None and string.strcmp(at_cf.attr, "CVoid") == 0: - continue - param_ty: llvmlite.LLVMType | t.CPtr = i32_ty - if arg.annotation is not None: - resolved: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type( - pool, arg.annotation, None, None, None) - if resolved is not None: - param_ty = resolved - pname: t.CChar | t.CPtr = pool.alloc(32) - if pname is not None: - viperlib.snprintf(pname, 32, "%%%s", arg.arg) - llvmlite.add_param(pool, func, param_ty, pname) - - return func diff --git a/TransPyV/App/lib/core/Handles/HandlesIf.py b/TransPyV/App/lib/core/Handles/HandlesIf.py deleted file mode 100644 index 64f6af2..0000000 --- a/TransPyV/App/lib/core/Handles/HandlesIf.py +++ /dev/null @@ -1,141 +0,0 @@ -import t, c -from stdint import * -import ast -import llvmlite -import memhub -import string -import stdio -import viperlib -import lib.core.Handles.HandlesBase as HandlesBase -import lib.core.Handles.HandlesTranslator as HT -import lib.core.Handles.HandlesExpr as HandlesExpr -import lib.core.Handles.HandlesBody as HandlesBody - - -# ============================================================ -# HandlesIf - if/elif/else 语句处理(Mixin 继承模式) -# -# 翻译 if 语句为 LLVM IR 控制流: -# br i1 %cond, label %then, label %else -# then: -# ... body ... -# br label %end -# else: -# ... orelse ... -# br label %end -# end: -# ============================================================ - - -@t.NoVTable -class IfHandle(HandlesBase.Mixin): - """if/elif/else 语句处理器:继承 Mixin 获得 Trans 回指针""" - - def __init__(self, trans: HT.Translator | t.CPtr): - self.Trans = trans - - # ============================================================ - # Handle - 处理 if 语句,返回新增变量数 - # ============================================================ - def Handle(self, node: ast.AST | t.CPtr) -> int: - """翻译 if/elif/else 语句""" - if node is None: - return 0 - - trans: HT.Translator | t.CPtr = self.Trans - pool: memhub.MemBuddy | t.CPtr = trans.Pool - builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder - func: llvmlite.Function | t.CPtr = trans._cur_func - - if builder is None or func is None: - return 0 - - if_node: ast.If | t.CPtr = (ast.If | t.CPtr)(node) - - # 1. 求值条件表达式 - cond_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( - builder, pool, trans.Module, if_node.test, - trans._funcs, trans._func_count, trans) - - # 2. 转换为 i1 条件 - # Compare/Not 表达式已返回 i1,直接使用;其他类型与 0 比较 - if cond_val is None: - cond_val = llvmlite.const_int32(pool, 0) - cond_bits: int = HandlesExpr.get_llvm_type_bits(cond_val.Ty) - if cond_bits == 1: - cond_i1: llvmlite.Value | t.CPtr = cond_val - else: - zero: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, 0) - cond_i1 = llvmlite.build_icmp( - builder, llvmlite.ICMP_NE, cond_val, zero) - - # 3. 创建基本块(使用 trans._label_counter 生成唯一标签名,不与 SSA 名共享) - cnt: int = trans._label_counter - trans._label_counter = cnt + 1 - - name_buf: t.CChar | t.CPtr = pool.alloc(32) - viperlib.snprintf(name_buf, 32, "if.then.%d", cnt) - then_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf) - - viperlib.snprintf(name_buf, 32, "if.end.%d", cnt) - merge_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf) - - # 检查是否有 else 分支 - has_else: int = 0 - orelse_list: list[ast.AST | t.CPtr] | t.CPtr = if_node.orelse - if orelse_list is not None: - if orelse_list.__len__() > 0: - has_else = 1 - - else_bb: llvmlite.BasicBlock | t.CPtr = None - if has_else == 1: - viperlib.snprintf(name_buf, 32, "if.else.%d", cnt) - else_bb = llvmlite.create_block(pool, func, name_buf) - - # 4. 发射条件分支 - if has_else == 1: - llvmlite.build_cond_br(builder, cond_i1, then_bb, else_bb) - else: - llvmlite.build_cond_br(builder, cond_i1, then_bb, merge_bb) - - # 5. 翻译 then body - llvmlite.position_at_end(builder, then_bb) - body: list[ast.AST | t.CPtr] | t.CPtr = if_node.children - if body is not None: - body_count: t.CSizeT = body.__len__() - for bi in range(body_count): - stmt: ast.AST | t.CPtr = body.get(bi) - if stmt is not None: - HandlesBody.translate_stmt(trans, stmt) - - # then 块未终止则跳到 merge - if llvmlite.builder_cur_block_is_terminated(builder) == 0: - llvmlite.build_br(builder, merge_bb) - - # 6. 翻译 else body(若有) - if has_else == 1: - llvmlite.position_at_end(builder, else_bb) - else_count: t.CSizeT = orelse_list.__len__() - for ei in range(else_count): - stmt: ast.AST | t.CPtr = orelse_list.get(ei) - if stmt is not None: - HandlesBody.translate_stmt(trans, stmt) - if llvmlite.builder_cur_block_is_terminated(builder) == 0: - llvmlite.build_br(builder, merge_bb) - - # 7. 定位到 merge 块继续后续代码 - llvmlite.position_at_end(builder, merge_bb) - return 0 - - -# ============================================================ -# NewIfHandle - 工厂函数 -# ============================================================ -def NewIfHandle(pool: memhub.MemBuddy | t.CPtr, - trans: HT.Translator | t.CPtr) -> IfHandle | t.CPtr: - h: IfHandle | t.CPtr = pool.alloc(IfHandle.__sizeof__()) - if h is None: - return None - string.memset(h, 0, IfHandle.__sizeof__()) - h.Trans = trans - return h diff --git a/TransPyV/App/lib/core/Handles/HandlesImports.py b/TransPyV/App/lib/core/Handles/HandlesImports.py deleted file mode 100644 index 4d9512a..0000000 --- a/TransPyV/App/lib/core/Handles/HandlesImports.py +++ /dev/null @@ -1,596 +0,0 @@ -import t, c -from stdint import * -import ast -import memhub -import string -import stdlib -import viperlib -import stdio -import lib.core.Handles.HandlesBase as HandlesBase -import lib.core.Handles.HandlesTranslator as HT -import lib.core.Handles.HandlesStruct as HandlesStruct - - -# ============================================================ -# HandlesImports - 导入语句处理(Mixin 继承模式) -# -# 管理 _imported_modules 和 _from_imports 字符串 -# 注意:str = bytes = t.CChar | t.CPtr = i8* -# ============================================================ - - -# ============================================================ -# 模块级工具函数(保留供外部调用) -# ============================================================ - -# ============================================================ -# 添加已导入模块名 -# ============================================================ -def add_imported_module(pool: memhub.MemBuddy | t.CPtr, - imported_modules: str, - name: str) -> str: - """记录已导入的模块名,返回新的 imported_modules 字符串指针""" - if name is None: - return imported_modules - if imported_modules is None: - nlen: t.CSizeT = string.strlen(name) - buf: t.CChar | t.CPtr = pool.alloc(nlen + 1) - if buf is not None: - string.strcpy(buf, name) - return buf - return None - else: - old_len: t.CSizeT = string.strlen(imported_modules) - name_len: t.CSizeT = string.strlen(name) - new_len: t.CSizeT = old_len + 1 + name_len - buf2: t.CChar | t.CPtr = pool.alloc(new_len + 1) - if buf2 is not None: - string.strcpy(buf2, imported_modules) - buf2[old_len] = ' ' - string.strcpy(buf2 + old_len + 1, name) - return buf2 - return imported_modules - - -# ============================================================ -# 检查模块是否已导入 -# ============================================================ -def is_module_imported(imported_modules: str, name: str) -> int: - """检查模块是否已导入(词边界精确匹配,避免子串误匹配)""" - if name is None or imported_modules is None: - return 0 - name_len: t.CSizeT = string.strlen(name) - cur: t.CChar | t.CPtr = imported_modules - total_len: t.CSizeT = string.strlen(imported_modules) - ci: t.CSizeT = 0 - while ci < total_len: - while ci < total_len and cur[ci] == ' ': - ci += 1 - if ci >= total_len: - break - word_start: t.CSizeT = ci - while ci < total_len and cur[ci] != ' ': - ci += 1 - word_len: t.CSizeT = ci - word_start - if word_len == name_len: - match: int = 1 - for ei in range(name_len): - if cur[word_start + ei] != name[ei]: - match = 0 - break - if match == 1: - return 1 - return 0 - - -# ============================================================ -# 添加 from-import 名称映射 -# ============================================================ -def add_from_import(pool: memhub.MemBuddy | t.CPtr, - from_imports: str, - local_name: str, - module_name: str, - original_name: str = None) -> str: - """添加 from-import 映射,返回新的 from_imports 字符串 - - 格式: - 无别名: "local_name:module_name" - 有别名: "local_name:module_name:original_name" - (original_name 为源模块中的真实函数名,用于跨模块 SHA1 修饰) - """ - if local_name is None or module_name is None: - return from_imports - entry: t.CChar | t.CPtr = pool.alloc(256) - if entry is None: - return from_imports - if original_name is not None and original_name != local_name: - viperlib.snprintf(entry, 256, "%s:%s:%s", local_name, module_name, original_name) - else: - viperlib.snprintf(entry, 256, "%s:%s", local_name, module_name) - if from_imports is None: - return entry - else: - old_len: t.CSizeT = string.strlen(from_imports) - entry_len: t.CSizeT = string.strlen(entry) - new_len: t.CSizeT = old_len + 1 + entry_len - buf: t.CChar | t.CPtr = pool.alloc(new_len + 1) - if buf is not None: - string.strcpy(buf, from_imports) - buf[old_len] = ' ' - string.strcpy(buf + old_len + 1, entry) - return buf - return from_imports - - -# ============================================================ -# 查找 from-import 名称 → 返回原始函数名(别名场景) -# -# 对于 from X import Y as Z,返回 Y(源模块中的真实函数名)。 -# 无别名时返回 None(local_name 即为原始名)。 -# ============================================================ -def lookup_from_import_original(from_imports: str, - local_name: str) -> str: - """查找 from-import 别名对应的原始函数名,返回 None=无别名或未找到""" - if local_name is None or from_imports is None: - return None - name_len: t.CSizeT = string.strlen(local_name) - cur: t.CChar | t.CPtr = from_imports - ci: t.CSizeT = 0 - total_len: t.CSizeT = string.strlen(from_imports) - while ci < total_len: - # 跳过前导空格 - while ci < total_len and cur[ci] == ' ': - ci += 1 - if ci >= total_len: - break - # 找到第一个 ':' 的位置 - colon1: t.CSizeT = ci - while colon1 < total_len and cur[colon1] != ':' and cur[colon1] != ' ': - colon1 += 1 - if colon1 >= total_len or cur[colon1] != ':': - break - entry_name_len: t.CSizeT = colon1 - ci - # 跳过 star import - if entry_name_len == 1 and cur[ci] == '*': - ci = colon1 - while ci < total_len and cur[ci] != ' ': - ci += 1 - continue - # 比较名称 - if entry_name_len == name_len: - match: int = 1 - ei: t.CSizeT = 0 - while ei < name_len: - if cur[ci + ei] != local_name[ei]: - match = 0 - break - ei += 1 - if match == 1: - # 找到匹配,检查是否有第三个字段(原始名) - pos: t.CSizeT = colon1 + 1 - # 跳过模块名 - while pos < total_len and cur[pos] != ':' and cur[pos] != ' ' and cur[pos] != '\0': - pos += 1 - if pos < total_len and cur[pos] == ':': - # 有第三个字段: original_name - orig_start: t.CSizeT = pos + 1 - orig_end: t.CSizeT = orig_start - while orig_end < total_len and cur[orig_end] != ' ' and cur[orig_end] != '\0': - orig_end += 1 - orig_len: t.CSizeT = orig_end - orig_start - if orig_len > 0: - orig_buf: str = cur + orig_start - # 返回指向内部的指针(调用方需在使用期内保持 from_imports 有效) - return orig_buf - return None - return None - # 跳到下一个条目 - ci = colon1 - while ci < total_len and cur[ci] != ' ': - ci += 1 - return None - - -# ============================================================ -# 查找 from-import 名称 → 返回模块名或 None -# -# allow_star_fallback: 是否允许 star import 回退(默认 1=允许)。 -# 当查询明确模块名(如 "BuildPipeline")时,应传 0 禁用回退, -# 避免被 star import 模块名误导(如 from stdint import * 后 -# 查询 "BuildPipeline" 错误回退到 "stdint")。 -# ============================================================ -def lookup_from_import(from_imports: str, name: str, - allow_star_fallback: int = 1) -> str: - """查找 from-import 名称,返回模块名或 None - - 支持 star import: 如果 from_imports 中有 "*:module" 条目, - 且未找到精确名称匹配,且 allow_star_fallback != 0,则返回 star import 的模块名。 - """ - if name is None or from_imports is None: - return None - name_len: t.CSizeT = string.strlen(name) - cur: t.CChar | t.CPtr = from_imports - ci: t.CSizeT = 0 - total_len: t.CSizeT = string.strlen(from_imports) - star_mod: str = None - while ci < total_len: - # 跳过前导空格 - while ci < total_len and cur[ci] == ' ': - ci += 1 - if ci >= total_len: - break - # 找到 ':' 的位置 - colon_pos: t.CSizeT = ci - while colon_pos < total_len and cur[colon_pos] != ':' and cur[colon_pos] != ' ': - colon_pos += 1 - if colon_pos >= total_len or cur[colon_pos] != ':': - break - entry_name_len: t.CSizeT = colon_pos - ci - # 检测 star import ("*:module") - if entry_name_len == 1 and cur[ci] == '*': - mod_start: t.CSizeT = colon_pos + 1 - mod_end: t.CSizeT = mod_start - while mod_end < total_len and cur[mod_end] != ' ' and cur[mod_end] != '\0' and cur[mod_end] != ':': - mod_end += 1 - star_mod = cur + mod_start - # 比较名称 - elif entry_name_len == name_len: - match: int = 1 - ei: t.CSizeT = 0 - while ei < name_len: - if cur[ci + ei] != name[ei]: - match = 0 - break - ei += 1 - if match == 1: - mod_start2: t.CSizeT = colon_pos + 1 - mod_end2: t.CSizeT = mod_start2 - # 模块名结束于: 空格、null、或第二个':'(别名格式的分隔符) - while mod_end2 < total_len and cur[mod_end2] != ' ' and cur[mod_end2] != '\0' and cur[mod_end2] != ':': - mod_end2 += 1 - return cur + mod_start2 - # 跳到下一个条目 - ci = colon_pos - while ci < total_len and cur[ci] != ' ': - ci += 1 - # 未找到精确匹配,仅在允许时回退到 star import - if allow_star_fallback == 0: - return None - return star_mod - - -# ============================================================ -# 全局 re-export 映射表(module_sha1 + func_name → source_module) -# -# 当 ast/__init__.py 中有 from .lexer import _lexer_init 时, -# _lexer_init 被 re-export 为 ast._lexer_init。 -# 跨模块调用 ast._lexer_init(...) 需使用 ast.lexer 的 SHA1 混淆, -# 而非 ast 的 SHA1。 -# -# 数据布局: -# _g_reexport_sha1s: 每条 17 字节(SHA1 16字符 + null) -# _g_reexport_funcs: 每条 64 字节(函数名 + null) -# _g_reexport_srcs: 每条 64 字节(源模块名 + null) -# ============================================================ -MAX_REEXPORT: t.CDefine = 512 - -_g_reexport_sha1s: bytes = None -_g_reexport_funcs: bytes = None -_g_reexport_srcs: bytes = None -_g_reexport_count: int = 0 - - -# ============================================================ -# register_reexport - 注册 re-export 映射 -# -# 在 HandleImportFromNames 中调用:当处理 from .X import Y 时, -# 记录当前模块(通过 ModuleSha1)re-export 了函数 Y,源模块为 X。 -# -# 幂等:重复注册相同映射不会增加条目。 -# 内存用 stdlib.malloc 分配(全局存储器,跨 Phase 持久化)。 -# ============================================================ -def register_reexport(mod_sha1: str, func_name: str, source_module: str) -> int: - """注册 re-export 映射(幂等),返回 0 成功,-1 失败""" - global _g_reexport_sha1s, _g_reexport_funcs, _g_reexport_srcs, _g_reexport_count - if mod_sha1 is None or func_name is None or source_module is None: - return -1 - # 懒初始化 - if _g_reexport_sha1s is None: - _g_reexport_sha1s = stdlib.malloc(MAX_REEXPORT * 17) - _g_reexport_funcs = stdlib.malloc(MAX_REEXPORT * 64) - _g_reexport_srcs = stdlib.malloc(MAX_REEXPORT * 64) - if _g_reexport_sha1s is None or _g_reexport_funcs is None or _g_reexport_srcs is None: - return -1 - string.memset(_g_reexport_sha1s, 0, MAX_REEXPORT * 17) - string.memset(_g_reexport_funcs, 0, MAX_REEXPORT * 64) - string.memset(_g_reexport_srcs, 0, MAX_REEXPORT * 64) - if _g_reexport_count >= MAX_REEXPORT: - return -1 - # 幂等检查:查找是否已存在相同映射 - for i in range(_g_reexport_count): - sidx: t.CSizeT = t.CSizeT(i) * 17 - fidx: t.CSizeT = t.CSizeT(i) * 64 - if string.strcmp(_g_reexport_sha1s + sidx, mod_sha1) == 0: - if string.strcmp(_g_reexport_funcs + fidx, func_name) == 0: - # 已存在,更新 source_module(以防变化) - string.strcpy(_g_reexport_srcs + fidx, source_module) - return 0 - # 添加新条目 - idx2: t.CSizeT = t.CSizeT(_g_reexport_count) * 17 - fidx2: t.CSizeT = t.CSizeT(_g_reexport_count) * 64 - string.strcpy(_g_reexport_sha1s + idx2, mod_sha1) - string.strcpy(_g_reexport_funcs + fidx2, func_name) - string.strcpy(_g_reexport_srcs + fidx2, source_module) - _g_reexport_count += 1 - return 0 - - -# ============================================================ -# lookup_reexport - 查找 re-export 映射 -# -# 给定模块 SHA1 和函数名,返回源模块名(如 "ast.lexer")或 None。 -# 调用方通过 _lookup_module_sha1(source_module) 获取源模块的 SHA1。 -# ============================================================ -def lookup_reexport(mod_sha1: str, func_name: str) -> str: - """查找 re-export 映射,返回源模块名或 None""" - if mod_sha1 is None or func_name is None: - return None - if _g_reexport_sha1s is None or _g_reexport_count <= 0: - return None - for i in range(_g_reexport_count): - sidx: t.CSizeT = t.CSizeT(i) * 17 - fidx: t.CSizeT = t.CSizeT(i) * 64 - if string.strcmp(_g_reexport_sha1s + sidx, mod_sha1) == 0: - if string.strcmp(_g_reexport_funcs + fidx, func_name) == 0: - return _g_reexport_srcs + fidx - return None - - -# ============================================================ -# _resolve_relative_module - 解析相对导入为完整模块名 -# -# 对于 from .X import Y(level=1, module="X")在包 pkg 中: -# 解析为 "pkg.X" -# 对于 from . import Y(level=1, module=None)在包 pkg 中: -# 解析为 "pkg" -# 对于 from ..X import Y(level=2, module="X")在包 pkg.sub 中: -# 解析为 "pkg.X"(先从 pkg.sub 上溯一级到 pkg,再追加 .X) -# -# Args: -# pool: 内存池 -# current_package: 当前文件所属包名(如 "llvmlite"),None 表示无包 -# level: 相对导入级别(0=绝对,1=., 2=..) -# module: ImportFrom 的 module 字段(可能为 None) -# -# Returns: -# 解析后的完整模块名;绝对导入(level<=0)直接返回 module; -# 无法解析时返回 module(回退到原始值) -# ============================================================ -def _resolve_relative_module(pool: memhub.MemBuddy | t.CPtr, - current_package: str, - level: t.CInt, - module: str) -> str: - """解析相对导入为完整模块名""" - if level <= 0: - return module - if current_package is None: - return module - - # 从 current_package 开始,上溯 (level-1) 级 - pkg: str = current_package - up: t.CInt = level - 1 - while up > 0: - pkg_len: t.CSizeT = string.strlen(pkg) - last_dot: t.CSizeT = 0 - found: int = 0 - i: t.CSizeT = 0 - while i < pkg_len: - if pkg[i] == '.': - last_dot = i - found = 1 - i += 1 - if found == 0: - # 无更多父级,包变为空 - pkg = None - break - # 截断到最后一个 '.' 处 - new_pkg: str = pool.alloc(last_dot + 1) - if new_pkg is None: - return module - string.strncpy(new_pkg, pkg, last_dot) - new_pkg[last_dot] = '\0' - pkg = new_pkg - up -= 1 - - if module is None: - # from . import Y → 模块就是包本身 - return pkg - if pkg is None: - # 包已上溯到空,直接用 module - return module - # 拼接 pkg + "." + module - pkg_len2: t.CSizeT = string.strlen(pkg) - mod_len: t.CSizeT = string.strlen(module) - buf: str = pool.alloc(pkg_len2 + 1 + mod_len + 1) - if buf is None: - return module - string.strcpy(buf, pkg) - buf[pkg_len2] = '.' - string.strcpy(buf + pkg_len2 + 1, module) - return buf - - -# ============================================================ -# compute_package_from_relpath - 从相对路径计算包名 -# -# 包名 = 文件所在目录路径,将 / 和 \ 替换为 . -# 对于顶级文件(无目录分隔符),返回 None -# -# 示例: -# "llvmlite/__init__.py" → "llvmlite" -# "llvmlite/__types.py" → "llvmlite" -# "ast/parser.py" → "ast" -# "ast.py" → None(顶级文件) -# ============================================================ -def compute_package_from_relpath(pool: memhub.MemBuddy | t.CPtr, - rel_path: str) -> str: - """从相对路径计算包名(目录部分,分隔符替换为 .)""" - if rel_path is None: - return None - rlen: t.CSizeT = string.strlen(rel_path) - # 找最后一个 / 或 \ - last_sep: t.CSizeT = 0 - found: int = 0 - i: t.CSizeT = 0 - while i < rlen: - ch: t.CChar = rel_path[i] - if ch == '/' or ch == '\\': - last_sep = i - found = 1 - i += 1 - if found == 0: - # 无目录分隔符 → 顶级文件,无包 - return None - # 复制目录部分,将 / 和 \ 替换为 . - dir_len: t.CSizeT = last_sep - buf: str = pool.alloc(dir_len + 1) - if buf is None: - return None - j: t.CSizeT = 0 - while j < dir_len: - ch2: t.CChar = rel_path[j] - if ch2 == '/' or ch2 == '\\': - buf[j] = '.' - else: - buf[j] = ch2 - j += 1 - buf[dir_len] = '\0' - return buf - - -# ============================================================ -# ImportsHandle - 导入语句处理器(Mixin 继承模式) -# -# 方法版本:直接更新 trans._imported_modules / trans._from_imports -# ============================================================ -@t.NoVTable -class ImportsHandle(HandlesBase.Mixin): - """导入语句处理器:继承 Mixin 获得 Trans 回指针""" - - def __init__(self, trans: HT.Translator | t.CPtr): - self.Trans = trans - - # ============================================================ - # HandleImport - 处理 import 语句,更新 trans._imported_modules - # ============================================================ - def HandleImport(self, node: ast.AST | t.CPtr) -> int: - """处理 import 语句,返回 0""" - imp: ast.Import | t.CPtr = (ast.Import | t.CPtr)(node) - if imp is None: - return 0 - names: list[ast.AST | t.CPtr] | t.CPtr = imp.names - if names is None: - return 0 - nn: t.CSizeT = names.__len__() - for ni in range(nn): - alias: ast.Alias | t.CPtr = (ast.Alias | t.CPtr)(names.get(ni)) - if alias is not None and alias.name is not None: - pool_val: memhub.MemBuddy | t.CPtr = self.Trans.Pool - im_val: str = self.Trans._imported_modules - self.Trans._imported_modules = add_imported_module( - pool_val, im_val, alias.name) - # 别名也加入导入模块列表(用于模块限定构造器检查 Module.Class()) - if alias.asname is not None: - self.Trans._imported_modules = add_imported_module( - pool_val, self.Trans._imported_modules, alias.asname) - # 别名也加入 from_imports(asname:fullname), - # 使 HT.func() 跨模块调用能通过 from_imports 查找别名→完整模块名→SHA1 - # 否则 _lookup_module_sha1("HT") 找不到(mod_arr 只存文件名 HandlesTranslator) - self.Trans._from_imports = add_from_import( - pool_val, self.Trans._from_imports, alias.asname, alias.name) - else: - # 无别名时(import a.b.c),将顶层包名 "a" 也加入 _imported_modules, - # 使 a.b.c 作为属性访问的 base 被翻译时能通过 is_module_imported("a") 检查 - dot_ptr: str = string.strstr(alias.name, '.') - if dot_ptr is not None: - pkg_len: t.CSizeT = t.CSizeT(t.CUInt64T(dot_ptr) - t.CUInt64T(alias.name)) - if pkg_len > 0 and pkg_len < 256: - pkg_buf: bytes = pool_val.alloc(pkg_len + 1) - if pkg_buf is not None: - string.strncpy(pkg_buf, alias.name, pkg_len) - pkg_buf[pkg_len] = '\0' - self.Trans._imported_modules = add_imported_module( - pool_val, self.Trans._imported_modules, pkg_buf) - return 0 - - # ============================================================ - # HandleImportFromModule - 处理 from X import Y 的模块部分 - # - # 对相对导入(level > 0),使用 trans.CurrentPackage 解析为 - # 完整模块名(如 __types → llvmlite.__types),确保 .deps.txt - # 记录的模块名与 SHA1 映射表一致。 - # ============================================================ - def HandleImportFromModule(self, node: ast.AST | t.CPtr) -> int: - """处理 from X import Y 的模块部分,更新 trans._imported_modules""" - impf: ast.ImportFrom | t.CPtr = (ast.ImportFrom | t.CPtr)(node) - if impf is None: - return 0 - # 解析模块名:相对导入需补充包前缀 - resolved: str = _resolve_relative_module( - self.Trans.Pool, self.Trans.CurrentPackage, - impf.level, impf.module) - if resolved is not None: - self.Trans._imported_modules = add_imported_module( - self.Trans.Pool, self.Trans._imported_modules, resolved) - return 0 - - # ============================================================ - # HandleImportFromNames - 处理 from X import Y 的名称部分 - # - # 同样使用解析后的完整模块名,确保 from-import 映射 - # (如 LLVMType:llvmlite.__types)能正确查到 SHA1。 - # ============================================================ - def HandleImportFromNames(self, node: ast.AST | t.CPtr) -> int: - """处理 from X import Y 的名称部分,更新 trans._from_imports""" - impf: ast.ImportFrom | t.CPtr = (ast.ImportFrom | t.CPtr)(node) - if impf is None: - return 0 - # 解析模块名:相对导入需补充包前缀 - resolved: str = _resolve_relative_module( - self.Trans.Pool, self.Trans.CurrentPackage, - impf.level, impf.module) - if resolved is not None: - names: list[ast.AST | t.CPtr] | t.CPtr = impf.names - if names is not None: - nn: t.CSizeT = names.__len__() - for ni in range(nn): - alias: ast.Alias | t.CPtr = (ast.Alias | t.CPtr)(names.get(ni)) - if alias is not None and alias.name is not None: - local_name: str = alias.name - orig_name: str = None - if alias.asname is not None: - local_name = alias.asname - orig_name = alias.name - self.Trans._from_imports = add_from_import( - self.Trans.Pool, self.Trans._from_imports, - local_name, resolved, orig_name) - # 命名空间隔离:from-import 的名称标记为可见结构体 - HandlesStruct.add_visible_struct(self.Trans.Pool, local_name) - # 注册 re-export 映射:当前模块 re-export 了 local_name,源模块为 resolved - # 使跨模块调用 module.func() 能解析到正确的源模块 SHA1 - if self.Trans.ModuleSha1 is not None: - register_reexport(self.Trans.ModuleSha1, local_name, resolved) - return 0 - - -# ============================================================ -# NewImportsHandle - 工厂函数 -# ============================================================ -def NewImportsHandle(pool: memhub.MemBuddy | t.CPtr, - trans: HT.Translator | t.CPtr) -> ImportsHandle | t.CPtr: - h: ImportsHandle | t.CPtr = pool.alloc(ImportsHandle.__sizeof__()) - if h is None: - return None - string.memset(h, 0, ImportsHandle.__sizeof__()) - h.Trans = trans - return h diff --git a/TransPyV/App/lib/core/Handles/HandlesMain.py b/TransPyV/App/lib/core/Handles/HandlesMain.py deleted file mode 100644 index 426bad6..0000000 --- a/TransPyV/App/lib/core/Handles/HandlesMain.py +++ /dev/null @@ -1,492 +0,0 @@ -import t, c -from stdint import * -import ast -import llvmlite -import memhub -import string -import stdio -import viperlib -import lib.core.VLogger as VLogger -import lib.core.Handles.HandlesTranslator as HT -import lib.core.Handles.HandlesVar as HandlesVar -import lib.core.Handles.HandlesExprCall as HandlesExprCall -import lib.core.Handles.HandlesImports as HandlesImports -import lib.core.Handles.HandlesBody as HandlesBody -import lib.core.Handles.HandlesFunctions as HandlesFunctions -import lib.core.Handles.HandlesType as HandlesType -import lib.core.Handles.HandlesClassDef as HandlesClassDef -import lib.core.Handles.HandlesAnnAssign as HandlesAnnAssign - - -# ============================================================ -# HandlesMain - 模块级翻译入口 + wrapper main 创建 -# -# 从 translator.py 拆分出来,负责: -# 1. create_wrapper_main() - 无用户 main 时创建包装 main -# 2. translate_children() - 遍历 AST 子节点并分派翻译 -# -# trans 单参模式:所有共享状态从 trans 获取,无需 11 个参数 -# 注意: str = bytes = t.CChar | t.CPtr = i8* -# ============================================================ - - -# ============================================================ -# _register_cexport_from_funcdef - Phase 1a 预注册 CExport/State 函数 -# -# 解决翻译顺序依赖问题:Phase 1b 按字母序翻译,后翻译的模块的 -# CExport 函数无法被先翻译的模块正确识别为裸名调用。 -# Phase 1a 预注册所有 CExport/State 函数名到全局表。 -# ============================================================ -def _register_cexport_from_funcdef(trans: HT.Translator | t.CPtr, - node: ast.AST | t.CPtr) -> int: - """预注册 CExport/State 函数到全局表(仅注册,不生成 IR)""" - fd: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(node) - if fd is None or fd.name is None: - return 0 - if trans is None or trans.ModuleSha1 is None: - return 0 - - # 检查返回类型是否有 CExport 或 State 标记 - has_export: int = 0 - has_state: int = 0 - if fd.returns is not None: - has_export = HandlesType.has_decorator_marker(fd.returns, "CExport") - has_state = HandlesType.has_decorator_marker(fd.returns, "State") - - if has_export != 0 or has_state != 0: - HandlesExprCall.register_cexport_func(trans.ModuleSha1, fd.name) - - return 0 - - -# ============================================================ -# translate_children - 遍历 AST 子节点并分派翻译 -# -# 对应 TransPyC translator._translate_children() -# 共享状态从 trans 获取,imported_modules/from_imports 更新到 trans -# ============================================================ -def translate_children(trans: HT.Translator | t.CPtr, - tree: ast.AST | t.CPtr) -> int: - """遍历 tree.children 并翻译每个子节点 - - Args: - trans: 翻译器(含所有共享状态) - tree: AST 模块节点 - - Returns: - t.CInt: 新增的变量数 - """ - ch: list[ast.AST | t.CPtr] | t.CPtr = tree.children - if ch is None: - return 0 - - cn_count: t.CSizeT = ch.__len__() - added_total: int = 0 - - for ci in range(cn_count): - child: ast.AST | t.CPtr = ch.get(ci) - if child is None: continue - kd: int = child.kind() - - # _declare_only == 0 时,_translate_module_level 已预处理导入语句, - # 此处跳过避免重复处理(from_imports 条目重复) - if trans._declare_only == 0 and (kd == ast.ASTKind.Import or kd == ast.ASTKind.ImportFrom): - continue - if kd == ast.ASTKind.Import: - trans.ImportsH.HandleImport(child) - elif kd == ast.ASTKind.ImportFrom: - trans.ImportsH.HandleImportFromModule(child) - trans.ImportsH.HandleImportFromNames(child) - elif kd == ast.ASTKind.FunctionDef: - # Phase 1a 声明模式:只注册 CExport/State 函数到全局表(解决翻译顺序依赖) - # Phase 1b 全量翻译:正常翻译函数体 - if trans._declare_only == 0: - added: int = HandlesFunctions.translate_function_def(trans, child) - added_total += added - elif trans._declare_only == 1: - _register_cexport_from_funcdef(trans, child) - elif kd == ast.ASTKind.ClassDef: - # ClassDef 在模块级直接处理(不需要 builder) - # _declare_only=2(import扫描模式)时跳过,只处理 import 依赖 - if trans._declare_only != 2: - HandlesClassDef.translate_class_def(trans, child) - elif trans._declare_only == 0 and trans._cur_builder is not None: - # 有 builder → 委托 HandlesBody 分派 - added = HandlesBody.translate_stmt(trans, child) - added_total += added - elif kd == ast.ASTKind.AnnAssign and trans._declare_only != 2: - # 模块级 AnnAssign - # _declare_only=2(import扫描模式)时跳过 - # _declare_only=1(struct注册模式)时只处理 CDefine(在 handle_module_level_var 内部判断) - # _declare_only=0(全量翻译)时处理所有模块级 AnnAssign - added = handle_module_level_var(trans, child) - added_total += added - elif trans._declare_only == 0 and kd == ast.ASTKind.Assign: - # 无 builder 的模块级 Assign → 创建全局变量(仅全量翻译模式) - added = handle_module_level_var(trans, child) - added_total += added - - return added_total - - -# ============================================================ -# _build_array_initializer_text - 从 AST List 生成 LLVM IR 数组初始化器 -# -# 生成格式: [N x elem_ty] [elem_ty val0, elem_ty val1, ...] -# 用于模块级 t.CArray 列表字面量初始化(不依赖 builder,直接生成常量初始化器) -# ============================================================ -def _build_array_initializer_text(pool: memhub.MemBuddy | t.CPtr, - var_ty: llvmlite.LLVMType | t.CPtr, - list_node: ast.List | t.CPtr) -> str: - """从 AST List 节点生成 LLVM IR 数组初始化器文本,None 失败""" - if var_ty is None or list_node is None: - return None - - # 重新进行类型转换,确保 TPV 编译器正确识别 ast.List 类型 - # (避免 init_list_node 初始值为 None 时类型推断退化为 t.CPtr) - ln: ast.List | t.CPtr = (ast.List | t.CPtr)(list_node) - if ln is None: - return None - - # 从 var_ty 提取数组元素类型和数量 - elem_ty: llvmlite.LLVMType | t.CPtr = None - arr_count: t.CInt = 0 - match var_ty: - case llvmlite.LLVMType.Array(et, cnt): - elem_ty = et - arr_count = cnt - - if elem_ty is None or arr_count <= 0: - return None - - # 确定元素类型的 IR 表示 - elem_ir_ty: str = "i8" - match elem_ty: - case llvmlite.LLVMType.Int(bits): - if bits == 8: - elem_ir_ty = "i8" - elif bits == 16: - elem_ir_ty = "i16" - elif bits == 32: - elem_ir_ty = "i32" - elif bits == 64: - elem_ir_ty = "i64" - - # 获取列表元素(通过 ln.elts 而非 list_node.elts,确保类型正确识别) - elts: list[ast.AST | t.CPtr] | t.CPtr = ln.elts - if elts is None: - return None - elts_count: t.CSizeT = elts.__len__() - - # 计算缓冲区大小: 每个元素最多 "i32 -9223372036854775808, " 约 26 字符 - buf_size: t.CSizeT = 64 + elts_count * 32 - buf: t.CChar | t.CPtr = pool.alloc(buf_size) - if buf is None: - return None - - # 写入前缀: "["(类型前缀由 _print_global 输出,初始化器只需元素列表) - written: t.CInt = viperlib.snprintf(buf, buf_size, "[") - pos: t.CSizeT = t.CSizeT(written) - - # 逐个元素写入 - i: t.CSizeT = 0 - while i < elts_count: - elem_node: ast.AST | t.CPtr = elts.get(i) - # 直接从 Constant 节点提取 int_val(避免 extract_cdefine_int_value 的 t.CInt 截断) - elem_val: t.CInt64T = 0 - if elem_node is not None: - ek: int = elem_node.kind() - if ek == ast.ASTKind.Constant: - ec: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(elem_node) - if ec is not None and ec.const_kind == ast.CONST_INT: - elem_val = ec.int_val - elif ek == ast.ASTKind.UnaryOp: - # 负数: UnaryOp(USub, Constant) - elem_val = HandlesAnnAssign.extract_cdefine_int_value(elem_node) - if i > 0: - written = viperlib.snprintf(buf + pos, buf_size - pos, ", ") - pos += t.CSizeT(written) - written = viperlib.snprintf(buf + pos, buf_size - pos, "%s %lld", elem_ir_ty, elem_val) - pos += t.CSizeT(written) - i += 1 - - # 写入后缀 "]" - viperlib.snprintf(buf + pos, buf_size - pos, "]") - return buf - - -# ============================================================ -# _build_string_ptr_initializer - 为字符串字面量初始化指针类型全局变量 -# -# 创建内部字符串常量全局 @.str.{var_name} = private constant [len+1 x i8] c"...\00" -# 返回 GEP 初始化器文本: getelementptr inbounds ([len+1 x i8], [len+1 x i8]* @.str.{var_name}, i32 0, i32 0) -# 用于 b64_tab: t.CArray[t.CChar, None] = "ABC..." 等字符串初始化指针类型 -# ============================================================ -def _build_string_ptr_initializer(pool: memhub.MemBuddy | t.CPtr, - mod: llvmlite.LLVMModule | t.CPtr, - var_name: str, - str_val: str) -> str: - """为字符串字面量创建内部常量全局并返回 GEP 初始化器文本,None 失败""" - if str_val is None or var_name is None: - return None - - # 构造内部字符串常量名称: .str.{var_name} - str_name_buf: t.CChar | t.CPtr = pool.alloc(64) - if str_name_buf is None: - return None - viperlib.snprintf(str_name_buf, 64, ".str.%s", var_name) - - # 调用 llvmlite.create_global_string 创建字符串常量全局 - str_gv: llvmlite.GlobalVariable | t.CPtr = llvmlite.create_global_string( - pool, mod, str_name_buf, str_val) - if str_gv is None: - return None - - # 生成 GEP 初始化器文本 - str_len: t.CSizeT = string.strlen(str_val) - init_buf: t.CChar | t.CPtr = pool.alloc(128) - if init_buf is None: - return None - viperlib.snprintf(init_buf, 128, - "getelementptr inbounds ([%d x i8], [%d x i8]* @%s, i32 0, i32 0)", - str_len + 1, str_len + 1, str_name_buf) - return init_buf - - -# ============================================================ -# handle_module_level_var - 模块级变量声明 → 创建 LLVM 全局变量 -# -# 当用户已定义 main(无 wrapper main builder)时,模块级 -# AnnAssign/Assign 创建全局变量 @var_name 并注册到 SymTab 模块作用域 -# 支持整数、列表字面量、字符串字面量初始值 -# ============================================================ -def handle_module_level_var(trans: HT.Translator | t.CPtr, - node: ast.AST | t.CPtr) -> int: - """处理模块级变量声明,创建全局变量""" - pool: memhub.MemBuddy | t.CPtr = trans.Pool - mod: llvmlite.LLVMModule | t.CPtr = trans.Module - - # CDefine 注解: 编译期常量,不创建全局变量 - # 注册到全局 CDefine 表供 t.CArray[elem_ty, NAME] 解析 - k: int = node.kind() - if k == ast.ASTKind.AnnAssign: - aa_cd: ast.AnnAssign | t.CPtr = (ast.AnnAssign | t.CPtr)(node) - if aa_cd is not None and aa_cd.target is not None: - if aa_cd.target.kind() == ast.ASTKind.Name: - nm_cd: ast.Name | t.CPtr = (ast.Name | t.CPtr)(aa_cd.target) - if nm_cd.id is not None: - if HandlesAnnAssign.is_cdefine_annotation(aa_cd.annotation) != 0: - val_cd: int = HandlesAnnAssign.extract_cdefine_int_value(aa_cd.value) - HandlesType.register_cdefine_constant(pool, nm_cd.id, val_cd) - return 0 - - # _declare_only=1(struct注册模式)时只处理 CDefine,不创建全局变量 - # CDefine 已在上面处理并返回,到这里说明不是 CDefine,直接跳过 - if trans._declare_only == 1: - return 0 - - var_name: str = None - var_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool) - init_val: t.CInt64T = 0 - init_kind: int = 0 # 0=none, 1=int, 2=list, 3=str - init_str_val: str = None - init_list_node: ast.List | t.CPtr = None - - if k == ast.ASTKind.AnnAssign: - aa: ast.AnnAssign | t.CPtr = (ast.AnnAssign | t.CPtr)(node) - if aa is None or aa.target is None: - return 0 - if aa.target.kind() != ast.ASTKind.Name: - return 0 - nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(aa.target) - var_name = nm.id - # 解析类型 - if aa.annotation is not None: - resolved: llvmlite.LLVMType | t.CPtr = HandlesType.resolve_annotation_type( - pool, aa.annotation, trans._imported_modules, trans._from_imports, trans) - if resolved is not None: - var_ty = resolved - # 解析初始值(支持整数、列表字面量、字符串字面量) - if aa.value is not None: - val_kind: int = aa.value.kind() - if val_kind == ast.ASTKind.Constant: - cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(aa.value) - if cn.const_kind == ast.CONST_INT: - init_val = cn.int_val - init_kind = 1 - elif cn.const_kind == ast.CONST_STR: - init_str_val = cn.str_val - init_kind = 3 - elif val_kind == ast.ASTKind.List: - init_list_node = (ast.List | t.CPtr)(aa.value) - init_kind = 2 - elif k == ast.ASTKind.Assign: - asgn: ast.Assign | t.CPtr = (ast.Assign | t.CPtr)(node) - if asgn is None or asgn.targets is None: - return 0 - targets: list[ast.AST | t.CPtr] | t.CPtr = asgn.targets - if targets.__len__() < 1: - return 0 - t0: ast.AST | t.CPtr = targets.get(0) - if t0 is None or t0.kind() != ast.ASTKind.Name: - return 0 - nm2: ast.Name | t.CPtr = (ast.Name | t.CPtr)(t0) - var_name = nm2.id - if asgn.value is not None: - val_kind2: int = asgn.value.kind() - if val_kind2 == ast.ASTKind.Constant: - cn2: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(asgn.value) - if cn2.const_kind == ast.CONST_INT: - init_val = cn2.int_val - init_kind = 1 - elif cn2.const_kind == ast.CONST_STR: - init_str_val = cn2.str_val - init_kind = 3 - elif val_kind2 == ast.ASTKind.List: - init_list_node = (ast.List | t.CPtr)(asgn.value) - init_kind = 2 - - if var_name is None: - return 0 - - # 检查是否已注册 - existing: llvmlite.Value | t.CPtr = HandlesVar.lookup_module_var( - trans.SymTab, var_name) - if existing is not None: - return 0 - - # 创建全局变量 @var_name - # 先确保 var_ty 中的跨模块结构体类型在模块中有 opaque 声明 - # 否则 @var_name = global %"sha1.ClassName"* zeroinitializer 会报 - # "use of undefined type named 'sha1.ClassName'" 错误 - # (如 _mbuddy: memhub.MemManager | t.CPtr → Ptr(Struct("aeb3...MemManager"))) - llvmlite.module_ensure_opaque_for_type(mod, pool, var_ty) - gv: llvmlite.GlobalVariable | t.CPtr = llvmlite.new_global_variable(pool, var_name, var_ty) - if gv is None: - return 0 - llvmlite.module_add_global(mod, gv) - - # 设置初始值(有初始值时清除 external linkage,因为 LLVM 22+ 不允许 external global 带初始值) - gv.Linkage = None - if init_kind == 1: - # 整数初始值 - init_buf: t.CChar | t.CPtr = pool.alloc(48) - if init_buf is not None: - viperlib.snprintf(init_buf, 48, "%lld", init_val) - gv.Initializer = init_buf - elif init_kind == 2: - # 列表字面量 → 数组初始化器 [N x elem_ty] [elem_ty val0, ...] - arr_init: str = _build_array_initializer_text(pool, var_ty, init_list_node) - if arr_init is not None: - gv.Initializer = arr_init - else: - gv.Initializer = "zeroinitializer" - elif init_kind == 3: - # 字符串字面量 → 创建字符串常量全局 + GEP 引用 - str_init: str = _build_string_ptr_initializer(pool, mod, var_name, init_str_val) - if str_init is not None: - gv.Initializer = str_init - else: - gv.Initializer = "zeroinitializer" - else: - # 使用 zeroinitializer 而非 "0":指针类型必须用 null/zeroinitializer, - # 整数/聚合类型也兼容 zeroinitializer,避免 "integer constant must have integer type" - gv.Initializer = "zeroinitializer" - - # 创建 Value 引用(@var_name, 类型为 var_ty*) - var_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, var_ty) - ref_name: t.CChar | t.CPtr = pool.alloc(64) - if ref_name is not None: - viperlib.snprintf(ref_name, 64, "@%s", var_name) - gv_ref: llvmlite.Value | t.CPtr = llvmlite.SSAValue(pool, var_ptr_ty, ref_name) - - # 注册到模块作用域 - if HandlesVar.define_module_var(trans.SymTab, var_name, gv_ref) == 0: - # 设置 AnnotClassName(联合类型如 Logger|t.CPtr 简化为 Ptr(i8) 时, - # 属性访问需要通过 AnnotClassName 回退到类名查找结构体) - if k == ast.ASTKind.AnnAssign: - aa_ml: ast.AnnAssign | t.CPtr = (ast.AnnAssign | t.CPtr)(node) - if aa_ml is not None and aa_ml.annotation is not None: - cls_nm_ml: str = HandlesType.extract_class_name_from_annotation( - aa_ml.annotation, trans._imported_modules) - if cls_nm_ml is not None: - HandlesVar.set_var_annot_class_name( - trans.SymTab, var_name, cls_nm_ml) - return 1 - return 0 - - -# ============================================================ -# create_wrapper_main - 创建包装 main 函数 -# -# 当用户未定义 main 函数时调用。 -# 创建 main() -> i32 函数 → 设置 trans._cur_func/_cur_builder → -# 预扫描 alloca → 翻译子节点 → ret 0 -# ============================================================ -def create_wrapper_main(trans: HT.Translator | t.CPtr, - tree: ast.AST | t.CPtr, - i32_ty: llvmlite.LLVMType | t.CPtr) -> int: - """创建包装 main 函数并翻译所有顶层语句 - - Args: - trans: 翻译器(含所有共享状态) - tree: AST 模块节点 - i32_ty: i32 LLVMType - - Returns: - t.CInt: 新增的变量数 - """ - pool: memhub.MemBuddy | t.CPtr = trans.Pool - mod: llvmlite.LLVMModule | t.CPtr = trans.Module - - main_func: llvmlite.Function | t.CPtr = llvmlite.create_function( - pool, mod, "main", i32_ty) - if main_func is None: - VLogger.error("CreateFunction main returned NULL", "TR") - return 0 - - entry_blk: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block( - pool, main_func, "entry") - if entry_blk is None: - VLogger.error("CreateBlock returned NULL", "TR") - return 0 - - builder: llvmlite.IRBuilder | t.CPtr = llvmlite.new_builder(pool, main_func) - if builder is None: - VLogger.error("NewBuilder returned NULL", "TR") - return 0 - llvmlite.position_at_end(builder, entry_blk) - - # 设置当前翻译上下文(供 Handle 通过 self.Trans._cur_builder 访问) - trans._cur_func = main_func - trans._cur_builder = builder - - # 预处理模块级变量:为 AnnAssign/Assign 创建 LLVM 全局变量 - # 必须在 pre_scan_allocas 之前执行,否则 PreScan 会创建局部 alloca, - # 导致其他函数通过 SSA 编号引用 wrapper main 的局部变量(无效 IR) - ch: list[ast.AST | t.CPtr] | t.CPtr = tree.children - if ch is not None: - cn_count: t.CSizeT = ch.__len__() - for ci in range(cn_count): - child: ast.AST | t.CPtr = ch.get(ci) - if child is not None: - kd: int = child.kind() - if kd == ast.ASTKind.AnnAssign or kd == ast.ASTKind.Assign: - handle_module_level_var(trans, child) - - # 预扫描顶层语句:为函数内 AnnAssign 提前创建 alloca - # (模块级变量已在上面注册到模块作用域,PreScan 的 lookup_current 会跳过它们) - if ch is not None: - for ci in range(cn_count): - child: ast.AST | t.CPtr = ch.get(ci) - if child is not None: - HandlesBody.pre_scan_allocas(trans, child) - - # 翻译子节点 - added_total: int = translate_children(trans, tree) - - # 返回 0 - zero_val: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, 0) - llvmlite.build_ret(builder, zero_val) - - return added_total diff --git a/TransPyV/App/lib/core/Handles/HandlesNonlocal.py b/TransPyV/App/lib/core/Handles/HandlesNonlocal.py deleted file mode 100644 index 6922f7e..0000000 --- a/TransPyV/App/lib/core/Handles/HandlesNonlocal.py +++ /dev/null @@ -1,127 +0,0 @@ -import t, c -from stdint import * -import ast -import llvmlite -import memhub -import string -import stdio -import lib.core.Handles.HandlesTranslator as HT -import lib.core.Handles.HandlesVar as HandlesVar - - -# ============================================================ -# HandlesNonlocal - nonlocal 变量访问(通过闭包 env) -# -# 闭包 env 结构: {i8* ptr0, i8* ptr1, ...} (每个 nonlocal 变量一个 i8* 指针) -# 指针指向原始变量(可能是 alloca 或全局变量) -# -# 在提升的嵌套函数中: -# 1. 函数签名: define i32 @__closure_{name}(i8* %env) -# 2. 入口处: %env_alloca = alloca i8*; store i8* %env, i8** %env_alloca -# 3. 访问 nonlocal var: -# a. %env_ptr = load i8*, i8** %env_alloca -# b. %addr = gep i8, i8* %env_ptr, i32 (index * 8) -# c. %ptr_addr = bitcast i8* %addr to i8** -# d. %var_ptr_raw = load i8*, i8** %ptr_addr -# e. %var_ptr = bitcast i8* %var_ptr_raw to i32* -# f. read: %val = load i32, i32* %var_ptr -# write: store i32 %new, i32* %var_ptr -# ============================================================ - - -# ============================================================ -# 获取或创建 _env_ptr 变量(存储 env 参数的 alloca) -# ============================================================ -def get_env_ptr_var(trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr: - """获取或创建 _env_ptr 变量(存储闭包 env 指针)""" - env_var: llvmlite.Value | t.CPtr = HandlesVar.lookup_var( - trans.SymTab, "_env_ptr") - if env_var is not None: - return env_var - # 创建 alloca 存储 env - pool: memhub.MemBuddy | t.CPtr = trans.Pool - builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder - i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool) - i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty) - alloca: llvmlite.Value | t.CPtr = llvmlite.build_alloca(builder, i8_ptr_ty) - if alloca is None: - return None - HandlesVar.define_var(trans.SymTab, "_env_ptr", alloca) - return alloca - - -# ============================================================ -# 加载 nonlocal 变量值 → 返回 i32 Value -# -# env 直接存储 i32 值(不是指针),每个 nonlocal 变量占 4 字节 -# ============================================================ -def load_nonlocal_var(trans: HT.Translator | t.CPtr, - name: str) -> llvmlite.Value | t.CPtr: - """从闭包 env 加载 nonlocal 变量值(env 直接存储 i32 值)""" - idx: int = HT.get_nonlocal_index(trans, name) - if idx < 0: - return None - - pool: memhub.MemBuddy | t.CPtr = trans.Pool - builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder - i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool) - i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty) - i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool) - i32_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i32_ty) - - # 1. 加载 env_ptr - env_alloca: llvmlite.Value | t.CPtr = get_env_ptr_var(trans) - if env_alloca is None: - return None - env_ptr: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, i8_ptr_ty, env_alloca) - if env_ptr is None: - return None - - # 2. GEP to offset (idx * 4) — env 直接存储 i32 值 - offset_val: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, idx * 4) - addr: llvmlite.Value | t.CPtr = llvmlite.build_gep(builder, i8_ty, env_ptr, offset_val) - if addr is None: - return None - - # 3. Bitcast to i32* and load - var_ptr: llvmlite.Value | t.CPtr = llvmlite.build_bitcast(builder, addr, i32_ptr_ty) - if var_ptr is None: - return None - return llvmlite.build_load(builder, i32_ty, var_ptr) - - -# ============================================================ -# 获取 nonlocal 变量指针(用于 store) -# -# 返回 env 中 i32 槽位的地址(i32*),用于直接 store -# ============================================================ -def get_nonlocal_var_ptr(trans: HT.Translator | t.CPtr, - name: str) -> llvmlite.Value | t.CPtr: - """获取 nonlocal 变量在 env 中的地址(i32*),用于 store 操作""" - idx: int = HT.get_nonlocal_index(trans, name) - if idx < 0: - return None - - pool: memhub.MemBuddy | t.CPtr = trans.Pool - builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder - i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool) - i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty) - i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool) - i32_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i32_ty) - - # 1. 加载 env_ptr - env_alloca: llvmlite.Value | t.CPtr = get_env_ptr_var(trans) - if env_alloca is None: - return None - env_ptr: llvmlite.Value | t.CPtr = llvmlite.build_load(builder, i8_ptr_ty, env_alloca) - if env_ptr is None: - return None - - # 2. GEP to offset (idx * 4) — env 直接存储 i32 值 - offset_val: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, idx * 4) - addr: llvmlite.Value | t.CPtr = llvmlite.build_gep(builder, i8_ty, env_ptr, offset_val) - if addr is None: - return None - - # 3. Bitcast to i32* and return (直接指向 env 中的 i32 槽位) - return llvmlite.build_bitcast(builder, addr, i32_ptr_ty) diff --git a/TransPyV/App/lib/core/Handles/HandlesReturn.py b/TransPyV/App/lib/core/Handles/HandlesReturn.py deleted file mode 100644 index a41c3f0..0000000 --- a/TransPyV/App/lib/core/Handles/HandlesReturn.py +++ /dev/null @@ -1,117 +0,0 @@ -import t, c -from stdint import * -import ast -import llvmlite -import memhub -import string -import lib.core.Handles.HandlesBase as HandlesBase -import lib.core.Handles.HandlesTranslator as HT -import lib.core.Handles.HandlesExpr as HandlesExpr -import lib.core.Handles.HandlesVar as HandlesVar - - -# ============================================================ -# HandlesReturn - Return 语句处理(Mixin 继承模式) -# ============================================================ - - -@t.NoVTable -class ReturnHandle(HandlesBase.Mixin): - """Return 语句处理器:继承 Mixin 获得 Trans 回指针""" - - def __init__(self, trans: HT.Translator | t.CPtr): - self.Trans = trans - - # ============================================================ - # Handle - 处理 Return 语句,返回 0 - # - # 翻译返回值(若有)并生成 ret 指令 - # ============================================================ - def Handle(self, node: ast.AST | t.CPtr) -> int: - """翻译 Return 语句""" - rt: ast.Return | t.CPtr = (ast.Return | t.CPtr)(node) - if rt is None: - return 0 - - pool: memhub.MemBuddy | t.CPtr = self.Trans.Pool - builder: llvmlite.IRBuilder | t.CPtr = self.Trans._cur_builder - mod: llvmlite.LLVMModule | t.CPtr = self.Trans.Module - - val: llvmlite.Value | t.CPtr = None - if rt.value is not None: - # return self: 直接返回指针(self 是 SSA 参数 Ptr(struct_ty)) - # translate_value 会 load 得到结构体值,但 return self 需要指针本身 - if rt.value.kind() == ast.ASTKind.Name: - ret_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(rt.value) - if ret_nm is not None and ret_nm.id is not None: - if string.strcmp(ret_nm.id, "self") == 0: - self_ptr: llvmlite.Value | t.CPtr = HandlesVar.lookup_var( - self.Trans.SymTab, "self") - if self_ptr is not None: - val = self_ptr - if val is None: - val = HandlesExpr.translate_value( - builder, pool, mod, rt.value, - self.Trans._funcs, self.Trans._func_count, self.Trans) - - # val 为 None 时(裸 return):检查当前函数返回类型 - # void 函数(如 __init__/__before_init__)生成 ret void, - # ptr 函数生成 ret ptr null,否则 ret i32 0 - if val is None: - cur_func: llvmlite.Function | t.CPtr = self.Trans._cur_func - is_void_ret: int = 0 - is_ptr_ret: int = 0 - ret_ty: llvmlite.LLVMType | t.CPtr = None - if cur_func is not None: - ret_ty = llvmlite.function_get_ret_ty(cur_func) - if ret_ty is not None: - match ret_ty: - case llvmlite.LLVMType.Void(): - is_void_ret = 1 - case llvmlite.LLVMType.Ptr(_pe): - is_ptr_ret = 1 - if is_void_ret != 0: - llvmlite.build_ret_void(builder) - return 0 - if is_ptr_ret != 0: - null_val: llvmlite.Value | t.CPtr = llvmlite.ConstNull(pool, ret_ty, "null") - llvmlite.build_ret(builder, null_val) - return 0 - val = llvmlite.const_int32(pool, 0) - - # 类型转换:确保 val 类型与函数返回类型匹配 - # 处理 i1(bool 比较结果)→ i8(t.CBool)等情况 - # i1 → 更宽整数用 zext(bool 语义:1 保持 1,而非 sext 的 0xFF) - # 注意:当 val 是整数而 ret_ty 是 ptr 时(即使 bits 相同,如 i64 vs ptr), - # 也必须 inttoptr 转换,否则 llc 报 "value doesn't match function result type" - cur_func_rt: llvmlite.Function | t.CPtr = self.Trans._cur_func - if cur_func_rt is not None and val is not None and val.Ty is not None: - ret_ty_rt: llvmlite.LLVMType | t.CPtr = llvmlite.function_get_ret_ty(cur_func_rt) - if ret_ty_rt is not None: - val_bits: int = HandlesExpr.get_llvm_type_bits(val.Ty) - ret_bits: int = HandlesExpr.get_llvm_type_bits(ret_ty_rt) - val_is_ptr: int = HandlesExpr.is_ptr_type(val.Ty) - ret_is_ptr: int = HandlesExpr.is_ptr_type(ret_ty_rt) - # ptr 类型不一致性:val 是整数但 ret 是 ptr(或反之),必须转换 - if val_is_ptr != ret_is_ptr: - val = HandlesExpr.coerce_to_type(builder, val, ret_ty_rt) - elif val_bits != 0 and ret_bits != 0 and val_bits != ret_bits: - if val_bits == 1 and val_bits < ret_bits: - val = llvmlite.build_zext(builder, val, ret_ty_rt) - else: - val = HandlesExpr.coerce_to_type(builder, val, ret_ty_rt) - llvmlite.build_ret(builder, val) - return 0 - - -# ============================================================ -# NewReturnHandle - 工厂函数 -# ============================================================ -def NewReturnHandle(pool: memhub.MemBuddy | t.CPtr, - trans: HT.Translator | t.CPtr) -> ReturnHandle | t.CPtr: - h: ReturnHandle | t.CPtr = pool.alloc(ReturnHandle.__sizeof__()) - if h is None: - return None - string.memset(h, 0, ReturnHandle.__sizeof__()) - h.Trans = trans - return h diff --git a/TransPyV/App/lib/core/Handles/HandlesStruct.py b/TransPyV/App/lib/core/Handles/HandlesStruct.py deleted file mode 100644 index 34ccbb8..0000000 --- a/TransPyV/App/lib/core/Handles/HandlesStruct.py +++ /dev/null @@ -1,1179 +0,0 @@ -import t, c -from stdint import * -import memhub -import string -import stdlib -import llvmlite -import stdio -import ast -import hashtable -import viperlib -import lib.core.VLogger as VLogger - - -# ============================================================ -# HandlesStruct - 结构体类型注册和字段查找 -# -# 管理 class 定义的结构体类型信息: -# - 类名 → LLVM StructType -# - 字段名 → 字段索引和类型 -# -# 使用全局数组存储,线性查找(结构体数量通常很少) -# ============================================================ - -STRUCT_MAX: t.CDefine = 512 -FIELD_MAX: t.CDefine = 48 -FIELD_NAME_MAX: t.CDefine = 64 - - -# ============================================================ -# FieldEntry - 字段信息条目 -# ============================================================ -@t.NoVTable -class FieldEntry: - Name: t.CChar | t.CPtr # 字段名(字符串) - Index: int # 字段在结构体中的索引 - Ty: llvmlite.LLVMType | t.CPtr # 字段的 LLVM 类型 - DefaultVal: ast.AST | t.CPtr # 默认值 AST 节点(None=无默认值) - AnnotClassName: t.CChar | t.CPtr # 原始类型注解的类名(str 别名在结构体字段中触发编译器 bug,改用显式联合类型) - - -# ============================================================ -# StructEntry - 结构体注册条目 -# ============================================================ -@t.NoVTable -class StructEntry: - Name: t.CChar | t.CPtr # 类名 - Ty: llvmlite.LLVMType | t.CPtr # LLVM StructType - FieldCount: int # 字段数量 - Fields: FieldEntry | t.CPtr # 字段数组(FIELD_MAX 个槽位) - IsUnion: int # 1=联合体 / 0=普通结构体 - IsOOP: int # 1=OOP结构体(有方法) / 0=纯内存结构体 - HasInit: int # 1=有__init__方法 / 0=无 - HasNew: int # 1=有__new__方法 / 0=无 - HasVTable: int # 1=有虚表 / 0=无虚表 - IsNoVTable: int # 1=明确标记 @t.NoVTable / 0=未标记 - ParentName: t.CChar | t.CPtr # 父类名(None=无父类) - VTableMethodCount: int # 虚表中的方法数量 - VTableMethods: t.CChar | t.CPtr # 虚表方法名数组(每个方法名 str,VTableMethodCount 个) - ModuleSha1: t.CChar | t.CPtr # 定义该类的模块 SHA1(None=无 SHA1) - - -# ============================================================ -# 全局注册表(静态分配) -# ============================================================ -_struct_table: StructEntry | t.CPtr = None -_struct_count: int = 0 - - -# ============================================================ -# 跨模块命名空间隔离:per-file 结构体可见性 -# -# _visible_structs: 当前文件可见的结构体名(HashTable,O(1) 查找) -# _strict_visibility: 1=严格模式(仅本地+import可见)/ 0=宽松模式(全部可见) -# -# 每个文件翻译前调用 reset_visible_structs 重置 -# ============================================================ -_visible_structs: hashtable.HashTable | t.CPtr = None -_strict_visibility: int = 0 - - -# ============================================================ -# reset_visible_structs — 重置可见性状态(每个文件翻译前调用) -# ============================================================ -def reset_visible_structs(pool: memhub.MemBuddy | t.CPtr, strict: int): - """重置可见性状态(每个文件翻译前调用) - - pool: 内存分配器(严格模式下创建 HashTable) - strict: 1=严格模式(用户文件),0=宽松模式(includes 文件) - """ - global _visible_structs - global _strict_visibility - _strict_visibility = strict - if strict != 0: - # 严格模式:创建新的 HashTable 记录可见结构体 - _visible_structs = hashtable.HashTable(pool) - else: - # 宽松模式:全部可见,不需要 HashTable - _visible_structs = None - - -# ============================================================ -# add_visible_struct — 添加可见结构体名 -# ============================================================ -def add_visible_struct(pool: memhub.MemBuddy | t.CPtr, name: str): - """添加可见结构体名(类定义时和 from-import 时调用)""" - global _visible_structs - if name is None: - return - # 宽松模式:全部可见,无需记录 - if _strict_visibility == 0: - return - if _visible_structs is None: - return - # 已存在则跳过(HashTable.__setitem__ 会覆盖,此处提前检查避免重复分配) - if _visible_structs.__contains__(name) != 0: - return - _visible_structs.set_int(name, 1) - - -# ============================================================ -# is_struct_visible — 检查结构体是否在当前文件可见 -# ============================================================ -def is_struct_visible(name: str) -> int: - """检查结构体是否可见,返回 1=可见 / 0=不可见""" - if _strict_visibility == 0: - return 1 - if name is None or _visible_structs is None: - return 0 - return _visible_structs.__contains__(name) - - -# ============================================================ -# 初始化结构体注册表 -# ============================================================ -def init_struct_table(pool: memhub.MemBuddy | t.CPtr) -> int: - """初始化结构体注册表,返回 1 成功""" - global _struct_table - global _struct_count - - if _struct_table is not None: - return 1 - - entry_size: t.CSizeT = StructEntry.__sizeof__() - _struct_table = pool.alloc(entry_size * STRUCT_MAX) - if _struct_table is None: - return 0 - string.memset(_struct_table, 0, entry_size * STRUCT_MAX) - _struct_count = 0 - return 1 - - -# ============================================================ -# _get_struct_entry — 获取第 i 个 StructEntry 槽位 -# ============================================================ -def _get_struct_entry(i: int) -> StructEntry | t.CPtr: - """获取第 i 个结构体条目""" - if _struct_table is None or i < 0 or i >= STRUCT_MAX: - return None - entry_size: t.CSizeT = StructEntry.__sizeof__() - addr: t.CUInt64T = t.CUInt64T(_struct_table) + i * entry_size - return (StructEntry | t.CPtr)(t.CVoid(addr, t.CPtr)) - - -# ============================================================ -# _get_field_entry — 获取结构体中第 i 个 FieldEntry 槽位 -# ============================================================ -def _get_field_entry(struct_entry: StructEntry | t.CPtr, i: int) -> FieldEntry | t.CPtr: - """获取结构体中第 i 个字段条目""" - if struct_entry is None or i < 0 or i >= FIELD_MAX: - return None - field_size: t.CSizeT = FieldEntry.__sizeof__() - addr: t.CUInt64T = t.CUInt64T(struct_entry.Fields) + i * field_size - return (FieldEntry | t.CPtr)(t.CVoid(addr, t.CPtr)) - - -# ============================================================ -# register_struct — 注册结构体类型 -# -# 返回 StructEntry 指针,可用于添加字段 -# ============================================================ -def register_struct(pool: memhub.MemBuddy | t.CPtr, - name: str, - struct_ty: llvmlite.LLVMType | t.CPtr, - sha1: str = None) -> StructEntry | t.CPtr: - """注册结构体类型,返回 StructEntry 指针 - - 用类型指针去重(is 比较),不用类名去重。 - 这样跨模块同名类可以共存,各自有独立的字段定义。 - sha1 参数在注册时直接设置 ModuleSha1(避免 set_struct_sha1 找错 entry)。 - """ - if init_struct_table(pool) == 0: - return None - - # 用类型指针去重(同一类型不重复注册,支持跨模块同名类) - for i in range(_struct_count): - existing: StructEntry | t.CPtr = _get_struct_entry(i) - if existing is not None and existing.Ty is not None: - if existing.Ty is struct_ty: - return existing - - if _struct_count >= STRUCT_MAX: - fb_st: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb_st is not None: - viperlib.snprintf(fb_st, 1024, "table full, cannot register %s", name) - VLogger.error(fb_st, "STRUCT") - return None - - entry: StructEntry | t.CPtr = _get_struct_entry(_struct_count) - if entry is None: - return None - - # 分配字段数组 - field_size: t.CSizeT = FieldEntry.__sizeof__() - entry.Fields = pool.alloc(field_size * FIELD_MAX) - if entry.Fields is None: - return None - string.memset(entry.Fields, 0, field_size * FIELD_MAX) - - # 复制类名 - name_len: t.CSizeT = string.strlen(name) - name_buf: t.CChar | t.CPtr = pool.alloc(name_len + 1) - if name_buf is not None: - string.strcpy(name_buf, name) - entry.Name = name_buf - - entry.Ty = struct_ty - entry.FieldCount = 0 - - # 注册时直接设置 SHA1(避免 set_struct_sha1 跨模块同名时找错 entry) - if sha1 is not None: - sha1_len: t.CSizeT = string.strlen(sha1) - sha1_buf: t.CChar | t.CPtr = pool.alloc(sha1_len + 1) - if sha1_buf is not None: - string.strcpy(sha1_buf, sha1) - entry.ModuleSha1 = sha1_buf - - _struct_count += 1 - return entry - - -# ============================================================ -# set_struct_sha1 — 设置结构体所属模块的 SHA1 -# -# 在翻译类定义时调用,记录类所属模块的 SHA1。 -# 跨模块方法调用时(如 __before_init__/__init__),通过 SHA1 -# 构造正确的函数名("{sha1}.{ClassName}.{method}")。 -# ============================================================ -def set_struct_sha1(pool: memhub.MemBuddy | t.CPtr, - class_name: str, sha1: str) -> int: - """设置结构体所属模块的 SHA1,返回 1=成功 / 0=失败""" - if class_name is None or sha1 is None: - return 0 - entry: StructEntry | t.CPtr = find_struct(class_name) - if entry is None: - return 0 - # 复制 SHA1 字符串(避免悬空指针) - sha1_len: t.CSizeT = string.strlen(sha1) - sha1_buf: t.CChar | t.CPtr = pool.alloc(sha1_len + 1) - if sha1_buf is None: - return 0 - string.strcpy(sha1_buf, sha1) - entry.ModuleSha1 = sha1_buf - return 1 - - -# ============================================================ -# get_struct_sha1 — 获取结构体所属模块的 SHA1 -# -# 跨模块方法调用时使用,返回 None=无 SHA1(本模块定义或无 SHA1) -# ============================================================ -def get_struct_sha1(class_name: str) -> str: - """获取结构体所属模块的 SHA1,返回 None=无 SHA1""" - if class_name is None or _struct_table is None: - return None - entry: StructEntry | t.CPtr = find_struct(class_name) - if entry is None: - return None - return entry.ModuleSha1 - - -# ============================================================ -# add_field — 向结构体添加字段信息 -# ============================================================ -def add_field(pool: memhub.MemBuddy | t.CPtr, - struct_entry: StructEntry | t.CPtr, - field_name: str, - field_ty: llvmlite.LLVMType | t.CPtr, - default_val: ast.AST | t.CPtr = None, - annot_class_name: t.CChar | t.CPtr = None) -> int: - """向结构体添加字段,返回字段索引(-1 失败) - - default_val: 字段默认值 AST 节点(可选,None=无默认值) - annot_class_name: 原始类型注解的类名(可选,用于联合类型字段的方法调用解析) - """ - if struct_entry is None or field_name is None or field_ty is None: - return -1 - - if struct_entry.FieldCount >= FIELD_MAX: - fb_sf: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb_sf is not None: - viperlib.snprintf(fb_sf, 1024, "field table full for %s", struct_entry.Name) - VLogger.error(fb_sf, "STRUCT") - return -1 - - idx: int = struct_entry.FieldCount - fe: FieldEntry | t.CPtr = _get_field_entry(struct_entry, idx) - if fe is None: - return -1 - - # 复制字段名 - name_len: t.CSizeT = string.strlen(field_name) - name_buf: t.CChar | t.CPtr = pool.alloc(name_len + 1) - if name_buf is not None: - string.strcpy(name_buf, field_name) - fe.Name = name_buf - - fe.Index = idx - fe.Ty = field_ty - fe.DefaultVal = default_val - fe.AnnotClassName = annot_class_name - - struct_entry.FieldCount = idx + 1 - return idx - - -# ============================================================ -# get_struct_count — 获取已注册结构体数量(供 Phase2 多遍预注册判断收敛) -# ============================================================ -def get_struct_count() -> int: - """返回当前已注册的结构体数量""" - return _struct_count - - -# ============================================================ -# find_struct — 按类名查找结构体 -# ============================================================ -def find_struct(name: str) -> StructEntry | t.CPtr: - """按类名查找结构体,返回 StructEntry 或 None - - 支持模块限定名(如 "HT.Translator"): - 第一遍精确匹配,第二遍按类名(最后一个 '.' 之后的部分)回退 - """ - if name is None or _struct_table is None: - return None - # 第一遍:精确匹配 - for i in range(_struct_count): - entry: StructEntry | t.CPtr = _get_struct_entry(i) - if entry is not None and entry.Name is not None: - if string.strcmp(entry.Name, name) == 0: - return entry - # 第二遍:类名回退(处理模块限定名 "HT.Translator" → "Translator") - dot_pos: str = string.strrchr(name, '.') - if dot_pos is not None: - class_name: str = dot_pos + 1 - if class_name is not None and class_name[0] != '\0': - for i in range(_struct_count): - entry: StructEntry | t.CPtr = _get_struct_entry(i) - if entry is not None and entry.Name is not None: - if string.strcmp(entry.Name, class_name) == 0: - return entry - return None - - -# ============================================================ -# find_struct_by_module — 按类名 + SHA1 查找结构体 -# -# 跨模块同名类区分:Phase B 重新翻译时,必须找到当前模块 -# 注册的结构体(而非第一个同名条目),否则 struct type、 -# 字段布局、GEP 索引全部错误。 -# ============================================================ -def find_struct_by_module(name: str, sha1: str) -> StructEntry | t.CPtr: - """按类名 + SHA1 查找结构体,返回 StructEntry 或 None - - SHA1 非 None 时:精确匹配 name+sha1,未找到返回 None(不回退,避免跨模块同名找错) - SHA1 为 None 时:回退到 find_struct(name) 按类名查找第一个 - """ - if name is None or _struct_table is None: - return None - if sha1 is not None: - for i in range(_struct_count): - entry: StructEntry | t.CPtr = _get_struct_entry(i) - if entry is not None and entry.Name is not None: - if string.strcmp(entry.Name, name) == 0: - if entry.ModuleSha1 is not None: - if string.strcmp(entry.ModuleSha1, sha1) == 0: - return entry - # SHA1 查找失败:不回退到 find_struct(会返回跨模块同名错误 entry) - # 返回 None 让调用方创建新类型,避免 Phase B 用错误类型短路 - return None - # 无 SHA1:按类名查找第一个 - return find_struct(name) - - -# ============================================================ -# find_struct_by_type — 按类型指针查找结构体(is 身份比较) -# -# 用于 _translate_oop_methods 等已有 struct_ty 的场景, -# 直接用指针身份定位 entry,规避跨模块同名类 find_struct 找错的问题。 -# ============================================================ -def find_struct_by_type(struct_ty: llvmlite.LLVMType | t.CPtr) -> StructEntry | t.CPtr: - """按类型指针查找结构体(is 比较),返回 StructEntry 或 None""" - if struct_ty is None or _struct_table is None: - return None - for i in range(_struct_count): - entry: StructEntry | t.CPtr = _get_struct_entry(i) - if entry is not None and entry.Ty is not None: - if entry.Ty is struct_ty: - return entry - return None - - -# ============================================================ -# lookup_field — 按结构体类型和字段名查找字段信息 -# ============================================================ -def lookup_field(struct_ty: llvmlite.LLVMType | t.CPtr, - field_name: str) -> FieldEntry | t.CPtr: - """按结构体类型和字段名查找字段信息 - - 两遍查找策略(跨模块同名类冲突的根本修复): - 第一遍: 类型指针 is 身份比较(最高优先级,类型唯一确定 entry) - 第二遍: 名称回退(is 未匹配时,按类名/strstr 匹配,字段未找到时 continue) - """ - if struct_ty is None or field_name is None or _struct_table is None: - return None - - # ============================================================ - # 两遍查找策略(跨模块同名类冲突的根本修复): - # - # 第一遍: 用类型指针 is 身份比较(最高优先级) - # - is 匹配唯一确定 entry,字段未找到直接返回 None - # - 规避联合类型 == BUG,且不受遍历顺序影响 - # - # 第二遍: 名称回退(is 未匹配到任何 entry 时才执行) - # - 用于未注册类型或 is 不可靠的场景 - # - 名称匹配但字段未找到时 continue(继续检查其他同名 entry) - # ============================================================ - - # 第一遍: is 身份比较 - for i in range(_struct_count): - entry: StructEntry | t.CPtr = _get_struct_entry(i) - if entry is not None and entry.Ty is not None: - if entry.Ty is struct_ty: - # is 匹配,查找字段 - for fi in range(entry.FieldCount): - fe: FieldEntry | t.CPtr = _get_field_entry(entry, fi) - if fe is not None and fe.Name is not None: - if string.strcmp(fe.Name, field_name) == 0: - return fe - # is 匹配但字段未找到(类型唯一确定,无需继续) - return None - - # 第二遍: 名称回退(is 未匹配到) - ty_name: str = _extract_struct_name(struct_ty) - if ty_name is not None: - for i in range(_struct_count): - entry: StructEntry | t.CPtr = _get_struct_entry(i) - if entry is not None and entry.Name is not None: - matched: int = 0 - if string.strcmp(entry.Name, ty_name) == 0: - matched = 1 - elif string.strstr(ty_name, entry.Name) is not None: - matched = 1 - if matched != 0: - # 查找字段 - for fi in range(entry.FieldCount): - fe: FieldEntry | t.CPtr = _get_field_entry(entry, fi) - if fe is not None and fe.Name is not None: - if string.strcmp(fe.Name, field_name) == 0: - return fe - # 名称匹配但字段未找到,继续检查其他同名 entry(跨模块同名) - continue - # 所有条目都未匹配 - return None - - -# ============================================================ -# lookup_field_by_class — 按类名和字段名查找字段信息 -# ============================================================ -def lookup_field_by_class(class_name: str, - field_name: str, - sha1: str = None) -> FieldEntry | t.CPtr: - """按类名和字段名查找字段信息 - - 优先用 SHA1 匹配(跨模块同名类区分),无 SHA1 时按类名查找第一个 - """ - if class_name is None or field_name is None: - return None - - # 优先用 SHA1 匹配(跨模块同名类区分) - # 支持模块限定名:class_name 可能是 "HT.Translator",entry.Name 是 "Translator" - # 先精确匹配,失败后用 strrchr 提取类名部分回退匹配 - if sha1 is not None: - sha1_matched: int = 0 - # 计算类名回退部分("HT.Translator" → "Translator") - bare_name: str = class_name - dot_pos_lfbc: str = string.strrchr(class_name, '.') - if dot_pos_lfbc is not None: - bare_name = dot_pos_lfbc + 1 - if bare_name is None or bare_name[0] == '\0': - bare_name = class_name - for i in range(_struct_count): - entry: StructEntry | t.CPtr = _get_struct_entry(i) - if entry is not None and entry.Name is not None: - # 精确匹配或类名回退匹配 - name_match: int = 0 - if string.strcmp(entry.Name, class_name) == 0: - name_match = 1 - elif bare_name is not class_name and string.strcmp(entry.Name, bare_name) == 0: - name_match = 1 - if name_match != 0: - if entry.ModuleSha1 is not None: - if string.strcmp(entry.ModuleSha1, sha1) == 0: - sha1_matched = 1 - # SHA1 + 类名匹配,查找字段 - for fi in range(entry.FieldCount): - fe: FieldEntry | t.CPtr = _get_field_entry(entry, fi) - if fe is not None and fe.Name is not None: - if string.strcmp(fe.Name, field_name) == 0: - return fe - return None - - # 回退: 无 SHA1 或 SHA1 匹配失败,按类名查找第一个 - entry = find_struct(class_name) - if entry is None: - # 诊断:目标类未注册 - fb_lfbc: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb_lfbc is not None: - viperlib.snprintf(fb_lfbc, 1024, - "lookup_field_by_class: 类 '%s' 未注册 (struct_count=%d)", - class_name, _struct_count) - VLogger.error(fb_lfbc, "STRUCT") - return None - # 诊断:找到结构体但字段未找到,打印字段表 - fb_fields: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb_fields is not None: - viperlib.snprintf(fb_fields, 1024, - "lookup_field_by_class: 类 '%s' 已注册 (FieldCount=%d) 但字段 '%s' 未找到", - class_name, entry.FieldCount, field_name) - VLogger.error(fb_fields, "STRUCT") - for fi in range(entry.FieldCount): - fe: FieldEntry | t.CPtr = _get_field_entry(entry, fi) - if fe is not None and fe.Name is not None: - fb_fn: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb_fn is not None: - viperlib.snprintf(fb_fn, 1024, " 字段[%d]: %s", fi, fe.Name) - VLogger.error(fb_fn, "STRUCT") - for fi in range(entry.FieldCount): - fe: FieldEntry | t.CPtr = _get_field_entry(entry, fi) - if fe is not None and fe.Name is not None: - if string.strcmp(fe.Name, field_name) == 0: - return fe - # 诊断:找到结构体但字段未找到 - return None - - -# ============================================================ -# get_struct_type — 按类名获取结构体的 LLVM 类型 -# ============================================================ -def get_struct_type(class_name: str) -> llvmlite.LLVMType | t.CPtr: - """按类名获取结构体的 LLVM 类型""" - entry: StructEntry | t.CPtr = find_struct(class_name) - if entry is not None: - return entry.Ty - return None - - -# ============================================================ -# get_field_by_index — 按类名和字段索引获取字段信息 -# -# 用于构造函数 Point(10, 20) 按顺序访问字段 -# ============================================================ -def get_field_by_index(class_name: str, - idx: int) -> FieldEntry | t.CPtr: - """按类名和字段索引获取字段信息""" - if class_name is None: - return None - entry: StructEntry | t.CPtr = find_struct(class_name) - if entry is None: - return None - if idx < 0 or idx >= entry.FieldCount: - return None - return _get_field_entry(entry, idx) - - -# ============================================================ -# struct_has_defaults — 检查结构体是否有任何带默认值的字段 -# ============================================================ -def struct_has_defaults(class_name: str) -> int: - """检查结构体是否有任何带默认值的字段,返回 1=有 / 0=无""" - if class_name is None: - return 0 - entry: StructEntry | t.CPtr = find_struct(class_name) - if entry is None: - return 0 - for fi in range(entry.FieldCount): - fe: FieldEntry | t.CPtr = _get_field_entry(entry, fi) - if fe is not None and fe.DefaultVal is not None: - return 1 - return 0 - - -# ============================================================ -# get_struct_type_from_value — 从 LLVM Value 的类型推断结构体类型 -# -# 如果 value 是 Ptr(Struct(...)),返回 Struct 类型 -# ============================================================ -def _is_struct_type(ty: llvmlite.LLVMType | t.CPtr) -> int: - """检查 ty 是否是 Struct 类型(独立函数,规避嵌套 match 编译器 BUG)""" - if ty is None: - return 0 - match ty: - case llvmlite.LLVMType.Struct(fields, fcount, name): - return 1 - case _: - return 0 - - -def _is_ptr_type(ty: llvmlite.LLVMType | t.CPtr) -> int: - """检查 ty 是否是 Ptr 类型(独立函数,规避嵌套 match 编译器 BUG)""" - if ty is None: - return 0 - match ty: - case llvmlite.LLVMType.Ptr(pointee): - return 1 - case _: - return 0 - - -def _get_ptr_pointee(ty: llvmlite.LLVMType | t.CPtr) -> llvmlite.LLVMType | t.CPtr: - """获取 Ptr 类型的 pointee(独立函数,规避嵌套 match 编译器 BUG)""" - if ty is None: - return None - match ty: - case llvmlite.LLVMType.Ptr(pointee): - return pointee - case _: - return None - - -def get_struct_type_from_value(val: llvmlite.Value | t.CPtr) -> llvmlite.LLVMType | t.CPtr: - """从 Value 的类型推断结构体类型""" - if val is None or val.Ty is None: - return None - match val.Ty: - case llvmlite.LLVMType.Ptr(pointee): - if _is_struct_type(pointee) != 0: - return pointee - return None - case _: - return None - - -# ============================================================ -# 联合体支持函数 -# ============================================================ - -# ============================================================ -# mark_as_union — 标记已注册的结构体为联合体 -# -# 联合体用 Struct([Array(Int8, max_size)]) 表示, -# 注册时用 register_struct 注册类型,再用此函数标记 IsUnion=1 -# ============================================================ -def mark_as_union(name: str) -> int: - """标记已注册的结构体为联合体,返回 1=成功 / 0=失败""" - if name is None: - return 0 - entry: StructEntry | t.CPtr = find_struct(name) - if entry is None: - return 0 - entry.IsUnion = 1 - return 1 - - -# ============================================================ -# is_union_by_name — 按类名检查是否为联合体 -# ============================================================ -def is_union_by_name(name: str) -> int: - """按类名检查是否为联合体,返回 1=是 / 0=否""" - if name is None: - return 0 - entry: StructEntry | t.CPtr = find_struct(name) - if entry is None: - return 0 - return entry.IsUnion - - -# ============================================================ -# is_union_by_type — 按类型指针检查是否为联合体 -# ============================================================ -def is_union_by_type(struct_ty: llvmlite.LLVMType | t.CPtr) -> int: - """按类型指针检查是否为联合体,返回 1=是 / 0=否 - - 先尝试类型指针 == 比较,失败时回退到名称匹配 - """ - if struct_ty is None or _struct_table is None: - return 0 - ty_name: str = _extract_struct_name(struct_ty) - for i in range(_struct_count): - entry: StructEntry | t.CPtr = _get_struct_entry(i) - if entry is not None and entry.Ty is not None: - matched: int = 0 - if entry.Ty is struct_ty: - matched = 1 - elif ty_name is not None and entry.Name is not None: - if string.strcmp(entry.Name, ty_name) == 0: - matched = 1 - elif string.strstr(ty_name, entry.Name) is not None: - matched = 1 - if matched != 0: - return entry.IsUnion - return 0 - - -# ============================================================ -# OOP 支持函数 -# ============================================================ - -# ============================================================ -# mark_as_oop — 标记已注册的结构体为 OOP(有方法) -# ============================================================ -def mark_as_oop(name: str) -> int: - """标记已注册的结构体为 OOP,返回 1=成功 / 0=失败""" - if name is None: - return 0 - entry: StructEntry | t.CPtr = find_struct(name) - if entry is None: - return 0 - entry.IsOOP = 1 - return 1 - - -# ============================================================ -# is_oop_by_name — 按类名检查是否为 OOP 结构体 -# ============================================================ -def is_oop_by_name(name: str) -> int: - """按类名检查是否为 OOP 结构体,返回 1=是 / 0=否""" - if name is None: - return 0 - entry: StructEntry | t.CPtr = find_struct(name) - if entry is None: - return 0 - return entry.IsOOP - - -# ============================================================ -# mark_has_init — 标记结构体拥有 __init__ 方法 -# ============================================================ -def mark_has_init(name: str) -> int: - """标记结构体拥有 __init__ 方法,返回 1=成功 / 0=失败""" - if name is None: - return 0 - entry: StructEntry | t.CPtr = find_struct(name) - if entry is None: - return 0 - entry.HasInit = 1 - return 1 - - -# ============================================================ -# has_init_by_name — 按类名检查是否有 __init__ 方法 -# ============================================================ -def has_init_by_name(name: str) -> int: - """按类名检查是否有 __init__ 方法,返回 1=有 / 0=无""" - if name is None: - return 0 - entry: StructEntry | t.CPtr = find_struct(name) - if entry is None: - return 0 - return entry.HasInit - - -# ============================================================ -# mark_has_new — 标记结构体拥有 __new__ 方法 -# ============================================================ -def mark_has_new(name: str) -> int: - """标记结构体拥有 __new__ 方法,返回 1=成功 / 0=失败""" - if name is None: - return 0 - entry: StructEntry | t.CPtr = find_struct(name) - if entry is None: - return 0 - entry.HasNew = 1 - return 1 - - -# ============================================================ -# has_new_by_name — 按类名检查是否有 __new__ 方法 -# ============================================================ -def has_new_by_name(name: str) -> int: - """按类名检查是否有 __new__ 方法,返回 1=有 / 0=无""" - if name is None: - return 0 - entry: StructEntry | t.CPtr = find_struct(name) - if entry is None: - return 0 - return entry.HasNew - - -# ============================================================ -# get_class_name_by_type — 按 LLVM 类型指针查找类名 -# -# 用于方法调用:从变量类型 Ptr(Struct(...)) 反查类名, -# 以构造 ClassName.method_name 进行方法查找 -# ============================================================ -def get_class_name_by_type(pool: memhub.MemBuddy | t.CPtr, - struct_ty: llvmlite.LLVMType | t.CPtr) -> str: - """按类型指针查找类名,返回类名字符串或 None""" - if struct_ty is None or _struct_table is None: - return None - for i in range(_struct_count): - entry: StructEntry | t.CPtr = _get_struct_entry(i) - if entry is not None and entry.Ty is not None: - if entry.Ty is struct_ty: - return entry.Name - # 回退: 类型指针比较失败时,遍历所有注册的结构体按名称匹配 - # 提取 struct_ty 的 Name 字段(可能是 "SHA1.ClassName" 格式) - ty_name: str = _extract_struct_name(struct_ty) - if ty_name is not None: - for j in range(_struct_count): - entry2: StructEntry | t.CPtr = _get_struct_entry(j) - if entry2 is not None and entry2.Name is not None: - # 构造 "SHA1.ClassName" 格式进行比较 - entry2_sha1: str = entry2.ModuleSha1 - if entry2_sha1 is not None: - full_nm: t.CChar | t.CPtr = pool.alloc(128) - if full_nm is not None: - viperlib.snprintf(full_nm, 128, "%s.%s", entry2_sha1, entry2.Name) - if string.strcmp(full_nm, ty_name) == 0: - return entry2.Name - # 也直接比较类名(struct_ty 的 Name 可能无 SHA1 前缀) - if string.strcmp(entry2.Name, ty_name) == 0: - return entry2.Name - # 最后回退: strstr 检查包含关系 - # ty_name 可能是 "SHA1.Counter",entry2.Name 是 "Counter" - if string.strstr(ty_name, entry2.Name) is not None: - return entry2.Name - return None - - -# ============================================================ -# _extract_struct_name — 从 LLVMType 提取 Struct 变体的 Name 字段 -# ============================================================ -def _extract_struct_name(ty: llvmlite.LLVMType | t.CPtr) -> str: - """从 LLVMType 提取 Struct 变体的 Name 字段,返回 None 非 Struct""" - if ty is None: - return None - match ty: - case llvmlite.LLVMType.Struct(fields, fcount, name): - return name - case _: - return None - - -# ============================================================ -# VTable 支持函数 -# ============================================================ - -# ============================================================ -# mark_has_vtable — 标记结构体拥有虚表 -# ============================================================ -def mark_has_vtable(name: str) -> int: - """标记结构体拥有虚表,返回 1=成功 / 0=失败""" - if name is None: - return 0 - entry: StructEntry | t.CPtr = find_struct(name) - if entry is None: - return 0 - entry.HasVTable = 1 - return 1 - - -# ============================================================ -# has_vtable_by_name — 按类名检查是否有虚表 -# ============================================================ -def has_vtable_by_name(name: str) -> int: - """按类名检查是否有虚表,返回 1=有 / 0=无""" - if name is None: - return 0 - entry: StructEntry | t.CPtr = find_struct(name) - if entry is None: - return 0 - return entry.HasVTable - - -# ============================================================ -# mark_novtable — 标记结构体为 @t.NoVTable -# ============================================================ -def mark_novtable(name: str) -> int: - """标记结构体为 NoVTable,返回 1=成功 / 0=失败""" - if name is None: - return 0 - entry: StructEntry | t.CPtr = find_struct(name) - if entry is None: - return 0 - entry.IsNoVTable = 1 - return 1 - - -# ============================================================ -# is_novtable_by_name — 按类名检查是否为 NoVTable -# ============================================================ -def is_novtable_by_name(name: str) -> int: - """按类名检查是否为 NoVTable,返回 1=是 / 0=否""" - if name is None: - return 0 - entry: StructEntry | t.CPtr = find_struct(name) - if entry is None: - return 0 - return entry.IsNoVTable - - -# ============================================================ -# set_parent_name — 设置父类名 -# ============================================================ -def set_parent_name(name: str, parent_name: str) -> int: - """设置结构体的父类名,返回 1=成功 / 0=失败""" - if name is None: - return 0 - entry: StructEntry | t.CPtr = find_struct(name) - if entry is None: - return 0 - entry.ParentName = parent_name - return 1 - - -# ============================================================ -# get_parent_name — 获取父类名 -# ============================================================ -def get_parent_name(name: str) -> str: - """获取结构体的父类名,返回 None=无父类""" - if name is None: - return None - entry: StructEntry | t.CPtr = find_struct(name) - if entry is None: - return None - return entry.ParentName - - -# ============================================================ -# set_vtable_methods — 设置虚表方法名数组 -# -# methods 是一个 str 数组(每个元素是方法名字符串指针), -# count 是方法数量。数组直接引用,不复制。 -# ============================================================ -def set_vtable_methods(name: str, methods: t.CChar | t.CPtr, count: int) -> int: - """设置虚表方法名数组,返回 1=成功 / 0=失败""" - if name is None: - return 0 - entry: StructEntry | t.CPtr = find_struct(name) - if entry is None: - return 0 - entry.VTableMethods = methods - entry.VTableMethodCount = count - return 1 - - -# ============================================================ -# get_vtable_method_index — 获取方法在虚表中的索引 -# -# 在 VTableMethods 数组中查找方法名,返回索引(-1=未找到) -# ============================================================ -def get_vtable_method_index(name: str, method_name: str) -> int: - """获取方法在虚表中的索引,返回 -1=未找到""" - if name is None or method_name is None: - return -1 - entry: StructEntry | t.CPtr = find_struct(name) - if entry is None or entry.VTableMethods is None: - return -1 - # VTableMethods 字段声明为 t.CChar*,但实际存储的是 t.CSizeT 数组 - # 必须转换为 t.CSizeT* 才能正确读取 8 字节指针值 - methods_arr: t.CSizeT | t.CPtr = (t.CSizeT | t.CPtr)(t.CVoid(entry.VTableMethods, t.CPtr)) - for i in range(entry.VTableMethodCount): - mname_addr: t.CSizeT = methods_arr[i] - if mname_addr == 0: - continue - mname: str = (str | t.CPtr)(t.CVoid(mname_addr, t.CPtr)) - if mname is not None and string.strcmp(mname, method_name) == 0: - return i - return -1 - - -# ============================================================ -# get_vtable_method_count — 获取虚表方法数量 -# ============================================================ -def get_vtable_method_count(name: str) -> int: - """获取虚表方法数量""" - if name is None: - return 0 - entry: StructEntry | t.CPtr = find_struct(name) - if entry is None: - return 0 - return entry.VTableMethodCount - - -# ============================================================ -# get_vtable_method_name — 获取虚表中第 idx 个方法名 -# -# 返回方法名字符串指针,None=越界或未设置 -# ============================================================ -def get_vtable_method_name(name: str, idx: int) -> str: - """获取虚表中第 idx 个方法名,返回 None=越界""" - if name is None or idx < 0: - return None - entry: StructEntry | t.CPtr = find_struct(name) - if entry is None or entry.VTableMethods is None: - return None - if idx >= entry.VTableMethodCount: - return None - methods_arr: t.CSizeT | t.CPtr = (t.CSizeT | t.CPtr)(t.CVoid(entry.VTableMethods, t.CPtr)) - mname_addr: t.CSizeT = methods_arr[idx] - if mname_addr == 0: - return None - return (str | t.CPtr)(t.CVoid(mname_addr, t.CPtr)) - - -# ============================================================ -# get_field_count — 获取结构体字段数量(访问器,绕过 stub 类型限制) -# ============================================================ -def get_field_count(name: str) -> int: - """获取结构体字段数量,返回 -1=未找到""" - if name is None: - return -1 - entry: StructEntry | t.CPtr = find_struct(name) - if entry is None: - return -1 - return entry.FieldCount - - -# ============================================================ -# ensure_struct_def_in_module — 确保跨模块结构体的完整定义在当前模块中可用 -# -# 当局部变量声明为值类型(如 f: File)时,alloca 需要完整类型定义。 -# 如果结构体定义在另一个模块(名称含 SHA1 前缀,如 "0035c95a18d4f8e8.File"), -# 将其完整定义复制到当前模块。module_add_named_type 会用完整定义替换 -# 已存在的 opaque 声明,使 alloca 能正确分配空间。 -# -# Args: -# pool: 内存池 -# mod: 当前 LLVM 模块 -# ty: 变量类型(Struct/Ptr/其他) -# ============================================================ -def ensure_struct_def_in_module(pool: memhub.MemBuddy | t.CPtr, - mod: llvmlite.LLVMModule | t.CPtr, - ty: llvmlite.LLVMType | t.CPtr): - """确保跨模块结构体的完整定义在当前模块中可用(供 alloca 使用) - - 处理两种情况: - 1. Struct 值类型:需要完整定义(供 alloca 分配空间) - 2. Ptr(Struct) 指针类型:需要 pointee 至少有 opaque 声明 - """ - if ty is None or mod is None or pool is None: - return - # 指针类型:确保 pointee 至少有 opaque 声明 - # 用 _is_ptr_type 检查(独立函数,规避嵌套 match BUG) - if _is_ptr_type(ty) != 0: - llvmlite.module_ensure_opaque_for_type(mod, pool, ty) - # 如果 pointee 是 Struct,递归复制完整定义 - # (GEP 访问字段需要 sized 类型,仅 opaque 会导致 llc 报错) - pointee: llvmlite.LLVMType | t.CPtr = _get_ptr_pointee(ty) - if pointee is not None: - ensure_struct_def_in_module(pool, mod, pointee) - return - # 获取结构体名称(非 Struct 类型返回 None) - sname: t.CChar | t.CPtr = llvmlite.get_struct_name(ty) - if sname is None: - return - # 检查是否为跨模块引用(名称包含 '.') - if string.strchr(sname, 46) is None: - return # 非跨模块引用,无需处理 - # 提取类名(第一个 '.' 之后的部分) - # 必须用 strchr 而非 strrchr:泛型特化名如 "list[ast.AST|t.CPtr]" - # 内部含 '.'(ast.AST),strrchr 会错误地把类名解析为 "AST|t.CPtr]" - dot_pos: str = string.strchr(sname, '.') - if dot_pos is None: - return - class_name: str = dot_pos + 1 - if class_name is None or class_name[0] == '\0': - return - # 提取 SHA1(sname 到 dot_pos 之间,用 strlen 避免指针减法) - total_len: t.CSizeT = string.strlen(sname) - class_name_len: t.CSizeT = string.strlen(class_name) - sha1_len: t.CSizeT = total_len - class_name_len - 1 - sha1_buf: t.CChar | t.CPtr = pool.alloc(32) - if sha1_buf is None: - return - string.strncpy(sha1_buf, sname, sha1_len) - sha1_buf[sha1_len] = '\0' - # 按类名 + SHA1 查找结构体定义 - entry: StructEntry | t.CPtr = find_struct_by_module(class_name, sha1_buf) - if entry is None: - # 回退到按类名查找(可能找到不同模块的同名类,但总比没有好) - entry = find_struct(class_name) - if entry is None: - return - if entry.Ty is None: - return - # 将完整定义添加到当前模块(会替换已存在的 opaque 声明) - llvmlite.module_add_named_type(mod, pool, entry.Ty) - # 递归扫描字段类型,确保值类型子结构体(如 WIN32_FIND_DATAA 中的 FILETIME) - # 也有完整定义。指针类型字段只需 opaque 声明(已由 module_ensure_opaque_for_type 处理)。 - _ensure_field_types_in_module(pool, mod, entry.Ty) - - -# ============================================================ -# _ensure_field_types_in_module - 递归扫描结构体字段类型 -# -# 遍历 Struct 的 Fields 链表,对每个值类型子结构体调用 -# ensure_struct_def_in_module。指针/数组/基本类型递归到 pointee/element。 -# ============================================================ -def _ensure_field_types_in_module(pool: memhub.MemBuddy | t.CPtr, - mod: llvmlite.LLVMModule | t.CPtr, - ty: llvmlite.LLVMType | t.CPtr): - """递归扫描类型树,确保值类型子结构体有完整定义""" - if ty is None or mod is None or pool is None: - return - # 用 match 遍历类型(独立函数,规避嵌套 match BUG) - match ty: - case llvmlite.LLVMType.Struct(fields, fcount, sname): - # 遍历字段链表 - if fields is not None: - fld: llvmlite.ParamNode | t.CPtr = fields - while fld is not None: - if fld.Ty is not None: - # 值类型子结构体(如 FILETIME)需要完整定义 - if _is_struct_type(fld.Ty) != 0: - ensure_struct_def_in_module(pool, mod, fld.Ty) - _ensure_field_types_in_module(pool, mod, fld.Ty) - fld = fld.Next - case llvmlite.LLVMType.Ptr(pointee): - # 指针类型:pointee 只需 opaque 声明,不需要完整定义 - # 但如果 pointee 是 Struct,确保 opaque 声明存在 - if pointee is not None: - llvmlite.module_ensure_opaque_for_type(mod, pool, ty) - case llvmlite.LLVMType.Array(elem_ty, acount): - # 数组类型:元素如果是值类型结构体,需要完整定义 - if elem_ty is not None: - _ensure_field_types_in_module(pool, mod, elem_ty) - case _: - pass - - -# ============================================================ -# get_field_name_ptr — 获取 FieldEntry 的字段名指针(访问器) -# ============================================================ -def get_field_name_ptr(fe: FieldEntry | t.CPtr) -> str: - """获取 FieldEntry 的字段名,返回 None=未设置""" - if fe is None: - return None - return fe.Name - - -# ============================================================ -# get_field_type_ptr — 获取 FieldEntry 的字段类型指针(访问器) -# ============================================================ -def get_field_type_ptr(fe: FieldEntry | t.CPtr) -> llvmlite.LLVMType | t.CPtr: - """获取 FieldEntry 的字段类型,返回 None=未设置""" - if fe is None: - return None - return fe.Ty - - -# ============================================================ -# get_field_default_ptr — 获取 FieldEntry 的默认值 AST 指针(访问器) -# ============================================================ -def get_field_default_ptr(fe: FieldEntry | t.CPtr) -> ast.AST | t.CPtr: - """获取 FieldEntry 的默认值 AST 节点,返回 None=无默认值""" - if fe is None: - return None - return fe.DefaultVal - - -# ============================================================ -# get_field_annot_class_name — 获取 FieldEntry 的注解类名(访问器) -# ============================================================ -def get_field_annot_class_name(fe: FieldEntry | t.CPtr) -> str: - """获取 FieldEntry 的原始类型注解类名,返回 None=未设置""" - if fe is None: - return None - return fe.AnnotClassName diff --git a/TransPyV/App/lib/core/Handles/HandlesTranslator.py b/TransPyV/App/lib/core/Handles/HandlesTranslator.py deleted file mode 100644 index 2b7d100..0000000 --- a/TransPyV/App/lib/core/Handles/HandlesTranslator.py +++ /dev/null @@ -1,434 +0,0 @@ -import t, c -from stdint import * -import ast -import llvmlite -import memhub -import string -import stdio -import stdlib -import viperlib -import lib.core.VLogger as VLogger -import lib.core.Handles.HandlesVar as HandlesVar -import lib.core.Handles.HandlesExprCall as HandlesExprCall -import lib.core.Handles.HandlesMain as HandlesMain -import lib.core.Handles.HandlesAssign as HandlesAssign -import lib.core.Handles.HandlesReturn as HandlesReturn -import lib.core.Handles.HandlesImports as HandlesImports -import lib.core.Handles.HandlesAnnAssign as HandlesAnnAssign -import lib.core.Handles.HandlesAugAssign as HandlesAugAssign -import lib.core.Handles.HandlesIf as HandlesIf -import lib.core.Handles.HandlesWhile as HandlesWhile -import lib.core.Handles.HandlesFor as HandlesFor -import lib.core.Handles.HandlesExpr as HandlesExpr -import lib.core.Handles.HandlesFunctions as HandlesFunctions -import lib.Projectrans.Config as Config - -# ============================================================ -# HandlesTranslator - 翻译器状态管理 + 主入口 -# -# 从 translator.py 拆分出来,负责: -# 1. Translator 类 - 状态管理(Module, 变量表, 函数表, 导入) -# 2. translate() - 主翻译入口 -# 3. dump_ir() - IR 输出 -# -# 语句/表达式翻译全部委托给 Handles 模块: -# HandlesMain - wrapper main 创建 + children 遍历 -# HandlesBody - 语句分派 -# HandlesExpr - 表达式翻译 -# HandlesFunctions - 函数定义处理 -# 注意:str = bytes = t.CChar | t.CPtr = i8* -# ============================================================ - -# 常量 -MAX_VARS: t.CDefine = 256 -MAX_FUNCS: t.CDefine = 256 -MAX_GLOBAL_NAMES: t.CDefine = 32 - - -@t.NoVTable -class Translator: - """翻译器:管理编译状态,委托 Handles 模块执行翻译""" - - # LLVM 上下文(共享状态) - Module: llvmlite.LLVMModule | t.CPtr - Pool: memhub.MemBuddy | t.CPtr - - # 函数表 - _funcs: HandlesExprCall.FuncEntry | t.CPtr - _func_count: t.CInt - - # 导入模块跟踪 - _imported_modules: str - _from_imports: str - - # 当前翻译上下文 - _cur_func: llvmlite.Function | t.CPtr - _cur_builder: llvmlite.IRBuilder | t.CPtr - - # 循环控制流目标(break/continue) - _break_bb: llvmlite.BasicBlock | t.CPtr - _continue_bb: llvmlite.BasicBlock | t.CPtr - - # 独立标签计数器(不与 builder.Counter 共享,避免 SSA 编号非单调) - _label_counter: t.CInt - - # global 声明的变量名集合(当前函数内) - _global_names: str - _global_name_count: t.CInt - - # nonlocal 声明的变量名集合(当前函数内) - _nonlocal_names: str - _nonlocal_name_count: t.CInt - - # 闭包相关:当前函数名(用于嵌套函数提升命名) - _cur_func_name: str - - # 模块 SHA1 前缀(16 字符),用于函数名混淆(SHA1 命名空间) - ModuleSha1: str - # 当前文件所属包名(如 "llvmlite"),用于解析相对导入(from . import ...) - # None 表示当前文件是顶级模块(无包),相对导入无法解析 - CurrentPackage: str - # 闭包 env 中的 nonlocal 变量偏移映射(每个 nonlocal 变量在 env 中的字节偏移) - _closure_env_offsets: t.CInt - _closure_env_count: t.CInt - - # 泛型特化上下文:当前正在特化的类型参数名/实参名列表 - # 由 _specialize_generic_class 设置,方法体翻译时用于将 T 替换为具体类型 - # None 表示不在泛型特化上下文中 - GenericTypeParamNames: list[str] | t.CPtr - GenericTypeArgs: list[str] | t.CPtr - - # Phase 1a 声明模式标志:1=只注册 struct/enum/union 不翻译代码体,0=全量翻译 - _declare_only: t.CInt - - # 子 Handle 指针(每个 Handle 一个槽,通过 Mixin 回指针访问本结构体) - AssignH: HandlesAssign.AssignHandle | t.CPtr - ReturnH: HandlesReturn.ReturnHandle | t.CPtr - ImportsH: HandlesImports.ImportsHandle | t.CPtr - AnnAssignH: HandlesAnnAssign.AnnAssignHandle | t.CPtr - AugAssignH: HandlesAugAssign.AugAssignHandle | t.CPtr - IfH: HandlesIf.IfHandle | t.CPtr - WhileH: HandlesWhile.WhileHandle | t.CPtr - ForH: HandlesFor.ForHandle | t.CPtr - ExprH: HandlesExpr.ExprHandle | t.CPtr - ExprCallH: HandlesExprCall.ExprCallHandle | t.CPtr - - # 嵌套作用域符号表 - SymTab: HandlesVar.SymbolTable | t.CPtr - - def __init__(self): - self.Module = None - self.Pool = None - self._funcs = None - self._func_count = 0 - self._cur_func = None - self._cur_builder = None - self._break_bb = None - self._continue_bb = None - self._label_counter = 0 - self._imported_modules = None - self._from_imports = None - self._global_names = None - self._global_name_count = 0 - self._nonlocal_names = None - self._nonlocal_name_count = 0 - self._cur_func_name = None - self.ModuleSha1 = None - self.CurrentPackage = None - self._closure_env_offsets = 0 - self._closure_env_count = 0 - self.GenericTypeParamNames = None - self.GenericTypeArgs = None - self._declare_only = 0 - self.AssignH = None - self.ReturnH = None - self.ImportsH = None - self.AnnAssignH = None - self.AugAssignH = None - self.IfH = None - self.WhileH = None - self.ForH = None - self.ExprH = None - self.ExprCallH = None - self.SymTab = None - - # ============================================================ - # 状态初始化 - # ============================================================ - def _init_state(self, pool: memhub.MemBuddy | t.CPtr): - """初始化变量表、函数表和子 Handle""" - self.Pool = pool - if self._funcs is None: - self._funcs = HandlesExprCall.init_func_table(pool, MAX_FUNCS) - # 嵌套作用域符号表(新版) - if self.SymTab is None: - self.SymTab = HandlesVar.init_symbol_table(pool) - # global/nonlocal 名称集合缓冲区(32 个 char* 指针 = 256 字节) - if self._global_names is None: - self._global_names = stdlib.malloc(MAX_GLOBAL_NAMES * 8) - if self._global_names is not None: - string.memset(self._global_names, 0, MAX_GLOBAL_NAMES * 8) - self._global_name_count = 0 - if self._nonlocal_names is None: - self._nonlocal_names = stdlib.malloc(MAX_GLOBAL_NAMES * 8) - if self._nonlocal_names is not None: - string.memset(self._nonlocal_names, 0, MAX_GLOBAL_NAMES * 8) - self._nonlocal_name_count = 0 - # 创建子 Handle(传入 self 作为 Mixin 回指针) - if self.AssignH is None: - self.AssignH = HandlesAssign.NewAssignHandle(pool, self) - if self.ReturnH is None: - self.ReturnH = HandlesReturn.NewReturnHandle(pool, self) - if self.ImportsH is None: - self.ImportsH = HandlesImports.NewImportsHandle(pool, self) - if self.AnnAssignH is None: - self.AnnAssignH = HandlesAnnAssign.NewAnnAssignHandle(pool, self) - if self.AugAssignH is None: - self.AugAssignH = HandlesAugAssign.NewAugAssignHandle(pool, self) - if self.IfH is None: - self.IfH = HandlesIf.NewIfHandle(pool, self) - if self.WhileH is None: - self.WhileH = HandlesWhile.NewWhileHandle(pool, self) - if self.ForH is None: - self.ForH = HandlesFor.NewForHandle(pool, self) - if self.ExprH is None: - self.ExprH = HandlesExpr.NewExprHandle(pool, self) - if self.ExprCallH is None: - self.ExprCallH = HandlesExprCall.NewExprCallHandle(pool, self) - - # ============================================================ - # 主翻译入口 - # ============================================================ - def translate(self, tree: ast.AST | t.CPtr) -> int: - """将 AST 翻译为 LLVM IR""" - if tree is None: - return 1 - if _mbuddy is None: - return 1 - - pool: memhub.MemBuddy | t.CPtr = _mbuddy - - # 初始化状态 - self._init_state(pool) - - # 创建 LLVM 模块 - mod: llvmlite.LLVMModule | t.CPtr = llvmlite.new_module(pool, "main") - if mod is None: - VLogger.error("NewModule returned NULL", "TR") - return 1 - self.Module = mod - - # 设置目标(优先使用 project.vpj 中的配置) - triple: str = Config.TargetTriple - if triple is None: - triple = "x86_64-pc-windows-msvc" - llvmlite.module_set_target(mod, triple) - - # 类型 - i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool) - i8_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int8(pool) - i8_ptr_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Ptr(pool, i8_ty) - - # 声明 printf - printf_func: llvmlite.Function | t.CPtr = llvmlite.create_declare( - pool, mod, "printf", i32_ty) - if printf_func is None: - VLogger.error("CreateDeclare printf returned NULL", "TR") - return 1 - llvmlite.add_param(pool, printf_func, i8_ptr_ty, "fmt") - printf_func.IsVarArg = 1 - - # 声明 malloc(闭包分配用) - malloc_func: llvmlite.Function | t.CPtr = llvmlite.create_declare( - pool, mod, "malloc", i8_ptr_ty) - if malloc_func is not None: - i64_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int64(pool) - llvmlite.add_param(pool, malloc_func, i64_ty, "size") - - # 检查用户是否定义了 main 函数 - has_user_main: int = 0 - ch: list[ast.AST | t.CPtr] | t.CPtr = tree.children - if ch is not None: - cn_count: t.CSizeT = ch.__len__() - for ci in range(cn_count): - child: ast.AST | t.CPtr = ch.get(ci) - if child is not None and child.kind() == ast.ASTKind.FunctionDef: - fd: ast.FunctionDef | t.CPtr = (ast.FunctionDef | t.CPtr)(child) - if fd is not None and fd.name is not None: - if string.strcmp(fd.name, "main") == 0: - has_user_main = 1 - break - - if self._declare_only != 0: - # Phase 1a-pre(2=import扫描) / Phase 1a(1=struct注册): 只处理模块级,不创建 main 函数和 builder - self._translate_module_level(pool, mod, tree) - elif has_user_main == 0: - # 无用户 main → 只翻译模块级语句,不创建 wrapper main - # 修复:避免每个文件都生成 define i32 @main() 导致链接时 main 冲突 - # 只有包含 def main() 的入口文件才会有 define i32 @main() - self._translate_module_level(pool, mod, tree) - else: - # 用户已定义 main → 委托 HandlesMain 翻译模块级 - self._translate_module_level(pool, mod, tree) - - return 0 - - # ============================================================ - # 包装 main 函数(无用户 main 时)→ 委托 HandlesMain - # ============================================================ - def _translate_wrapper_main(self, pool: memhub.MemBuddy | t.CPtr, - mod: llvmlite.LLVMModule | t.CPtr, - tree: ast.AST | t.CPtr, - i32_ty: llvmlite.LLVMType | t.CPtr): - """委托 HandlesMain.create_wrapper_main() 创建包装 main(trans 单参)""" - added: int = HandlesMain.create_wrapper_main(self, tree, i32_ty) - - # ============================================================ - # 模块级翻译(用户已定义 main)→ 委托 HandlesMain - # ============================================================ - def _translate_module_level(self, pool: memhub.MemBuddy | t.CPtr, - mod: llvmlite.LLVMModule | t.CPtr, - tree: ast.AST | t.CPtr): - """委托 HandlesMain.translate_children() 翻译模块级语句(trans 单参)""" - # 全量翻译模式下,先处理导入语句,再创建前向声明,解决前向引用问题 - if self._declare_only == 0: - # 预处理导入语句,确保 _imported_modules 和 _from_imports 已填充 - # (前向声明需要解析类型注解,如 t.CArray[str] 依赖 t 模块已导入) - ch: list[ast.AST | t.CPtr] | t.CPtr = tree.children - if ch is not None: - cn_count: t.CSizeT = ch.__len__() - for ci in range(cn_count): - child: ast.AST | t.CPtr = ch.get(ci) - if child is None: - continue - kd: int = child.kind() - if kd == ast.ASTKind.Import: - self.ImportsH.HandleImport(child) - elif kd == ast.ASTKind.ImportFrom: - self.ImportsH.HandleImportFromModule(child) - self.ImportsH.HandleImportFromNames(child) - # 预注册模块级变量(AnnAssign/Assign)到 SymTab - # 解决时序问题:class Logger 的 __init__ 引用 _mbuddy 时, - # _mbuddy 的 AnnAssign 在 AST 中位于 class Logger 之后, - # 按 AST 顺序翻译时 _mbuddy 尚未注册 → lookup_var 返回 None → rhs_val is None - # 预处理先于 translate_children 注册所有模块级变量, - # 后续 translate_children 遍历到同一 AnnAssign 时 handle_module_level_var - # 通过 lookup_module_var 检测已存在并跳过(HandlesMain.py:206-209) - if ch is not None: - for ci in range(cn_count): - child: ast.AST | t.CPtr = ch.get(ci) - if child is None: - continue - kd_mv: int = child.kind() - if kd_mv == ast.ASTKind.AnnAssign or kd_mv == ast.ASTKind.Assign: - HandlesMain.handle_module_level_var(self, child) - # 创建前向声明 - HandlesFunctions.forward_declare_functions(self, tree) - added: int = HandlesMain.translate_children(self, tree) - - # ============================================================ - # IR 输出 - # ============================================================ - def dump_ir(self, buf: bytes, size: t.CSizeT, mode: int): - """将 LLVM IR 输出到缓冲区 - - mode: 0=完整, 1=stub(仅声明), 2=text(仅代码) - """ - if self.Module is None or buf is None: - return - if _mbuddy is None: - return - buf[0] = '\0' - llvmlite.LLVMModulePrint(buf, size, self.Module, _mbuddy, mode) - - -# ============================================================ -# global/nonlocal 名称管理(模块级辅助函数) -# ============================================================ -def add_global_name(trans: HT.Translator | t.CPtr, name: str): - """添加一个 global 变量名""" - if trans is None or name is None: - return - if trans._global_name_count >= MAX_GLOBAL_NAMES: - return - if trans._global_names is None: - return - # 检查是否已存在 - if is_global_name(trans, name) != 0: - return - entry_addr: t.CUInt64T = t.CUInt64T(trans._global_names) + trans._global_name_count * 8 - slot_ptr: str | t.CPtr = (t.CVoid | t.CPtr)(entry_addr) - slot_ptr[0] = name - trans._global_name_count += 1 - - -def is_global_name(trans: HT.Translator | t.CPtr, name: str) -> int: - """检查 name 是否在当前函数的 global 集合中""" - if trans is None or name is None or trans._global_names is None: - return 0 - for i in range(trans._global_name_count): - entry_addr: t.CUInt64T = t.CUInt64T(trans._global_names) + i * 8 - slot_ptr: str | t.CPtr = (t.CVoid | t.CPtr)(entry_addr) - entry: str = slot_ptr[0] - if entry is not None: - if string.strcmp(entry, name) == 0: - return 1 - return 0 - - -def add_nonlocal_name(trans: HT.Translator | t.CPtr, name: str): - """添加一个 nonlocal 变量名""" - if trans is None or name is None: - return - if trans._nonlocal_name_count >= MAX_GLOBAL_NAMES: - return - if trans._nonlocal_names is None: - return - if is_nonlocal_name(trans, name) != 0: - return - entry_addr: t.CUInt64T = t.CUInt64T(trans._nonlocal_names) + trans._nonlocal_name_count * 8 - slot_ptr: str | t.CPtr = (t.CVoid | t.CPtr)(entry_addr) - slot_ptr[0] = name - trans._nonlocal_name_count += 1 - trans._closure_env_count += 1 - - -def is_nonlocal_name(trans: HT.Translator | t.CPtr, name: str) -> int: - """检查 name 是否在当前函数的 nonlocal 集合中""" - if trans is None or name is None or trans._nonlocal_names is None: - return 0 - for i in range(trans._nonlocal_name_count): - entry_addr: t.CUInt64T = t.CUInt64T(trans._nonlocal_names) + i * 8 - slot_ptr: str | t.CPtr = (t.CVoid | t.CPtr)(entry_addr) - entry: str = slot_ptr[0] - if entry is not None: - if string.strcmp(entry, name) == 0: - return 1 - return 0 - - -def get_nonlocal_index(trans: HT.Translator | t.CPtr, name: str) -> int: - """获取 nonlocal 变量在 env 中的索引(0-based),找不到返回 -1""" - if trans is None or name is None or trans._nonlocal_names is None: - return -1 - for i in range(trans._nonlocal_name_count): - entry_addr: t.CUInt64T = t.CUInt64T(trans._nonlocal_names) + i * 8 - slot_ptr: str | t.CPtr = (t.CVoid | t.CPtr)(entry_addr) - entry: str = slot_ptr[0] - if entry is not None: - if string.strcmp(entry, name) == 0: - return i - return -1 - - -def clear_scope_names(trans: HT.Translator | t.CPtr): - """清空当前函数的 global/nonlocal 名称集合(进入新函数时调用)""" - if trans is None: - return - trans._global_name_count = 0 - trans._nonlocal_name_count = 0 - trans._closure_env_count = 0 - - -# 全局 mbuddy 指针 -_mbuddy: memhub.MemBuddy | t.CPtr \ No newline at end of file diff --git a/TransPyV/App/lib/core/Handles/HandlesType.py b/TransPyV/App/lib/core/Handles/HandlesType.py deleted file mode 100644 index ecb4f7e..0000000 --- a/TransPyV/App/lib/core/Handles/HandlesType.py +++ /dev/null @@ -1,1387 +0,0 @@ -import t, c -from stdint import * -import ast -import llvmlite -import memhub -import string -import stdio -import sys -import stdlib -import viperlib -import w32.fileio as fileio -import lib.core.VLogger as VLogger -import lib.core.Handles.HandlesTranslator as HT -import lib.core.Handles.HandlesImports as HandlesImports -import lib.core.Handles.HandlesStruct as HandlesStruct - - -# ============================================================ -# HandlesType - 类型映射与解析(模块级纯函数) -# -# str = bytes = t.CChar | t.CPtr = i8* -# ============================================================ - - -# ============================================================ -# 全局当前文件名(每个文件翻译前由 BuildPipeline 设置) -# ============================================================ -_g_current_file: str = None - - -# ============================================================ -# 全局 temp_dir(pyi 文件所在目录,由 BuildPipeline/Phase1 设置) -# -# 用于跨模块 CDefine 常量查找:当当前模块的 CDefine 表中找不到 -# 某个 Name 时,从 from_imports 解析出源模块,再从该模块的 pyi -# 文件中解析 CDefine 常量值。 -# ============================================================ -_g_temp_dir: str = None - - -def set_temp_dir(temp_dir: str) -> None: - """设置全局 temp_dir(每个项目编译开始时由 BuildPipeline/Phase1 设置)""" - global _g_temp_dir - _g_temp_dir = temp_dir - - -def get_temp_dir() -> str: - """获取全局 temp_dir""" - return _g_temp_dir - - -# ============================================================ -# 全局泛型特化上下文(由 _specialize_generic_class 设置/清除) -# -# 当翻译泛型类方法体时,需要将类型参数 T 替换为具体类型。 -# resolve_annotation_type 在解析 Name 节点时检查此上下文。 -# ============================================================ -_g_generic_tp_names: list[str] | t.CPtr = None -_g_generic_type_args: list[str] | t.CPtr = None - - -# ============================================================ -# 全局 CDefine 编译期常量表 -# -# 存储 NAME: t.CDefine = value 定义的常量, -# 供 t.CArray[elem_ty, NAME] 等 编译期类型解析使用。 -# 每个模块翻译开始时由 clear_cdefine_constants 清空。 -# ============================================================ -_g_cdefine_names: list[str] | t.CPtr = None -_g_cdefine_values: list[str] | t.CPtr = None - -# ============================================================ -# 当前模块 SHA1(Phase1 在模块开始翻译前设置,供报错使用) -# ============================================================ -_g_current_module_sha1: str = None - - -def set_current_module_sha1(sha1: str) -> None: - """设置当前正在编译的模块 SHA1(Phase1 在模块开始翻译前调用)""" - global _g_current_module_sha1 - _g_current_module_sha1 = sha1 - - -def register_cdefine_constant(pool: memhub.MemBuddy | t.CPtr, - name: str, value: int) -> None: - """注册 CDefine 编译期常量到本地表 - - 值以十进制字符串存储。注意:value 是 32 位有符号整数, - 0xFFFFFFFF 会存储为 "-1",lookup 时用 found 标志区分"未找到"和值为 -1。 - """ - global _g_cdefine_names, _g_cdefine_values - if _g_cdefine_names is None: - _g_cdefine_names = list[str](pool, 64) - _g_cdefine_values = list[str](pool, 64) - _g_cdefine_names.append(name) - val_buf: str = pool.alloc(32) - if val_buf is not None: - viperlib.snprintf(val_buf, 32, "%d", value) - _g_cdefine_values.append(val_buf) - else: - _g_cdefine_values.append("0") - - -def lookup_cdefine_constant(name: str) -> int: - """查找 CDefine 编译期常量 - - 返回找到的值。由于 -1 是合法值(如 INVALID_HANDLE_VALUE=0xFFFFFFFF=-1), - 用全局 _g_cdefine_found 标志区分"未找到"和值为 -1。 - 调用方应在调用后检查 _g_cdefine_found。 - """ - global _g_cdefine_found - _g_cdefine_found = 0 - if _g_cdefine_names is None: - return 0 - n: t.CSizeT = _g_cdefine_names.__len__() - i: t.CSizeT - for i in range(n): - nm: str = _g_cdefine_names.get(i) - if nm is not None and string.strcmp(nm, name) == 0: - val_str: str = _g_cdefine_values.get(i) - if val_str is not None: - _g_cdefine_found = 1 - return string.atoi(val_str) - return 0 - - -_g_cdefine_found: int = 0 - - -def is_cdefine_found() -> int: - """检查上次 lookup_cdefine_constant 是否找到值""" - return _g_cdefine_found - - -def set_cdefine_found(val: int) -> None: - """设置 cdefine_found 标志(供跨模块查找函数使用)""" - global _g_cdefine_found - _g_cdefine_found = val - - -def clear_cdefine_constants() -> None: - """清空 CDefine 常量表(模块切换时调用)""" - global _g_cdefine_names, _g_cdefine_values - _g_cdefine_names = None - _g_cdefine_values = None - - -# 常量整数表达式计算成功标志(供 _eval_const_int_expr 使用) -_g_const_eval_ok: int = 0 - - -# ============================================================ -# _eval_const_int_expr - 递归计算常量整数表达式 -# -# 支持: -# - Constant (CONST_INT): 整数字面量 -# - Name: CDefine 常量名(通过 lookup_cdefine_constant 查找) -# - BinOp (Add/Sub/Mult/FloorDiv/BitOr/BitAnd): 递归计算左右操作数 -# -# 成功: 设置 _g_const_eval_ok=1, 返回计算值 -# 失败: 设置 _g_const_eval_ok=0, 返回 0 -# -# 用于 t.CArray count 的静态计算,如 2 * ZHUFF_MAX_CODES -# ============================================================ -def _eval_const_int_expr(node: ast.AST | t.CPtr) -> int: - """递归计算常量整数表达式""" - global _g_const_eval_ok - if node is None: - _g_const_eval_ok = 0 - return 0 - k: int = node.kind() - - # Constant: 整数字面量 - if k == ast.ASTKind.Constant: - cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(node) - if cn.const_kind == ast.CONST_INT: - _g_const_eval_ok = 1 - return cn.int_val - _g_const_eval_ok = 0 - return 0 - - # Name: CDefine 常量名 - if k == ast.ASTKind.Name: - nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(node) - if nm.id is None: - _g_const_eval_ok = 0 - return 0 - val: int = lookup_cdefine_constant(nm.id) - if is_cdefine_found() == 0: - _g_const_eval_ok = 0 - return 0 - _g_const_eval_ok = 1 - return val - - # BinOp: 算术/位运算 - if k == ast.ASTKind.BinOp: - bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(node) - # 递归计算左操作数 - lv: int = _eval_const_int_expr(bop.left) - if _g_const_eval_ok == 0: - return 0 - # 递归计算右操作数 - rv: int = _eval_const_int_expr(bop.right) - if _g_const_eval_ok == 0: - return 0 - # 根据运算符执行计算 - if bop.op == ast.OpKind.Add: - _g_const_eval_ok = 1 - return lv + rv - if bop.op == ast.OpKind.Sub: - _g_const_eval_ok = 1 - return lv - rv - if bop.op == ast.OpKind.Mult: - _g_const_eval_ok = 1 - return lv * rv - if bop.op == ast.OpKind.FloorDiv: - if rv == 0: - _g_const_eval_ok = 0 - return 0 - _g_const_eval_ok = 1 - return lv // rv - if bop.op == ast.OpKind.BitOr: - _g_const_eval_ok = 1 - return lv | rv - if bop.op == ast.OpKind.BitAnd: - _g_const_eval_ok = 1 - return lv & rv - # 不支持的运算符 - _g_const_eval_ok = 0 - return 0 - - # 不支持的节点类型 - _g_const_eval_ok = 0 - return 0 - - -def set_generic_context(tp_names: list[str] | t.CPtr, - type_args: list[str] | t.CPtr): - """设置泛型特化上下文(进入泛型类方法体翻译时调用)""" - global _g_generic_tp_names, _g_generic_type_args - _g_generic_tp_names = tp_names - _g_generic_type_args = type_args - - -def clear_generic_context(): - """清除泛型特化上下文(离开泛型类方法体翻译时调用)""" - global _g_generic_tp_names, _g_generic_type_args - _g_generic_tp_names = None - _g_generic_type_args = None - - -def resolve_generic_type_name(name: str) -> str: - """如果 name 是泛型类型参数,返回对应的具体类型名;否则返回 name 本身 - - 用于表达式中的 T 替换(如 T.__sizeof__() → int.__sizeof__()) - """ - if name is None: - return name - if _g_generic_tp_names is not None and _g_generic_type_args is not None: - rg_n: t.CSizeT = _g_generic_tp_names.__len__() - rg_i: t.CSizeT - for rg_i in range(rg_n): - rg_tpn: str = _g_generic_tp_names.get(rg_i) - if rg_tpn is not None and string.strcmp(name, rg_tpn) == 0: - rg_ta: str = _g_generic_type_args.get(rg_i) - if rg_ta is not None: - return rg_ta - return name - - -# ============================================================ -# _get_type_name_from_annotation - 从类型注解节点提取类型名字符串 -# -# 用于泛型特化时构造 mangled name(如 "list[AST|t.CPtr]") -# -# Name(id="AST") -> "AST" -# Attribute(value=Name(id="t"), attr="CPtr") -> "t.CPtr" -# BinOp(Name("AST"), BitOr, Attribute(Name("t"), "CPtr")) -> "AST|t.CPtr" -# ============================================================ -def _get_type_name_from_annotation(pool: memhub.MemBuddy | t.CPtr, - node: ast.AST | t.CPtr) -> str: - """从类型注解节点提取类型名(支持 Name/Attribute/BinOp)""" - if node is None: - return None - k: int = node.kind() - # Constant: 字符串注解,直接返回字符串值 - if k == ast.ASTKind.Constant: - cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(node) - if cn.const_kind == ast.CONST_STR and cn.str_val is not None: - return cn.str_val - return None - # Name: 直接返回 id - if k == ast.ASTKind.Name: - nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(node) - return nm.id - # Attribute: 构造 "module.attr" 格式 - if k == ast.ASTKind.Attribute: - at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(node) - if at.attr is None: - return None - if at.value is not None and at.value.kind() == ast.ASTKind.Name: - mod_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value) - if mod_nm.id is not None: - total: t.CSizeT = string.strlen(mod_nm.id) + 1 + string.strlen(at.attr) + 1 - buf: str = pool.alloc(total) - if buf is not None: - buf[0] = '\0' - string.strcat(buf, mod_nm.id) - string.strcat(buf, ".") - string.strcat(buf, at.attr) - return buf - return at.attr - # BinOp (BitOr): 构造 "left|right" 格式 - if k == ast.ASTKind.BinOp: - bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(node) - if bop.op == ast.OpKind.BitOr: - left_str: str = _get_type_name_from_annotation(pool, bop.left) - right_str: str = _get_type_name_from_annotation(pool, bop.right) - if left_str is not None and right_str is not None: - total2: t.CSizeT = string.strlen(left_str) + 1 + string.strlen(right_str) + 1 - buf2: str = pool.alloc(total2) - if buf2 is not None: - buf2[0] = '\0' - string.strcat(buf2, left_str) - string.strcat(buf2, "|") - string.strcat(buf2, right_str) - return buf2 - return None - return None - - -# ============================================================ -# _parse_type_string - 将类型名字符串解析回 AST 节点 -# -# _get_type_name_from_annotation 的逆操作,用于泛型特化时 -# 从 type_args 字符串重建 AST 节点(_clone_annotation 和 -# resolve_annotation_type 的泛型上下文替换) -# -# "AST" -> Name("AST") -# "t.CPtr" -> Attribute(Name("t"), "CPtr") -# "AST|t.CPtr" -> BinOp(Name("AST"), BitOr, Attribute(Name("t"), "CPtr")) -# ============================================================ -def _parse_type_string(pool: memhub.MemBuddy | t.CPtr, - type_str: str, - ctx: t.CInt) -> ast.AST | t.CPtr: - """将类型名字符串解析为 AST 节点""" - if type_str is None or pool is None: - return None - - # 检查是否包含 | (BinOp) - pipe_pos: str = string.strchr(type_str, 124) # '|' = 124 - if pipe_pos is not None: - # 临时将 | 替换为 \0,分割左右部分 - old_char: t.CInt = pipe_pos[0] - pipe_pos[0] = 0 - left_node: ast.AST | t.CPtr = _parse_type_string(pool, type_str, ctx) - right_str: str = pipe_pos + 1 - pipe_pos[0] = old_char - right_node: ast.AST | t.CPtr = _parse_type_string(pool, right_str, ctx) - if left_node is not None and right_node is not None: - return ast.BinOp(pool, left_node, ast.OpKind.BitOr, right_node) - return None - - # 检查是否包含 . (Attribute) - dot_pos: str = string.strchr(type_str, 46) # '.' = 46 - if dot_pos is not None: - old_char2: t.CInt = dot_pos[0] - dot_pos[0] = 0 - module_node: ast.AST | t.CPtr = ast.Name(pool, type_str, ctx) - attr_str: str = dot_pos + 1 - dot_pos[0] = old_char2 - if module_node is not None: - return ast.Attribute(pool, module_node, attr_str, ctx) - return None - - # 普通 Name - return ast.Name(pool, type_str, ctx) - - -# ============================================================ -# _parse_type_string_ptr - _parse_type_string 的 t.CPtr 返回类型包装 -# -# 旧编译器对 ast.AST | t.CPtr 跨模块返回类型推断有 bug(解析为 i32), -# 用 t.CPtr 包装绕过,外部模块应调用此函数而非 _parse_type_string -# ============================================================ -def _parse_type_string_ptr(pool: memhub.MemBuddy | t.CPtr, - type_str: str, - ctx: t.CInt) -> t.CPtr: - """_parse_type_string 的 t.CPtr 返回类型包装(绕过旧编译器类型推断 bug)""" - result: ast.AST | t.CPtr = _parse_type_string(pool, type_str, ctx) - return result - - -# ============================================================ -# set_current_file - 设置当前编译的文件名 -# -# 在 BuildPipeline.TranslateFileGetTrans 中每翻译一个文件前调用 -# ============================================================ -def set_current_file(file_path: str): - """设置当前编译的文件名(供报错使用)""" - global _g_current_file - _g_current_file = file_path - - -# ============================================================ -# _read_source_line - 从源文件读取第 lineno 行 -# -# 返回行内容字符串(不含换行符),失败返回 None -# ============================================================ -_SRC_BUF_SIZE: t.CDefine = 262144 - -def _read_source_line(file_path: str, lineno: int) -> str: - """从源文件读取第 lineno 行内容""" - if file_path is None or lineno <= 0: - return None - f: fileio.File | t.CPtr = fileio.File(file_path, fileio.MODE.R) - if f.closed: - return None - buf: bytes = stdlib.malloc(_SRC_BUF_SIZE) - if buf is None: - f.close() - return None - bytes_read: LONG = f.read_all(buf, _SRC_BUF_SIZE) - f.close() - if bytes_read <= 0: - stdlib.free(buf) - return None - # 逐行查找第 lineno 行 - cur_line: int = 1 - line_start: t.CSizeT = 0 - for i in range(bytes_read): - if buf[i] == '\n': - if cur_line == lineno: - line_len: t.CSizeT = i - line_start - if line_len > 0 and buf[line_start + line_len - 1] == '\r': - line_len -= 1 - line_buf: bytes = stdlib.malloc(line_len + 1) - if line_buf is not None: - string.strncpy(line_buf, buf + line_start, line_len) - line_buf[line_len] = '\0' - stdlib.free(buf) - return line_buf - stdlib.free(buf) - return None - cur_line += 1 - line_start = i + 1 - stdlib.free(buf) - return None - - -# ============================================================ -# fatal_error - 以 Python 风格报错并退出(带源代码行) -# -# 格式: -# Traceback (most recent call last): -# File "path", line N -# source code line -# SyntaxError: msg -# ============================================================ -def fatal_error(node: ast.AST | t.CPtr, msg: str): - """以 Python 风格报错并退出(带源代码行)""" - lineno: int = 0 - if node is not None: - lineno = node.lineno - file_name: str = _g_current_file - if file_name is None: - file_name = "" - stdio.printf("Traceback (most recent call last):\n") - stdio.printf(' File "%s", line %d\n', file_name, lineno) - if lineno > 0 and file_name != "": - src_line: str = _read_source_line(file_name, lineno) - if src_line is not None: - stdio.printf(" %s\n", src_line) - stdlib.free(src_line) - stdio.printf("SyntaxError: %s\n", msg) - sys.exit(1) - - -# ============================================================ -# fatal_type_error - 兼容别名(指向 fatal_error) -# ============================================================ -def fatal_type_error(node: ast.AST | t.CPtr, msg: str): - """以 Python 风格报错并退出(fatal_error 的别名)""" - fatal_error(node, msg) - -# ============================================================ -# 将 t.CXxx 类型名映射到 LLVMType(纯函数) -# ============================================================ -def map_t_type(pool: memhub.MemBuddy | t.CPtr, - type_name: str) -> llvmlite.LLVMType | t.CPtr: - """将 t.CXxx / c.CXxx 类型名映射到 LLVMType - - 注意: t.CChar | t.CPtr = i8* = str = bytes - """ - if type_name is None: - return None - - # 基本整数类型 - if string.strcmp(type_name, "CInt") == 0: - return llvmlite.Int32(pool) - elif string.strcmp(type_name, "CChar") == 0: - return llvmlite.Int8(pool) - elif string.strcmp(type_name, "CShort") == 0: - return llvmlite.Int16(pool) - elif string.strcmp(type_name, "CLong") == 0: - return llvmlite.Int64(pool) - elif string.strcmp(type_name, "CLongLong") == 0: - return llvmlite.Int64(pool) - # 精确宽度有符号类型 - elif string.strcmp(type_name, "CInt8T") == 0: - return llvmlite.Int8(pool) - elif string.strcmp(type_name, "CInt16T") == 0: - return llvmlite.Int16(pool) - elif string.strcmp(type_name, "CInt32T") == 0: - return llvmlite.Int32(pool) - elif string.strcmp(type_name, "CInt64T") == 0: - return llvmlite.Int64(pool) - # 精确宽度无符号类型 - elif string.strcmp(type_name, "CUInt8T") == 0: - return llvmlite.Int8(pool) - elif string.strcmp(type_name, "CUInt16T") == 0: - return llvmlite.Int16(pool) - elif string.strcmp(type_name, "CUInt32T") == 0: - return llvmlite.Int32(pool) - elif string.strcmp(type_name, "CUInt64T") == 0: - return llvmlite.Int64(pool) - # 浮点类型 - elif string.strcmp(type_name, "CFloat") == 0: - return llvmlite.Float(pool) - elif string.strcmp(type_name, "CDouble") == 0: - return llvmlite.Double(pool) - # 指针/void: t.CPtr = i8*, t.CChar | t.CPtr = i8* = str = bytes - elif string.strcmp(type_name, "CPtr") == 0: - return llvmlite.Ptr(pool, llvmlite.Int8(pool)) - elif string.strcmp(type_name, "CVoid") == 0: - return llvmlite.Void(pool) - # 无符号修饰 - elif string.strcmp(type_name, "CUnsigned") == 0: - return llvmlite.Int32(pool) - elif string.strcmp(type_name, "CUnsignedInt") == 0: - return llvmlite.Int32(pool) - elif string.strcmp(type_name, "CUnsignedChar") == 0: - return llvmlite.Int8(pool) - elif string.strcmp(type_name, "CUnsignedShort") == 0: - return llvmlite.Int16(pool) - elif string.strcmp(type_name, "CUnsignedLong") == 0: - return llvmlite.Int64(pool) - elif string.strcmp(type_name, "CUnsignedLongLong") == 0: - return llvmlite.Int64(pool) - # size_t / ptr 类型 - elif string.strcmp(type_name, "CSizeT") == 0: - return llvmlite.Int64(pool) - elif string.strcmp(type_name, "CIntPtrT") == 0: - return llvmlite.Int64(pool) - elif string.strcmp(type_name, "CUIntPtrT") == 0: - return llvmlite.Int64(pool) - # bool - elif string.strcmp(type_name, "CBool") == 0: - return llvmlite.Int8(pool) - # ptrdiff_t - elif string.strcmp(type_name, "CPtrDiffT") == 0: - return llvmlite.Int64(pool) - - # ============================================================ - # stdint.py 大写别名(Win32/TransPyC 风格) - # ============================================================ - # 整数类型 - elif string.strcmp(type_name, "INT") == 0: - return llvmlite.Int32(pool) - elif string.strcmp(type_name, "BOOL") == 0: - return llvmlite.Int32(pool) - elif string.strcmp(type_name, "UINT") == 0: - return llvmlite.Int32(pool) - elif string.strcmp(type_name, "BYTE") == 0: - return llvmlite.Int8(pool) - elif string.strcmp(type_name, "WORD") == 0: - return llvmlite.Int16(pool) - elif string.strcmp(type_name, "DWORD") == 0: - return llvmlite.Int32(pool) - elif string.strcmp(type_name, "QWORD") == 0: - return llvmlite.Int64(pool) - elif string.strcmp(type_name, "TCHAR") == 0: - return llvmlite.Int8(pool) - elif string.strcmp(type_name, "VOID") == 0: - return llvmlite.Void(pool) - elif string.strcmp(type_name, "SHORT") == 0: - return llvmlite.Int16(pool) - elif string.strcmp(type_name, "USHORT") == 0: - return llvmlite.Int16(pool) - elif string.strcmp(type_name, "LONGLONG") == 0: - return llvmlite.Int64(pool) - elif string.strcmp(type_name, "ULONGLONG") == 0: - return llvmlite.Int64(pool) - elif string.strcmp(type_name, "LONG") == 0: - return llvmlite.Int64(pool) - elif string.strcmp(type_name, "ULONG") == 0: - return llvmlite.Int64(pool) - elif string.strcmp(type_name, "WCHAR") == 0: - return llvmlite.Int16(pool) - elif string.strcmp(type_name, "FLOAT") == 0: - return llvmlite.Float(pool) - elif string.strcmp(type_name, "DOUBLE") == 0: - return llvmlite.Double(pool) - elif string.strcmp(type_name, "FSIZE_t") == 0: - return llvmlite.Int32(pool) - elif string.strcmp(type_name, "LBA_t") == 0: - return llvmlite.Int32(pool) - # 定长整数 - elif string.strcmp(type_name, "INT8") == 0: - return llvmlite.Int8(pool) - elif string.strcmp(type_name, "INT16") == 0: - return llvmlite.Int16(pool) - elif string.strcmp(type_name, "INT32") == 0: - return llvmlite.Int32(pool) - elif string.strcmp(type_name, "INT64") == 0: - return llvmlite.Int64(pool) - elif string.strcmp(type_name, "UINT8") == 0: - return llvmlite.Int8(pool) - elif string.strcmp(type_name, "UINT16") == 0: - return llvmlite.Int16(pool) - elif string.strcmp(type_name, "UINT32") == 0: - return llvmlite.Int32(pool) - elif string.strcmp(type_name, "UINT64") == 0: - return llvmlite.Int64(pool) - elif string.strcmp(type_name, "CHAR8") == 0: - return llvmlite.Int8(pool) - elif string.strcmp(type_name, "CHAR16") == 0: - return llvmlite.Int16(pool) - elif string.strcmp(type_name, "CHAR32") == 0: - return llvmlite.Int32(pool) - # 小写简写 - elif string.strcmp(type_name, "i8") == 0: - return llvmlite.Int8(pool) - elif string.strcmp(type_name, "i16") == 0: - return llvmlite.Int16(pool) - elif string.strcmp(type_name, "i32") == 0: - return llvmlite.Int32(pool) - elif string.strcmp(type_name, "i64") == 0: - return llvmlite.Int64(pool) - elif string.strcmp(type_name, "u8") == 0: - return llvmlite.Int8(pool) - elif string.strcmp(type_name, "u16") == 0: - return llvmlite.Int16(pool) - elif string.strcmp(type_name, "u32") == 0: - return llvmlite.Int32(pool) - elif string.strcmp(type_name, "u64") == 0: - return llvmlite.Int64(pool) - # size_t 系列 - elif string.strcmp(type_name, "SIZE_T") == 0: - return llvmlite.Int64(pool) - elif string.strcmp(type_name, "SSIZE_T") == 0: - return llvmlite.Int64(pool) - elif string.strcmp(type_name, "PTRDIFF_T") == 0: - return llvmlite.Int64(pool) - - # stdint 指针类型(XxxPTR = XxxType | t.CPtr) - elif string.strcmp(type_name, "INTPTR") == 0: - return llvmlite.Ptr(pool, llvmlite.Int32(pool)) - elif string.strcmp(type_name, "UINTPTR") == 0: - return llvmlite.Ptr(pool, llvmlite.Int32(pool)) - elif string.strcmp(type_name, "BYTEPTR") == 0: - return llvmlite.Ptr(pool, llvmlite.Int8(pool)) - elif string.strcmp(type_name, "CHARLIST") == 0: - return llvmlite.Ptr(pool, llvmlite.Int8(pool)) - elif string.strcmp(type_name, "SHORTPTR") == 0: - return llvmlite.Ptr(pool, llvmlite.Int16(pool)) - elif string.strcmp(type_name, "USHORTPTR") == 0: - return llvmlite.Ptr(pool, llvmlite.Int16(pool)) - elif string.strcmp(type_name, "WCHARPTR") == 0: - return llvmlite.Ptr(pool, llvmlite.Int16(pool)) - elif string.strcmp(type_name, "CHARPTR") == 0: - return llvmlite.Ptr(pool, llvmlite.Int8(pool)) - elif string.strcmp(type_name, "VOIDPTR") == 0: - return llvmlite.Ptr(pool, llvmlite.Int8(pool)) - # Windows API 跨模块 typedef(win32base.py 中定义) - # HANDLE = VOIDPTR = i8*,LPCSTR = const char* = i8*,LPCWSTR = const wchar_t* = i16* - elif string.strcmp(type_name, "HANDLE") == 0: - return llvmlite.Ptr(pool, llvmlite.Int8(pool)) - elif string.strcmp(type_name, "LPCSTR") == 0: - return llvmlite.Ptr(pool, llvmlite.Int8(pool)) - elif string.strcmp(type_name, "LPCWSTR") == 0: - return llvmlite.Ptr(pool, llvmlite.Int16(pool)) - elif string.strcmp(type_name, "INT8PTR") == 0: - return llvmlite.Ptr(pool, llvmlite.Int8(pool)) - elif string.strcmp(type_name, "INT16PTR") == 0: - return llvmlite.Ptr(pool, llvmlite.Int16(pool)) - elif string.strcmp(type_name, "INT32PTR") == 0: - return llvmlite.Ptr(pool, llvmlite.Int32(pool)) - elif string.strcmp(type_name, "INT64PTR") == 0: - return llvmlite.Ptr(pool, llvmlite.Int64(pool)) - elif string.strcmp(type_name, "UINT8PTR") == 0: - return llvmlite.Ptr(pool, llvmlite.Int8(pool)) - elif string.strcmp(type_name, "UINT16PTR") == 0: - return llvmlite.Ptr(pool, llvmlite.Int16(pool)) - elif string.strcmp(type_name, "UINT32PTR") == 0: - return llvmlite.Ptr(pool, llvmlite.Int32(pool)) - elif string.strcmp(type_name, "UINT64PTR") == 0: - return llvmlite.Ptr(pool, llvmlite.Int64(pool)) - elif string.strcmp(type_name, "CHAR8PTR") == 0: - return llvmlite.Ptr(pool, llvmlite.Int8(pool)) - elif string.strcmp(type_name, "CHAR16PTR") == 0: - return llvmlite.Ptr(pool, llvmlite.Int16(pool)) - elif string.strcmp(type_name, "CHAR32PTR") == 0: - return llvmlite.Ptr(pool, llvmlite.Int32(pool)) - - # C 标准 小写 _t 类型 - elif string.strcmp(type_name, "int8_t") == 0: - return llvmlite.Int8(pool) - elif string.strcmp(type_name, "int16_t") == 0: - return llvmlite.Int16(pool) - elif string.strcmp(type_name, "int32_t") == 0: - return llvmlite.Int32(pool) - elif string.strcmp(type_name, "int64_t") == 0: - return llvmlite.Int64(pool) - elif string.strcmp(type_name, "uint8_t") == 0: - return llvmlite.Int8(pool) - elif string.strcmp(type_name, "uint16_t") == 0: - return llvmlite.Int16(pool) - elif string.strcmp(type_name, "uint32_t") == 0: - return llvmlite.Int32(pool) - elif string.strcmp(type_name, "uint64_t") == 0: - return llvmlite.Int64(pool) - elif string.strcmp(type_name, "size_t") == 0: - return llvmlite.Int64(pool) - elif string.strcmp(type_name, "ssize_t") == 0: - return llvmlite.Int64(pool) - elif string.strcmp(type_name, "ptrdiff_t") == 0: - return llvmlite.Int64(pool) - elif string.strcmp(type_name, "intptr_t") == 0: - return llvmlite.Int64(pool) - elif string.strcmp(type_name, "uintptr_t") == 0: - return llvmlite.Int64(pool) - elif string.strcmp(type_name, "wchar_t") == 0: - return llvmlite.Int16(pool) - elif string.strcmp(type_name, "char8_t") == 0: - return llvmlite.Int8(pool) - elif string.strcmp(type_name, "char16_t") == 0: - return llvmlite.Int16(pool) - elif string.strcmp(type_name, "char32_t") == 0: - return llvmlite.Int32(pool) - elif string.strcmp(type_name, "_Bool") == 0: - return llvmlite.Int8(pool) - return None - - -# ============================================================ -# _is_t_attr - 检测节点是否是 t.attr_name 形式(如 t.CPtr, t.CVoid) -# -# 用于联合类型注解中检测指针包装标记 (t.CPtr) 和 void 标记 (t.CVoid) -# ============================================================ -def _is_t_attr(node: ast.AST | t.CPtr, - attr_name: str, - imported_modules: str) -> int: - """检测节点是否是 t.attr_name 形式""" - if node is None or attr_name is None: - return 0 - if node.kind() != ast.ASTKind.Attribute: - return 0 - at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(node) - if at.attr is None: - return 0 - if string.strcmp(at.attr, attr_name) != 0: - return 0 - if at.value is None or at.value.kind() != ast.ASTKind.Name: - return 0 - val_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value) - if val_nm.id is None: - return 0 - if HandlesImports.is_module_imported(imported_modules, val_nm.id) == 0: - return 0 - if string.strcmp(val_nm.id, "t") == 0: - return 1 - return 0 - - -# ============================================================ -# extract_class_name_from_annotation - 从类型注解 AST 中提取类名 -# -# 用于联合类型简化为 i8* 时,回退查找结构体类名。 -# 支持: -# Name 节点 (MemBuddy) → "MemBuddy" -# Attribute 节点 (memhub.MemBuddy) → "MemBuddy" -# BinOp 联合类型 (MemBuddy | t.CPtr) → 非 CPtr 一边的类名 -# ============================================================ -def extract_class_name_from_annotation(node: ast.AST | t.CPtr, - imported_modules: str) -> str: - """从类型注解 AST 中提取类名,返回 None=无法提取""" - if node is None: - return None - k: int = node.kind() - - # Constant 节点: 字符串注解(如 'MemManager'),简单类名直接返回 - if k == ast.ASTKind.Constant: - cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(node) - if cn.const_kind == ast.CONST_STR and cn.str_val is not None: - # 仅处理简单类名(不含 . 和 |),复杂形式返回 None - if string.strchr(cn.str_val, 46) is None and string.strchr(cn.str_val, 124) is None: - if string.strcmp(cn.str_val, "str") == 0: - return None - if string.strcmp(cn.str_val, "int") == 0: - return None - if string.strcmp(cn.str_val, "bytes") == 0: - return None - return cn.str_val - return None - - # Name 节点: MemBuddy → "MemBuddy" - if k == ast.ASTKind.Name: - nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(node) - if nm.id is None: - return None - # 跳过内置类型名 - if string.strcmp(nm.id, "str") == 0: - return None - if string.strcmp(nm.id, "int") == 0: - return None - if string.strcmp(nm.id, "bytes") == 0: - return None - return nm.id - - # Attribute 节点: memhub.MemBuddy → "memhub.MemBuddy"(模块限定名) - if k == ast.ASTKind.Attribute: - at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(node) - if at.attr is None: - return None - # 跳过 t.XXX 形式(内置类型) - if at.value is not None and at.value.kind() == ast.ASTKind.Name: - val_nm2: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value) - if val_nm2.id is not None and string.strcmp(val_nm2.id, "t") == 0: - return None - # 返回模块限定名 "module.Class"(如 "memhub.MemBuddy") - mod_qual_buf: t.CChar | t.CPtr = stdlib.malloc( - string.strlen(val_nm2.id) + string.strlen(at.attr) + 2) - if mod_qual_buf is not None: - viperlib.snprintf(mod_qual_buf, - string.strlen(val_nm2.id) + string.strlen(at.attr) + 2, - "%s.%s", val_nm2.id, at.attr) - return mod_qual_buf - return at.attr - - # BinOp 节点: 联合类型 A | B - if k == ast.ASTKind.BinOp: - bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(node) - if bop.op == ast.OpKind.BitOr: - left_is_cptr: int = _is_t_attr(bop.left, "CPtr", imported_modules) - right_is_cptr: int = _is_t_attr(bop.right, "CPtr", imported_modules) - # 提取非 CPtr 一边的类名 - if left_is_cptr != 0 and right_is_cptr == 0: - return extract_class_name_from_annotation(bop.right, imported_modules) - if right_is_cptr != 0 and left_is_cptr == 0: - return extract_class_name_from_annotation(bop.left, imported_modules) - # 无 CPtr 标记:尝试两边 - if left_is_cptr == 0 and right_is_cptr == 0: - left_name: str = extract_class_name_from_annotation(bop.left, imported_modules) - if left_name is not None: - return left_name - return extract_class_name_from_annotation(bop.right, imported_modules) - return None - - # Subscript 节点: list[AST | t.CPtr] → "list" - if k == ast.ASTKind.Subscript: - sub: ast.Subscript | t.CPtr = (ast.Subscript | t.CPtr)(node) - if sub.value is not None: - return extract_class_name_from_annotation(sub.value, imported_modules) - return None - - return None - - -# ============================================================ -# 解析类型注解节点为 LLVMType -# -# 支持的注解形式: -# - int → i32 -# - t.CUInt64T → i64 -# - str → i8* (t.CChar | t.CPtr = i8* = bytes) -# - int → i32 -# - bytes → i8* -# ============================================================ -def resolve_annotation_type(pool: memhub.MemBuddy | t.CPtr, - node: ast.AST | t.CPtr, - imported_modules: str, - from_imports: str, - trans: HT.Translator | t.CPtr = None) -> llvmlite.LLVMType | t.CPtr: - """解析类型注解节点为 LLVMType - - Args: - pool: 内存分配器 - node: 类型注解 AST 节点(Name 或 Attribute) - imported_modules: 已导入模块名字符串(空格分隔) - from_imports: from-import 映射字符串("name:module name:module" 格式) - trans: 翻译器对象(可选,用于触发泛型特化) - """ - if node is None: - return None - - k: int = node.kind() - - # Constant 节点: 字符串注解(如 'MemManager'),当作无引号的 Name/Attribute/BinOp 处理 - if k == ast.ASTKind.Constant: - cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(node) - if cn.const_kind == ast.CONST_STR and cn.str_val is not None: - sub_node: ast.AST | t.CPtr = _parse_type_string(pool, cn.str_val, ast.ASTCtx.Load) - if sub_node is not None: - return resolve_annotation_type(pool, sub_node, imported_modules, from_imports, trans) - return None - - # Name 节点: str, int, bytes, from-import 名称, class 名称等 - if k == ast.ASTKind.Name: - nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(node) - if nm.id is None: - return None - # 泛型类型参数 T 替换:在泛型特化上下文中,将 T 替换为具体类型 - if _g_generic_tp_names is not None and _g_generic_type_args is not None: - gp_n: t.CSizeT = _g_generic_tp_names.__len__() - gp_i: t.CSizeT - for gp_i in range(gp_n): - gp_tpn: str = _g_generic_tp_names.get(gp_i) - if gp_tpn is not None and string.strcmp(nm.id, gp_tpn) == 0: - gp_ta: str = _g_generic_type_args.get(gp_i) - if gp_ta is not None: - # 用具体类型名递归解析(支持 BinOp/Attribute 类型实参) - gp_sub_node: ast.AST | t.CPtr = _parse_type_string(pool, gp_ta, nm.ctx) - if gp_sub_node is not None: - return resolve_annotation_type(pool, gp_sub_node, imported_modules, from_imports, trans) - # str = bytes = t.CChar | t.CPtr = i8* - if string.strcmp(nm.id, "str") == 0: - return llvmlite.Ptr(pool, llvmlite.Int8(pool)) - elif string.strcmp(nm.id, "int") == 0: - return llvmlite.Int32(pool) - elif string.strcmp(nm.id, "bytes") == 0: - return llvmlite.Ptr(pool, llvmlite.Int8(pool)) - # class 名称: 查找已注册的 StructType,返回 StructType 本身(不包装 Ptr) - # 这样 build_alloca 会分配结构体大小的空间,alloca 返回 struct_ty* - # 命名空间隔离:严格模式下仅解析可见的结构体 - if HandlesStruct.is_struct_visible(nm.id) != 0: - struct_ty: llvmlite.LLVMType | t.CPtr = HandlesStruct.get_struct_type(nm.id) - if struct_ty is not None: - return struct_ty - # from-import 名称: 查找 from_imports 获取模块名后映射 - mod_name: str = HandlesImports.lookup_from_import(from_imports, nm.id) - if mod_name is not None: - return map_t_type(pool, nm.id) - # 兜底: 尝试 map_t_type 中的硬编码 typedef 映射(VOIDPTR, HANDLE, ULONG 等) - # 这些是跨模块通用的 C typedef 名,即使 from-import 查找失败也能解析 - mapped_ty_fallback: llvmlite.LLVMType | t.CPtr = map_t_type(pool, nm.id) - if mapped_ty_fallback is not None: - return mapped_ty_fallback - return None - - # Attribute 节点: t.CInt, t.CUInt64T, namespace_defs.PlainStruct 等 - if k == ast.ASTKind.Attribute: - at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(node) - if at.attr is None: - return None - # 检查 value 是否是 Name('t') 或 Name('c') - if at.value is not None and at.value.kind() == ast.ASTKind.Name: - val_name: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value) - if val_name.id is not None: - # 仅当模块已导入时才解析 - mod_imp: int = HandlesImports.is_module_imported(imported_modules, val_name.id) - if mod_imp == 0: - return None - # 先尝试内置类型映射(int 等) - mapped_ty: llvmlite.LLVMType | t.CPtr = map_t_type(pool, at.attr) - if mapped_ty is not None: - return mapped_ty - # 模块限定类类型:Module.ClassName(命名空间隔离) - mod_struct_ty: llvmlite.LLVMType | t.CPtr = HandlesStruct.get_struct_type(at.attr) - if mod_struct_ty is not None: - return mod_struct_ty - return None - # 嵌套 Attribute: w32.win32base.SECURITY_ATTRIBUTES 等三级及以上限定名 - # at.value 是 Attribute 而非 Name,递归提取最终类名(at.attr)查结构体表 - # find_struct 支持模块限定名回退,此处用最外层 attr(简单类名)即可 - if at.value is not None and at.value.kind() == ast.ASTKind.Attribute: - nested_struct_ty: llvmlite.LLVMType | t.CPtr = HandlesStruct.get_struct_type(at.attr) - if nested_struct_ty is not None: - return nested_struct_ty - return None - - # BinOp 节点: 联合类型注解 A | B - # 处理三种语义: - # 1. ActualType | t.CPtr → Ptr(ActualType)(指针包装,如 MemBuddy | t.CPtr → MemBuddy*) - # 2. t.CVoid | t.CPtr → i8* (void* 等价于 i8*) - # 3. ActualType | DecoratorMarker → ActualType(忽略装饰器标记如 CExport/CExtern) - if k == ast.ASTKind.BinOp: - bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(node) - if bop.op == ast.OpKind.BitOr: - # 检测 t.CPtr 标记(指针包装标记) - left_is_cptr: int = _is_t_attr(bop.left, "CPtr", imported_modules) - right_is_cptr: int = _is_t_attr(bop.right, "CPtr", imported_modules) - - if left_is_cptr != 0 or right_is_cptr != 0: - # 有 CPtr 标记:解析非 CPtr 一边的实际类型,包装为 Ptr - # left 是 CPtr → other 是 right;right 是 CPtr → other 是 left - other_node: ast.AST | t.CPtr = bop.left - if left_is_cptr != 0: - other_node = bop.right - # 检测另一边是否是 t.CVoid (void* = i8*) - other_is_cvoid: int = _is_t_attr(other_node, "CVoid", imported_modules) - if other_is_cvoid != 0: - return llvmlite.Ptr(pool, llvmlite.Int8(pool)) - other_ty: llvmlite.LLVMType | t.CPtr = resolve_annotation_type( - pool, other_node, imported_modules, from_imports, trans) - if other_ty is None: - # CPtr 单独使用或其他无效类型 → i8* - return llvmlite.Ptr(pool, llvmlite.Int8(pool)) - return llvmlite.Ptr(pool, other_ty) - - # 无 CPtr 标记:返回第一个非 None(装饰器标记如 CExport/CExtern 被忽略) - left_ty: llvmlite.LLVMType | t.CPtr = resolve_annotation_type( - pool, bop.left, imported_modules, from_imports, trans) - if left_ty is not None: - return left_ty - right_ty: llvmlite.LLVMType | t.CPtr = resolve_annotation_type( - pool, bop.right, imported_modules, from_imports, trans) - if right_ty is not None: - return right_ty - return None - - # Subscript 节点: t.CArray[elem_ty, count] → [count x elem_ty] - # t.CArray[elem_ty] → Ptr(elem_ty)(静态推导长度数组) - # list[int] → 特化类 struct type(泛型类类型注解) - # value 是 Attribute(Name('t'), 'CArray') 或 Name('list')(泛型类) - # slice 是 Tuple(elts=[elem_ty_node, count_node]) 或单 elem_ty_node - if k == ast.ASTKind.Subscript: - sub: ast.Subscript | t.CPtr = (ast.Subscript | t.CPtr)(node) - if sub.value is None or sub.slice is None: - fatal_type_error(node, "Subscript 节点缺少 value 或 slice") - # 泛型类类型注解: list[int] → 查找已特化的 struct - # value 是 Name(泛型类名),slice 是类型实参 - if sub.value.kind() == ast.ASTKind.Name: - gen_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(sub.value) - # tuple[...] 类型注解:TransPyV 暂不支持 tuple 返回类型,返回 None 让上层默认处理 - # 避免走到 list[str](pool, 4) 构造路径崩溃(tuple 未定义为泛型类) - if gen_nm.id is not None: - if string.strcmp(gen_nm.id, "tuple") == 0: - return None - # 先收集类型实参名,再分配缓冲区拼接 mangled name - gen_arg_names: list[str] | t.CPtr = list[str](pool, 4) - if sub.slice.kind() == ast.ASTKind.Tuple: - gen_tp: ast.Tuple | t.CPtr = (ast.Tuple | t.CPtr)(sub.slice) - gen_elts: list[ast.AST | t.CPtr] | t.CPtr = gen_tp.elts - if gen_elts is not None: - gen_en: t.CSizeT = gen_elts.__len__() - gen_ei: t.CSizeT - for gen_ei in range(gen_en): - gen_elt: ast.AST | t.CPtr = gen_elts.get(gen_ei) - gen_tn: str = _get_type_name_from_annotation(pool, gen_elt) - gen_arg_names.append(gen_tn) - else: - gen_tn_single: str = _get_type_name_from_annotation(pool, sub.slice) - gen_arg_names.append(gen_tn_single) - # 计算总长度并分配缓冲区 - gen_total: t.CSizeT = string.strlen(gen_nm.id) + 2 # "[" 和 "]" - gen_an: t.CSizeT = gen_arg_names.__len__() - gen_ai: t.CSizeT - for gen_ai in range(gen_an): - if gen_ai > 0: - gen_total += 1 # "," - gen_atn: str = gen_arg_names.get(gen_ai) - if gen_atn is not None: - gen_total += string.strlen(gen_atn) - gen_total += 1 # NUL - gen_mangled: str = pool.alloc(gen_total) - if gen_mangled is None: - return None - gen_mangled[0] = '\0' - string.strcat(gen_mangled, gen_nm.id) - string.strcat(gen_mangled, "[") - for gen_ai in range(gen_an): - if gen_ai > 0: - string.strcat(gen_mangled, ",") - gen_atn: str = gen_arg_names.get(gen_ai) - if gen_atn is not None: - string.strcat(gen_mangled, gen_atn) - string.strcat(gen_mangled, "]") - # 查找已特化的 struct(特化由实例化调用 list[int](pool) 触发) - gen_spec_ty: llvmlite.LLVMType | t.CPtr = HandlesStruct.get_struct_type(gen_mangled) - if gen_spec_ty is not None: - return gen_spec_ty - # 未特化:尝试主动触发泛型特化(与 TPC _HandleSubscript 对齐) - # 当 trans 可用时,检查是否是泛型模板并触发特化 - if trans is not None: - import lib.core.Handles.HandlesClassDef as HandlesClassDef - import lib.core.Handles.HandlesExprCall as HandlesExprCall - template_cd_chk: ast.ClassDef | t.CPtr = HandlesClassDef._find_generic_template(gen_nm.id) - if template_cd_chk is not None: - type_args_chk: list[str] | t.CPtr = HandlesExprCall._extract_type_args_from_slice( - pool, sub.slice) - if type_args_chk is not None and type_args_chk.__len__() > 0: - spec_name_chk: str = HandlesClassDef._specialize_generic_class( - trans, gen_nm.id, type_args_chk) - if spec_name_chk is not None: - gen_spec_ty = HandlesStruct.get_struct_type(gen_mangled) - if gen_spec_ty is not None: - return gen_spec_ty - # 未特化:返回 None(不报错,让后续流程处理) - return None - # 检查 value 是否是 Attribute(Name('t'), 'CArray') - if sub.value.kind() != ast.ASTKind.Attribute: - fatal_type_error(node, "不支持的 Subscript 类型注解(仅支持 t.CArray)") - arr_at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(sub.value) - if arr_at.attr is None: - fatal_type_error(node, "Subscript Attribute 缺少 attr") - if string.strcmp(arr_at.attr, "CArray") != 0: - fatal_type_error(node, "不支持的 Subscript 类型注解(仅支持 t.CArray)") - if arr_at.value is None or arr_at.value.kind() != ast.ASTKind.Name: - fatal_type_error(node, "t.CArray 必须通过模块名限定") - arr_val_name: ast.Name | t.CPtr = (ast.Name | t.CPtr)(arr_at.value) - if arr_val_name.id is None: - fatal_type_error(node, "t.CArray 模块名为 None") - if HandlesImports.is_module_imported(imported_modules, arr_val_name.id) == 0: - fatal_type_error(node, "t.CArray 模块未导入") - # 单参数形式: t.CArray[elem_ty] → Ptr(elem_ty) - # 相当于 t.CArray[elem_ty, None],表示静态推导长度数组 - if sub.slice.kind() != ast.ASTKind.Tuple: - elem_ty_single: llvmlite.LLVMType | t.CPtr = resolve_annotation_type( - pool, sub.slice, imported_modules, from_imports, trans) - if elem_ty_single is None: - fatal_type_error(sub.slice, "t.CArray[?] 元素类型解析失败") - return llvmlite.Ptr(pool, elem_ty_single) - # 双参数形式: t.CArray[elem_ty, count] → [count x elem_ty] - tup: ast.Tuple | t.CPtr = (ast.Tuple | t.CPtr)(sub.slice) - if tup.elts is None: - fatal_type_error(node, "t.CArray Tuple 缺少 elts") - elts_list: list[ast.AST | t.CPtr] | t.CPtr = tup.elts - elts_n: t.CSizeT = elts_list.__len__() - if elts_n < 2: - fatal_type_error(node, "t.CArray Tuple 元素不足") - elem_node: ast.AST | t.CPtr = elts_list.get(0) - count_node: ast.AST | t.CPtr = elts_list.get(1) - if elem_node is None or count_node is None: - fatal_type_error(node, "t.CArray Tuple 元素为 None") - # 递归解析元素类型 - elem_ty: llvmlite.LLVMType | t.CPtr = resolve_annotation_type( - pool, elem_node, imported_modules, from_imports, trans) - if elem_ty is None: - fatal_type_error(elem_node, "t.CArray 元素类型解析失败") - # 解析 count(支持整数常量、None、CDefine 常量名、常量表达式如 2*MAX) - # t.CArray[elem_ty, None] 等价于单参数形式 → Ptr(elem_ty) - # t.CArray[elem_ty, NAME] 其中 NAME: t.CDefine = value → [value x elem_ty] - # t.CArray[elem_ty, 2 * MAX] 常量表达式静态计算 → [2*MAX x elem_ty] - count_val: int = 0 - if count_node.kind() == ast.ASTKind.Constant: - cnt_cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(count_node) - if cnt_cn.const_kind == ast.CONST_NONE: - return llvmlite.Ptr(pool, elem_ty) - # 统一用 _eval_const_int_expr 计算常量整数表达式 - # 支持 Constant(INT)、Name(CDefine)、BinOp(2*MAX 等算术/位运算) - count_val = _eval_const_int_expr(count_node) - if _g_const_eval_ok == 0: - fatal_type_error(count_node, "t.CArray count 必须是整数常量、None、CDefine 常量名或常量表达式") - if count_val <= 0: - fatal_type_error(count_node, "t.CArray count 必须为正数") - # 创建 ArrayType(不包装 Ptr) - # 这样 build_alloca 会分配数组大小的空间,alloca 返回 [N x elem_ty]* - return llvmlite.Array(pool, elem_ty, count_val) - - # 未知 AST kind:fail-fast,不宽容返回 None - fatal_type_error(node, "不支持的类型注解语法") - - -# ============================================================ -# has_decorator_marker - 检测类型注解中是否包含指定的装饰器标记 -# -# 支持联合类型注解:int | t.CExtern | t.CExport -# 递归检测 BinOp 节点的左右子节点。 -# -# marker_name 取值: "CExtern", "CExport", "CInline", "State" -# ============================================================ -def has_decorator_marker(node: ast.AST | t.CPtr, - marker_name: str) -> int: - """检测类型注解中是否包含指定的装饰器标记""" - if node is None or marker_name is None: - return 0 - - k: int = node.kind() - - # Attribute 节点: t.CExtern, t.State, t.CExport, t.CInline - if k == ast.ASTKind.Attribute: - at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(node) - if at.attr is not None: - if string.strcmp(at.attr, marker_name) == 0: - return 1 - return 0 - - # BinOp 节点: int | t.CExtern(递归检测左右子节点) - if k == ast.ASTKind.BinOp: - bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(node) - if has_decorator_marker(bop.left, marker_name) != 0: - return 1 - if has_decorator_marker(bop.right, marker_name) != 0: - return 1 - return 0 - - return 0 - - -# ============================================================ -# is_pass_body - 检测函数体是否为 pass(空体) -# -# pass 体函数用于声明外部函数(t.CExtern / t.State), -# 翻译器应生成 declare 而非 define。 -# ============================================================ -def is_pass_body(body: list[ast.AST | t.CPtr] | t.CPtr) -> int: - """检测函数体是否为 pass(空体或仅含 pass 语句)""" - if body is None: - return 1 - bn: t.CSizeT = body.__len__() - if bn == 0: - return 1 - if bn == 1: - stmt: ast.AST | t.CPtr = body.get(0) - if stmt is not None and stmt.kind() == ast.ASTKind.Pass: - return 1 - return 0 - - -# ============================================================ -# 获取 LLVM 整数类型的位宽 -# ============================================================ -def get_llvm_type_bits(ty: llvmlite.LLVMType | t.CPtr) -> int: - """获取 LLVM 整数类型的位宽,非整数类型返回 0""" - if ty is None: - return 0 - match ty: - case llvmlite.LLVMType.Int(bits): - return bits - case _: - return 0 - - -# ============================================================ -# 推断表达式的 LLVM 类型 -# ============================================================ -def infer_expr_type(pool: memhub.MemBuddy | t.CPtr, - node: ast.AST | t.CPtr, - param_types: str) -> llvmlite.LLVMType | t.CPtr: - """推断表达式的 LLVM 类型 - - param_types 格式: "name:bits,name:bits,..." - """ - if node is None: - return llvmlite.Int32(pool) - - k: int = node.kind() - - if k == ast.ASTKind.Constant: - return llvmlite.Int32(pool) - - elif k == ast.ASTKind.Name: - nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(node) - if nm.id is not None and param_types is not None: - # 在 param_types 中查找: "name:bits" 格式 - search_key: t.CChar | t.CPtr = pool.alloc(64) - if search_key is not None: - viperlib.snprintf(search_key, 64, "%s:", nm.id) - found: t.CChar | t.CPtr = string.strstr(param_types, search_key) - if found is not None: - colon_pos: t.CSizeT = string.strlen(nm.id) + 1 - bits_str: t.CChar | t.CPtr = found + colon_pos - bits: int = 0 - for bi in range(4): - ch: t.CChar = bits_str[bi] - if ch >= '0' and ch <= '9': - bits = bits * 10 + (ch - '0') - else: - break - if bits == 64: - return llvmlite.Int64(pool) - elif bits == 16: - return llvmlite.Int16(pool) - elif bits == 8: - return llvmlite.Int8(pool) - return llvmlite.Int32(pool) - - elif k == ast.ASTKind.BinOp: - binop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(node) - lhs_ty: llvmlite.LLVMType | t.CPtr = infer_expr_type( - pool, binop.left, param_types) - rhs_ty: llvmlite.LLVMType | t.CPtr = infer_expr_type( - pool, binop.right, param_types) - lhs_bits: int = get_llvm_type_bits(lhs_ty) - rhs_bits: int = get_llvm_type_bits(rhs_ty) - if lhs_bits >= rhs_bits: - return lhs_ty - return rhs_ty - - return llvmlite.Int32(pool) - - -# ============================================================ -# 推断函数返回类型 -# ============================================================ -def infer_return_type(pool: memhub.MemBuddy | t.CPtr, - body: list[ast.AST | t.CPtr] | t.CPtr, - param_types: str) -> llvmlite.LLVMType | t.CPtr: - """扫描函数体中的 return 语句,推断返回类型""" - if body is None: - return llvmlite.Int32(pool) - - ret_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool) - bn: t.CSizeT = body.__len__() - for bi in range(bn): - stmt: ast.AST | t.CPtr = body.get(bi) - if stmt is not None and stmt.kind() == ast.ASTKind.Return: - rt: ast.Return | t.CPtr = (ast.Return | t.CPtr)(stmt) - if rt.value is not None: - expr_ty: llvmlite.LLVMType | t.CPtr = infer_expr_type( - pool, rt.value, param_types) - if expr_ty is not None: - cur_bits: int = get_llvm_type_bits(ret_ty) - new_bits: int = get_llvm_type_bits(expr_ty) - if new_bits > cur_bits: - ret_ty = expr_ty - return ret_ty - - -# ============================================================ -# 构建参数类型编码字符串 -# ============================================================ -def build_param_types_str(pool: memhub.MemBuddy | t.CPtr, - args_node: ast.AST | t.CPtr) -> str: - """构建参数类型编码字符串 "name:bits,name:bits,..." """ - if args_node is None: - return None - ags: ast.Arguments | t.CPtr = (ast.Arguments | t.CPtr)(args_node) - if ags.args is None: - return None - alist: list[ast.AST | t.CPtr] | t.CPtr = ags.args - an: t.CSizeT = alist.__len__() - if an == 0: - return None - - buf_size: t.CSizeT = an * 32 + 1 - buf: t.CChar | t.CPtr = pool.alloc(buf_size) - if buf is None: - return None - buf[0] = '\0' - - i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(pool) - for ai in range(an): - arg: ast.Arg | t.CPtr = (ast.Arg | t.CPtr)(alist.get(ai)) - if arg is not None and arg.arg is not None: - param_ty: llvmlite.LLVMType | t.CPtr = i32_ty - if arg.annotation is not None: - # 直接调用 map_t_type 解析 Attribute 注解 - if arg.annotation.kind() == ast.ASTKind.Attribute: - at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(arg.annotation) - if at.attr is not None: - resolved: llvmlite.LLVMType | t.CPtr = map_t_type(pool, at.attr) - if resolved is not None: - param_ty = resolved - bits: int = get_llvm_type_bits(param_ty) - if bits == 0: - bits = 32 - tmp: t.CChar | t.CPtr = pool.alloc(32) - if tmp is not None: - viperlib.snprintf(tmp, 32, "%s:%d", arg.arg, bits) - if ai > 0: - _strappend(buf, buf_size, ",") - _strappend(buf, buf_size, tmp) - return buf - - -# ============================================================ -# 辅助函数 -# ============================================================ -def _strappend(dst: t.CChar | t.CPtr, dst_size: t.CSizeT, src: t.CChar | t.CPtr): - """将 src 追加到 dst 末尾""" - if dst is None or src is None: - return - dlen: t.CSizeT = string.strlen(dst) - slen: t.CSizeT = string.strlen(src) - remain: t.CSizeT = dst_size - dlen - if remain <= 0: - return - # 内联 min(slen, remain - 1) 避免 builtin min 未定义(TransPyV 无 builtin min) - limit: t.CSizeT = slen - cap: t.CSizeT = remain - 1 - if cap < limit: - limit = cap - for i in range(limit): - dst[dlen + i] = src[i] - dst[dlen + i] = '\0' \ No newline at end of file diff --git a/TransPyV/App/lib/core/Handles/HandlesVar.py b/TransPyV/App/lib/core/Handles/HandlesVar.py deleted file mode 100644 index 719b587..0000000 --- a/TransPyV/App/lib/core/Handles/HandlesVar.py +++ /dev/null @@ -1,406 +0,0 @@ -import t, c -from stdint import * -import llvmlite -import memhub -import string - - -# ============================================================ -# HandlesVar - 嵌套作用域符号表 + 变量管理 -# -# 使用 Scope 链(Parent 指针)管理嵌套作用域, -# 每个作用域包含一个 VarEntry 数组(扁平化,已验证可工作)。 -# -# 作用域类型: -# SCOPE_MODULE — 模块级(根作用域) -# SCOPE_FUNCTION — 函数级 -# SCOPE_BLOCK — 块级(if/for/while,当前未使用块作用域) -# ============================================================ - -# 作用域类型常量 -SCOPE_MODULE: t.CDefine = 0 -SCOPE_FUNCTION: t.CDefine = 1 -SCOPE_BLOCK: t.CDefine = 2 - -# 每个作用域最大变量数 -MAX_VARS: t.CDefine = 256 - - -# ============================================================ -# VarEntry - 变量表条目 -# ============================================================ -@t.NoVTable -class VarEntry: - """变量表条目""" - Name: t.CChar | t.CPtr - Alloca: llvmlite.Value | t.CPtr - Used: t.CInt - AnnotClassName: t.CChar | t.CPtr # 原始类型注解的类名(str 别名在结构体字段中触发编译器 bug,改用显式联合类型) - IsPtrElement: t.CInt # 标志: 1=注解为 bytes|t.CPtr 或 str|t.CPtr, 下标按 8 字节步长 - - -# ============================================================ -# Scope - 作用域节点 -# -# Parent 指向父作用域(None 表示根), -# Vars 是 VarEntry 数组,VarCount 是当前变量数。 -# ============================================================ -@t.NoVTable -class Scope: - """作用域节点""" - Parent: Scope | t.CPtr - Vars: VarEntry | t.CPtr - VarCount: t.CInt - Kind: t.CInt - - -# ============================================================ -# SymbolTable - 嵌套作用域符号表 -# -# Root 是模块级根作用域,Current 是当前作用域。 -# enter_scope/exit_scope 管理作用域栈。 -# ============================================================ -@t.NoVTable -class SymbolTable: - """嵌套作用域符号表""" - Pool: memhub.MemBuddy | t.CPtr - Root: Scope | t.CPtr - Current: Scope | t.CPtr - - -# ============================================================ -# init_vars — 分配并清零 VarEntry 数组 -# ============================================================ -def init_vars(pool: memhub.MemBuddy | t.CPtr) -> VarEntry | t.CPtr: - """分配并清零变量表数组""" - size: t.CSizeT = MAX_VARS * VarEntry.__sizeof__() - vars_ptr: VarEntry | t.CPtr = pool.alloc(size) - if vars_ptr is not None: - string.memset(vars_ptr, 0, size) - return vars_ptr - - -# ============================================================ -# find_var — 在变量表中按名称查找 -# ============================================================ -def find_var(vars_ptr: VarEntry | t.CPtr, - var_count: int, - name: str) -> llvmlite.Value | t.CPtr: - """在变量表中按名称查找""" - if name is None or vars_ptr is None: - return None - entry_size: t.CSizeT = VarEntry.__sizeof__() - for i in range(var_count): - entry_addr: t.CUInt64T = t.CUInt64T(vars_ptr) + i * entry_size - entry: VarEntry | t.CPtr = (VarEntry | t.CPtr)(t.CVoid(entry_addr, t.CPtr)) - if entry.Name is not None and entry.Used != 0: - if string.strcmp(entry.Name, name) == 0: - return entry.Alloca - return None - - -# ============================================================ -# find_var_entry — 在变量表中按名称查找,返回 VarEntry(含 AnnotTy) -# ============================================================ -def find_var_entry(vars_ptr: VarEntry | t.CPtr, - var_count: int, - name: str) -> VarEntry | t.CPtr: - """在变量表中按名称查找,返回 VarEntry 或 None""" - if name is None or vars_ptr is None: - return None - entry_size: t.CSizeT = VarEntry.__sizeof__() - for i in range(var_count): - entry_addr: t.CUInt64T = t.CUInt64T(vars_ptr) + i * entry_size - entry: VarEntry | t.CPtr = (VarEntry | t.CPtr)(t.CVoid(entry_addr, t.CPtr)) - if entry.Name is not None and entry.Used != 0: - if string.strcmp(entry.Name, name) == 0: - return entry - return None - - -# ============================================================ -# lookup_var_entry — 从当前作用域逐级向上查找变量,返回 VarEntry -# ============================================================ -def lookup_var_entry(symtab: SymbolTable | t.CPtr, - name: str) -> VarEntry | t.CPtr: - """从当前作用域逐级向上查找变量,返回 VarEntry 或 None""" - if symtab is None or name is None: - return None - scope: Scope | t.CPtr = symtab.Current - while scope is not None: - result: VarEntry | t.CPtr = find_var_entry(scope.Vars, scope.VarCount, name) - if result is not None: - return result - scope = scope.Parent - return None - - -# ============================================================ -# set_var_annot_class_name — 设置变量的原始类型注解类名 -# -# 在函数参数定义后调用,存储原始类型注解的类名。 -# 方法调用检测时,当 alloca 类型是 Ptr(i8)(联合类型简化), -# 通过 AnnotClassName 查找实际结构体类型。 -# ============================================================ -def set_var_annot_class_name(symtab: SymbolTable | t.CPtr, - name: str, - class_name: str) -> int: - """设置变量的原始类型注解类名,返回 0=成功 / 1=失败""" - if symtab is None or name is None: - return 1 - entry: VarEntry | t.CPtr = lookup_var_entry(symtab, name) - if entry is None: - return 1 - entry.AnnotClassName = class_name - return 0 - - -# ============================================================ -# set_var_ptr_element — 标记变量为"指针到 str/bytes"类型 -# -# 注解为 bytes|t.CPtr 或 str|t.CPtr 的变量,其 alloca 类型是 i8*, -# 但下标访问应按 8 字节步长(i8** 语义),而非 1 字节步长(i8* 语义)。 -# 此标志在 HandlesAnnAssign 中根据注解形式设置。 -# ============================================================ -def set_var_ptr_element(symtab: SymbolTable | t.CPtr, - name: str) -> int: - """标记变量为 ptr_element 类型,返回 0=成功 / 1=失败""" - if symtab is None or name is None: - return 1 - entry: VarEntry | t.CPtr = lookup_var_entry(symtab, name) - if entry is None: - return 1 - entry.IsPtrElement = 1 - return 0 - - -# ============================================================ -# add_var — 添加变量到变量表 -# ============================================================ -def add_var(vars_ptr: VarEntry | t.CPtr, - var_count: int, - name: str, - alloca: llvmlite.Value | t.CPtr) -> int: - """添加变量到变量表""" - if name is None or alloca is None or vars_ptr is None: - return 1 - if var_count >= MAX_VARS: - return 1 - entry_size: t.CSizeT = VarEntry.__sizeof__() - entry_addr: t.CUInt64T = t.CUInt64T(vars_ptr) + var_count * entry_size - entry: VarEntry | t.CPtr = (VarEntry | t.CPtr)(t.CVoid(entry_addr, t.CPtr)) - entry.Name = name - entry.Alloca = alloca - entry.Used = 1 - return 0 - - -# ============================================================ -# _alloca_at_entry - 在函数入口块生成 alloca(确保支配性) -# -# LLVM IR 要求指令支配所有使用点。如果 alloca 在条件分支内生成, -# 但在其他分支使用,会违反支配性(Instruction does not dominate all uses)。 -# 标准做法:所有 alloca 在函数入口块生成。 -# -# 临时切换 builder.CurBlock 到入口块,生成 alloca,然后恢复。 -# ============================================================ -def _alloca_at_entry(builder: llvmlite.IRBuilder | t.CPtr, - ty: llvmlite.LLVMType | t.CPtr) -> llvmlite.Value | t.CPtr: - """在函数入口块生成 alloca,返回 alloca 值 - - 使用 llvmlite.build_alloca_at_entry 在入口块终止指令之前插入 alloca, - 确保所有 alloca 在入口块,避免支配性违规。 - """ - if builder is None or ty is None: - return None - return llvmlite.build_alloca_at_entry(builder, ty) - - -# ============================================================ -# get_or_create_var — 查找或创建变量 alloca(旧版兼容) -# ============================================================ -def get_or_create_var(pool: memhub.MemBuddy | t.CPtr, - builder: llvmlite.IRBuilder | t.CPtr, - vars_ptr: VarEntry | t.CPtr, - var_count: int, - name: str, - ty: llvmlite.LLVMType | t.CPtr) -> llvmlite.Value | t.CPtr: - """查找或创建变量 alloca""" - existing: llvmlite.Value | t.CPtr = find_var(vars_ptr, var_count, name) - if existing is not None: - return existing - alloca: llvmlite.Value | t.CPtr = _alloca_at_entry(builder, ty) - if alloca is None: - return None - if add_var(vars_ptr, var_count, name, alloca) != 0: - return None - return alloca - - -# ============================================================ -# _create_scope — 创建新作用域节点(内部辅助函数) -# ============================================================ -def _create_scope(pool: memhub.MemBuddy | t.CPtr, - parent: Scope | t.CPtr, - kind: int) -> Scope | t.CPtr: - """创建并初始化作用域节点""" - scope: Scope | t.CPtr = pool.alloc(Scope.__sizeof__()) - if scope is None: - return None - string.memset(scope, 0, Scope.__sizeof__()) - scope.Parent = parent - scope.Vars = init_vars(pool) - scope.VarCount = 0 - scope.Kind = kind - if scope.Vars is None: - return None - return scope - - -# ============================================================ -# init_symbol_table — 创建符号表(含模块级根作用域) -# ============================================================ -def init_symbol_table(pool: memhub.MemBuddy | t.CPtr) -> SymbolTable | t.CPtr: - """创建并初始化符号表,包含模块级根作用域""" - if pool is None: - return None - symtab: SymbolTable | t.CPtr = pool.alloc(SymbolTable.__sizeof__()) - if symtab is None: - return None - string.memset(symtab, 0, SymbolTable.__sizeof__()) - symtab.Pool = pool - - # 创建根作用域(模块级) - root: Scope | t.CPtr = _create_scope(pool, None, SCOPE_MODULE) - if root is None: - return None - - symtab.Root = root - symtab.Current = root - return symtab - - -# ============================================================ -# enter_scope — 进入新作用域 -# ============================================================ -def enter_scope(symtab: SymbolTable | t.CPtr, - kind: int) -> Scope | t.CPtr: - """进入新作用域,返回新创建的作用域""" - if symtab is None: - return None - pool: memhub.MemBuddy | t.CPtr = symtab.Pool - scope: Scope | t.CPtr = _create_scope(pool, symtab.Current, kind) - if scope is None: - return None - symtab.Current = scope - return scope - - -# ============================================================ -# exit_scope — 退出当前作用域 -# ============================================================ -def exit_scope(symtab: SymbolTable | t.CPtr): - """退出当前作用域,恢复到父作用域""" - if symtab is not None and symtab.Current is not None: - symtab.Current = symtab.Current.Parent - - -# ============================================================ -# define_var — 在当前作用域定义变量 -# ============================================================ -def define_var(symtab: SymbolTable | t.CPtr, - name: str, - alloca: llvmlite.Value | t.CPtr) -> int: - """在当前作用域定义变量,返回 0 成功""" - if symtab is None or name is None or alloca is None: - return 1 - scope: Scope | t.CPtr = symtab.Current - if scope is None: - return 1 - ret: int = add_var(scope.Vars, scope.VarCount, name, alloca) - if ret == 0: - scope.VarCount = scope.VarCount + 1 - return ret - - -# ============================================================ -# define_module_var — 在模块作用域定义变量 -# ============================================================ -def define_module_var(symtab: SymbolTable | t.CPtr, - name: str, - alloca: llvmlite.Value | t.CPtr) -> int: - """在模块作用域定义变量,返回 0 成功""" - if symtab is None or name is None or alloca is None: - return 1 - scope: Scope | t.CPtr = symtab.Root - if scope is None: - return 1 - ret: int = add_var(scope.Vars, scope.VarCount, name, alloca) - if ret == 0: - scope.VarCount = scope.VarCount + 1 - return ret - - -# ============================================================ -# lookup_var — 从当前作用域逐级向上查找变量 -# ============================================================ -def lookup_var(symtab: SymbolTable | t.CPtr, - name: str) -> llvmlite.Value | t.CPtr: - """从当前作用域逐级向上查找变量,返回 alloca 或 None""" - if symtab is None or name is None: - return None - scope: Scope | t.CPtr = symtab.Current - while scope is not None: - result: llvmlite.Value | t.CPtr = find_var( - scope.Vars, scope.VarCount, name) - if result is not None: - return result - scope = scope.Parent - return None - - -# ============================================================ -# lookup_current — 仅在当前作用域查找变量 -# ============================================================ -def lookup_current(symtab: SymbolTable | t.CPtr, - name: str) -> llvmlite.Value | t.CPtr: - """仅在当前作用域查找变量""" - if symtab is None or name is None: - return None - scope: Scope | t.CPtr = symtab.Current - if scope is None: - return None - return find_var(scope.Vars, scope.VarCount, name) - - -# ============================================================ -# lookup_module_var — 在模块作用域查找变量 -# ============================================================ -def lookup_module_var(symtab: SymbolTable | t.CPtr, - name: str) -> llvmlite.Value | t.CPtr: - """在模块作用域查找变量""" - if symtab is None or name is None: - return None - scope: Scope | t.CPtr = symtab.Root - if scope is None: - return None - return find_var(scope.Vars, scope.VarCount, name) - - -# ============================================================ -# get_or_create_sym — 查找或创建变量(在当前作用域) -# ============================================================ -def get_or_create_sym(symtab: SymbolTable | t.CPtr, - pool: memhub.MemBuddy | t.CPtr, - builder: llvmlite.IRBuilder | t.CPtr, - name: str, - ty: llvmlite.LLVMType | t.CPtr) -> llvmlite.Value | t.CPtr: - """查找或创建变量 alloca(在当前作用域)""" - existing: llvmlite.Value | t.CPtr = lookup_current(symtab, name) - if existing is not None: - return existing - alloca: llvmlite.Value | t.CPtr = _alloca_at_entry(builder, ty) - if alloca is None: - return None - define_var(symtab, name, alloca) - return alloca diff --git a/TransPyV/App/lib/core/Handles/HandlesWhile.py b/TransPyV/App/lib/core/Handles/HandlesWhile.py deleted file mode 100644 index 397899e..0000000 --- a/TransPyV/App/lib/core/Handles/HandlesWhile.py +++ /dev/null @@ -1,130 +0,0 @@ -import t, c -from stdint import * -import ast -import llvmlite -import memhub -import string -import stdio -import viperlib -import lib.core.Handles.HandlesBase as HandlesBase -import lib.core.Handles.HandlesTranslator as HT -import lib.core.Handles.HandlesExpr as HandlesExpr -import lib.core.Handles.HandlesBody as HandlesBody - - -# ============================================================ -# HandlesWhile - while 循环语句处理(Mixin 继承模式) -# -# 翻译 while 语句为 LLVM IR 控制流: -# br label %cond -# cond: -# %t = -# %c = icmp ne i32 %t, 0 -# br i1 %c, label %body, label %end -# body: -# ... body ... -# br label %cond -# end: -# ============================================================ - - -@t.NoVTable -class WhileHandle(HandlesBase.Mixin): - """while 循环语句处理器:继承 Mixin 获得 Trans 回指针""" - - def __init__(self, trans: HT.Translator | t.CPtr): - self.Trans = trans - - # ============================================================ - # Handle - 处理 while 语句,返回新增变量数 - # ============================================================ - def Handle(self, node: ast.AST | t.CPtr) -> int: - """翻译 while 循环语句""" - if node is None: - return 0 - - trans: HT.Translator | t.CPtr = self.Trans - pool: memhub.MemBuddy | t.CPtr = trans.Pool - builder: llvmlite.IRBuilder | t.CPtr = trans._cur_builder - func: llvmlite.Function | t.CPtr = trans._cur_func - - if builder is None or func is None: - return 0 - - while_node: ast.While | t.CPtr = (ast.While | t.CPtr)(node) - - # 1. 创建基本块: cond / body / end(使用 trans._label_counter,不与 SSA 名共享) - cnt: int = trans._label_counter - trans._label_counter = cnt + 1 - - name_buf: t.CChar | t.CPtr = pool.alloc(32) - viperlib.snprintf(name_buf, 32, "while.cond.%d", cnt) - cond_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf) - - viperlib.snprintf(name_buf, 32, "while.body.%d", cnt) - body_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf) - - viperlib.snprintf(name_buf, 32, "while.end.%d", cnt) - end_bb: llvmlite.BasicBlock | t.CPtr = llvmlite.create_block(pool, func, name_buf) - - # 2. 跳转到 cond 块 - llvmlite.build_br(builder, cond_bb) - - # 3. cond 块: 求值条件,条件分支 - llvmlite.position_at_end(builder, cond_bb) - cond_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( - builder, pool, trans.Module, while_node.test, - trans._funcs, trans._func_count, trans) - if cond_val is None: - cond_val = llvmlite.const_int32(pool, 0) - - # Compare/Not 表达式已返回 i1,直接使用;其他类型与 0 比较 - cond_bits: int = HandlesExpr.get_llvm_type_bits(cond_val.Ty) - if cond_bits == 1: - cond_i1: llvmlite.Value | t.CPtr = cond_val - else: - zero: llvmlite.Value | t.CPtr = llvmlite.const_int32(pool, 0) - cond_i1 = llvmlite.build_icmp( - builder, llvmlite.ICMP_NE, cond_val, zero) - llvmlite.build_cond_br(builder, cond_i1, body_bb, end_bb) - - # 4. body 块: 翻译循环体,跳回 cond - llvmlite.position_at_end(builder, body_bb) - - # 保存旧循环上下文,设置 break/continue 目标 - old_break: llvmlite.BasicBlock | t.CPtr = trans._break_bb - old_continue: llvmlite.BasicBlock | t.CPtr = trans._continue_bb - trans._break_bb = end_bb - trans._continue_bb = cond_bb - - body: list[ast.AST | t.CPtr] | t.CPtr = while_node.children - if body is not None: - body_count: t.CSizeT = body.__len__() - for bi in range(body_count): - stmt: ast.AST | t.CPtr = body.get(bi) - if stmt is not None: - HandlesBody.translate_stmt(trans, stmt) - - # 恢复旧循环上下文 - trans._break_bb = old_break - trans._continue_bb = old_continue - - if llvmlite.builder_cur_block_is_terminated(builder) == 0: - llvmlite.build_br(builder, cond_bb) - - # 5. 定位到 end 块 - llvmlite.position_at_end(builder, end_bb) - return 0 - - -# ============================================================ -# NewWhileHandle - 工厂函数 -# ============================================================ -def NewWhileHandle(pool: memhub.MemBuddy | t.CPtr, - trans: HT.Translator | t.CPtr) -> WhileHandle | t.CPtr: - h: WhileHandle | t.CPtr = pool.alloc(WhileHandle.__sizeof__()) - if h is None: - return None - string.memset(h, 0, WhileHandle.__sizeof__()) - h.Trans = trans - return h diff --git a/TransPyV/App/lib/core/Handles/__init__.py b/TransPyV/App/lib/core/Handles/__init__.py deleted file mode 100644 index 619fc36..0000000 --- a/TransPyV/App/lib/core/Handles/__init__.py +++ /dev/null @@ -1,23 +0,0 @@ -import t, c -from stdint import * - -# Handles 模块(绝对导入,Viper 兼容) -# 参考 Python 版 TransPyC lib/core/Handles 的细粒度拆分 -import lib.core.Handles.HandlesBase as HandlesBase -import lib.core.Handles.HandlesVar as HandlesVar -import lib.core.Handles.HandlesExpr as HandlesExpr -import lib.core.Handles.HandlesExprCall as HandlesExprCall -import lib.core.Handles.HandlesExprOps as HandlesExprOps -import lib.core.Handles.HandlesType as HandlesType -import lib.core.Handles.HandlesAssign as HandlesAssign -import lib.core.Handles.HandlesAnnAssign as HandlesAnnAssign -import lib.core.Handles.HandlesReturn as HandlesReturn -import lib.core.Handles.HandlesImports as HandlesImports -import lib.core.Handles.HandlesFunctions as HandlesFunctions -import lib.core.Handles.HandlesBody as HandlesBody -import lib.core.Handles.HandlesIf as HandlesIf -import lib.core.Handles.HandlesWhile as HandlesWhile -import lib.core.Handles.HandlesFor as HandlesFor -import lib.core.Handles.HandlesAugAssign as HandlesAugAssign -import lib.core.Handles.HandlesMain as HandlesMain -import lib.core.Handles.HandlesTranslator as HandlesTranslator diff --git a/TransPyV/App/lib/core/IncludesScanner.py b/TransPyV/App/lib/core/IncludesScanner.py deleted file mode 100644 index 8d317e3..0000000 --- a/TransPyV/App/lib/core/IncludesScanner.py +++ /dev/null @@ -1,365 +0,0 @@ -import t, c -from stdint import * -import memhub -import string -import stdio -import stdlib -import w32.win32file as win32file -import w32.win32base as win32base -import w32.fileio as fileio -import hashlib -import viperlib -import lib.core.VLogger as VLogger - - -# ============================================================ -# IncludesScanner - includes 目录递归扫描 -# -# 递归扫描 includes 目录,收集所有 .py 文件路径和 SHA1, -# 为 Phase1 stub 生成和 Phase2 stub 合并提供基础数据。 -# -# 使用 Win32 FindFirstFileA/FindNextFileA 实现目录遍历。 -# ============================================================ - -# 全局 mbuddy 指针 -_mbuddy: memhub.MemBuddy | t.CPtr - -# 文件路径最大长度 -MAX_PATH_LEN: t.CDefine = 512 -# 单次扫描最大文件数 -MAX_FILES: t.CDefine = 256 - - -# ============================================================ -# FileEntry - 文件条目(路径 + SHA1) -# ============================================================ -@t.NoVTable -class FileEntry: - """扫描到的文件条目""" - Path: str # 文件绝对路径 - Sha1: str # SHA1 前16字符(16字节+null) - RelPath: str # 相对于 includes 根目录的路径 - ModuleName: str # 模块名(如 "ast.parser") - - -# ============================================================ -# ScanResult - 扫描结果 -# ============================================================ -@t.NoVTable -class ScanResult: - """扫描结果集合""" - Entries: FileEntry | t.CPtr # FileEntry 数组 - Count: t.CInt - Capacity: t.CInt - - -# ============================================================ -# create_scan_result - 创建扫描结果容器 -# ============================================================ -def create_scan_result(pool: memhub.MemBuddy | t.CPtr) -> ScanResult | t.CPtr: - """创建扫描结果容器,预分配 MAX_FILES 个槽位""" - if pool is None: - return None - size: t.CSizeT = MAX_FILES * FileEntry.__sizeof__() - # 使用 stdlib.malloc 避免 mbuddy 池耗尽(与 StubMerger 保持一致) - entries: FileEntry | t.CPtr = stdlib.malloc(size) - if entries is None: - return None - string.memset(entries, 0, size) - - result: ScanResult | t.CPtr = stdlib.malloc(ScanResult.__sizeof__()) - if result is None: - return None - string.memset(result, 0, ScanResult.__sizeof__()) - result.Entries = entries - result.Count = 0 - result.Capacity = MAX_FILES - return result - - -# ============================================================ -# add_file_entry - 向扫描结果添加文件条目 -# ============================================================ -def add_file_entry(result: ScanResult | t.CPtr, - pool: memhub.MemBuddy | t.CPtr, - abs_path: str, rel_path: str, - sha1: str) -> int: - """添加文件条目到扫描结果,返回 0 成功""" - if result is None or pool is None: - return 1 - if result.Count >= result.Capacity: - return 1 - - # 计算模块名:rel_path 中的 / 替换为 .,去掉 .py 扩展名 - rel_len: t.CSizeT = string.strlen(rel_path) - mod_buf: str = stdlib.malloc(rel_len + 1) - if mod_buf is None: - return 1 - string.strcpy(mod_buf, rel_path) - # 替换 / 为 . - for i in range(rel_len): - ch: t.CChar = mod_buf[i] - if ch == '/' or ch == '\\': - mod_buf[i] = '.' - # 去掉 .py 扩展名 - if rel_len >= 3: - if mod_buf[rel_len - 3] == '.' and mod_buf[rel_len - 2] == 'p' and mod_buf[rel_len - 1] == 'y': - mod_buf[rel_len - 3] = '\0' - - # 获取条目地址 - entry_size: t.CSizeT = FileEntry.__sizeof__() - entry_addr: t.CUInt64T = t.CUInt64T(result.Entries) + result.Count * entry_size - entry: FileEntry | t.CPtr = (FileEntry | t.CPtr)(t.CVoid(entry_addr, t.CPtr)) - if entry is None: - return 1 - - # 复制路径字符串 - abs_len: t.CSizeT = string.strlen(abs_path) - abs_buf: str = stdlib.malloc(abs_len + 1) - if abs_buf is None: - return 1 - string.strcpy(abs_buf, abs_path) - entry.Path = abs_buf - - # 复制 SHA1 - sha1_buf: str = stdlib.malloc(17) - if sha1_buf is None: - return 1 - string.strcpy(sha1_buf, sha1) - entry.Sha1 = sha1_buf - - # 复制相对路径 - rel_buf: str = stdlib.malloc(rel_len + 1) - if rel_buf is None: - return 1 - string.strcpy(rel_buf, rel_path) - entry.RelPath = rel_buf - - # 复制模块名 - entry.ModuleName = mod_buf - - result.Count += 1 - return 0 - - -# ============================================================ -# compute_file_sha1 - 读取文件内容并计算 SHA1 -# -# 与 Projectrans.py 一致:CRLF → LF 转换后计算 SHA1。 -# Projectrans.py 用 Python 文本模式读取(自动 CRLF→LF), -# IncludesScanner 用二进制模式读取,需手动去除 \r。 -# ============================================================ -def compute_file_sha1(pool: memhub.MemBuddy | t.CPtr, - file_path: str) -> str: - """读取文件内容并计算 SHA1 前16字符(CRLF→LF 后计算,与 Projectrans.py 一致)""" - if pool is None or file_path is None: - return None - - # 打开文件 - f: fileio.File | t.CPtr = fileio.File(file_path, fileio.MODE.R) - if f.closed: - return None - - # 分配读取缓冲区(128KB,足够大多数 .py 文件) - # 使用 stdlib.malloc 避免 mbuddy 池耗尽(每文件 128KB,60+ 文件会耗尽 16MB 池) - BUF_SIZE: t.CSizeT = 131072 - buf: bytes = stdlib.malloc(BUF_SIZE) - if buf is None: - f.close() - return None - - # 读取文件内容 - bytes_read: t.CInt64T = f.read_all(buf, BUF_SIZE) - f.close() - if bytes_read <= 0: - return None - - # 原地去除 \r(CRLF → LF),与 Projectrans.py 文本模式读取一致 - write_pos: t.CSizeT = 0 - read_pos: t.CSizeT = 0 - while read_pos < bytes_read: - ch: t.CChar = buf[read_pos] - if ch != '\r': - buf[write_pos] = ch - write_pos += 1 - read_pos += 1 - - # 添加 null 终止符 - buf[write_pos] = 0 - - # 计算 SHA1 - ctx: hashlib.sha1 | t.CPtr = hashlib.sha1() - if ctx is None: - return None - ctx.update(buf) - - digest: bytes = stdlib.malloc(hashlib.SHA1_DIGEST_LEN) - if digest is None: - return None - ctx.final(digest) - - # 转为十六进制字符串(取前 8 字节 = 16 个十六进制字符) - hex_buf: str = stdlib.malloc(17) - if hex_buf is None: - return None - for i in range(8): - hi: int = (digest[i] >> 4) & 0xF - lo: int = digest[i] & 0xF - if hi < 10: - hex_buf[i * 2] = '0' + hi - else: - hex_buf[i * 2] = 'a' + (hi - 10) - if lo < 10: - hex_buf[i * 2 + 1] = '0' + lo - else: - hex_buf[i * 2 + 1] = 'a' + (lo - 10) - hex_buf[16] = '\0' - return hex_buf - - -# ============================================================ -# scan_directory_recursive - 递归扫描目录 -# -# 使用 FindFirstFileA/FindNextFileA 遍历目录树, -# 对每个 .py 文件计算 SHA1 并添加到结果中。 -# ============================================================ -def scan_directory_recursive(pool: memhub.MemBuddy | t.CPtr, - root_dir: str, - rel_prefix: str, - result: ScanResult | t.CPtr) -> int: - """递归扫描目录,收集 .py 文件""" - if pool is None or root_dir is None or result is None: - return 1 - - # 构造搜索模式: root_dir/* - root_len: t.CSizeT = string.strlen(root_dir) - pattern: bytes = stdlib.malloc(root_len + 4) - if pattern is None: - return 1 - viperlib.snprintf(pattern, root_len + 4, "%s/*", root_dir) - - # 使用 FindFirstFileA 开始搜索 - find_data: win32file.WIN32_FIND_DATAA | t.CPtr = stdlib.malloc(win32file.WIN32_FIND_DATAA.__sizeof__()) - if find_data is None: - return 1 - string.memset(find_data, 0, win32file.WIN32_FIND_DATAA.__sizeof__()) - - handle: win32base.HANDLE = win32file.FindFirstFileA(pattern, find_data) - if handle == win32base.INVALID_HANDLE_VALUE: - return 1 - - # 遍历所有文件和子目录 - while True: - # 跳过 . 和 .. - fname: str = find_data.cFileName - if fname is not None: - fname0: t.CChar = fname[0] - if fname0 == '.': - fname1: t.CChar = fname[1] - if fname1 == '\0': - # "." - if win32file.FindNextFileA(handle, find_data) == 0: - break - continue - elif fname1 == '.': - fname2: t.CChar = fname[2] - if fname2 == '\0': - # ".." - if win32file.FindNextFileA(handle, find_data) == 0: - break - continue - - # 检查是否为目录 - is_dir: int = find_data.dwFileAttributes & win32file.FILE_ATTRIBUTE_DIRECTORY - - # 构造完整路径 - fname_len: t.CSizeT = string.strlen(fname) - full_path: bytes = stdlib.malloc(root_len + fname_len + 2) - if full_path is None: - break - viperlib.snprintf(full_path, root_len + fname_len + 2, "%s/%s", root_dir, fname) - - # 构造相对路径 - prefix_len: t.CSizeT = 0 - if rel_prefix is not None: - prefix_len = string.strlen(rel_prefix) - rel_path: bytes = stdlib.malloc(prefix_len + fname_len + 2) - if rel_path is None: - break - if rel_prefix is not None and prefix_len > 0: - viperlib.snprintf(rel_path, prefix_len + fname_len + 2, "%s/%s", rel_prefix, fname) - else: - string.strcpy(rel_path, fname) - - if is_dir != 0: - # 递归扫描子目录 - scan_directory_recursive(pool, full_path, rel_path, result) - else: - # 检查是否为 .py 文件 - is_py: int = 0 - if fname_len >= 3: - if fname[fname_len - 3] == '.' and fname[fname_len - 2] == 'p' and fname[fname_len - 1] == 'y': - is_py = 1 - - if is_py != 0: - # 跳过 __pycache__ 目录下的文件 - is_pycache: int = 0 - if rel_prefix is not None: - if string.strcmp(rel_prefix, "__pycache__") == 0: - is_pycache = 1 - - if is_pycache == 0: - # 计算 SHA1 - sha1: str = compute_file_sha1(pool, full_path) - if sha1 is not None: - add_file_entry(result, pool, full_path, rel_path, sha1) - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "扫描: %s -> %s", rel_path, sha1) - VLogger.debug(fb, "scan") - - # 继续搜索下一个文件 - if win32file.FindNextFileA(handle, find_data) == 0: - break - - win32file.FindClose(handle) - return 0 - - -# ============================================================ -# scan_includes - 扫描 includes 目录入口 -# -# 扫描指定的 includes 目录,返回所有 .py 文件的路径和 SHA1。 -# ============================================================ -def scan_includes(pool: memhub.MemBuddy | t.CPtr, - includes_dir: str) -> ScanResult | t.CPtr: - """扫描 includes 目录,返回所有 .py 文件的扫描结果""" - if pool is None or includes_dir is None: - return None - - result: ScanResult | t.CPtr = create_scan_result(pool) - if result is None: - return None - - scan_directory_recursive(pool, includes_dir, None, result) - - return result - - -# ============================================================ -# find_entry_by_module - 按模块名查找文件条目 -# ============================================================ -def find_entry_by_module(result: ScanResult | t.CPtr, - module_name: str) -> FileEntry | t.CPtr: - """按模块名查找文件条目""" - if result is None or module_name is None: - return None - entry_size: t.CSizeT = FileEntry.__sizeof__() - for i in range(result.Count): - entry_addr: t.CUInt64T = t.CUInt64T(result.Entries) + i * entry_size - entry: FileEntry | t.CPtr = (FileEntry | t.CPtr)(t.CVoid(entry_addr, t.CPtr)) - if entry is not None: - if entry.ModuleName is not None: - if entry.ModuleName == module_name: - return entry - return None diff --git a/TransPyV/App/lib/core/Phase1.py b/TransPyV/App/lib/core/Phase1.py deleted file mode 100644 index c741a8d..0000000 --- a/TransPyV/App/lib/core/Phase1.py +++ /dev/null @@ -1,1204 +0,0 @@ -import t, c -from stdint import * -import stdio -import string -import stdlib -import memhub -import viperlib -import w32.fileio as fileio -import w32.win32file -import w32.win32base -import ast -import llvmlite -import lib.core.VLogger as VLogger -import lib.core.Handles.HandlesTranslator as HandlesTranslator -import lib.core.Handles.HandlesStruct as HandlesStruct -import lib.core.Handles.HandlesType as HandlesType -import lib.core.Handles.HandlesExprCall as HandlesExprCall -import lib.core.Handles.HandlesImports as HandlesImports -import lib.core.Handles.HandlesClassDef as HandlesClassDef -import lib.core.IncludesScanner as IncludesScanner -import lib.core.StubMerger as StubMerger -import lib.core.BuildPipeline as BuildPipeline -import lib.Projectrans.Config as Config -import lib.StubGen.Converter as StubConverter - -# 全局 mbuddy 指针 -_mbuddy: memhub.MemBuddy | t.CPtr - -# 源代码缓冲区大小(1MB) -SRC_BUF_SIZE: t.CDefine = 1048576 - -# pyi 缓冲区大小(256KB) -PYI_BUF_SIZE: t.CSizeT = 262144 - -# 拓扑排序相关常量 -MAX_CLASSES: t.CDefine = 512 -MAX_FILE_DEPS: t.CDefine = 256 -MAX_DEP_EDGES: t.CDefine = 16 -SHA1_LEN: t.CDefine = 17 -CLASS_NAME_LEN: t.CDefine = 64 - -# 拓扑排序使用扁平字节数组存储类信息和文件依赖, -# 避免结构体中的 str 指针字段在 mb.alloc 零填充时为 NULL 导致崩溃。 -# 类名/父类名存储在 class_names_buf/parent_names_buf(每个 CLASS_NAME_LEN 字节), -# 定义 SHA1 存储在 def_sha1s_buf(每个 SHA1_LEN 字节)。 - - -# ============================================================ -# _ScanClassInheritance - 预扫描 includes 文件,收集类继承关系 -# -# 遍历所有可达 includes 文件,解析 AST 收集 ClassDef 的类名和父类名。 -# 结果存入扁平字节数组,返回收集到的类数量。 -# -# Args: -# mb: 内存池 -# result: IncludesScanner 扫描结果 -# reachable_set: 可达 SHA1 集合 -# reachable_count: 可达 SHA1 数量 -# use_reachable: 是否使用可达集合过滤 -# sha1_set: SHA1 集合(use_reachable=0 时使用) -# set_count: SHA1 集合数量 -# class_names_buf: 类名扁平数组(每个 CLASS_NAME_LEN 字节,连续内存) -# parent_names_buf: 父类名扁平数组(每个 CLASS_NAME_LEN 字节,无父类填 '\0') -# def_sha1s_buf: 定义 SHA1 扁平数组(每个 SHA1_LEN 字节) -# -# Returns: -# 收集到的类数量,-1 失败 -# ============================================================ -def _ScanClassInheritance(mb: memhub.MemBuddy | t.CPtr, - result: IncludesScanner.ScanResult | t.CPtr, - reachable_set: str, reachable_count: int, - use_reachable: int, - sha1_set: str, set_count: int, - class_names_buf: bytes, - parent_names_buf: bytes, - def_sha1s_buf: bytes, - generic_file_indices: t.CPtr, - generic_file_count_box: t.CPtr) -> int: - """预扫描 includes 文件,收集类继承关系""" - if result is None or class_names_buf is None or parent_names_buf is None or def_sha1s_buf is None: - return -1 - - entry_size: t.CSizeT = IncludesScanner.FileEntry.__sizeof__() - class_count: int = 0 - - for i in range(result.Count): - entry_addr: t.CUInt64T = t.CUInt64T(result.Entries) + i * entry_size - entry: IncludesScanner.FileEntry | t.CPtr = (IncludesScanner.FileEntry | t.CPtr)(t.CVoid(entry_addr, t.CPtr)) - if entry is None or entry.Sha1 is None: - continue - - sha1_e: str = entry.Sha1 - file_has_generic: int = 0 - - # 按需翻译过滤 - in_set: int = 0 - if use_reachable != 0: - in_set = StubMerger._is_in_sha1_set(sha1_e, reachable_set, reachable_count) - else: - in_set = StubMerger._is_in_sha1_set(sha1_e, sha1_set, set_count) - if in_set == 0: - continue - - # 读取文件 - file_path: str = entry.Path - f: fileio.File | t.CPtr = fileio.File(file_path, fileio.MODE.R) - if f.closed: - continue - - src_buf: bytes = stdlib.malloc(SRC_BUF_SIZE) - if src_buf is None: - f.close() - continue - - bytes_read: LONG = f.read_all(src_buf, SRC_BUF_SIZE) - f.close() - if bytes_read <= 0: - stdlib.free(src_buf) - continue - if bytes_read < SRC_BUF_SIZE: - src_buf[bytes_read] = 0 - else: - src_buf[SRC_BUF_SIZE - 1] = 0 - - # 解析 AST - lx: ast.Lexer | t.CPtr = ast.new_lexer(mb) - if lx is None: - stdlib.free(src_buf) - continue - ast._lexer_init(lx, src_buf, mb) - tokens: ast.Token | t.CPtr = ast.tokenize(lx) - tree: ast.AST | t.CPtr = ast.parse_tokens(mb, tokens) - if tree is None: - stdlib.free(src_buf) - continue - - # 遍历 AST 顶层节点,收集 ClassDef - ch: list[ast.AST | t.CPtr] | t.CPtr = tree.children - if ch is not None: - cn: t.CSizeT = ch.__len__() - for ci in range(cn): - child: ast.AST | t.CPtr = ch.get(ci) - if child is None: - continue - kd: int = child.kind() - if kd != ast.ASTKind.ClassDef: - continue - - cd: ast.ClassDef | t.CPtr = (ast.ClassDef | t.CPtr)(child) - if cd is None or cd.name is None: - continue - - # 检测泛型类(有 type_params),记录文件索引以供 Phase 1a 预注册 - if file_has_generic == 0: - tp_scan: list[str] | t.CPtr = cd.type_params - if tp_scan is not None: - file_has_generic = 1 - if generic_file_count_box is not None: - gfc_ptr_scan: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(generic_file_count_box, t.CPtr)) - if gfc_ptr_scan is not None: - gfc_scan: int = gfc_ptr_scan[0] - if gfc_scan < MAX_FILE_DEPS and generic_file_indices is not None: - gi_addr_scan: t.CUInt64T = t.CUInt64T(generic_file_indices) + gfc_scan * 4 - gi_ptr_scan: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(gi_addr_scan, t.CPtr)) - if gi_ptr_scan is not None: - gi_ptr_scan[0] = i - gfc_ptr_scan[0] = gfc_scan + 1 - - if class_count >= MAX_CLASSES: - break - - # 填充扁平数组:类名(偏移 = class_count * CLASS_NAME_LEN) - name_dst: str = class_names_buf + class_count * CLASS_NAME_LEN - nm_len: t.CSizeT = string.strlen(cd.name) - if nm_len >= CLASS_NAME_LEN: - string.strncpy(name_dst, cd.name, CLASS_NAME_LEN - 1) - name_dst[CLASS_NAME_LEN - 1] = '\0' - else: - string.strcpy(name_dst, cd.name) - - # 填充扁平数组:父类名(无父类填 '\0') - parent_dst: str = parent_names_buf + class_count * CLASS_NAME_LEN - parent_dst[0] = '\0' - parent_nm: str = HandlesClassDef._get_parent_class(cd, None) - # parent_nm 是 AST 节点内部指针,不需要释放 - if parent_nm is not None: - pnm_len: t.CSizeT = string.strlen(parent_nm) - if pnm_len >= CLASS_NAME_LEN: - string.strncpy(parent_dst, parent_nm, CLASS_NAME_LEN - 1) - parent_dst[CLASS_NAME_LEN - 1] = '\0' - else: - string.strcpy(parent_dst, parent_nm) - - # 填充扁平数组:定义 SHA1(偏移 = class_count * SHA1_LEN) - sha1_dst: str = def_sha1s_buf + class_count * SHA1_LEN - string.strcpy(sha1_dst, sha1_e) - - class_count += 1 - - stdlib.free(src_buf) - - return class_count - - -# ============================================================ -# _FindClassDefSha1 - 在扁平数组中查找类名对应的定义文件 SHA1 -# -# Args: -# class_names_buf: 类名扁平数组 -# def_sha1s_buf: 定义 SHA1 扁平数组 -# class_count: 类数量 -# class_name: 要查找的类名 -# -# Returns: -# SHA1 字符串指针(指向 def_sha1s_buf 内部偏移),None 未找到 -# ============================================================ -def _FindClassDefSha1(class_names_buf: bytes, def_sha1s_buf: bytes, - class_count: int, class_name: str) -> str: - """查找类名对应的定义文件 SHA1""" - if class_names_buf is None or def_sha1s_buf is None or class_name is None: - return None - for i in range(class_count): - name_ptr: str = class_names_buf + i * CLASS_NAME_LEN - if string.strcmp(name_ptr, class_name) == 0: - return def_sha1s_buf + i * SHA1_LEN - return None - - -# ============================================================ -# _TopoSortFiles - 根据类继承关系对文件进行拓扑排序 -# -# 算法(Kahn): -# 1. 从扁平类信息数组构建"文件 SHA1 → 依赖文件 SHA1 集合"映射 -# 2. 计算每个文件的入度(依赖数量) -# 3. 入度为 0 的文件先处理,处理后减少依赖它的文件入度 -# 4. 重复直到所有文件处理完成 -# -# 注意:依赖方向是"父类所在文件 → 子类所在文件", -# 即父类文件必须先处理。Kahn 用 DepCount 作为剩余依赖计数, -# 依赖为 0 的先处理,初始化 InDegree = DepCount。 -# -# Args: -# mb: 内存池 -# result: IncludesScanner 扫描结果 -# reachable_set: 可达 SHA1 集合 -# reachable_count: 可达 SHA1 数量 -# use_reachable: 是否使用可达集合过滤 -# sha1_set: SHA1 集合 -# set_count: SHA1 集合数量 -# class_names_buf: 类名扁平数组 -# parent_names_buf: 父类名扁平数组 -# def_sha1s_buf: 定义 SHA1 扁平数组 -# class_count: 类数量 -# out_order: 输出拓扑顺序的文件索引数组(调用者分配,int 数组) -# out_count: 输出文件数量 -# -# Returns: -# 0 成功,-1 失败 -# ============================================================ -def _TopoSortFiles(mb: memhub.MemBuddy | t.CPtr, - result: IncludesScanner.ScanResult | t.CPtr, - reachable_set: str, reachable_count: int, - use_reachable: int, - sha1_set: str, set_count: int, - class_names_buf: bytes, parent_names_buf: bytes, - def_sha1s_buf: bytes, class_count: int, - out_order: t.CPtr, out_count: t.CPtr) -> int: - """根据类继承关系对文件进行拓扑排序""" - if result is None or out_order is None or out_count is None: - return -1 - - entry_size: t.CSizeT = IncludesScanner.FileEntry.__sizeof__() - - # 1. 分配扁平数组:文件 SHA1、依赖 SHA1 列表、依赖数量、入度、处理状态 - # 用扁平数组代替 FileDepEntry 结构体,避免 str 指针字段 NULL 崩溃 - file_sha1s_buf: bytes = mb.alloc(MAX_FILE_DEPS * SHA1_LEN) - file_deps_buf: bytes = mb.alloc(MAX_FILE_DEPS * MAX_DEP_EDGES * SHA1_LEN) - file_dep_counts: t.CPtr = mb.alloc(MAX_FILE_DEPS * 4) - file_indegrees: t.CPtr = mb.alloc(MAX_FILE_DEPS * 4) - file_processed: t.CPtr = mb.alloc(MAX_FILE_DEPS * 4) - - if file_sha1s_buf is None or file_deps_buf is None or file_dep_counts is None or file_indegrees is None or file_processed is None: - if file_sha1s_buf is not None: - mb.free(file_sha1s_buf) - if file_deps_buf is not None: - mb.free(file_deps_buf) - if file_dep_counts is not None: - mb.free(file_dep_counts) - if file_indegrees is not None: - mb.free(file_indegrees) - if file_processed is not None: - mb.free(file_processed) - return -1 - - string.memset(file_sha1s_buf, 0, MAX_FILE_DEPS * SHA1_LEN) - string.memset(file_deps_buf, 0, MAX_FILE_DEPS * MAX_DEP_EDGES * SHA1_LEN) - string.memset(file_dep_counts, 0, MAX_FILE_DEPS * 4) - string.memset(file_indegrees, 0, MAX_FILE_DEPS * 4) - string.memset(file_processed, 0, MAX_FILE_DEPS * 4) - - file_count: int = 0 - # sha1→file_index 映射(简单线性查找,文件数不多) - for i in range(result.Count): - entry_addr: t.CUInt64T = t.CUInt64T(result.Entries) + i * entry_size - entry: IncludesScanner.FileEntry | t.CPtr = (IncludesScanner.FileEntry | t.CPtr)(t.CVoid(entry_addr, t.CPtr)) - if entry is None or entry.Sha1 is None: - continue - - sha1_e: str = entry.Sha1 - in_set: int = 0 - if use_reachable != 0: - in_set = StubMerger._is_in_sha1_set(sha1_e, reachable_set, reachable_count) - else: - in_set = StubMerger._is_in_sha1_set(sha1_e, sha1_set, set_count) - if in_set == 0: - continue - - if file_count >= MAX_FILE_DEPS: - break - - # 初始化扁平数组:文件 SHA1(偏移 = file_count * SHA1_LEN) - # DepCount/InDegree/Processed 已由 memset 清零 - sha1_dst: str = file_sha1s_buf + file_count * SHA1_LEN - string.strcpy(sha1_dst, sha1_e) - - file_count += 1 - - # 2. 构建依赖边:对每个类,找到父类定义所在文件,建立 子文件→父文件 依赖 - for ci in range(class_count): - # 读取父类名(偏移 = ci * CLASS_NAME_LEN) - parent_ptr: str = parent_names_buf + ci * CLASS_NAME_LEN - if parent_ptr[0] == '\0': - continue - - # 读取子类定义 SHA1(偏移 = ci * SHA1_LEN) - child_def_sha1: str = def_sha1s_buf + ci * SHA1_LEN - - # 查找父类定义所在文件的 SHA1 - parent_sha1: str = _FindClassDefSha1(class_names_buf, def_sha1s_buf, class_count, parent_ptr) - if parent_sha1 is None: - continue # 父类不在 includes 中(如 Object、CEnum 等标记基类) - - # 父类文件 SHA1 不能等于子类文件 SHA1(同文件内继承不需要依赖) - if string.strcmp(parent_sha1, child_def_sha1) == 0: - continue - - # 找到子类文件对应的索引,添加父文件 SHA1 到依赖列表 - for fi in range(file_count): - fsha1: str = file_sha1s_buf + fi * SHA1_LEN - if string.strcmp(fsha1, child_def_sha1) != 0: - continue - - # 读取当前依赖数量 - cnt_addr: t.CUInt64T = t.CUInt64T(file_dep_counts) + fi * 4 - cnt_ptr: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(cnt_addr, t.CPtr)) - if cnt_ptr is None: - break - cur_cnt: int = cnt_ptr[0] - - # 检查依赖是否已添加(去重) - already: int = 0 - for di in range(cur_cnt): - dep_slot: str = file_deps_buf + fi * MAX_DEP_EDGES * SHA1_LEN + di * SHA1_LEN - if string.strcmp(dep_slot, parent_sha1) == 0: - already = 1 - break - if already != 0: - break - - if cur_cnt < MAX_DEP_EDGES: - dep_dst: str = file_deps_buf + fi * MAX_DEP_EDGES * SHA1_LEN + cur_cnt * SHA1_LEN - string.strcpy(dep_dst, parent_sha1) - cnt_ptr[0] = cur_cnt + 1 - break - - # 3. Kahn 算法:InDegree = DepCount(依赖多少个父文件) - # 依赖为 0 的先处理,处理后减少依赖它的文件入度 - for fi in range(file_count): - cnt_addr3: t.CUInt64T = t.CUInt64T(file_dep_counts) + fi * 4 - cnt_ptr3: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(cnt_addr3, t.CPtr)) - ind_addr3: t.CUInt64T = t.CUInt64T(file_indegrees) + fi * 4 - ind_ptr3: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(ind_addr3, t.CPtr)) - if cnt_ptr3 is not None and ind_ptr3 is not None: - ind_ptr3[0] = cnt_ptr3[0] - - # 4. 拓扑排序输出 - out_idx: int = 0 - changed: int = 1 - while changed != 0: - changed = 0 - for fi in range(file_count): - # 检查处理状态 - proc_addr4: t.CUInt64T = t.CUInt64T(file_processed) + fi * 4 - proc_ptr4: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(proc_addr4, t.CPtr)) - if proc_ptr4 is None or proc_ptr4[0] != 0: - continue - # 检查入度 - ind_addr4: t.CUInt64T = t.CUInt64T(file_indegrees) + fi * 4 - ind_ptr4: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(ind_addr4, t.CPtr)) - if ind_ptr4 is None or ind_ptr4[0] > 0: - continue - - # 入度为 0,可以处理 - # 找到对应的 result.Entries 索引 - target_sha1: str = file_sha1s_buf + fi * SHA1_LEN - for ri in range(result.Count): - ea_r: t.CUInt64T = t.CUInt64T(result.Entries) + ri * entry_size - ent_r: IncludesScanner.FileEntry | t.CPtr = (IncludesScanner.FileEntry | t.CPtr)(t.CVoid(ea_r, t.CPtr)) - if ent_r is not None and ent_r.Sha1 is not None: - if string.strcmp(ent_r.Sha1, target_sha1) == 0: - # 写入输出索引数组 - out_idx_addr: t.CUInt64T = t.CUInt64T(out_order) + out_idx * 4 - out_int_ptr: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(out_idx_addr, t.CPtr)) - if out_int_ptr is not None: - out_int_ptr[0] = ri - out_idx += 1 - break - - # 标记已处理 - proc_ptr4[0] = 1 - changed = 1 - - # 减少依赖该文件的其他文件的入度 - for fj in range(file_count): - proc_addr5: t.CUInt64T = t.CUInt64T(file_processed) + fj * 4 - proc_ptr5: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(proc_addr5, t.CPtr)) - if proc_ptr5 is None or proc_ptr5[0] != 0: - continue - # 读取 fj 的依赖数量 - cnt_addr5: t.CUInt64T = t.CUInt64T(file_dep_counts) + fj * 4 - cnt_ptr5: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(cnt_addr5, t.CPtr)) - if cnt_ptr5 is None: - continue - fj_dep_cnt: int = cnt_ptr5[0] - for di in range(fj_dep_cnt): - dep_slot5: str = file_deps_buf + fj * MAX_DEP_EDGES * SHA1_LEN + di * SHA1_LEN - if string.strcmp(dep_slot5, target_sha1) == 0: - ind_addr5: t.CUInt64T = t.CUInt64T(file_indegrees) + fj * 4 - ind_ptr5: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(ind_addr5, t.CPtr)) - if ind_ptr5 is not None: - ind_ptr5[0] = ind_ptr5[0] - 1 - break - - # 处理循环依赖(未处理的文件按原顺序追加) - if out_idx < file_count: - for fi in range(file_count): - proc_addr6: t.CUInt64T = t.CUInt64T(file_processed) + fi * 4 - proc_ptr6: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(proc_addr6, t.CPtr)) - if proc_ptr6 is None or proc_ptr6[0] != 0: - continue - target_sha1_2: str = file_sha1s_buf + fi * SHA1_LEN - for ri in range(result.Count): - ea_r2: t.CUInt64T = t.CUInt64T(result.Entries) + ri * entry_size - ent_r2: IncludesScanner.FileEntry | t.CPtr = (IncludesScanner.FileEntry | t.CPtr)(t.CVoid(ea_r2, t.CPtr)) - if ent_r2 is not None and ent_r2.Sha1 is not None: - if string.strcmp(ent_r2.Sha1, target_sha1_2) == 0: - out_idx_addr2: t.CUInt64T = t.CUInt64T(out_order) + out_idx * 4 - out_int_ptr2: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(out_idx_addr2, t.CPtr)) - if out_int_ptr2 is not None: - out_int_ptr2[0] = ri - out_idx += 1 - break - proc_ptr6[0] = 1 - - # 写入输出数量 - out_count_ptr: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(out_count, t.CPtr)) - if out_count_ptr is not None: - out_count_ptr[0] = out_idx - - # 释放扁平数组 - mb.free(file_sha1s_buf) - mb.free(file_deps_buf) - mb.free(file_dep_counts) - mb.free(file_indegrees) - mb.free(file_processed) - - return 0 - - -# ============================================================ -# RunPhase1 - Phase1: 扫描 includes 目录,按需翻译并生成 stub -# -# 对每个 .py 文件检查 stub 是否已存在,若不存在则翻译并分离 stub。 -# "按需翻译":仅对 stub 不存在的文件执行翻译,避免重复工作。 -# -# Args: -# mb: 内存池 -# includes_dir: includes 目录路径 -# temp_dir: 临时目录(保存 stub) -# log: 日志器 -# -# Returns: -# 0 成功,非 0 失败 -# ============================================================ -def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str, - log: VLogger.Logger | t.CPtr) -> int: - """Phase1: 扫描 includes 目录,按需翻译并生成 stub""" - if includes_dir is None or temp_dir is None: - VLogger.warning("includes_dir 或 temp_dir 为空,跳过", "Phase1") - return 1 - - # 设置全局 temp_dir(供跨模块 CDefine 查找使用) - HandlesType.set_temp_dir(temp_dir) - - # 确保 temp 目录存在(build_dir/temp 可能尚未创建) - BuildPipeline.ensure_dir(temp_dir) - - if log is not None: - log.banner("Phase1: 扫描 includes(按需翻译)") - - # 扫描 includes 目录 - result: IncludesScanner.ScanResult | t.CPtr = IncludesScanner.scan_includes(mb, includes_dir) - if result is None: - VLogger.error("扫描失败", "Phase1") - return 1 - - # 从扫描结果直接构建 SHA1 集合(不依赖 _sha1_map.txt 文件) - # Phase1 作为编译器自身,应从内存中的扫描结果获取 SHA1,避免外部文件依赖 - sha1_set: str = stdlib.malloc(StubMerger.MAX_INCLUDES_SHA1 * 17) - if sha1_set is None: - VLogger.error("sha1_set 分配失败", "Phase1") - return 1 - string.memset(sha1_set, 0, StubMerger.MAX_INCLUDES_SHA1 * 17) - set_count: int = 0 - p1_entry_size_init: t.CSizeT = IncludesScanner.FileEntry.__sizeof__() - for se_i in range(result.Count): - if set_count >= StubMerger.MAX_INCLUDES_SHA1: - break - se_addr: t.CUInt64T = t.CUInt64T(result.Entries) + se_i * p1_entry_size_init - se_ent: IncludesScanner.FileEntry | t.CPtr = (IncludesScanner.FileEntry | t.CPtr)(t.CVoid(se_addr, t.CPtr)) - if se_ent is None or se_ent.Sha1 is None: - continue - string.strcpy(sha1_set + set_count * 17, se_ent.Sha1) - set_count += 1 - # 先填充全局 SHA1 映射存储器(即使 set_count==0 也填充,确保 Phase2 能获取 includes 条目) - # 注意:PopulateSha1MapStore 会先 free 旧存储器再重新分配 - StubMerger.PopulateSha1MapStore(result) - # 写入 _sha1_map.txt(人类可读输出,程序内部不读取;机器分析使用 PopulateSha1MapStore 内存存储器) - StubMerger.WriteIncludesSha1Map(mb, temp_dir, result, None, 0) - if set_count <= 0: - VLogger.warning("扫描结果无有效 SHA1,跳过 Phase1(项目可能无 includes 依赖)", "Phase1") - stdlib.free(sha1_set) - return 0 - # 构建模块 SHA1 映射(供跨模块函数调用名混淆使用) - td_len_p1map: t.CSizeT = string.strlen(temp_dir) - p1_sha1_arr: bytes = stdlib.malloc(StubMerger.MAX_INCLUDES * 17) - p1_mod_arr: bytes = stdlib.malloc(StubMerger.MAX_INCLUDES * 64) - p1_inc_count: int = 0 - if p1_sha1_arr is not None and p1_mod_arr is not None: - p1_inc_count = StubMerger._BuildIncludesSha1Map(temp_dir, td_len_p1map, p1_sha1_arr, p1_mod_arr) - HandlesExprCall.set_module_sha1_map(p1_sha1_arr, p1_mod_arr, p1_inc_count) - - # 初始化 AST 表(只需一次) - ast._init_tables(mb) - - # FileEntry 结构体大小(Phase 1a 和 1b 共用) - entry_size: t.CSizeT = IncludesScanner.FileEntry.__sizeof__() - - # ============================================================ - # Phase 1a-pre: 扫描所有 includes 文件的 import 依赖 - # - # 只处理 Import/ImportFrom 语句,跳过 ClassDef/FunctionDef 等, - # 不调用 resolve_annotation_type,避免 list[...] 等不支持的语法触发 crash。 - # 生成 .deps.txt 供依赖图按需翻译使用。 - # ============================================================ - p1a_registered: int = 0 - p1a_skipped: int = 0 - p1a_failed: int = 0 - - for i in range(result.Count): - entry_addr_a: t.CUInt64T = t.CUInt64T(result.Entries) + i * entry_size - entry_a: IncludesScanner.FileEntry | t.CPtr = (IncludesScanner.FileEntry | t.CPtr)(t.CVoid(entry_addr_a, t.CPtr)) - if entry_a is None: - p1a_failed += 1 - continue - - sha1_a: str = entry_a.Sha1 - if sha1_a is None: - p1a_failed += 1 - continue - - if StubMerger._is_in_sha1_set(sha1_a, sha1_set, set_count) == 0: - p1a_skipped += 1 - continue - - # 读取文件内容 - file_path_a: str = entry_a.Path - f_a: fileio.File | t.CPtr = fileio.File(file_path_a, fileio.MODE.R) - if f_a.closed: - p1a_failed += 1 - continue - - src_buf_a: bytes = stdlib.malloc(SRC_BUF_SIZE) - if src_buf_a is None: - f_a.close() - p1a_failed += 1 - continue - - bytes_read_a: LONG = f_a.read_all(src_buf_a, SRC_BUF_SIZE) - f_a.close() - if bytes_read_a <= 0: - stdlib.free(src_buf_a) - p1a_failed += 1 - continue - if bytes_read_a < SRC_BUF_SIZE: - src_buf_a[bytes_read_a] = 0 - else: - src_buf_a[SRC_BUF_SIZE - 1] = 0 - - # 解析 AST - lx_a: ast.Lexer | t.CPtr = ast.new_lexer(mb) - if lx_a is None: - stdlib.free(src_buf_a) - p1a_failed += 1 - continue - ast._lexer_init(lx_a, src_buf_a, mb) - tokens_a: ast.Token | t.CPtr = ast.tokenize(lx_a) - tree_a: ast.AST | t.CPtr = ast.parse_tokens(mb, tokens_a) - if tree_a is None: - stdlib.free(src_buf_a) - p1a_failed += 1 - continue - - # 创建 Translator,设置 _declare_only=2(只扫描 import,跳过 ClassDef) - tr_a: HandlesTranslator.Translator | t.CPtr = HandlesTranslator.Translator() - if tr_a is None: - stdlib.free(src_buf_a) - p1a_failed += 1 - continue - tr_a.ModuleSha1 = sha1_a - tr_a._declare_only = 2 - tr_a.CurrentPackage = HandlesImports.compute_package_from_relpath(mb, entry_a.RelPath) - HandlesType.set_current_file(file_path_a) - HandlesType.set_current_module_sha1(sha1_a) - HandlesType.clear_cdefine_constants() - HandlesStruct.reset_visible_structs(mb, 0) - ret_a: int = tr_a.translate(tree_a) - if ret_a != 0: - p1a_failed += 1 - else: - p1a_registered += 1 - - # 生成 .deps.txt(记录依赖模块名,供依赖图按需翻译使用) - # 同时填充内存依赖存储器(PopulateIncludesDeps),供 _BuildReachableSha1Set - # 直接从内存读取,不依赖 .deps.txt 过程文件 - td_len_a: t.CSizeT = string.strlen(temp_dir) - deps_path_a: str = StubMerger._sliced_path(temp_dir, td_len_a, sha1_a, "deps.txt") - if deps_path_a is not None: - df_a: fileio.File | t.CPtr = fileio.File(deps_path_a, fileio.MODE.W) - if not df_a.closed: - if tr_a._imported_modules is not None: - dl_a: t.CSizeT = string.strlen(tr_a._imported_modules) - df_a.write(tr_a._imported_modules, dl_a) - df_a.close() - stdlib.free(deps_path_a) - # 填充内存依赖存储器(供 _BuildReachableSha1Set 使用,不读 .deps.txt) - if tr_a._imported_modules is not None: - StubMerger.PopulateIncludesDeps(sha1_a, tr_a._imported_modules) - - # 释放 Translator 的 C malloc 资源 - if tr_a._global_names is not None: - stdlib.free(tr_a._global_names) - if tr_a._nonlocal_names is not None: - stdlib.free(tr_a._nonlocal_names) - - stdlib.free(src_buf_a) - - # ============================================================ - # 依赖图按需翻译:构建可达 SHA1 集合 - # - # 从 Config.SourceDir 的源文件开始,解析 import 语句,递归收集 - # 可达的 includes 文件 SHA1。Phase 1b 只翻译可达集合中的文件, - # 避免翻译不需要的 includes(如 Test 不依赖 llvmlite,则不翻译)。 - # 如果 Config.SourceDir 不可用(仅运行 Phase1),回退到 sha1_set。 - # ============================================================ - reachable_set: str = None - reachable_count: int = 0 - use_reachable: int = 0 - if Config.SourceDir is not None: - reachable_set = stdlib.malloc(StubMerger.MAX_INCLUDES_SHA1 * 17) - if reachable_set is not None: - string.memset(reachable_set, 0, StubMerger.MAX_INCLUDES_SHA1 * 17) - reachable_count = StubMerger._BuildReachableSha1Set(mb, Config.SourceDir, temp_dir, reachable_set) - if reachable_count > 0: - use_reachable = 1 - # 用可达集合重新生成 _sha1_map.txt(按图求索的最终产物) - # Phase B+ 只遍历这些条目,避免编译不需要的 includes(如 asm.py) - StubMerger.WriteIncludesSha1Map(mb, temp_dir, result, reachable_set, reachable_count) - # 重新加载 sha1_set,使后续 Phase 1a-pre/1a/1b 的过滤也使用可达集合 - string.memset(sha1_set, 0, StubMerger.MAX_INCLUDES_SHA1 * 17) - set_count = StubMerger._load_includes_sha1_set(mb, temp_dir, sha1_set) - else: - stdlib.free(reachable_set) - reachable_set = None - - # ============================================================ - # Phase 1a: 注册可达 includes 文件的 struct/enum/union - # - # 解决字母序依赖问题:按字母顺序翻译时,后面的 struct 未注册 - # 前面就需要用。Phase 1a 先注册所有 struct/enum/union 到全局表, - # Phase 1b 全量翻译时 struct 已注册,走 existing 路径只翻译方法体。 - # 只处理可达文件,避免翻译不需要的 includes(如 Test 不依赖 ast 模块)。 - # - # 拓扑排序:预扫描所有文件收集类继承关系,按依赖顺序处理文件, - # 确保父类所在文件先于子类所在文件处理(如 base.py 先于 astaux.py)。 - # ============================================================ - p1a_reg: int = 0 - p1a_skp: int = 0 - p1a_fl: int = 0 - - # 预扫描类继承关系,构建拓扑顺序(用扁平字节数组,避免结构体 str 指针 NULL 崩溃) - class_names_buf: bytes = mb.alloc(MAX_CLASSES * CLASS_NAME_LEN) - parent_names_buf: bytes = mb.alloc(MAX_CLASSES * CLASS_NAME_LEN) - def_sha1s_buf: bytes = mb.alloc(MAX_CLASSES * SHA1_LEN) - topo_order: t.CPtr = mb.alloc(4 * MAX_FILE_DEPS) - topo_count_box: t.CPtr = mb.alloc(4) - generic_file_indices: t.CPtr = mb.alloc(4 * MAX_FILE_DEPS) - generic_file_count_box: t.CPtr = mb.alloc(4) - if generic_file_indices is not None: - string.memset(generic_file_indices, 0, 4 * MAX_FILE_DEPS) - if generic_file_count_box is not None: - string.memset(generic_file_count_box, 0, 4) - topo_count: int = 0 - - if class_names_buf is not None and parent_names_buf is not None and def_sha1s_buf is not None and topo_order is not None and topo_count_box is not None: - string.memset(class_names_buf, 0, MAX_CLASSES * CLASS_NAME_LEN) - string.memset(parent_names_buf, 0, MAX_CLASSES * CLASS_NAME_LEN) - string.memset(def_sha1s_buf, 0, MAX_CLASSES * SHA1_LEN) - string.memset(topo_order, 0, 4 * MAX_FILE_DEPS) - string.memset(topo_count_box, 0, 4) - if generic_file_indices is not None: - string.memset(generic_file_indices, 0, 4 * MAX_FILE_DEPS) - if generic_file_count_box is not None: - string.memset(generic_file_count_box, 0, 4) - - class_count_scanned: int = _ScanClassInheritance( - mb, result, reachable_set, reachable_count, - use_reachable, sha1_set, set_count, - class_names_buf, parent_names_buf, def_sha1s_buf, - generic_file_indices, generic_file_count_box) - - if class_count_scanned > 0: - ret_topo: int = _TopoSortFiles( - mb, result, reachable_set, reachable_count, - use_reachable, sha1_set, set_count, - class_names_buf, parent_names_buf, def_sha1s_buf, class_count_scanned, - topo_order, topo_count_box) - if ret_topo == 0: - tc_ptr: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(topo_count_box, t.CPtr)) - if tc_ptr is not None: - topo_count = tc_ptr[0] - fb_topo: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb_topo is not None: - viperlib.snprintf(fb_topo, 1024, - "拓扑排序: %d 个类, %d 个文件按依赖顺序处理", - class_count_scanned, topo_count) - VLogger.info(fb_topo, "Phase1") - else: - VLogger.warning("拓扑排序失败,回退到字母序", "Phase1") - topo_count = 0 - else: - VLogger.warning("类继承预扫描无结果,回退到字母序", "Phase1") - topo_count = 0 - - # ============================================================ - # Phase 1a-pre-generic: 预注册所有泛型类模板 - # - # 在 Phase 1a(struct 注册)之前执行,确保所有泛型类模板 - #(如 GSListNode[T]、GSList[T])已注册。这样当其他文件的 - # 结构体字段使用 GSListNode[Value] 等特化类型时,模板能被找到。 - # ============================================================ - generic_file_count: int = 0 - if generic_file_count_box is not None: - gfc_box_ptr: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(generic_file_count_box, t.CPtr)) - if gfc_box_ptr is not None: - generic_file_count = gfc_box_ptr[0] - - if generic_file_count > 0 and generic_file_indices is not None: - fb_gpre: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb_gpre is not None: - viperlib.snprintf(fb_gpre, 1024, "预注册 %d 个泛型类模板文件", generic_file_count) - VLogger.info(fb_gpre, "Phase1") - - for gi in range(generic_file_count): - gi_addr_p: t.CUInt64T = t.CUInt64T(generic_file_indices) + gi * 4 - gi_ptr_p: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(gi_addr_p, t.CPtr)) - if gi_ptr_p is None: - continue - file_idx_gen: int = gi_ptr_p[0] - - gen_entry_addr: t.CUInt64T = t.CUInt64T(result.Entries) + file_idx_gen * entry_size - gen_entry: IncludesScanner.FileEntry | t.CPtr = (IncludesScanner.FileEntry | t.CPtr)(t.CVoid(gen_entry_addr, t.CPtr)) - if gen_entry is None or gen_entry.Sha1 is None: - continue - - gen_path: str = gen_entry.Path - gen_f: fileio.File | t.CPtr = fileio.File(gen_path, fileio.MODE.R) - if gen_f.closed: - continue - - gen_src: bytes = stdlib.malloc(SRC_BUF_SIZE) - if gen_src is None: - gen_f.close() - continue - - gen_br: LONG = gen_f.read_all(gen_src, SRC_BUF_SIZE) - gen_f.close() - if gen_br <= 0: - stdlib.free(gen_src) - continue - if gen_br < SRC_BUF_SIZE: - gen_src[gen_br] = 0 - else: - gen_src[SRC_BUF_SIZE - 1] = 0 - - gen_lx: ast.Lexer | t.CPtr = ast.new_lexer(mb) - if gen_lx is None: - stdlib.free(gen_src) - continue - ast._lexer_init(gen_lx, gen_src, mb) - gen_tokens: ast.Token | t.CPtr = ast.tokenize(gen_lx) - gen_tree: ast.AST | t.CPtr = ast.parse_tokens(mb, gen_tokens) - if gen_tree is None: - stdlib.free(gen_src) - continue - - gen_tr: HandlesTranslator.Translator | t.CPtr = HandlesTranslator.Translator() - if gen_tr is None: - stdlib.free(gen_src) - continue - gen_tr.ModuleSha1 = gen_entry.Sha1 - gen_tr._declare_only = 1 - gen_tr.CurrentPackage = HandlesImports.compute_package_from_relpath(mb, gen_entry.RelPath) - HandlesType.set_current_file(gen_path) - HandlesType.set_current_module_sha1(gen_entry.Sha1) - HandlesType.clear_cdefine_constants() - HandlesStruct.reset_visible_structs(mb, 0) - gen_tr.translate(gen_tree) - - if gen_tr._global_names is not None: - stdlib.free(gen_tr._global_names) - if gen_tr._nonlocal_names is not None: - stdlib.free(gen_tr._nonlocal_names) - stdlib.free(gen_src) - - # 遍历文件:优先使用拓扑顺序,回退到字母序 - iter_count: int = topo_count if topo_count > 0 else result.Count - for i in range(iter_count): - # 获取文件索引:拓扑顺序或字母序 - file_idx: int = i - if topo_count > 0: - od_addr: t.CUInt64T = t.CUInt64T(topo_order) + i * 4 - od_ptr: t.CPtr = (t.CInt | t.CPtr)(t.CVoid(od_addr, t.CPtr)) - if od_ptr is not None: - file_idx = od_ptr[0] - - entry_addr_r: t.CUInt64T = t.CUInt64T(result.Entries) + file_idx * entry_size - entry_r: IncludesScanner.FileEntry | t.CPtr = (IncludesScanner.FileEntry | t.CPtr)(t.CVoid(entry_addr_r, t.CPtr)) - if entry_r is None: - p1a_fl += 1 - continue - - sha1_r: str = entry_r.Sha1 - if sha1_r is None: - p1a_fl += 1 - continue - - # 按需翻译过滤(拓扑排序已过滤,但字母序回退需要检查) - if topo_count == 0: - if use_reachable != 0: - if StubMerger._is_in_sha1_set(sha1_r, reachable_set, reachable_count) == 0: - p1a_skp += 1 - continue - else: - if StubMerger._is_in_sha1_set(sha1_r, sha1_set, set_count) == 0: - p1a_skp += 1 - continue - - # 读取文件内容 - file_path_r: str = entry_r.Path - f_r: fileio.File | t.CPtr = fileio.File(file_path_r, fileio.MODE.R) - if f_r.closed: - p1a_fl += 1 - continue - - src_buf_r: bytes = stdlib.malloc(SRC_BUF_SIZE) - if src_buf_r is None: - f_r.close() - p1a_fl += 1 - continue - - bytes_read_r: LONG = f_r.read_all(src_buf_r, SRC_BUF_SIZE) - f_r.close() - if bytes_read_r <= 0: - stdlib.free(src_buf_r) - p1a_fl += 1 - continue - if bytes_read_r < SRC_BUF_SIZE: - src_buf_r[bytes_read_r] = 0 - else: - src_buf_r[SRC_BUF_SIZE - 1] = 0 - - # 解析 AST - lx_r: ast.Lexer | t.CPtr = ast.new_lexer(mb) - if lx_r is None: - stdlib.free(src_buf_r) - p1a_fl += 1 - continue - ast._lexer_init(lx_r, src_buf_r, mb) - tokens_r: ast.Token | t.CPtr = ast.tokenize(lx_r) - tree_r: ast.AST | t.CPtr = ast.parse_tokens(mb, tokens_r) - if tree_r is None: - stdlib.free(src_buf_r) - p1a_fl += 1 - continue - - # 创建 Translator,设置 _declare_only=1(注册 struct/enum/union) - tr_r: HandlesTranslator.Translator | t.CPtr = HandlesTranslator.Translator() - if tr_r is None: - stdlib.free(src_buf_r) - p1a_fl += 1 - continue - tr_r.ModuleSha1 = sha1_r - tr_r._declare_only = 1 - tr_r.CurrentPackage = HandlesImports.compute_package_from_relpath(mb, entry_r.RelPath) - HandlesType.set_current_file(file_path_r) - HandlesType.set_current_module_sha1(sha1_r) - HandlesType.clear_cdefine_constants() - HandlesStruct.reset_visible_structs(mb, 0) - ret_r: int = tr_r.translate(tree_r) - if ret_r != 0: - p1a_fl += 1 - else: - p1a_reg += 1 - - # 释放 Translator 的 C malloc 资源 - if tr_r._global_names is not None: - stdlib.free(tr_r._global_names) - if tr_r._nonlocal_names is not None: - stdlib.free(tr_r._nonlocal_names) - stdlib.free(src_buf_r) - - # 释放拓扑排序资源 - if class_names_buf is not None: - mb.free(class_names_buf) - if parent_names_buf is not None: - mb.free(parent_names_buf) - if def_sha1s_buf is not None: - mb.free(def_sha1s_buf) - if topo_order is not None: - mb.free(topo_order) - if topo_count_box is not None: - mb.free(topo_count_box) - if generic_file_indices is not None: - mb.free(generic_file_indices) - if generic_file_count_box is not None: - mb.free(generic_file_count_box) - - # ============================================================ - # Phase 1b: 全量翻译(struct 已注册,走 existing 路径翻译方法体) - # ============================================================ - # 遍历每个文件 - translated: int = 0 - skipped: int = 0 - failed: int = 0 - - for i in range(result.Count): - # 获取 entry - entry_addr: t.CUInt64T = t.CUInt64T(result.Entries) + i * entry_size - entry: IncludesScanner.FileEntry | t.CPtr = (IncludesScanner.FileEntry | t.CPtr)(t.CVoid(entry_addr, t.CPtr)) - if entry is None: - failed += 1 - continue - - sha1: str = entry.Sha1 - if sha1 is None: - failed += 1 - continue - - # 检查 SHA1 是否在翻译集合中(按需翻译:只翻译可达的文件) - in_set: int = 0 - if use_reachable != 0: - in_set = StubMerger._is_in_sha1_set(sha1, reachable_set, reachable_count) - else: - in_set = StubMerger._is_in_sha1_set(sha1, sha1_set, set_count) - if in_set == 0: - skipped += 1 - continue - - # 构造 stub 路径: {temp_dir}/{sha1}.stub.ll - dir_len: t.CSizeT = string.strlen(temp_dir) - sha1_len: t.CSizeT = string.strlen(sha1) - stub_path: str = StubMerger._sliced_path(temp_dir, dir_len, sha1, "stub.ll") - if stub_path is None: - failed += 1 - continue - - # 检查 stub 是否已存在(按需翻译:跳过已存在的) - sf: fileio.File | t.CPtr = fileio.File(stub_path, fileio.MODE.R) - if not sf.closed: - sf.close() - # 检查 text.ll 是否也存在(虚表扫描需要 text.ll) - text_path: str = StubMerger._sliced_path(temp_dir, dir_len, sha1, "text.ll") - if text_path is not None: - tf: fileio.File | t.CPtr = fileio.File(text_path, fileio.MODE.R) - if not tf.closed: - tf.close() - stdlib.free(text_path) - stdlib.free(stub_path) - continue - stdlib.free(text_path) - # text.ll 不存在,需要重新翻译 - rp: str = entry.RelPath - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "text.ll 不存在,重新翻译: %s (sha1=%s)", rp, sha1) - VLogger.info(fb, "Phase1") - else: - # stub 不存在,需要翻译 - rp: str = entry.RelPath - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "翻译: %s (sha1=%s)", rp, sha1) - VLogger.info(fb, "Phase1") - - stdlib.free(stub_path) - - # 读取文件内容 - file_path: str = entry.Path - f: fileio.File | t.CPtr = fileio.File(file_path, fileio.MODE.R) - if f is None: - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "无法打开(None): %s", file_path) - VLogger.error(fb, "Phase1") - failed += 1 - continue - if f.closed: - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "无法打开: %s", file_path) - VLogger.error(fb, "Phase1") - failed += 1 - continue - - src_buf: bytes = stdlib.malloc(SRC_BUF_SIZE) - if src_buf is None: - f.close() - failed += 1 - continue - - bytes_read: LONG = f.read_all(src_buf, SRC_BUF_SIZE) - f.close() - if bytes_read <= 0: - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "读取失败: %s", file_path) - VLogger.error(fb, "Phase1") - stdlib.free(src_buf) - failed += 1 - continue - if bytes_read < SRC_BUF_SIZE: - src_buf[bytes_read] = 0 - else: - src_buf[SRC_BUF_SIZE - 1] = 0 - - # 解析 AST - lx: ast.Lexer | t.CPtr = ast.new_lexer(mb) - if lx is None: - stdlib.free(src_buf) - failed += 1 - continue - ast._lexer_init(lx, src_buf, mb) - tokens: ast.Token | t.CPtr = ast.tokenize(lx) - tree: ast.AST | t.CPtr = ast.parse_tokens(mb, tokens) - if tree is None: - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "AST 解析失败: %s", file_path) - VLogger.error(fb, "Phase1") - stdlib.free(src_buf) - failed += 1 - continue - - # 生成 .pyi 存根文件(直接遍历 AST,不依赖 PythonToStubConverter) - pyi_buf: bytes = stdlib.malloc(PYI_BUF_SIZE) - if pyi_buf is not None: - pyi_pos: t.CSizeT = StubConverter._GeneratePyiFromAst(mb, tree, entry.RelPath, pyi_buf, PYI_BUF_SIZE) - if pyi_pos > 0: - pyi_path: str = StubMerger._sliced_path(temp_dir, dir_len, sha1, "pyi") - if pyi_path is not None: - pf: fileio.File | t.CPtr = fileio.File(pyi_path, fileio.MODE.W) - if not pf.closed: - pf.write(pyi_buf, pyi_pos) - pf.close() - stdlib.free(pyi_path) - stdlib.free(pyi_buf) - - # 翻译 AST → LLVM IR - tr: HandlesTranslator.Translator | t.CPtr = HandlesTranslator.Translator() - if tr is None: - stdlib.free(src_buf) - failed += 1 - continue - tr.ModuleSha1 = sha1 - tr.CurrentPackage = HandlesImports.compute_package_from_relpath(mb, entry.RelPath) - HandlesType.set_current_file(file_path) - HandlesType.set_current_module_sha1(sha1) - HandlesType.clear_cdefine_constants() - HandlesStruct.reset_visible_structs(mb, 0) - ret: int = tr.translate(tree) - if ret != 0: - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "翻译失败: %s", file_path) - VLogger.error(fb, "Phase1") - stdlib.free(src_buf) - if tr._global_names is not None: - stdlib.free(tr._global_names) - if tr._nonlocal_names is not None: - stdlib.free(tr._nonlocal_names) - failed += 1 - continue - - # dump stub IR (declarations only) - PHASE1_IR_SIZE: t.CSizeT = 1048576 - stub_buf: bytes = stdlib.malloc(PHASE1_IR_SIZE) - if stub_buf is None: - stdlib.free(src_buf) - if tr._global_names is not None: - stdlib.free(tr._global_names) - if tr._nonlocal_names is not None: - stdlib.free(tr._nonlocal_names) - failed += 1 - continue - tr.dump_ir(stub_buf, PHASE1_IR_SIZE, llvmlite.OUTPUT_STUB) - stub_len: t.CSizeT = string.strlen(stub_buf) - - # save stub.ll - dir_len_p1: t.CSizeT = string.strlen(temp_dir) - stub_path_p1: str = StubMerger._sliced_path(temp_dir, dir_len_p1, sha1, "stub.ll") - if stub_path_p1 is not None: - sf_p1: fileio.File | t.CPtr = fileio.File(stub_path_p1, fileio.MODE.W) - if not sf_p1.closed: - sf_p1.write(stub_buf, stub_len) - sf_p1.close() - stdlib.free(stub_path_p1) - stdlib.free(stub_buf) - - # dump text IR (definitions only) - text_buf: bytes = stdlib.malloc(PHASE1_IR_SIZE) - if text_buf is None: - stdlib.free(src_buf) - if tr._global_names is not None: - stdlib.free(tr._global_names) - if tr._nonlocal_names is not None: - stdlib.free(tr._nonlocal_names) - failed += 1 - continue - tr.dump_ir(text_buf, PHASE1_IR_SIZE, llvmlite.OUTPUT_TEXT) - text_len: t.CSizeT = string.strlen(text_buf) - - # save text.ll - text_path_p1: str = StubMerger._sliced_path(temp_dir, dir_len_p1, sha1, "text.ll") - if text_path_p1 is not None: - tf_p1: fileio.File | t.CPtr = fileio.File(text_path_p1, fileio.MODE.W) - if not tf_p1.closed: - tf_p1.write(text_buf, text_len) - tf_p1.close() - stdlib.free(text_path_p1) - stdlib.free(text_buf) - - # save dependencies (_imported_modules) for Phase B - deps_path_p1: str = StubMerger._sliced_path(temp_dir, dir_len_p1, sha1, "deps.txt") - if deps_path_p1 is not None: - df_p1: fileio.File | t.CPtr = fileio.File(deps_path_p1, fileio.MODE.W) - if not df_p1.closed: - if tr._imported_modules is not None: - dl: t.CSizeT = string.strlen(tr._imported_modules) - df_p1.write(tr._imported_modules, dl) - df_p1.close() - stdlib.free(deps_path_p1) - - # 释放 Translator 的 C malloc 资源 - if tr._global_names is not None: - stdlib.free(tr._global_names) - if tr._nonlocal_names is not None: - stdlib.free(tr._nonlocal_names) - - # 所有 dump_ir 完成,src_buf 不再需要 - stdlib.free(src_buf) - - translated += 1 - - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "完成: 翻译=%d 跳过=%d 失败=%d", translated, skipped, failed) - VLogger.info(fb, "Phase1") - - # 释放可达 SHA1 集合(如果分配了) - if reachable_set is not None: - stdlib.free(reachable_set) - - return 0 diff --git a/TransPyV/App/lib/core/Phase2.py b/TransPyV/App/lib/core/Phase2.py deleted file mode 100644 index 21fd1ec..0000000 --- a/TransPyV/App/lib/core/Phase2.py +++ /dev/null @@ -1,953 +0,0 @@ -import t, c -from stdint import * -import stdio -import string -import stdlib -import memhub -import viperlib -import w32.fileio as fileio -import w32.win32file -import w32.win32base -import sys -import ast -import llvmlite -import subprocess -import argparse -import lib.core.VLogger as VLogger -import lib.core.Handles.HandlesTranslator as HandlesTranslator -import lib.core.Handles.HandlesExprCall as HandlesExprCall -import lib.core.Handles.HandlesImports as HandlesImports -import lib.core.Handles.HandlesStruct as HandlesStruct -import lib.core.BuildPipeline as BuildPipeline -import lib.core.IncludesScanner as IncludesScanner -import lib.core.StubMerger as StubMerger -import lib.Projectrans.Utils as Utils -import lib.Projectrans.Config as Config - -# 全局 mbuddy 指针 -_mbuddy: memhub.MemBuddy | t.CPtr - -# 源代码缓冲区大小(1MB) -SRC_BUF_SIZE: t.CDefine = 1048576 - -# 最大源文件数(递归扫描子目录后文件数增多,增大到 64) -MAX_SRC_FILES: t.CDefine = 64 - -# 全局栈金丝雀(避免局部变量改变栈布局) -_g_canary: t.CUInt32T - - -@t.NoVTable -class SrcFileEntry: - """源文件条目""" - Path: str # 完整路径 - Sha1: str # SHA1 前16字符 - - -# ============================================================ -# _ScanDirForPyFiles - 递归扫描目录,收集 .py 文件到 entries -# -# 替代旧的非递归 FindFirstFileA(dir/*.py) 扫描,支持子目录 -# (如 App/lib/core/Handles/)。遇到目录递归扫描,遇到 .py -# 文件读取内容、计算 SHA1、加入 entries。 -# -# Args: -# mb: 内存池 -# dir_path: 当前扫描目录 -# entries: SrcFileEntry 数组 -# entry_size: 单个条目大小(SrcFileEntry.__sizeof__()) -# file_count: 当前已收集的文件数 -# max_files: 最大文件数 -# -# Returns: -# 新的 file_count -# ============================================================ -def _ScanDirForPyFiles(mb: memhub.MemBuddy | t.CPtr, - dir_path: str, - entries: SrcFileEntry | t.CPtr, - entry_size: t.CSizeT, - file_count: int, max_files: int) -> int: - """递归扫描目录,收集 .py 文件到 entries,返回新的 file_count""" - if dir_path is None or entries is None: - return file_count - if file_count >= max_files: - return file_count - - dir_len: t.CSizeT = string.strlen(dir_path) - pattern: bytes = stdlib.malloc(dir_len + 16) - if pattern is None: - return file_count - viperlib.snprintf(pattern, dir_len + 16, "%s/*", dir_path) - - find_data_size: t.CSizeT = w32.win32file.WIN32_FIND_DATAA.__sizeof__() - find_data: w32.win32file.WIN32_FIND_DATAA | t.CPtr = stdlib.malloc(find_data_size + 16) - if find_data is None: - stdlib.free(pattern) - return file_count - string.memset(find_data, 0, find_data_size + 16) - - handle: w32.win32base.HANDLE = w32.win32file.FindFirstFileA(pattern, find_data) - if handle == w32.win32base.INVALID_HANDLE_VALUE: - stdlib.free(pattern) - stdlib.free(find_data) - return file_count - - while True: - fname: str = find_data.cFileName - if fname is not None: - fname_len: t.CSizeT = string.strlen(fname) - if fname_len > 0: - # 跳过 . 和 .. - is_dot: int = 0 - if fname_len == 1 and fname[0] == '.': - is_dot = 1 - elif fname_len == 2 and fname[0] == '.' and fname[1] == '.': - is_dot = 1 - if is_dot == 0: - # 检查是否是目录 - attrs: ULONG = find_data.dwFileAttributes - is_dir: int = 0 - if (attrs & w32.win32file.FILE_ATTRIBUTE_DIRECTORY) != 0: - is_dir = 1 - if is_dir != 0: - # 递归扫描子目录 - sub_dir: bytes = stdlib.malloc(dir_len + fname_len + 2) - if sub_dir is not None: - viperlib.snprintf(sub_dir, dir_len + fname_len + 2, "%s/%s", dir_path, fname) - file_count = _ScanDirForPyFiles(mb, sub_dir, entries, entry_size, file_count, max_files) - stdlib.free(sub_dir) - else: - # 检查是否是 .py 文件 - if fname_len > 3: - if fname[fname_len - 3] == '.' and fname[fname_len - 2] == 'p' and fname[fname_len - 1] == 'y': - if file_count < max_files: - full_path: bytes = stdlib.malloc(dir_len + fname_len + 2) - if full_path is not None: - viperlib.snprintf(full_path, dir_len + fname_len + 2, "%s/%s", dir_path, fname) - sf: fileio.File | t.CPtr = fileio.File(full_path, fileio.MODE.R) - if not sf.closed: - sbuf: bytes = stdlib.malloc(SRC_BUF_SIZE) - if sbuf is not None: - br: LONG = sf.read_all(sbuf, SRC_BUF_SIZE) - sf.close() - if br > 0: - if br < SRC_BUF_SIZE: - sbuf[br] = 0 - else: - sbuf[SRC_BUF_SIZE - 1] = 0 - sha1_val: str = Utils.compute_sha1(mb, sbuf) - if sha1_val is not None: - ea: t.CUInt64T = t.CUInt64T(entries) + file_count * entry_size - ent: SrcFileEntry | t.CPtr = (SrcFileEntry | t.CPtr)(t.CVoid(ea, t.CPtr)) - if ent is not None: - ent.Path = full_path - ent.Sha1 = sha1_val - file_count += 1 - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "%s (sha1=%s)", fname, sha1_val) - VLogger.info(fb, "project") - stdlib.free(sbuf) - # full_path 不释放:ent.Path 引用它 - - if w32.win32file.FindNextFileA(handle, find_data) == 0: - break - - w32.win32file.FindClose(handle) - stdlib.free(pattern) - stdlib.free(find_data) - return file_count - - -def RunMultiFileProject(mb: memhub.MemBuddy | t.CPtr, - source_dir: str, temp_dir: str, output_dir: str, - cc_cmd: str, cc_flags: str, - linker_cmd: str, linker_flags: str, linker_output: str, - includes_binary_dir: str, - includes_dir: str, - do_phase1: int, do_phase2: int, - log: VLogger.Logger | t.CPtr, - args: argparse.ParsedArgs | t.CPtr) -> int: - """多文件项目编译 - - Returns: 0 成功,非 0 失败 - """ - if source_dir is None: - VLogger.error("source_dir 为空", "project") - return 1 - - # === 栈金丝雀检查(全局变量,不影响栈布局)=== - _g_canary = 305419896 - - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "多文件项目编译: %s", source_dir) - VLogger.info(fb, "project") - - # === 1. 递归扫描 source_dir 下的 .py 文件(包括子目录)=== - entry_size: t.CSizeT = SrcFileEntry.__sizeof__() - entries: SrcFileEntry | t.CPtr = stdlib.malloc(MAX_SRC_FILES * entry_size) - if entries is None: - return 1 - string.memset(entries, 0, MAX_SRC_FILES * entry_size) - - file_count: int = _ScanDirForPyFiles(mb, source_dir, entries, entry_size, 0, MAX_SRC_FILES) - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "共 %d 个源文件", file_count) - VLogger.info(fb, "project") - - if file_count == 0: - stdlib.free(entries) - return 1 - - # 初始化 AST 表 - ast._init_tables(mb) - - # 确保 temp/output 目录存在 - BuildPipeline.ensure_dir(temp_dir) - BuildPipeline.ensure_dir(output_dir) - - # === 0.5 扫描 includes 目录填充 Sha1Store(消除 Phase1 依赖)=== - # Phase2 不依赖 Phase1 的副作用:如果 Sha1Store 为空(Phase1 未运行或提前返回), - # 自行扫描 includes 目录并填充 Sha1Store,确保后续"编译缺失 includes"逻辑能正常工作 - if includes_dir is not None: - if StubMerger.GetSha1StoreCount() == 0: - inc_scan_result: IncludesScanner.ScanResult | t.CPtr = IncludesScanner.scan_includes(mb, includes_dir) - if inc_scan_result is not None: - inc_filled: int = StubMerger.PopulateSha1MapStore(inc_scan_result) - fb_inc: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb_inc is not None: - viperlib.snprintf(fb_inc, 1024, "Phase2 自主填充 includes Sha1Store: %d 个", inc_filled) - VLogger.info(fb_inc, "project") - - # 追加 App 源文件 SHA1 到 _sha1_map.txt(人类可读输出,程序内部不读取此文件) - # 格式: {sha1}:{rel_path}\n (保留目录结构,如 lib/core/VLogger.py) - # 同步追加到内存存储器(AppendToSha1MapStore,供跨模块 CDefine 查找) - td_len_am: t.CSizeT = string.strlen(temp_dir) - src_dir_len_am: t.CSizeT = string.strlen(source_dir) - map_path_am: bytes = stdlib.malloc(td_len_am + 32) - if map_path_am is not None: - viperlib.snprintf(map_path_am, td_len_am + 32, "%s/_sha1_map.txt", temp_dir) - mf: fileio.File | t.CPtr = fileio.File(map_path_am, fileio.MODE.A) - line_am: bytes = stdlib.malloc(512) - # 先遍历一次填充内存存储器(不依赖文件 I/O),再写入 _sha1_map.txt - app_filled: int = 0 - for i in range(file_count): - ea_am: t.CUInt64T = t.CUInt64T(entries) + i * entry_size - ent_am: SrcFileEntry | t.CPtr = (SrcFileEntry | t.CPtr)(t.CVoid(ea_am, t.CPtr)) - if ent_am is None or ent_am.Path is None or ent_am.Sha1 is None: - continue - # 计算相对路径(去除 source_dir 前缀,保留目录结构) - p_str: str = ent_am.Path - p_len: t.CSizeT = string.strlen(p_str) - rel_path_am: str = p_str - if p_len > src_dir_len_am + 1: - if string.strncmp(p_str, source_dir, src_dir_len_am) == 0: - rel_path_am = p_str + src_dir_len_am + 1 - # 同步追加到内存存储器(供跨模块 CDefine 查找) - # rel_path_am 格式如 "lib/core/StubMerger.py",与 _sha1_map.txt 一致 - if StubMerger.AppendToSha1MapStore(ent_am.Sha1, rel_path_am) == 0: - app_filled += 1 - # 写入 _sha1_map.txt(人类可读输出) - if not mf.closed and line_am is not None: - viperlib.snprintf(line_am, 512, "%s:%s\n", ent_am.Sha1, rel_path_am) - ll_am: t.CSizeT = string.strlen(line_am) - mf.write(line_am, ll_am) - if line_am is not None: - stdlib.free(line_am) - if not mf.closed: - mf.close() - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "已追加 %d 个 App 文件到 _sha1_map.txt 和内存存储器", app_filled) - VLogger.info(fb, "project") - stdlib.free(map_path_am) - - # 构建模块 SHA1 映射(供跨模块函数调用名混淆使用) - td_len_pb: t.CSizeT = string.strlen(temp_dir) - pb_sha1_arr: bytes = stdlib.malloc(StubMerger.MAX_INCLUDES * 17) - pb_mod_arr: bytes = stdlib.malloc(StubMerger.MAX_INCLUDES * 64) - pb_inc_count: int = 0 - if pb_sha1_arr is not None and pb_mod_arr is not None: - pb_inc_count = StubMerger._BuildIncludesSha1Map(temp_dir, td_len_pb, pb_sha1_arr, pb_mod_arr) - # 追加用户源文件的 (模块名, SHA1) 到全局映射 - # 使跨模块方法调用能通过 from_imports + _lookup_module_sha1 找到正确的 SHA1 - if pb_sha1_arr is not None and pb_mod_arr is not None: - src_dir_len_us: t.CSizeT = string.strlen(source_dir) - for i in range(file_count): - ea_us: t.CUInt64T = t.CUInt64T(entries) + i * entry_size - ent_us: SrcFileEntry | t.CPtr = (SrcFileEntry | t.CPtr)(t.CVoid(ea_us, t.CPtr)) - if ent_us is None or ent_us.Path is None or ent_us.Sha1 is None: - continue - if pb_inc_count >= StubMerger.MAX_INCLUDES: - break - # 计算相对路径并转换为点分模块名(保留完整包路径) - path_str: str = ent_us.Path - path_len_us: t.CSizeT = string.strlen(path_str) - rel_path_us: str = path_str - if path_len_us > src_dir_len_us + 1: - if string.strncmp(path_str, source_dir, src_dir_len_us) == 0: - rel_path_us = path_str + src_dir_len_us + 1 - # 使用 _PathToModuleName 转换为点分模块名(处理 __init__.py → 包名) - mod_name_us: str = StubMerger._PathToModuleName(rel_path_us) - if mod_name_us is None: - continue - # 写入模块名 - mod_idx: t.CSizeT = t.CSizeT(pb_inc_count) * 64 - mn_len_us: t.CSizeT = string.strlen(mod_name_us) - if mn_len_us >= 64: - string.strncpy(pb_mod_arr + mod_idx, mod_name_us, 63) - pb_mod_arr[mod_idx + 63] = '\0' - else: - string.strcpy(pb_mod_arr + mod_idx, mod_name_us) - stdlib.free(mod_name_us) - # 写入 SHA1 - sha1_idx: t.CSizeT = t.CSizeT(pb_inc_count) * 17 - string.strcpy(pb_sha1_arr + sha1_idx, ent_us.Sha1) - pb_inc_count += 1 - HandlesExprCall.set_module_sha1_map(pb_sha1_arr, pb_mod_arr, pb_inc_count) - - - # === 2. Phase A: 为每个文件生成 stub + text === - # app_deps_buf: 收集所有 App 源文件的直接依赖模块名(空格分隔) - # 供 Phase B+ 的 _BuildReachableSha1Set 作为初始 worklist,实现按需编译 - # 声明在 if 块外,确保 Phase B+ 和清理代码能访问 - APP_DEPS_BUF_SIZE: t.CSizeT = 8192 - app_deps_buf: bytes = None - app_deps_len: t.CSizeT = 0 - if do_phase1 != 0: - if log is not None: - log.banner("Phase A: 生成 stub + text") - - # === Phase A-pre-inc: includes 预注册 struct + 依赖填充 === - # 必须在 App 源文件预注册之前执行:App 源文件(strict_mode=1)可能继承 - # 或引用 includes 中的 struct(如 ast.AST)。若 includes struct 未注册, - # App 源文件翻译会失败 → .obj 缺失 → undefined reference。 - # 同时填充 PopulateIncludesDeps,供 Phase B+ 的 _BuildReachableSha1Set 使用。 - # 多遍扫描:解决跨文件继承问题(如 Constant(AST) 在 AST 未注册时被跳过)。 - if includes_dir is not None and includes_binary_dir is not None: - store_count_inc_pre: int = StubMerger.GetSha1StoreCount() - if store_count_inc_pre > 0: - store_sha1_inc_pre: bytes | t.CPtr = StubMerger.GetSha1StoreArrPtr() - store_rel_inc_pre: bytes | t.CPtr = StubMerger.GetSha1StoreRelArrPtr() - inc_dir_len_pre: t.CSizeT = string.strlen(includes_dir) - deps_filled_pre: int = 0 - PHASE_A_INC_MAX_PASSES: t.CInt = 3 - for pass_inc_i in range(PHASE_A_INC_MAX_PASSES): - struct_count_before_inc: int = HandlesStruct.get_struct_count() - for si_inc in range(store_count_inc_pre): - inc_sha1_pre: str = store_sha1_inc_pre + t.CSizeT(si_inc) * 17 - inc_rel_pre: str = store_rel_inc_pre + t.CSizeT(si_inc) * StubMerger.MAX_REL_PATH_LEN - if inc_rel_pre is None or inc_rel_pre[0] == '\0': - continue - rel_len_pre: t.CSizeT = string.strlen(inc_rel_pre) - full_path_pre: bytes = stdlib.malloc(inc_dir_len_pre + rel_len_pre + 2) - if full_path_pre is None: - continue - viperlib.snprintf(full_path_pre, inc_dir_len_pre + rel_len_pre + 2, - "%s/%s", includes_dir, inc_rel_pre) - pkg_inc_pre: str = HandlesImports.compute_package_from_relpath(mb, inc_rel_pre) - tr_inc_pre: HandlesTranslator.Translator | t.CPtr = BuildPipeline.TranslateFileGetTrans( - mb, full_path_pre, inc_sha1_pre, pkg_inc_pre, 1) - stdlib.free(full_path_pre) - if tr_inc_pre is not None: - # 依赖填充只在第一遍执行(PopulateIncludesDeps 内部有去重) - if pass_inc_i == 0: - if tr_inc_pre._imported_modules is not None: - if StubMerger.PopulateIncludesDeps(inc_sha1_pre, tr_inc_pre._imported_modules) == 0: - deps_filled_pre = deps_filled_pre + 1 - struct_count_after_inc: int = HandlesStruct.get_struct_count() - # 收敛检查:本遍没有新结构体注册 → 所有类已注册 - if struct_count_after_inc == struct_count_before_inc: - break - fb_inc_pre: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb_inc_pre is not None: - viperlib.snprintf(fb_inc_pre, 1024, "includes 预注册 + 依赖填充: %d/%d", deps_filled_pre, store_count_inc_pre) - VLogger.info(fb_inc_pre, "prePhaseA") - - # === Phase A-pre: 预注册所有源文件的 struct/enum/union === - # 解决循环引用问题:circ_a 翻译时需要知道 circ_b.ClassB 的 struct 定义 - # 仅注册 struct/enum/union(declare_only=1),不翻译方法体 - # 多遍扫描:解决跨文件继承的字母序问题(如 HandlesAnnAssign.py 在 HandlesBase.py 之前, - # AnnAssignHandle 继承 Mixin 时 Mixin 未注册)。每遍注册新类后,下一遍子类可继承。 - VLogger.info("预注册 struct/enum/union...", "PhaseA") - src_dir_len_pre: t.CSizeT = string.strlen(source_dir) - PHASE_A_PRE_MAX_PASSES: t.CInt = 3 - for pass_i in range(PHASE_A_PRE_MAX_PASSES): - struct_count_before: int = HandlesStruct.get_struct_count() - for i in range(file_count): - ea_pre: t.CUInt64T = t.CUInt64T(entries) + i * entry_size - ent_pre: SrcFileEntry | t.CPtr = (SrcFileEntry | t.CPtr)(t.CVoid(ea_pre, t.CPtr)) - if ent_pre is None or ent_pre.Path is None: - continue - pkg_pre: str = None - if string.strlen(ent_pre.Path) > src_dir_len_pre + 1: - rel_path_pre: str = ent_pre.Path + src_dir_len_pre + 1 - pkg_pre = HandlesImports.compute_package_from_relpath(mb, rel_path_pre) - tr_pre: HandlesTranslator.Translator | t.CPtr = BuildPipeline.TranslateFileGetTrans(mb, ent_pre.Path, ent_pre.Sha1, pkg_pre, 1) - if tr_pre is None: - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "预注册失败: %s", ent_pre.Path) - VLogger.warning(fb, "PhaseA") - struct_count_after: int = HandlesStruct.get_struct_count() - # 收敛检查:本遍没有新结构体注册 → 所有类已注册 - if struct_count_after == struct_count_before: - break - VLogger.info("预注册完成", "PhaseA") - - PHASE_A_IR_SIZE: t.CSizeT = 1048576 - td_len_pa: t.CSizeT = string.strlen(temp_dir) - - # app_deps_buf: 收集所有 App 源文件的直接依赖模块名(空格分隔) - # 供 Phase B+ 的 _BuildReachableSha1Set 作为初始 worklist 使用 - # 声明已在 if 块外,此处仅赋值 - app_deps_buf = stdlib.malloc(APP_DEPS_BUF_SIZE) - app_deps_len = 0 - if app_deps_buf is not None: - app_deps_buf[0] = '\0' - - for i in range(file_count): - ea: t.CUInt64T = t.CUInt64T(entries) + i * entry_size - ent: SrcFileEntry | t.CPtr = (SrcFileEntry | t.CPtr)(t.CVoid(ea, t.CPtr)) - if ent is None or ent.Path is None: - continue - # 计算源文件的包名(相对 source_dir 的目录部分) - src_dir_len_pa: t.CSizeT = string.strlen(source_dir) - pkg_pa: str = None - if string.strlen(ent.Path) > src_dir_len_pa + 1: - rel_path_pa: str = ent.Path + src_dir_len_pa + 1 - pkg_pa = HandlesImports.compute_package_from_relpath(mb, rel_path_pa) - tr_a: HandlesTranslator.Translator | t.CPtr = BuildPipeline.TranslateFileGetTrans(mb, ent.Path, ent.Sha1, pkg_pa) - if tr_a is None: - continue - - # dump stub IR (declarations only) - stub_buf_a: bytes = stdlib.malloc(PHASE_A_IR_SIZE) - if stub_buf_a is None: - continue - tr_a.dump_ir(stub_buf_a, PHASE_A_IR_SIZE, llvmlite.OUTPUT_STUB) - stub_len_a: t.CSizeT = string.strlen(stub_buf_a) - - # save stub.ll (切片路径: temp_dir/{sha1前缀}/{sha1}.stub.ll) - stub_path_a: str = StubMerger._sliced_path(temp_dir, td_len_pa, ent.Sha1, "stub.ll") - if stub_path_a is not None: - sf_a: fileio.File | t.CPtr = fileio.File(stub_path_a, fileio.MODE.W) - if not sf_a.closed: - sf_a.write(stub_buf_a, stub_len_a) - sf_a.close() - stdlib.free(stub_path_a) - stdlib.free(stub_buf_a) - - # dump text IR (definitions only) - text_buf_a: bytes = stdlib.malloc(PHASE_A_IR_SIZE) - if text_buf_a is None: - continue - tr_a.dump_ir(text_buf_a, PHASE_A_IR_SIZE, llvmlite.OUTPUT_TEXT) - text_len_a: t.CSizeT = string.strlen(text_buf_a) - - # save text.ll (切片路径) - text_path_a: str = StubMerger._sliced_path(temp_dir, td_len_pa, ent.Sha1, "text.ll") - if text_path_a is not None: - tf_a: fileio.File | t.CPtr = fileio.File(text_path_a, fileio.MODE.W) - if not tf_a.closed: - tf_a.write(text_buf_a, text_len_a) - tf_a.close() - stdlib.free(text_path_a) - stdlib.free(text_buf_a) - - # save dependencies (_imported_modules) for Phase B (切片路径) - deps_path_a: str = StubMerger._sliced_path(temp_dir, td_len_pa, ent.Sha1, "deps.txt") - if deps_path_a is not None: - df_a: fileio.File | t.CPtr = fileio.File(deps_path_a, fileio.MODE.W) - if not df_a.closed: - if tr_a._imported_modules is not None: - dl_a: t.CSizeT = string.strlen(tr_a._imported_modules) - df_a.write(tr_a._imported_modules, dl_a) - df_a.close() - stdlib.free(deps_path_a) - - # 收集 _imported_modules 到 app_deps_buf(供 Phase B+ 按需编译) - if tr_a._imported_modules is not None and app_deps_buf is not None: - im_len_a: t.CSizeT = string.strlen(tr_a._imported_modules) - if im_len_a > 0 and app_deps_len + im_len_a + 1 < APP_DEPS_BUF_SIZE: - if app_deps_len > 0: - app_deps_buf[app_deps_len] = ' ' - app_deps_len = app_deps_len + 1 - string.strcpy(app_deps_buf + app_deps_len, tr_a._imported_modules) - app_deps_len = app_deps_len + im_len_a - app_deps_buf[app_deps_len] = '\0' - - if do_phase2 == 0: - VLogger.info("Phase A 完成(仅 stub 生成)", "project") - if app_deps_buf is not None: - stdlib.free(app_deps_buf) - stdlib.free(entries) - return 0 - - # === 3. Phase B: 编译每个文件为 .obj === - if do_phase2 != 0: - if log is not None: - log.banner("Phase B: 编译 .obj") - - # 收集 .obj 路径(增大到 64KB,避免 includes .obj 路径溢出导致链接丢失符号) - # reachable_set/reachable_count: Phase B+ 填充,Phase C 用于按需链接 - reachable_set: bytes = None - reachable_count: int = 0 - OBJ_PATHS_SIZE: t.CSizeT = 65536 - obj_paths: bytes = stdlib.malloc(OBJ_PATHS_SIZE) - if obj_paths is None: - return 1 - obj_paths[0] = '\0' - obj_pos: t.CSizeT = 0 - # main_obj_path: 存放定义了用户 main 的 .obj 路径(链接时放在最前面, - # 避免 --allow-multiple-definition 选择了其他模块的 wrapper main) - main_obj_path: bytes = stdlib.malloc(512) - if main_obj_path is None: - return 1 - main_obj_path[0] = '\0' - compiled_count: int = 0 - - # 组合 IR 缓冲区大小(4MB,足够容纳本地 stub + 所有依赖 stub + 本地 text) - COMBINED_IR_SIZE: t.CSizeT = 4194304 - - for i in range(file_count): - ea: t.CUInt64T = t.CUInt64T(entries) + i * entry_size - ent: SrcFileEntry | t.CPtr = (SrcFileEntry | t.CPtr)(t.CVoid(ea, t.CPtr)) - if ent is None or ent.Path is None or ent.Sha1 is None: - continue - # 组合本地 stub + 所有依赖 stub + 本地 text → 完整 IR - combined_ir: bytes = stdlib.malloc(COMBINED_IR_SIZE) - if combined_ir is None: - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "combined_ir 分配失败: %s", ent.Path) - VLogger.error(fb, "PhaseB") - continue - combined_len: t.CSizeT = StubMerger.BuildCombinedIR(temp_dir, ent.Sha1, combined_ir, COMBINED_IR_SIZE) - if combined_len == 0: - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "BuildCombinedIR 失败: %s", ent.Path) - VLogger.error(fb, "PhaseB") - stdlib.free(combined_ir) - continue - - # 编译为 .obj - cret: int = BuildPipeline.compile_module_to_obj( - combined_ir, combined_len, temp_dir, output_dir, ent.Sha1, - cc_cmd, cc_flags) - stdlib.free(combined_ir) - if cret != 0: - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "llc 编译失败,终止编译: %s", ent.Path) - VLogger.error(fb, "PhaseB") - sys.exit(1) - - compiled_count += 1 - # 显示编译完成的文件 - fb_comp: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb_comp is not None: - viperlib.snprintf(fb_comp, 1024, "[%d/%d] 编译完成: %s", i + 1, file_count, ent.Path) - VLogger.info(fb_comp, "PhaseB") - # 构造 .obj 路径,检测是否是 main 模块(test_main.py 或 main.py) - od_len: t.CSizeT = string.strlen(output_dir) - is_main_mod: int = 0 - if string.strstr(ent.Path, "test_main.py") is not None: - is_main_mod = 1 - elif string.strstr(ent.Path, "main.py") is not None: - is_main_mod = 1 - - # 切片路径: output_dir/{sha1前缀}/{sha1}.obj - obj_path_sliced: str = StubMerger._sliced_path(output_dir, od_len, ent.Sha1, "obj") - if obj_path_sliced is not None: - op_sliced_len: t.CSizeT = string.strlen(obj_path_sliced) - if is_main_mod != 0: - # main 模块: 复制到 main_obj_path(确保链接时 main 在最前) - if op_sliced_len < 512: - string.strcpy(main_obj_path, obj_path_sliced) - else: - VLogger.warning("main_obj_path 缓冲区不足", "PhaseB") - else: - # 其他模块: 追加到 obj_paths - if obj_pos + op_sliced_len + 2 < OBJ_PATHS_SIZE: - if obj_pos > 0: - obj_paths[obj_pos] = ' ' - obj_pos += 1 - string.strcpy(obj_paths + obj_pos, obj_path_sliced) - obj_pos += op_sliced_len - obj_paths[obj_pos] = '\0' - else: - VLogger.warning(".obj 路径缓冲区不足", "PhaseB") - stdlib.free(obj_path_sliced) - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "编译完成: %d/%d", compiled_count, file_count) - VLogger.success(fb, "PhaseB") - - if compiled_count == 0: - VLogger.error("无成功编译的文件", "PhaseB") - stdlib.free(entries) - return 1 - - # === 3.5 编译缺失的 includes 文件(按依赖图按需编译)=== - # 只编译被 App 源文件直接/间接引用的 includes 文件(可达集合), - # 而非遍历整个 includes 目录。通过 _BuildReachableSha1Set 构建依赖图。 - if includes_dir is not None and includes_binary_dir is not None: - inc_compiled: int = 0 - td_len_mi: t.CSizeT = string.strlen(temp_dir) - - # 诊断日志:确认 Phase B+ 入口和 Sha1Store 状态 - fb_pbp_enter: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb_pbp_enter is not None: - viperlib.snprintf(fb_pbp_enter, 1024, - "PhaseB+ 入口: store_count=%d includes_binary_dir=%s", - StubMerger.GetSha1StoreCount(), includes_binary_dir) - VLogger.info(fb_pbp_enter, "PhaseB+") - - # 创建 includes_binary_dir 目录(确保 .obj 能写入和 collect_obj_files 能扫描) - BuildPipeline.ensure_dir(includes_binary_dir) - - # declare_only 预处理已移至 Phase A 之前(Phase A-pre-inc), - # 确保 Phase A 翻译 App 源文件时 includes struct 已注册。 - # PopulateIncludesDeps 已在 Phase A-pre-inc 中填充。 - - # 构建可达 SHA1 集合(依赖图遍历) - # app_deps_buf 为 None 时回退到扫描 source_dir(非递归) - REACHABLE_SET_SIZE: t.CSizeT = t.CSizeT(StubMerger.MAX_INCLUDES_SHA1) * 17 - reachable_set: bytes = stdlib.malloc(REACHABLE_SET_SIZE) - reachable_count: int = 0 - if reachable_set is not None: - string.memset(reachable_set, 0, REACHABLE_SET_SIZE) - reachable_count = StubMerger._BuildReachableSha1Set( - mb, source_dir, temp_dir, reachable_set, app_deps_buf) - fb_reach: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb_reach is not None: - viperlib.snprintf(fb_reach, 1024, "可达 includes SHA1: %d 个", reachable_count) - VLogger.info(fb_reach, "PhaseB+") - # fast-fail: 可达集合构建失败(依赖未找到),永不回退,直接终止 - if reachable_count < 0: - VLogger.error("可达集合构建失败(fast-fail),终止编译", "PhaseB+") - return 1 - else: - VLogger.error("reachable_set 分配失败,终止编译", "PhaseB+") - return 1 - - # 释放 app_deps_buf(已构建完 reachable_set,不再需要) - if app_deps_buf is not None: - stdlib.free(app_deps_buf) - app_deps_buf = None - - # 从全局存储器获取 SHA1/模块名/rel_path 数组(直接访问器,避免 box 解引用问题) - store_count_mi: int = StubMerger.GetSha1StoreCount() - if store_count_mi > 0: - store_sha1_arr_mi: bytes | t.CPtr = StubMerger.GetSha1StoreArrPtr() - store_mod_arr_mi: bytes | t.CPtr = StubMerger.GetSha1StoreModArrPtr() - store_rel_arr_mi: bytes | t.CPtr = StubMerger.GetSha1StoreRelArrPtr() - - for si_mi in range(store_count_mi): - # 获取当前条目的 SHA1 和 rel_path - inc_sha1_mi: str = store_sha1_arr_mi + t.CSizeT(si_mi) * 17 - inc_rel_mi: str = store_rel_arr_mi + t.CSizeT(si_mi) * StubMerger.MAX_REL_PATH_LEN - # 按需编译过滤:只处理 reachable_set 中的 includes - # 永不回退:reachable_count > 0 时严格按可达集合过滤 - if reachable_count > 0: - if StubMerger._is_in_sha1_set(inc_sha1_mi, reachable_set, reachable_count) == 0: - continue - # 检查 .obj 是否已存在于 includes.binary(切片子目录) - ibd_len_mi: t.CSizeT = string.strlen(includes_binary_dir) - check_pat_mi: str = StubMerger._sliced_path(includes_binary_dir, ibd_len_mi, inc_sha1_mi, "obj") - check_fd_mi: w32.win32file.WIN32_FIND_DATAA | t.CPtr = stdlib.malloc(w32.win32file.WIN32_FIND_DATAA.__sizeof__()) - obj_exists_mi: int = 0 - if check_pat_mi is not None and check_fd_mi is not None: - string.memset(check_fd_mi, 0, w32.win32file.WIN32_FIND_DATAA.__sizeof__()) - check_h_mi: w32.win32base.HANDLE = w32.win32file.FindFirstFileA(check_pat_mi, check_fd_mi) - if check_h_mi != w32.win32base.INVALID_HANDLE_VALUE: - w32.win32file.FindClose(check_h_mi) - obj_exists_mi = 1 - if obj_exists_mi != 0: - if check_pat_mi is not None: - stdlib.free(check_pat_mi) - stdlib.free(check_fd_mi) - continue - - # .obj 不存在,需要编译 - # 构造源文件路径: {includes_dir}/{rel_path} - rel_path_len_mi: t.CSizeT = string.strlen(inc_rel_mi) - inc_dir_len_mi: t.CSizeT = string.strlen(includes_dir) - src_fp_mi: bytes = stdlib.malloc(inc_dir_len_mi + 1 + rel_path_len_mi + 1) - if src_fp_mi is None: - stdlib.free(check_pat_mi) - if check_fd_mi is not None: - stdlib.free(check_fd_mi) - continue - viperlib.snprintf(src_fp_mi, inc_dir_len_mi + 1 + rel_path_len_mi + 1, - "%s/%s", includes_dir, inc_rel_mi) - - # 检查是否为声明文件(只有 declare 没有实质 define) - # 判断方法: text.ll 中若有混淆函数 define(含 @")则为实现文件 - is_decl_mi: int = -1 - tpath_mi: str = StubMerger._sliced_path(temp_dir, td_len_mi, inc_sha1_mi, "text.ll") - if tpath_mi is not None: - tf_mi: fileio.File | t.CPtr = fileio.File(tpath_mi, fileio.MODE.R) - if not tf_mi.closed: - is_decl_mi = 1 - tbuf_mi: bytes = stdlib.malloc(StubMerger.STUB_READ_BUF_SIZE) - if tbuf_mi is not None: - tbr_mi: t.CInt64T = tf_mi.read_all(tbuf_mi, StubMerger.STUB_READ_BUF_SIZE) - if tbr_mi > 0: - if tbr_mi < StubMerger.STUB_READ_BUF_SIZE: - tbuf_mi[tbr_mi] = '\0' - else: - tbuf_mi[StubMerger.STUB_READ_BUF_SIZE - 1] = '\0' - # 逐行扫描: 找 define 行中含 @" 的(混淆函数名) - tpos_mi: t.CSizeT = 0 - while tpos_mi < tbr_mi: - tls_mi: t.CSizeT = tpos_mi - while tpos_mi < tbr_mi: - if tbuf_mi[tpos_mi] == '\n': - break - tpos_mi += 1 - tll_mi: t.CSizeT = tpos_mi - tls_mi - if tpos_mi < tbr_mi: - tpos_mi += 1 - if tll_mi >= 7 and string.strncmp(tbuf_mi + tls_mi, "define ", 7) == 0: - # 临时在行尾加 \0 供 strstr 使用 - # 仅当行尾不在缓冲区末尾时才需保存/恢复 - # (缓冲区末尾已在上方 read_all 后截断为 '\0',直接用即可) - # 避免 tls_mi + tll_mi == tbr_mi 时越界写 - end_pos_mi: t.CSizeT = tls_mi + tll_mi - saved_mi: t.CChar = '\0' - need_restore_mi: int = 0 - if end_pos_mi < tbr_mi: - saved_mi = tbuf_mi[end_pos_mi] - tbuf_mi[end_pos_mi] = '\0' - need_restore_mi = 1 - if string.strstr(tbuf_mi + tls_mi, "@\"") is not None: - if need_restore_mi != 0: - tbuf_mi[end_pos_mi] = saved_mi - is_decl_mi = 0 - break - if need_restore_mi != 0: - tbuf_mi[end_pos_mi] = saved_mi - stdlib.free(tbuf_mi) - tf_mi.close() - stdlib.free(tpath_mi) - # is_decl_mi == -1: text.ll 不存在(Phase1 未翻译此文件) - # is_decl_mi == 1: 声明文件(仅 declare 无 define) - # is_decl_mi == 0: 实现文件(有 define) - # 只跳过声明文件(is_decl_mi == 1);text.ll 不存在时继续,让后续翻译逻辑处理 - if is_decl_mi == 1: - stdlib.free(check_pat_mi) - if check_fd_mi is not None: - stdlib.free(check_fd_mi) - stdlib.free(src_fp_mi) - continue - - # 尝试 BuildCombinedIR(stub/text 应已由 Phase1 生成) - inc_combined_mi: bytes = stdlib.malloc(COMBINED_IR_SIZE) - inc_combined_len_mi: t.CSizeT = 0 - if inc_combined_mi is not None: - inc_combined_len_mi = StubMerger.BuildCombinedIR(temp_dir, inc_sha1_mi, inc_combined_mi, COMBINED_IR_SIZE) - - # 如果 stub/text 不存在,翻译源文件并保存 stub + text,然后重试 - if inc_combined_len_mi == 0 and inc_combined_mi is not None: - # 计算 includes 文件的包名(相对 includes_dir 的目录部分) - inc_pkg_mi: str = None - if string.strlen(src_fp_mi) > inc_dir_len_mi + 1: - inc_rel_mi2: str = src_fp_mi + inc_dir_len_mi + 1 - inc_pkg_mi = HandlesImports.compute_package_from_relpath(mb, inc_rel_mi2) - tr_mi: HandlesTranslator.Translator | t.CPtr = BuildPipeline.TranslateFileGetTrans(mb, src_fp_mi, inc_sha1_mi, inc_pkg_mi) - if tr_mi is not None: - PBP_IR_SIZE: t.CSizeT = 1048576 - # 保存 stub.ll (切片路径) - inc_stub_buf: bytes = stdlib.malloc(PBP_IR_SIZE) - if inc_stub_buf is not None: - tr_mi.dump_ir(inc_stub_buf, PBP_IR_SIZE, llvmlite.OUTPUT_STUB) - inc_stub_len: t.CSizeT = string.strlen(inc_stub_buf) - inc_stub_path: str = StubMerger._sliced_path(temp_dir, td_len_mi, inc_sha1_mi, "stub.ll") - if inc_stub_path is not None: - isf: fileio.File | t.CPtr = fileio.File(inc_stub_path, fileio.MODE.W) - if not isf.closed: - isf.write(inc_stub_buf, inc_stub_len) - isf.close() - stdlib.free(inc_stub_path) - stdlib.free(inc_stub_buf) - # 保存 text.ll (切片路径) - inc_text_buf: bytes = stdlib.malloc(PBP_IR_SIZE) - if inc_text_buf is not None: - tr_mi.dump_ir(inc_text_buf, PBP_IR_SIZE, llvmlite.OUTPUT_TEXT) - inc_text_len: t.CSizeT = string.strlen(inc_text_buf) - inc_text_path: str = StubMerger._sliced_path(temp_dir, td_len_mi, inc_sha1_mi, "text.ll") - if inc_text_path is not None: - itf: fileio.File | t.CPtr = fileio.File(inc_text_path, fileio.MODE.W) - if not itf.closed: - itf.write(inc_text_buf, inc_text_len) - itf.close() - stdlib.free(inc_text_path) - stdlib.free(inc_text_buf) - # 重试 BuildCombinedIR - inc_combined_len_mi = StubMerger.BuildCombinedIR(temp_dir, inc_sha1_mi, inc_combined_mi, COMBINED_IR_SIZE) - - if inc_combined_len_mi == 0: - # 诊断:检查 stub.ll/text.ll 是否存在 - diag_stub: str = StubMerger._sliced_path(temp_dir, td_len_mi, inc_sha1_mi, "stub.ll") - diag_text: str = StubMerger._sliced_path(temp_dir, td_len_mi, inc_sha1_mi, "text.ll") - diag_stub_ex: int = 0 - diag_text_ex: int = 0 - if diag_stub is not None: - df_diag_s: fileio.File | t.CPtr = fileio.File(diag_stub, fileio.MODE.R) - if not df_diag_s.closed: - diag_stub_ex = 1 - df_diag_s.close() - stdlib.free(diag_stub) - if diag_text is not None: - df_diag_t: fileio.File | t.CPtr = fileio.File(diag_text, fileio.MODE.R) - if not df_diag_t.closed: - diag_text_ex = 1 - df_diag_t.close() - stdlib.free(diag_text) - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, - "BuildCombinedIR 失败: %s (stub=%d text=%d is_decl=%d)", - src_fp_mi, diag_stub_ex, diag_text_ex, is_decl_mi) - VLogger.error(fb, "PhaseB+") - if inc_combined_mi is not None: - stdlib.free(inc_combined_mi) - stdlib.free(check_pat_mi) - if check_fd_mi is not None: - stdlib.free(check_fd_mi) - stdlib.free(src_fp_mi) - continue - - # 编译为 .obj(输出到 includes_binary_dir,与存在性检查和链接收集一致) - inc_cret_mi: int = BuildPipeline.compile_module_to_obj( - inc_combined_mi, inc_combined_len_mi, temp_dir, includes_binary_dir, inc_sha1_mi, - cc_cmd, cc_flags) - stdlib.free(inc_combined_mi) - - if inc_cret_mi != 0: - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "llc 编译失败,终止编译: %s", src_fp_mi) - VLogger.error(fb, "PhaseB+") - sys.exit(1) - - inc_compiled += 1 - # 显示编译完成的 includes 文件 - fb_inc_comp: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb_inc_comp is not None: - viperlib.snprintf(fb_inc_comp, 1024, "[includes %d] 编译完成: %s", inc_compiled, src_fp_mi) - VLogger.info(fb_inc_comp, "PhaseB+") - - # 添加到 obj_paths (切片路径,从 includes_binary_dir 取) - ibd_len_mi2: t.CSizeT = string.strlen(includes_binary_dir) - inc_obj_sliced: str = StubMerger._sliced_path(includes_binary_dir, ibd_len_mi2, inc_sha1_mi, "obj") - - if inc_obj_sliced is not None: - inc_obj_len: t.CSizeT = string.strlen(inc_obj_sliced) - if obj_pos + inc_obj_len + 2 < OBJ_PATHS_SIZE: - if obj_pos > 0: - obj_paths[obj_pos] = ' ' - obj_pos += 1 - string.strcpy(obj_paths + obj_pos, inc_obj_sliced) - obj_pos += inc_obj_len - obj_paths[obj_pos] = '\0' - stdlib.free(inc_obj_sliced) - - # 释放本次迭代的临时内存 - if check_pat_mi is not None: - stdlib.free(check_pat_mi) - - if check_fd_mi is not None: - stdlib.free(check_fd_mi) - - stdlib.free(src_fp_mi) - - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "编译缺失 includes: %d 个", inc_compiled) - VLogger.info(fb, "PhaseB+") - - # 释放 app_deps_buf(Phase B+ 块未执行时此处兜底释放) - if app_deps_buf is not None: - stdlib.free(app_deps_buf) - app_deps_buf = None - - # === 4. Phase C: 链接所有 .obj → .exe === - if log is not None: - log.banner("Phase C: 链接") - - od_len2: t.CSizeT = string.strlen(output_dir) - lo_len: t.CSizeT = string.strlen(linker_output) - exe_path: bytes = stdlib.malloc(od_len2 + lo_len + 2) - if exe_path is not None: - viperlib.snprintf(exe_path, od_len2 + lo_len + 2, "%s/%s", output_dir, linker_output) - else: - exe_path = linker_output - - # 构造最终 .obj 路径列表:main_obj_path 在前,其他 .obj 在后 - final_obj_paths: bytes = stdlib.malloc(OBJ_PATHS_SIZE + 512) - if final_obj_paths is None: - stdlib.free(entries) - return 1 - final_obj_paths[0] = '\0' - fop_pos: t.CSizeT = 0 - # main_obj_path 放在最前面(确保 --allow-multiple-definition 选择用户 main) - if main_obj_path[0] != '\0': - mlen: t.CSizeT = string.strlen(main_obj_path) - string.strcpy(final_obj_paths, main_obj_path) - fop_pos = mlen - if obj_paths[0] != '\0': - final_obj_paths[fop_pos] = ' ' - fop_pos += 1 - # 追加其他 .obj - if obj_paths[0] != '\0': - string.strcpy(final_obj_paths + fop_pos, obj_paths) - fop_pos += string.strlen(obj_paths) - final_obj_paths[fop_pos] = '\0' - - obj_paths_len: t.CSizeT = fop_pos - - # 暂时禁用按图链接:始终全量链接 includes.binary 中的 .obj - # 按图链接在 --clean 后 deps.txt 缺失时无法正确工作(跨包传递依赖丢失) - # 按图编译(Phase B+)仍保留:只编译 reachable_set 中的缺失 includes - # TODO: 待 deps.txt 生成机制完善后(如 Phase A 翻译所有 includes 的 imports),重新启用按图链接 - - # 释放 reachable_set(Phase B+ 已使用完毕) - if reachable_set is not None: - stdlib.free(reachable_set) - reachable_set = None - - # 始终传 includes_binary_dir 给 link_objs_to_exe,由其全量收集 .obj - lret: int = BuildPipeline.link_objs_to_exe( - final_obj_paths, obj_paths_len, - linker_cmd, linker_flags, exe_path, - includes_binary_dir) - - if lret == 0: - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "输出: %s", exe_path) - VLogger.success(fb, "PhaseC") - if args.get_bool("run"): - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "执行: %s", exe_path) - VLogger.info(fb, "run") - rp: subprocess.CompletedProcess | t.CPtr = subprocess.run(exe_path, False, False) - if rp is not None: - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "退出码: %d", rp.returncode) - VLogger.info(fb, "run") - else: - VLogger.error("链接失败", "PhaseC") - stdlib.free(entries) - return 1 - - stdlib.free(entries) - return 0 diff --git a/TransPyV/App/lib/core/StubMerger.py b/TransPyV/App/lib/core/StubMerger.py deleted file mode 100644 index 04e8ccc..0000000 --- a/TransPyV/App/lib/core/StubMerger.py +++ /dev/null @@ -1,2043 +0,0 @@ -import t, c -from stdint import * -import memhub -import string -import stdio -import stdlib -import llvmlite -import w32.win32file as win32file -import w32.win32base as win32base -import w32.fileio as fileio -import viperlib -import sys -import ast -import lib.core.VLogger as VLogger -import lib.core.IncludesScanner as IncludesScanner -import lib.core.Handles.HandlesStruct as HandlesStruct -import lib.core.Handles.HandlesImports as HandlesImports -import lib.core.Handles.HandlesTranslator as HandlesTranslator -import lib.core.BuildPipeline as BuildPipeline -import lib.Projectrans.Config as Config - - -# ============================================================ -# StubMerger - stub 声明合并模块 -# -# 从 temp 目录加载所有 .stub.ll 文件,将声明内容合并到主 IR。 -# 这是 Phase2 的核心功能:翻译主文件时,将所有依赖的 stub -# 声明合并到主 IR 前面,使链接器能解析跨模块符号引用。 -# -# 合并策略: -# 1. 扫描 temp 目录,收集所有 {sha1}.stub.ll 文件 -# 2. 读取每个 stub 文件内容 -# 3. 过滤去重(避免重复声明) -# 4. 将声明插入到主 IR 的 target triple 之后 -# ============================================================ - -# 全局 mbuddy 指针 -_mbuddy: memhub.MemBuddy | t.CPtr - -# 最大 includes SHA1 数(用于过滤) -MAX_INCLUDES_SHA1: t.CDefine = 256 -# stub 读取缓冲区大小 -STUB_READ_BUF_SIZE: t.CDefine = 1048576 -# 最大 includes 条目数 -MAX_INCLUDES: t.CDefine = 256 - -# 全局 SHA1 映射存储器(内存中,不依赖 _sha1_map.txt 文件) -# Phase1 扫描完成后填充,供所有函数使用 -_sha1_store_arr: bytes # SHA1 数组(每个 17 字节,MAX_INCLUDES 个) -_sha1_store_mod: bytes # 模块名数组(每个 64 字节,MAX_INCLUDES 个) -_sha1_store_rel: bytes # 相对路径数组(每个 256 字节,MAX_INCLUDES 个) -_sha1_store_count: int # 条目数 - -# 可达集合是否不完整(1=有 includes deps.txt 缺失,Phase C 应回退全量链接) -_g_reachable_incomplete: int - -# includes 依赖内存存储(不依赖 deps.txt 过程文件) -# Phase B+ 前用 declare_only 翻译所有 includes 文件,提取 _imported_modules 存入此处 -# _BuildReachableSha1Set 从此处读取依赖,不读 deps.txt -_includes_deps_sha1: bytes # SHA1 数组(每个 17 字节,MAX_INCLUDES 个) -_includes_deps_str: bytes # 依赖字符串数组(每个 512 字节,MAX_INCLUDES 个) -_includes_deps_count: int # 条目数 - -# 单条依赖字符串最大长度 -MAX_DEPS_STR_LEN: t.CDefine = 512 - -# rel_path 最大长度 -MAX_REL_PATH_LEN: t.CDefine = 256 - - -# ============================================================ -# _sliced_path - 构建切片路径(stdlib.malloc 分配,调用者负责 free) -# -# 根据 Config.Sha1SliceLevel 将文件分散到 SHA1 前缀子目录: -# level=0 → {temp_dir}/{sha1}.{ext} -# level=1 → {temp_dir}/b7/{sha1}.{ext} -# level=2 → {temp_dir}/b7/90/{sha1}.{ext} -# -# 自动调用 BuildPipeline.ensure_dir 创建子目录(level>0 时)。 -# -# Args: -# temp_dir: 基础目录 -# td_len: temp_dir 长度(避免重复 strlen) -# sha1: SHA1 字符串 -# ext: 文件扩展名(如 "stub.ll") -# -# Returns: -# 完整路径(stdlib.malloc 分配,需 stdlib.free),None 失败 -# ============================================================ -def _sliced_path(temp_dir: str, td_len: t.CSizeT, sha1: str, ext: str) -> str: - """构建切片路径(stdlib.malloc 分配,调用者负责 free) - - level>0 时自动调用 ensure_dir 创建子目录。 - """ - if temp_dir is None or sha1 is None or ext is None: - return None - sha1_len: t.CSizeT = string.strlen(sha1) - ext_len: t.CSizeT = string.strlen(ext) - - # 子目录前缀缓冲区(最多 3 层 = 8 字节 + null = 16 足够) - SUBDIR_BUF_SIZE: t.CSizeT = 16 - subdir_buf: bytes = stdlib.malloc(SUBDIR_BUF_SIZE) - if subdir_buf is None: - return None - subdir_buf[0] = '\0' - sub_len: t.CSizeT = 0 - level: int = Config.Sha1SliceLevel - if level > 0: - li: int = 0 - while li < level: - if li > 0: - subdir_buf[sub_len] = '/' - sub_len += 1 - idx: int = li * 2 - subdir_buf[sub_len] = sha1[idx] - subdir_buf[sub_len + 1] = sha1[idx + 1] - sub_len += 2 - li += 1 - subdir_buf[sub_len] = '\0' - - # 确保子目录存在: {temp_dir}/{subdir} - # 不创建目录会导致 fileio.File(MODE.W) 静默失败(file.closed==True), - # 进而 BuildCombinedIR 读不到文件返回 0("BuildCombinedIR 失败")。 - dir_path_len: t.CSizeT = td_len + sub_len + 2 - dir_path: bytes = stdlib.malloc(dir_path_len) - if dir_path is not None: - viperlib.snprintf(dir_path, dir_path_len, "%s/%s", temp_dir, subdir_buf) - BuildPipeline.ensure_dir(dir_path) - stdlib.free(dir_path) - - # 构建完整路径 - path: str = None - path_len: t.CSizeT = 0 - if sub_len > 0: - path_len = td_len + sub_len + sha1_len + ext_len + 4 - path = stdlib.malloc(path_len) - if path is not None: - viperlib.snprintf(path, path_len, "%s/%s/%s.%s", temp_dir, subdir_buf, sha1, ext) - else: - path_len = td_len + sha1_len + ext_len + 3 - path = stdlib.malloc(path_len) - if path is not None: - viperlib.snprintf(path, path_len, "%s/%s.%s", temp_dir, sha1, ext) - - stdlib.free(subdir_buf) - return path - - -# ============================================================ -# _collect_stub_sha1s - 递归扫描子目录,收集 .stub.ll 文件的 SHA1 -# -# 根据 level 递归扫描子目录: -# level=0 → 扫描 {base_dir}/*.stub.ll,从文件名提取 SHA1 -# level>0 → 扫描 {base_dir}/* 的子目录,对每个子目录递归调用 -# -# Args: -# base_dir: 当前扫描目录 -# bd_len: base_dir 长度 -# level: 剩余递归层数 -# out_arr: 输出数组(每个 SHA1 17 字节 = 16字符 + null) -# out_count: 当前已收集数量 -# max_count: 最大数量 -# -# Returns: -# 收集后的总数量 -# ============================================================ -def _collect_stub_sha1s(base_dir: str, bd_len: t.CSizeT, level: int, - out_arr: str, out_count: int, max_count: int) -> int: - """递归扫描子目录,收集 .stub.ll 文件的 SHA1""" - if base_dir is None or out_arr is None: - return out_count - if out_count >= max_count: - return out_count - - find_data: win32file.WIN32_FIND_DATAA | t.CPtr = stdlib.malloc(win32file.WIN32_FIND_DATAA.__sizeof__()) - if find_data is None: - return out_count - string.memset(find_data, 0, win32file.WIN32_FIND_DATAA.__sizeof__()) - - if level <= 0: - # 扫描 {base_dir}/*.stub.ll - pattern: bytes = stdlib.malloc(bd_len + 16) - if pattern is None: - stdlib.free(find_data) - return out_count - viperlib.snprintf(pattern, bd_len + 16, "%s/*.stub.ll", base_dir) - handle: win32base.HANDLE = win32file.FindFirstFileA(pattern, find_data) - stdlib.free(pattern) - if handle != win32base.INVALID_HANDLE_VALUE: - while 1: - if out_count >= max_count: - break - fname: str = find_data.cFileName - if fname is not None: - if fname[0] != '\0': - # 从文件名提取 SHA1(前 16 字符) - string.strncpy(out_arr + out_count * 17, fname, 16) - out_arr[out_count * 17 + 16] = '\0' - out_count += 1 - if win32file.FindNextFileA(handle, find_data) == 0: - break - win32file.FindClose(handle) - else: - # 扫描 {base_dir}/* 的子目录 - pattern = stdlib.malloc(bd_len + 4) - if pattern is None: - stdlib.free(find_data) - return out_count - viperlib.snprintf(pattern, bd_len + 4, "%s/*", base_dir) - handle = win32file.FindFirstFileA(pattern, find_data) - stdlib.free(pattern) - if handle != win32base.INVALID_HANDLE_VALUE: - while 1: - # 检查是否是目录(FILE_ATTRIBUTE_DIRECTORY = 0x10 = 16) - attrs: t.CUInt32T = find_data.dwFileAttributes - if (attrs & 16) != 0: - fname = find_data.cFileName - if fname is not None: - # 跳过 "." 和 ".." - is_dot: int = 0 - if fname[0] == '.': - if fname[1] == '\0': - is_dot = 1 - elif fname[1] == '.' and fname[2] == '\0': - is_dot = 1 - if is_dot == 0: - # 构建子目录路径并递归扫描 - fname_len: t.CSizeT = string.strlen(fname) - sub_dir: str = stdlib.malloc(bd_len + fname_len + 2) - if sub_dir is not None: - viperlib.snprintf(sub_dir, bd_len + fname_len + 2, "%s/%s", base_dir, fname) - sub_dir_len: t.CSizeT = string.strlen(sub_dir) - out_count = _collect_stub_sha1s(sub_dir, sub_dir_len, level - 1, out_arr, out_count, max_count) - stdlib.free(sub_dir) - if win32file.FindNextFileA(handle, find_data) == 0: - break - win32file.FindClose(handle) - - stdlib.free(find_data) - return out_count - - -# ============================================================ -# _load_includes_sha1_set - 从全局内存存储器收集 includes 的 SHA1 -# -# 数据来源是 PopulateSha1MapStore 填充的全局存储器(不读取 _sha1_map.txt)。 -# 用于过滤 stub 文件,避免加载 TransPyV 自身源文件(lib/*)的 stub 导致链接失败。 -# ============================================================ -def _load_includes_sha1_set(pool: memhub.MemBuddy | t.CPtr, - temp_dir: str, - sha1_set: str) -> int: - """从全局内存存储器将 includes 的 SHA1 写入 sha1_set - - pool/temp_dir 参数保留以兼容现有调用者,但不再使用。 - 数据来源是 PopulateSha1MapStore 填充的全局存储器。 - sha1_set 大小为 MAX_INCLUDES_SHA1 * 17(每个 SHA1 16字符+null) - 返回找到的 includes SHA1 数量,-1 表示错误""" - if sha1_set is None: - return -1 - if _sha1_store_arr is None: - return -1 - count: int = 0 - for i in range(_sha1_store_count): - if count >= MAX_INCLUDES_SHA1: - break - idx: t.CSizeT = t.CSizeT(i) * 17 - string.strcpy(sha1_set + t.CSizeT(count) * 17, _sha1_store_arr + idx) - count += 1 - return count - - -# ============================================================ -# _is_in_sha1_set - 检查 SHA1 是否在集合中 -# ============================================================ -def _is_in_sha1_set(sha1: str, sha1_set: str, set_count: int) -> int: - """检查 sha1 是否在集合中""" - if sha1 is None or sha1_set is None: - return 0 - for i in range(set_count): - if string.strcmp(sha1_set + i * 17, sha1) == 0: - return 1 - return 0 - - -# ============================================================ -# WriteIncludesSha1Map - 将 includes 扫描结果写入 _sha1_map.txt(人类可读输出) -# -# _sha1_map.txt 仅作为人类可读的调试输出,程序内部不读取此文件。 -# 机器分析使用 PopulateSha1MapStore 填充的全局内存存储器。 -# -# Args: -# mb: 内存池 -# temp_dir: 临时目录(_sha1_map.txt 写入位置) -# scan_result: IncludesScanner 扫描结果 -# -# Returns: -# 0 成功,非 0 失败 -# ============================================================ -def WriteIncludesSha1Map(mb: memhub.MemBuddy | t.CPtr, temp_dir: str, - scan_result: IncludesScanner.ScanResult | t.CPtr, - filter_set: t.CChar | t.CPtr, - filter_count: int) -> int: - """将 includes 扫描结果写入 _sha1_map.txt(人类可读输出,程序内部使用内存存储器) - - 若 filter_set 不为 None 且 filter_count > 0,只写入 filter_set 中的条目。 - """ - if temp_dir is None or scan_result is None: - return 1 - - # 构造路径 temp_dir/_sha1_map.txt - dir_len: t.CSizeT = string.strlen(temp_dir) - map_path: bytes = stdlib.malloc(dir_len + 32) - if map_path is None: - return 1 - viperlib.snprintf(map_path, dir_len + 32, "%s/_sha1_map.txt", temp_dir) - - # 打开文件写入(CREATE_ALWAYS) - f: fileio.File | t.CPtr = fileio.File(map_path, fileio.MODE.W) - if f.closed: - return 1 - - # 写入每个 include 条目: {sha1}:includes/{rel_path}\n - entry_size_w: t.CSizeT = IncludesScanner.FileEntry.__sizeof__() - line_buf: bytes = stdlib.malloc(512) - if line_buf is None: - f.close() - return 1 - - written_count: int = 0 - for i in range(scan_result.Count): - ea_w: t.CUInt64T = t.CUInt64T(scan_result.Entries) + i * entry_size_w - ent_w: IncludesScanner.FileEntry | t.CPtr = (IncludesScanner.FileEntry | t.CPtr)(t.CVoid(ea_w, t.CPtr)) - if ent_w is None or ent_w.Sha1 is None or ent_w.RelPath is None: - continue - # 若提供过滤集合,只写入集合中的条目 - if filter_set is not None and filter_count > 0: - if _is_in_sha1_set(ent_w.Sha1, filter_set, filter_count) == 0: - continue - viperlib.snprintf(line_buf, 512, "%s:includes/%s\n", ent_w.Sha1, ent_w.RelPath) - line_len_w: t.CSizeT = string.strlen(line_buf) - f.write(line_buf, line_len_w) - written_count += 1 - - f.close() - return 0 - - -# ============================================================ -# PopulateSha1MapStore - 从扫描结果填充全局 SHA1 映射存储器 -# -# 遍历 ScanResult.Entries,为每个条目构建 sha1→module_name 映射。 -# 模块名通过 _PathToModuleName(includes/rel_path) 计算。 -# 内存用 stdlib.malloc 分配(全局存储器,不随 mbuddy 释放)。 -# -# Args: -# scan_result: IncludesScanner 扫描结果 -# -# Returns: -# 填充的条目数,-1 表示失败 -# ============================================================ -def PopulateSha1MapStore(scan_result: IncludesScanner.ScanResult | t.CPtr) -> int: - """从扫描结果填充全局 SHA1 映射存储器 - - 遍历 ScanResult.Entries,为每个条目构建 sha1→module_name 映射。 - 模块名通过 _PathToModuleName(includes/rel_path) 计算。 - 内存用 stdlib.malloc 分配(全局存储器,不随 mbuddy 释放)。 - """ - global _sha1_store_arr, _sha1_store_mod, _sha1_store_rel, _sha1_store_count - if scan_result is None: - return -1 - # 释放旧存储器 - if _sha1_store_arr is not None: - stdlib.free(_sha1_store_arr) - if _sha1_store_mod is not None: - stdlib.free(_sha1_store_mod) - if _sha1_store_rel is not None: - stdlib.free(_sha1_store_rel) - _sha1_store_arr = stdlib.malloc(MAX_INCLUDES * 17) - _sha1_store_mod = stdlib.malloc(MAX_INCLUDES * 64) - _sha1_store_rel = stdlib.malloc(MAX_INCLUDES * MAX_REL_PATH_LEN) - if _sha1_store_arr is None or _sha1_store_mod is None or _sha1_store_rel is None: - return -1 - string.memset(_sha1_store_arr, 0, MAX_INCLUDES * 17) - string.memset(_sha1_store_mod, 0, MAX_INCLUDES * 64) - string.memset(_sha1_store_rel, 0, MAX_INCLUDES * MAX_REL_PATH_LEN) - _sha1_store_count = 0 - entry_size_p: t.CSizeT = IncludesScanner.FileEntry.__sizeof__() - for i in range(scan_result.Count): - if _sha1_store_count >= MAX_INCLUDES: - break - ea: t.CUInt64T = t.CUInt64T(scan_result.Entries) + i * entry_size_p - ent: IncludesScanner.FileEntry | t.CPtr = (IncludesScanner.FileEntry | t.CPtr)(t.CVoid(ea, t.CPtr)) - if ent is None or ent.Sha1 is None or ent.RelPath is None: - continue - # 构建完整路径 includes/{RelPath}(_PathToModuleName 需要) - rp_len: t.CSizeT = string.strlen(ent.RelPath) - full_path_buf: bytes = stdlib.malloc(rp_len + 10) - if full_path_buf is None: - continue - viperlib.snprintf(full_path_buf, rp_len + 10, "includes/%s", ent.RelPath) - mod_name: str = _PathToModuleName(full_path_buf) - stdlib.free(full_path_buf) - if mod_name is not None: - idx: t.CSizeT = t.CSizeT(_sha1_store_count) * 17 - string.strcpy(_sha1_store_arr + idx, ent.Sha1) - idx2: t.CSizeT = t.CSizeT(_sha1_store_count) * 64 - mn_len: t.CSizeT = string.strlen(mod_name) - if mn_len < 64: - string.strcpy(_sha1_store_mod + idx2, mod_name) - else: - string.strncpy(_sha1_store_mod + idx2, mod_name, 63) - _sha1_store_mod[idx2 + 63] = '\0' - stdlib.free(mod_name) - # 保存 rel_path(供 Phase2 3.5 编译缺失 includes 使用) - idx3: t.CSizeT = t.CSizeT(_sha1_store_count) * MAX_REL_PATH_LEN - if rp_len < MAX_REL_PATH_LEN: - string.strcpy(_sha1_store_rel + idx3, ent.RelPath) - else: - string.strncpy(_sha1_store_rel + idx3, ent.RelPath, MAX_REL_PATH_LEN - 1) - _sha1_store_rel[idx3 + MAX_REL_PATH_LEN - 1] = '\0' - _sha1_store_count += 1 - return _sha1_store_count - - -# ============================================================ -# AppendToSha1MapStore - 追加条目到全局 SHA1 映射存储器 -# -# Phase1 调用 PopulateSha1MapStore 填充 includes 文件, -# Phase2 扫描 App 源文件后调用此函数追加 App 模块条目, -# 确保编译 App 自身时跨模块 CDefine 查找能命中 App 模块 -# (如 StubMerger.MAX_INCLUDES 在编译 Phase2 时通过 -# _build_source_path_from_sha1 查找 StubMerger 的源路径)。 -# -# 若存储器未初始化(PopulateSha1MapStore 未调用),自动初始化。 -# 若 SHA1 已存在(去重),跳过。 -# -# Args: -# sha1: SHA1 字符串(16 字符 + null) -# rel_path: 相对路径(如 "lib/core/StubMerger.py", -# 不含 includes/ 前缀,与 _sha1_map.txt 格式一致) -# -# Returns: -# 0 成功(含去重跳过),1 失败 -# ============================================================ -def AppendToSha1MapStore(sha1: str, rel_path: str) -> int: - """追加条目到全局 SHA1 映射存储器(Phase2 用)""" - global _sha1_store_arr, _sha1_store_mod, _sha1_store_rel, _sha1_store_count - if sha1 is None or rel_path is None: - return 1 - # 存储器未初始化:自动初始化(Phase2 可能先于 Phase1 调用) - if _sha1_store_arr is None: - _sha1_store_arr = stdlib.malloc(MAX_INCLUDES * 17) - _sha1_store_mod = stdlib.malloc(MAX_INCLUDES * 64) - _sha1_store_rel = stdlib.malloc(MAX_INCLUDES * MAX_REL_PATH_LEN) - if _sha1_store_arr is None or _sha1_store_mod is None or _sha1_store_rel is None: - return 1 - string.memset(_sha1_store_arr, 0, MAX_INCLUDES * 17) - string.memset(_sha1_store_mod, 0, MAX_INCLUDES * 64) - string.memset(_sha1_store_rel, 0, MAX_INCLUDES * MAX_REL_PATH_LEN) - _sha1_store_count = 0 - if _sha1_store_count >= MAX_INCLUDES: - return 1 - # 去重:若 SHA1 已存在则跳过 - for i in range(_sha1_store_count): - sidx_d: t.CSizeT = t.CSizeT(i) * 17 - if string.strcmp(_sha1_store_arr + sidx_d, sha1) == 0: - return 0 - # 模块名:rel_path "lib/core/StubMerger.py" → "lib.core.StubMerger" - full_path_buf: bytes = stdlib.malloc(string.strlen(rel_path) + 10) - if full_path_buf is None: - return 1 - viperlib.snprintf(full_path_buf, string.strlen(rel_path) + 10, "includes/%s", rel_path) - mod_name: str = _PathToModuleName(full_path_buf) - stdlib.free(full_path_buf) - if mod_name is None: - return 1 - # 写入 SHA1 - idx_a: t.CSizeT = t.CSizeT(_sha1_store_count) * 17 - string.strcpy(_sha1_store_arr + idx_a, sha1) - # 写入模块名 - idx_m: t.CSizeT = t.CSizeT(_sha1_store_count) * 64 - mn_len: t.CSizeT = string.strlen(mod_name) - if mn_len < 64: - string.strcpy(_sha1_store_mod + idx_m, mod_name) - else: - string.strncpy(_sha1_store_mod + idx_m, mod_name, 63) - _sha1_store_mod[idx_m + 63] = '\0' - stdlib.free(mod_name) - # 写入相对路径 - idx_r: t.CSizeT = t.CSizeT(_sha1_store_count) * MAX_REL_PATH_LEN - rp_len: t.CSizeT = string.strlen(rel_path) - if rp_len < MAX_REL_PATH_LEN: - string.strcpy(_sha1_store_rel + idx_r, rel_path) - else: - string.strncpy(_sha1_store_rel + idx_r, rel_path, MAX_REL_PATH_LEN - 1) - _sha1_store_rel[idx_r + MAX_REL_PATH_LEN - 1] = '\0' - _sha1_store_count += 1 - return 0 - - -# ============================================================ -# GetSha1StoreCount - 获取全局存储器条目数 -# ============================================================ -def GetSha1StoreCount() -> int: - """返回全局 SHA1 存储器的条目数""" - return _sha1_store_count - - -def IsReachableIncomplete() -> int: - """返回可达集合是否不完整(1=有 deps.txt 缺失,应回退全量链接)""" - return _g_reachable_incomplete - - -# ============================================================ -# PopulateIncludesDeps - 将 includes 文件的依赖存入内存 -# -# Phase B+ 前用 declare_only 翻译 includes 文件,提取 _imported_modules -# 后调用此函数存入内存。_BuildReachableSha1Set 从内存读取,不读 deps.txt。 -# -# Args: -# sha1: includes 文件的 SHA1(16字符) -# deps_str: 依赖模块名字符串(空格分隔,如 "t c stdint string") -# -# Returns: -# 0 成功,非 0 失败 -# ============================================================ -def PopulateIncludesDeps(sha1: str, deps_str: str) -> int: - """将 includes 文件的依赖存入内存""" - global _includes_deps_sha1, _includes_deps_str, _includes_deps_count - if sha1 is None: - return 1 - # 延迟初始化 - if _includes_deps_sha1 is None: - _includes_deps_sha1 = stdlib.malloc(MAX_INCLUDES * 17) - _includes_deps_str = stdlib.malloc(MAX_INCLUDES * MAX_DEPS_STR_LEN) - if _includes_deps_sha1 is None or _includes_deps_str is None: - return 1 - string.memset(_includes_deps_sha1, 0, MAX_INCLUDES * 17) - string.memset(_includes_deps_str, 0, MAX_INCLUDES * MAX_DEPS_STR_LEN) - _includes_deps_count = 0 - if _includes_deps_count >= MAX_INCLUDES: - return 1 - # 去重:若 SHA1 已存在则跳过 - for i in range(_includes_deps_count): - sidx: t.CSizeT = t.CSizeT(i) * 17 - if string.strcmp(_includes_deps_sha1 + sidx, sha1) == 0: - return 0 - # 写入 SHA1 - idx: t.CSizeT = t.CSizeT(_includes_deps_count) * 17 - string.strcpy(_includes_deps_sha1 + idx, sha1) - # 写入依赖字符串 - idx2: t.CSizeT = t.CSizeT(_includes_deps_count) * MAX_DEPS_STR_LEN - if deps_str is not None: - dl: t.CSizeT = string.strlen(deps_str) - if dl < MAX_DEPS_STR_LEN: - string.strcpy(_includes_deps_str + idx2, deps_str) - else: - string.strncpy(_includes_deps_str + idx2, deps_str, MAX_DEPS_STR_LEN - 1) - else: - _includes_deps_str[idx2] = '\0' - _includes_deps_count = _includes_deps_count + 1 - return 0 - - -# ============================================================ -# LookupIncludesDeps - 从内存查找 includes 文件的依赖 -# -# Args: -# sha1: includes 文件的 SHA1(16字符) -# -# Returns: -# 依赖模块名字符串指针(空格分隔),None 表示未找到 -# ============================================================ -def LookupIncludesDeps(sha1: str) -> str: - """从内存查找 includes 文件的依赖""" - if sha1 is None or _includes_deps_sha1 is None: - return None - if _includes_deps_count <= 0: - return None - for i in range(_includes_deps_count): - sidx: t.CSizeT = t.CSizeT(i) * 17 - if string.strcmp(_includes_deps_sha1 + sidx, sha1) == 0: - idx2: t.CSizeT = t.CSizeT(i) * MAX_DEPS_STR_LEN - return _includes_deps_str + idx2 - return None - - -def GetSha1StoreArrPtr() -> bytes | t.CPtr: - """返回 SHA1 数组指针(每个条目 17 字节)""" - return _sha1_store_arr - - -def GetSha1StoreModArrPtr() -> bytes | t.CPtr: - """返回模块名数组指针(每个条目 64 字节)""" - return _sha1_store_mod - - -def GetSha1StoreRelArrPtr() -> bytes | t.CPtr: - """返回相对路径数组指针(每个条目 MAX_REL_PATH_LEN 字节)""" - return _sha1_store_rel - - -# ============================================================ -# GetSha1StoreArr - 获取全局存储器数组指针(直接遍历用) -# -# 返回 sha1_arr、mod_arr、rel_arr 三个数组的指针和条目数。 -# 调用者直接遍历数组:sha1_arr[i*17]、mod_arr[i*64]、rel_arr[i*MAX_REL_PATH_LEN] -# 内存归全局存储器所有,调用者不要 free -# ============================================================ -def GetSha1StoreArr(out_sha1_arr: t.CPtr, out_mod_arr: t.CPtr, out_rel_arr: t.CPtr) -> int: - """获取全局存储器数组指针 - - out_sha1_arr/out_mod_arr/out_rel_arr 是调用者提供的 t.CPtr 指针, - 函数将存储器数组指针写入这些位置。 - 返回条目数,-1 失败 - """ - if out_sha1_arr is None or out_mod_arr is None or out_rel_arr is None: - return -1 - if _sha1_store_arr is None or _sha1_store_mod is None or _sha1_store_rel is None: - return -1 - sp: t.CPtr = (t.CPtr | t.CPtr)(t.CVoid(out_sha1_arr, t.CPtr)) - if sp is not None: - sp[0] = _sha1_store_arr - mp: t.CPtr = (t.CPtr | t.CPtr)(t.CVoid(out_mod_arr, t.CPtr)) - if mp is not None: - mp[0] = _sha1_store_mod - rp: t.CPtr = (t.CPtr | t.CPtr)(t.CVoid(out_rel_arr, t.CPtr)) - if rp is not None: - rp[0] = _sha1_store_rel - return _sha1_store_count - - -# ============================================================ -# LookupSha1RelPath - 通过 SHA1 查找相对路径 -# -# 遍历全局存储器,返回 sha1 对应的相对路径指针(只读,不要 free)。 -# 用于错误提示:将 sha1 转换为人类可读的文件路径。 -# -# Args: -# sha1: SHA1 字符串(16 字符) -# -# Returns: -# 相对路径字符串指针(只读),None=未找到 -# ============================================================ -def LookupSha1RelPath(sha1: str) -> str: - """通过 SHA1 查找相对路径,返回只读指针,None=未找到""" - if sha1 is None: - return None - if _sha1_store_arr is None or _sha1_store_rel is None: - return None - for i in range(_sha1_store_count): - sidx: t.CSizeT = t.CSizeT(i) * 17 - if string.strcmp(_sha1_store_arr + sidx, sha1) == 0: - ridx: t.CSizeT = t.CSizeT(i) * MAX_REL_PATH_LEN - return _sha1_store_rel + ridx - return None - - -# ============================================================ -# _IsFuncDeclaredOrDefined - 检查 out_buf 中是否已有函数的 declare/define -# -# 逐字节strncmp搜索 func_sig(如 @"sha1.func"(/ @printf( ),每次 -# 找到匹配后检查行首是否以 "declare " 或 "define " 开头,跳过 call 语句。 -# 避免 strstr 子串匹配误匹配 call ... @"func"(...) 中的 @"func"( 子串。 -# -# Args: -# out_buf: 已有的 IR 文本缓冲区 -# func_sig: 函数签名片段,如 @"sha1.func"(/ @printf( -# -# Returns: -# 1=已存在 declare/define, 0=不存在 -# ============================================================ -def _IsFuncDeclaredOrDefined(out_buf: bytes, func_sig: str) -> int: - """检查 out_buf 中是否已有函数的 declare 或 define 行""" - if out_buf is None or func_sig is None: - return 0 - sig_len: t.CSizeT = string.strlen(func_sig) - out_len: t.CSizeT = string.strlen(out_buf) - if sig_len == 0 or out_len == 0 or sig_len > out_len: - return 0 - pos: t.CSizeT = 0 - while pos + sig_len <= out_len: - if string.strncmp(out_buf + pos, func_sig, sig_len) == 0: - ls: t.CSizeT = pos - while ls > 0 and out_buf[ls - 1] != '\n': - ls -= 1 - if string.strncmp(out_buf + ls, "declare ", 8) == 0: - return 1 - if string.strncmp(out_buf + ls, "define ", 7) == 0: - return 1 - pos += 1 - return 0 - - -# ============================================================ -# _CommentOutDeclareInBuf - 将 out_buf 中匹配 func_sig 的 declare 行注释掉 -# -# 用于解决 declare/define 冲突:当本地 text.ll 包含 define 而依赖 -# text.ll 已生成了同函数的 declare 时,将 declare 行首字符改为 ';' -# 使其成为注释,然后追加 define 行。 -# ============================================================ -def _CommentOutDeclareInBuf(out_buf: bytes, func_sig: str) -> int: - """在 out_buf 中搜索 declare 行(包含 func_sig),将其注释掉""" - if out_buf is None or func_sig is None: - return 0 - sig_len: t.CSizeT = string.strlen(func_sig) - out_len: t.CSizeT = string.strlen(out_buf) - if sig_len == 0 or out_len == 0 or sig_len > out_len: - return 0 - pos: t.CSizeT = 0 - while pos + sig_len <= out_len: - if string.strncmp(out_buf + pos, func_sig, sig_len) == 0: - ls: t.CSizeT = pos - while ls > 0 and out_buf[ls - 1] != '\n': - ls -= 1 - if string.strncmp(out_buf + ls, "declare ", 8) == 0: - out_buf[ls] = ';' - return 1 - pos += 1 - return 0 - - -# ============================================================ -# _CommentOutGlobalInBuf - 将 out_buf 中匹配全局变量名的行注释掉 -# -# 解决 stub/text 全局变量重复定义问题:stub 中可能是 external 声明 -# 或完整定义,以 text 中的定义为准,将 stub 中的同名行注释掉。 -# ============================================================ -def _CommentOutGlobalInBuf(out_buf: bytes, global_name: str) -> int: - """在 out_buf 中搜索全局变量定义行(以 global_name 开头),将行首改为 ';'""" - if out_buf is None or global_name is None: - return 0 - name_len: t.CSizeT = string.strlen(global_name) - out_len: t.CSizeT = string.strlen(out_buf) - if name_len == 0 or out_len == 0 or name_len > out_len: - return 0 - pos: t.CSizeT = 0 - while pos + name_len <= out_len: - if string.strncmp(out_buf + pos, global_name, name_len) == 0: - # 确认是行首(前一个是换行或 pos==0) - if pos == 0 or out_buf[pos - 1] == '\n': - out_buf[pos] = ';' - return 1 - pos += 1 - return 0 - - -# ============================================================ -# _CommentOutOpaqueTypeInBuf - 将 out_buf 中匹配类型名的 opaque 声明行注释掉 -# -# 解决跨模块类型定义冲突:本地 stub 可能包含自动生成的 opaque 声明 -#(如 %"sha1.Widget" = type opaque),而依赖 stub 包含完整定义 -#(如 %"sha1.Widget" = type { i8*, i32 })。去重时需要将 opaque 声明 -# 注释掉,让完整定义被追加,否则 LLC 报错 "Cannot allocate unsized type"。 -# ============================================================ -def _CommentOutOpaqueTypeInBuf(out_buf: bytes, type_name_prefix: str) -> int: - """在 out_buf 中搜索 type_name_prefix 对应的 opaque 声明行,将行首改为 ';' - - type_name_prefix 格式: '%"sha1.ClassName"'(不含 '=' 和后续内容) - 返回 1=已注释, 0=未找到 - """ - if out_buf is None or type_name_prefix is None: - return 0 - prefix_len: t.CSizeT = string.strlen(type_name_prefix) - out_len: t.CSizeT = string.strlen(out_buf) - if prefix_len == 0 or out_len == 0 or prefix_len > out_len: - return 0 - pos: t.CSizeT = 0 - while pos + prefix_len <= out_len: - if string.strncmp(out_buf + pos, type_name_prefix, prefix_len) == 0: - # 确认是行首(前一个是换行或 pos==0) - if pos == 0 or out_buf[pos - 1] == '\n': - # 检查后面是否是 " = type opaque" - p: t.CSizeT = pos + prefix_len - # 跳过空格 - while p < out_len and out_buf[p] == ' ': - p += 1 - if p < out_len and out_buf[p] == '=': - p += 1 - while p < out_len and out_buf[p] == ' ': - p += 1 - if p + 11 <= out_len: - if string.strncmp(out_buf + p, "type opaque", 11) == 0: - # 找到 opaque 声明,将行首改为 ';' - out_buf[pos] = ';' - return 1 - pos += 1 - return 0 - - -# ============================================================ -# _is_submodule_of_imported - 检查模块名是否是已导入包的子模块 -# -# deps.txt 只记录直接导入的模块名(如 "ast"),但包的 __init__.py -# 内部 from .lexer import Lexer 会让 IR 引用 ast.lexer 子模块类型。 -# 当模块名包含 '.' 时,检查其顶层包名是否在 deps_buf 中。 -# -# 例如: -# deps_buf = "ast stdio string" -# mod_name = "ast.lexer" → 顶层包 "ast" 在 deps_buf 中 → 返回 1 -# mod_name = "ast.token" → 顶层包 "ast" 在 deps_buf 中 → 返回 1 -# mod_name = "foo.bar" → 顶层包 "foo" 不在 deps_buf 中 → 返回 0 -# ============================================================ -def _is_submodule_of_imported(deps_buf: str, mod_name: str) -> int: - """检查 mod_name 是否是 deps_buf 中已导入包的子模块""" - if deps_buf is None or mod_name is None: - return 0 - # 查找第一个 '.',提取顶层包名 - dot_pos: str = string.strchr(mod_name, 46) # '.' = 46 - if dot_pos is None: - return 0 - pkg_len: t.CSizeT = t.CSizeT(t.CUInt64T(dot_pos) - t.CUInt64T(mod_name)) - if pkg_len == 0 or pkg_len >= 256: - return 0 - # 构造顶层包名(截断到 '.' 之前) - # 直接在 mod_name 上临时截断检查,避免分配 - saved_ch: t.CChar = mod_name[pkg_len] - mod_name[pkg_len] = '\0' - result: int = HandlesImports.is_module_imported(deps_buf, mod_name) - mod_name[pkg_len] = saved_ch - return result - - -# ============================================================ -# _HasFullTypeDefinition - 检查 out_buf 中是否已有完整类型定义(非 opaque) -# -# type_name_prefix 格式: '%"sha1.ClassName"'(不含 '=') -# 完整定义: %"name" = type { ... } 或 %"name" = type < { ... } > -# 返回 1=已有完整定义, 0=无完整定义 -# ============================================================ -def _HasFullTypeDefinition(out_buf: bytes, type_name_prefix: str) -> int: - """检查 out_buf 中是否已有 type_name_prefix 的完整定义""" - if out_buf is None or type_name_prefix is None: - return 0 - prefix_len: t.CSizeT = string.strlen(type_name_prefix) - out_len: t.CSizeT = string.strlen(out_buf) - if prefix_len == 0 or out_len == 0 or prefix_len > out_len: - return 0 - pos: t.CSizeT = 0 - while pos + prefix_len <= out_len: - if string.strncmp(out_buf + pos, type_name_prefix, prefix_len) == 0: - # 确认是行首(前一个是换行或 pos==0),且未被注释(行首不是 ';') - is_line_start: int = 0 - if pos == 0: - is_line_start = 1 - elif out_buf[pos - 1] == '\n': - is_line_start = 1 - if is_line_start == 1: - # 检查后面是否是 " = type {" 或 " = type <" - p: t.CSizeT = pos + prefix_len - while p < out_len and out_buf[p] == ' ': - p += 1 - if p < out_len and out_buf[p] == '=': - p += 1 - while p < out_len and out_buf[p] == ' ': - p += 1 - if p + 5 < out_len: - if string.strncmp(out_buf + p, "type ", 5) == 0: - p += 5 - if p < out_len: - if out_buf[p] == '{' or out_buf[p] == '<': - return 1 - pos += 1 - return 0 - - -# ============================================================ -# _LoadAndAppendStub - 加载依赖 stub 并追加到 out_buf -# -# 读取 {temp_dir}/{sha1}.stub.ll,跳过 header(;, target, source_filename), -# 去重 declare/global,追加到 out_buf。返回新 out_pos。 -# ============================================================ -def _LoadAndAppendStub(temp_dir: str, td_len: t.CSizeT, dep_sha1: str, - dep_buf: bytes, out_buf: bytes, out_size: t.CSizeT, - out_pos: t.CSizeT) -> t.CSizeT: - """加载依赖 stub 并追加(跳过 header,去重)""" - if temp_dir is None or dep_sha1 is None or dep_buf is None or out_buf is None: - return out_pos - - dep_path: str = _sliced_path(temp_dir, td_len, dep_sha1, "stub.ll") - if dep_path is None: - return out_pos - df_ls: fileio.File | t.CPtr = fileio.File(dep_path, fileio.MODE.R) - if df_ls.closed: - stdlib.free(dep_path) - return out_pos - dep_br_ls: t.CInt64T = df_ls.read_all(dep_buf, STUB_READ_BUF_SIZE) - df_ls.close() - stdlib.free(dep_path) - if dep_br_ls <= 0: - return out_pos - if dep_br_ls < STUB_READ_BUF_SIZE: - dep_buf[dep_br_ls] = '\0' - else: - dep_buf[STUB_READ_BUF_SIZE - 1] = '\0' - - # 注释掉依赖 stub 中的字符串常量行(模块内部的,不需要) - # 简单方案:搜索 "= external unnamed_addr constant" 并将行首的 @ 改为 ;@ - cfs_pos: t.CSizeT = 0 - while cfs_pos + 30 < t.CSizeT(dep_br_ls): - ext_p: t.CPtr = string.strstr(dep_buf + cfs_pos, "= external unnamed_addr constant") - if ext_p is None: - break - ext_off2: t.CSizeT = t.CSizeT(t.CUInt64T(ext_p) - t.CUInt64T(dep_buf)) - # 向前查找行首的 @ - ls: t.CSizeT = ext_off2 - while ls > 0: - if dep_buf[ls] == '\n': - ls += 1 - break - ls -= 1 - if ls < ext_off2 and dep_buf[ls] == '@': - dep_buf[ls] = ';' - cfs_pos = ext_off2 + 30 - - # 跳过 header,追加内容(去重 declare/global) - dep_pos: t.CSizeT = 0 - skipping: int = 1 - while dep_pos < dep_br_ls: - line_start: t.CSizeT = dep_pos - while dep_pos < dep_br_ls: - if dep_buf[dep_pos] == '\n': - break - dep_pos += 1 - line_len: t.CSizeT = dep_pos - line_start - if dep_pos < dep_br_ls: - dep_pos += 1 - if skipping != 0: - if line_len == 0: - continue - ch0: int = dep_buf[line_start] - if ch0 == ';': - continue - if ch0 == 't' and line_len >= 6: - if string.strncmp(dep_buf + line_start, "target", 6) == 0: - continue - if ch0 == 's' and line_len >= 15: - if string.strncmp(dep_buf + line_start, "source_filename", 15) == 0: - continue - skipping = 0 - # 去重:declare(用 _IsFuncDeclaredOrDefined 避免误匹配 call 语句) - if line_len >= 8 and string.strncmp(dep_buf + line_start, "declare ", 8) == 0: - at: t.CSizeT = line_start + 8 - while at < line_start + line_len: - if dep_buf[at] == '@': - break - at += 1 - if at < line_start + line_len: - lp: t.CSizeT = at + 1 - while lp < line_start + line_len: - if dep_buf[lp] == '(': - break - lp += 1 - if lp < line_start + line_len: - saved: t.CChar = dep_buf[lp + 1] - dep_buf[lp + 1] = '\0' - if _IsFuncDeclaredOrDefined(out_buf, dep_buf + at) != 0: - dep_buf[lp + 1] = saved - continue - dep_buf[lp + 1] = saved - # 去重:external global - if line_len > 0 and dep_buf[line_start] == '@': - eq: t.CSizeT = line_start + 1 - while eq < line_start + line_len: - if dep_buf[eq] == '=': - break - eq += 1 - if eq < line_start + line_len: - saved: t.CChar = dep_buf[eq + 1] - dep_buf[eq + 1] = '\0' - if string.strstr(out_buf, dep_buf + line_start) is not None: - dep_buf[eq + 1] = saved - continue - dep_buf[eq + 1] = saved - # 去重:type 定义(如 %"sha1.Point" = type {i32, i32}) - # 区分完整定义(= type { ... } / = type < ... >)和 opaque 声明(= type opaque) - # 当本地 stub 有 opaque 声明而依赖 stub 有完整定义时,注释掉 opaque 行, - # 让完整定义被追加,避免 LLC "Cannot allocate unsized type" 错误。 - if line_len > 0 and dep_buf[line_start] == '%': - eq2: t.CSizeT = line_start + 1 - while eq2 < line_start + line_len: - if dep_buf[eq2] == '=': - break - eq2 += 1 - if eq2 < line_start + line_len: - saved2: t.CChar = dep_buf[eq2 + 1] - dep_buf[eq2 + 1] = '\0' - # 检查依赖行是否为完整定义(= type { 或 = type <) - dep_is_full_def: int = 0 - if eq2 + 8 <= line_start + line_len: - if dep_buf[eq2 + 2] == 't' and dep_buf[eq2 + 3] == 'y' and dep_buf[eq2 + 4] == 'p' and dep_buf[eq2 + 5] == 'e' and dep_buf[eq2 + 6] == ' ': - if dep_buf[eq2 + 7] == '{' or dep_buf[eq2 + 7] == '<': - dep_is_full_def = 1 - if dep_is_full_def == 1: - # 依赖行是完整定义 - # 临时截断到 '=' 之前(不含 '='),辅助函数期望纯类型名前缀 - saved_eq: t.CChar = dep_buf[eq2] - dep_buf[eq2] = '\0' - # 1. 注释掉 out_buf 中的 opaque 声明(如果有) - commented: int = _CommentOutOpaqueTypeInBuf(out_buf, dep_buf + line_start) - # 2. 检查 out_buf 中是否已有完整定义(避免重复) - has_full: int = _HasFullTypeDefinition(out_buf, dep_buf + line_start) - dep_buf[eq2] = saved_eq - if has_full == 1: - dep_buf[eq2 + 1] = saved2 - continue - # 3. 追加完整定义 - else: - # 依赖行是 opaque 声明,用原有子串匹配去重 - found_opaque: t.CPtr = string.strstr(out_buf, dep_buf + line_start) - if found_opaque is not None: - dep_buf[eq2 + 1] = saved2 - continue - dep_buf[eq2 + 1] = saved2 - # 追加 - if out_pos + line_len + 2 < out_size: - string.strncpy(out_buf + out_pos, dep_buf + line_start, line_len) - out_pos += line_len - out_buf[out_pos] = '\n' - out_pos += 1 - out_buf[out_pos] = '\0' - return out_pos - - -# ============================================================ -# _LoadAndAppendTextDeclares - 从依赖 text.ll 提取 declare 追加到 out_buf -# -# 读取 {temp_dir}/{sha1}.text.ll,将 define 行转为 declare(提取函数签名), -# 跳过函数体,去重后追加到 out_buf。返回新 out_pos。 -# ============================================================ -def _LoadAndAppendTextDeclares(temp_dir: str, td_len: t.CSizeT, dep_sha1: str, - dep_buf: bytes, out_buf: bytes, out_size: t.CSizeT, - out_pos: t.CSizeT) -> t.CSizeT: - """从依赖 text.ll 提取 declare(define 转 declare),追加到 out_buf""" - if temp_dir is None or dep_sha1 is None or dep_buf is None or out_buf is None: - return out_pos - - text_path: str = _sliced_path(temp_dir, td_len, dep_sha1, "text.ll") - if text_path is None: - return out_pos - tf_lt: fileio.File | t.CPtr = fileio.File(text_path, fileio.MODE.R) - if tf_lt.closed: - stdlib.free(text_path) - return out_pos - text_br: t.CInt64T = tf_lt.read_all(dep_buf, STUB_READ_BUF_SIZE) - tf_lt.close() - stdlib.free(text_path) - if text_br <= 0: - return out_pos - if text_br < STUB_READ_BUF_SIZE: - dep_buf[text_br] = '\0' - else: - dep_buf[STUB_READ_BUF_SIZE - 1] = '\0' - - dep_pos_lt: t.CSizeT = 0 - in_body: int = 0 - while dep_pos_lt < text_br: - ls: t.CSizeT = dep_pos_lt - while dep_pos_lt < text_br: - if dep_buf[dep_pos_lt] == '\n': - break - dep_pos_lt += 1 - ll: t.CSizeT = dep_pos_lt - ls - if dep_pos_lt < text_br: - dep_pos_lt += 1 - - # 函数体跳过:直到单独的 } 行 - if in_body != 0: - if ll == 1 and dep_buf[ls] == '}': - in_body = 0 - continue - - # 跳过空行和 header - if ll == 0: - continue - c0: int = dep_buf[ls] - if c0 == ';': - continue - if c0 == 't' and ll >= 6 and string.strncmp(dep_buf + ls, "target", 6) == 0: - continue - if c0 == 's' and ll >= 15 and string.strncmp(dep_buf + ls, "source_filename", 15) == 0: - continue - - # 处理 define 行:转为 declare - if ll >= 7 and string.strncmp(dep_buf + ls, "define ", 7) == 0: - # 提取 @funcname( 用于去重 - at_lt: t.CSizeT = ls + 7 - while at_lt < ls + ll: - if dep_buf[at_lt] == '@': - break - at_lt += 1 - if at_lt >= ls + ll: - in_body = 1 - continue - lp_lt: t.CSizeT = at_lt + 1 - while lp_lt < ls + ll: - if dep_buf[lp_lt] == '(': - break - lp_lt += 1 - if lp_lt >= ls + ll: - in_body = 1 - continue - # 去重检查:用 _IsFuncDeclaredOrDefined 避免误匹配 call 语句 - saved_lt: t.CChar = dep_buf[lp_lt + 1] - dep_buf[lp_lt + 1] = '\0' - if _IsFuncDeclaredOrDefined(out_buf, dep_buf + at_lt) != 0: - dep_buf[lp_lt + 1] = saved_lt - in_body = 1 - continue - dep_buf[lp_lt + 1] = saved_lt - - # 找行尾的 ' {' 并截断 - decl_end: t.CSizeT = ls + ll - if decl_end > ls + 1: - if dep_buf[decl_end - 1] == '{' and dep_buf[decl_end - 2] == ' ': - decl_end -= 2 - - # 输出: declare + content (skip "define " 7 chars, up to decl_end) - copy_len_lt: t.CSizeT = decl_end - (ls + 7) - if out_pos + 8 + copy_len_lt + 2 < out_size: - string.strncpy(out_buf + out_pos, "declare ", 8) - out_pos += 8 - string.strncpy(out_buf + out_pos, dep_buf + ls + 7, copy_len_lt) - out_pos += copy_len_lt - out_buf[out_pos] = '\n' - out_pos += 1 - out_buf[out_pos] = '\0' - in_body = 1 - continue - - # 提取类型定义(%... = type { ... } 或 %... = type < ... >) - # stub.ll 中只有 opaque 声明,需要从 text.ll 中提取完整定义 - # 用于 alloca 和 getelementptr 等需要完整类型的指令 - if ll > 0 and dep_buf[ls] == '%': - eq_td: t.CSizeT = ls + 1 - while eq_td < ls + ll: - if dep_buf[eq_td] == '=': - break - eq_td += 1 - if eq_td < ls + ll: - # 检查是否为完整定义(= type { 或 = type <) - dep_is_full_td: int = 0 - if eq_td + 8 <= ls + ll: - if dep_buf[eq_td + 2] == 't' and dep_buf[eq_td + 3] == 'y' \ - and dep_buf[eq_td + 4] == 'p' and dep_buf[eq_td + 5] == 'e' \ - and dep_buf[eq_td + 6] == ' ': - if dep_buf[eq_td + 7] == '{' or dep_buf[eq_td + 7] == '<': - dep_is_full_td = 1 - if dep_is_full_td == 1: - # 临时截断到 '=' 之前(不含 '='),辅助函数期望纯类型名前缀 - saved_eq_td: t.CChar = dep_buf[eq_td] - dep_buf[eq_td] = '\0' - # 1. 注释掉 out_buf 中的 opaque 声明(如果有) - _CommentOutOpaqueTypeInBuf(out_buf, dep_buf + ls) - # 2. 检查 out_buf 中是否已有完整定义(避免重复) - has_full_td: int = _HasFullTypeDefinition(out_buf, dep_buf + ls) - dep_buf[eq_td] = saved_eq_td - if has_full_td == 0: - # 追加完整类型定义 - if out_pos + ll + 2 < out_size: - string.strncpy(out_buf + out_pos, dep_buf + ls, ll) - out_pos += ll - out_buf[out_pos] = '\n' - out_pos += 1 - out_buf[out_pos] = '\0' - continue - - # 提取全局变量定义(@... = ...) - # 依赖 text.ll 中的全局变量带初值定义(如 @_mbuddy = global ...) - # stub.ll 中只有 external 声明,需要从 text.ll 提取完整定义 - # 注释掉 out_buf 中的同名行(external 声明或旧定义),追加 text.ll 中的完整定义 - if ll > 0 and dep_buf[ls] == '@': - eq_gv: t.CSizeT = ls + 1 - while eq_gv < ls + ll: - if dep_buf[eq_gv] == '=': - break - eq_gv += 1 - if eq_gv < ls + ll: - # 截断到 '=' 之前(不含 '='),得到全局变量名 @name - saved_gv: t.CChar = dep_buf[eq_gv] - dep_buf[eq_gv] = '\0' - # 注释掉 out_buf 中的同名行(external 声明或旧定义) - _CommentOutGlobalInBuf(out_buf, dep_buf + ls) - dep_buf[eq_gv] = saved_gv - # 追加完整定义 - if out_pos + ll + 2 < out_size: - string.strncpy(out_buf + out_pos, dep_buf + ls, ll) - out_pos += ll - out_buf[out_pos] = '\n' - out_pos += 1 - out_buf[out_pos] = '\0' - continue - - # 跳过其他行 - return out_pos - - -# ============================================================ -# _PathToModuleName - 将文件路径转换为模块名 -# -# 输入: "includes/stdio.py" 或 "includes/lib/core/Handles/HandlesType.py" -# 输出: "stdio" 或 "lib.core.Handles.HandlesType" -# 去除 includes/ 前缀和 .py 后缀,/ 替换为 . -# 返回 stdlib.malloc 分配的字符串,调用者负责释放 -# ============================================================ -def _PathToModuleName(path: str) -> str: - """将文件路径转换为模块名 - - 特殊处理 __init__.py:includes/ast/__init__.py → ast(而非 ast.__init__) - """ - if path is None: - return None - plen: t.CSizeT = string.strlen(path) - # 跳过 includes/ 或 includes\ 前缀(Windows 反斜杠兼容) - prefix_len: t.CSizeT = 9 - path_start: t.CSizeT = 0 - if plen > prefix_len and string.strncmp(path, "includes", 8) == 0: - psep_ch: t.CChar = path[8] - if psep_ch == '/' or psep_ch == '\\': - path_start = prefix_len - plen = plen - prefix_len - # 去掉 .py 后缀 - if plen > 3 and path[path_start + plen - 3] == '.' and path[path_start + plen - 2] == 'p' and path[path_start + plen - 1] == 'y': - plen -= 3 - if plen == 0: - return None - # 检查是否以 /__init__ 或 \__init__ 结尾(包的 __init__.py) - # /__init__ 是 9 个字符:/ _ _ i n i t _ _ - # 如果是,去掉分隔符+__init__ 后缀,模块名就是包名(如 ast/__init__ → ast) - # 注意:顶级 __init__.py(plen=8)不会进入此分支,因为 plen > 9 才检查 - # 同时支持 / 和 \ 两种分隔符(TPC 写入的路径可能混合使用) - if plen > 9: - tail_off: t.CSizeT = path_start + plen - 9 - sep_char: t.CChar = path[tail_off] - if (sep_char == '/' or sep_char == '\\') \ - and path[tail_off + 1] == '_' and path[tail_off + 2] == '_' \ - and path[tail_off + 3] == 'i' and path[tail_off + 4] == 'n' and path[tail_off + 5] == 'i' \ - and path[tail_off + 6] == 't' and path[tail_off + 7] == '_' and path[tail_off + 8] == '_': - # 去掉 分隔符+__init__ 后缀,plen 就是包名部分长度 - plen = tail_off - path_start - if plen == 0: - return None - # 复制并替换 / 为 . - result: str = stdlib.malloc(plen + 1) - if result is None: - return None - for ri in range(plen): - ch: t.CChar = path[path_start + ri] - if ch == '/' or ch == '\\': - result[ri] = '.' - else: - result[ri] = ch - result[plen] = '\0' - return result - - -# ============================================================ -# _BuildIncludesSha1Map - 从全局内存存储器构建 sha1 → module_name 映射 -# -# 数据来源是 PopulateSha1MapStore 填充的全局存储器(不读取 _sha1_map.txt)。 -# 返回两个数组(sha1_list 和 mod_list),长度存储在 count 中。 -# 所有内存由 stdlib.malloc 分配,调用者负责释放。 -# ============================================================ -def _BuildIncludesSha1Map(temp_dir: str, td_len: t.CSizeT, - sha1_list: t.CChar | t.CPtr, - mod_list: t.CChar | t.CPtr) -> int: - """从全局内存存储器复制 sha1→module_name 映射到调用者数组 - - temp_dir/td_len 参数保留以兼容现有调用者,但不再使用。 - 数据来源是 PopulateSha1MapStore 填充的全局存储器。 - """ - if sha1_list is None or mod_list is None: - return 0 - if _sha1_store_arr is None or _sha1_store_mod is None: - return 0 - count: int = 0 - for i in range(_sha1_store_count): - if count >= MAX_INCLUDES: - break - idx: t.CSizeT = t.CSizeT(i) * 17 - idx2: t.CSizeT = t.CSizeT(i) * 64 - string.strcpy(sha1_list + t.CSizeT(count) * 17, _sha1_store_arr + idx) - string.strcpy(mod_list + t.CSizeT(count) * 64, _sha1_store_mod + idx2) - count += 1 - return count - - -# ============================================================ -# _FindSha1ByModName - 从模块名查找 SHA1(精确匹配) -# -# 在 sha1_arr/mod_arr 映射中查找模块名对应的 SHA1。 -# 用于依赖图分析:模块名 → SHA1。 -# -# Args: -# sha1_arr: SHA1 数组(每个 17 字节) -# mod_arr: 模块名数组(每个 64 字节) -# count: 映射条目数 -# mod_name: 要查找的模块名 -# -# Returns: -# SHA1 字符串指针(指向 sha1_arr 内部,无需释放),未找到返回 None -# ============================================================ -def _FindSha1ByModName(sha1_arr: t.CChar | t.CPtr, mod_arr: t.CChar | t.CPtr, - count: int, mod_name: str) -> str: - """从模块名查找 SHA1(精确匹配 + 包名回退) - - 精确匹配失败时,尝试 "{mod_name}.__init__" 回退, - 支持 import ast(包)→ ast.__init__ 的 SHA1 查找。 - """ - if sha1_arr is None or mod_arr is None or mod_name is None: - return None - if count <= 0: - return None - # 第一遍:精确匹配 - for i in range(count): - idx: t.CSizeT = t.CSizeT(i) * 64 - if string.strcmp(mod_arr + idx, mod_name) == 0: - sidx: t.CSizeT = t.CSizeT(i) * 17 - return sha1_arr + sidx - # 第二遍:包名回退("ast" → "ast.__init__") - nm_len: t.CSizeT = string.strlen(mod_name) - init_buf: bytes = stdlib.malloc(nm_len + 12) - if init_buf is not None: - viperlib.snprintf(init_buf, nm_len + 12, "%s.__init__", mod_name) - for i in range(count): - idx2: t.CSizeT = t.CSizeT(i) * 64 - if string.strcmp(mod_arr + idx2, init_buf) == 0: - sidx2: t.CSizeT = t.CSizeT(i) * 17 - stdlib.free(init_buf) - return sha1_arr + sidx2 - stdlib.free(init_buf) - return None - - -# ============================================================ -# _AddSha1ToSet - 将 SHA1 加入集合(去重) -# -# 检查 SHA1 是否已在集合中,若不在则加入。返回新的 count。 -# -# Args: -# set_buf: SHA1 集合缓冲区(每个 17 字节) -# count: 当前集合中的 SHA1 数量 -# sha1: 要加入的 SHA1 -# -# Returns: -# 新的 count(如果已存在则不变) -# ============================================================ -def _AddSha1ToSet(set_buf: t.CChar | t.CPtr, count: int, sha1: str) -> int: - """将 SHA1 加入集合,返回新 count""" - if set_buf is None or sha1 is None: - return count - for i in range(count): - idx: t.CSizeT = t.CSizeT(i) * 17 - if string.strcmp(set_buf + idx, sha1) == 0: - return count - if count < MAX_INCLUDES_SHA1: - idx: t.CSizeT = t.CSizeT(count) * 17 - string.strcpy(set_buf + idx, sha1) - return count + 1 - return count - - -# ============================================================ -# _BuildReachableSha1Set - 构建可达 SHA1 集合(依赖图按需翻译) -# -# 从 source_dir 的源文件开始,解析 import 语句,递归收集可达的 -# includes 文件 SHA1。Phase 1b 只翻译可达集合中的文件,避免 -# 翻译不需要的 includes(如 Test 不依赖 llvmlite,则不翻译)。 -# -# 算法(工作列表): -# 1. 扫描 source_dir 下的 .py 文件,解析 AST 获取 _imported_modules -# 2. 构建 SHA1→module_name 映射(从全局内存存储器) -# 3. 工作列表递归:模块名 → 查 SHA1 → 加入 reachable_set → 读 .deps.txt → 追加新模块名 -# -# Args: -# mb: 内存池 -# source_dir: 源文件目录(Config.SourceDir) -# temp_dir: 临时目录(.deps.txt 所在位置;_sha1_map.txt 仅人类可读输出,不读取) -# reachable_set: 输出参数,可达 SHA1 集合缓冲区(MAX_INCLUDES_SHA1 * 17 字节) -# -# Returns: -# 可达 SHA1 数量(>0 成功,<=0 失败) -# ============================================================ -def _BuildReachableSha1Set(mb: memhub.MemBuddy | t.CPtr, source_dir: str, - temp_dir: str, - reachable_set: t.CChar | t.CPtr, - app_deps: str = None) -> int: - """构建可达 SHA1 集合(依赖图按需翻译) - - app_deps: App 源文件的直接依赖模块名(空格分隔),如果非空则跳过自己的扫描步骤 - """ - global _g_reachable_incomplete - if source_dir is None or temp_dir is None or reachable_set is None: - return -1 - - # 重置不完整标志 - _g_reachable_incomplete = 0 - - SRC_BUF_SIZE_R: t.CSizeT = 1048576 - - # 1. 构建 SHA1→module_name 映射 - td_len_r: t.CSizeT = string.strlen(temp_dir) - sha1_arr: bytes = stdlib.malloc(MAX_INCLUDES * 17) - mod_arr: bytes = stdlib.malloc(MAX_INCLUDES * 64) - if sha1_arr is None or mod_arr is None: - if sha1_arr is not None: - stdlib.free(sha1_arr) - if mod_arr is not None: - stdlib.free(mod_arr) - return -1 - map_count: int = _BuildIncludesSha1Map(temp_dir, td_len_r, sha1_arr, mod_arr) - if map_count <= 0: - VLogger.error("无法构建 SHA1 映射", "Reachable") - stdlib.free(sha1_arr) - stdlib.free(mod_arr) - return -1 - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "SHA1 映射: %d 个", map_count) - VLogger.debug(fb, "Reachable") - - # 工作列表(空格分隔的模块名) - worklist: bytes = stdlib.malloc(8192) - if worklist is None: - stdlib.free(sha1_arr) - stdlib.free(mod_arr) - return -1 - worklist[0] = '\0' - wl_len: t.CSizeT = 0 - - reachable_count: int = 0 - - # 2. 如果 app_deps 非空,直接使用它作为初始 worklist(跳过自己的非递归扫描) - # 否则,回退到自己的非递归扫描(source_dir/*.py,只扫描顶层) - if app_deps is not None and app_deps[0] != '\0': - ad_len: t.CSizeT = string.strlen(app_deps) - if ad_len > 0 and ad_len < 8192: - string.strcpy(worklist, app_deps) - wl_len = ad_len - else: - # 回退到自己的非递归扫描 - dir_len: t.CSizeT = string.strlen(source_dir) - pattern: bytes = stdlib.malloc(dir_len + 8) - if pattern is None: - stdlib.free(sha1_arr) - stdlib.free(mod_arr) - stdlib.free(worklist) - return -1 - viperlib.snprintf(pattern, dir_len + 8, "%s/*.py", source_dir) - - find_data_size: t.CSizeT = win32file.WIN32_FIND_DATAA.__sizeof__() - find_data: win32file.WIN32_FIND_DATAA | t.CPtr = stdlib.malloc(find_data_size + 16) - if find_data is None: - stdlib.free(pattern) - stdlib.free(sha1_arr) - stdlib.free(mod_arr) - stdlib.free(worklist) - return -1 - string.memset(find_data, 0, find_data_size + 16) - - handle: win32base.HANDLE = win32file.FindFirstFileA(pattern, find_data) - if handle == win32base.INVALID_HANDLE_VALUE: - fb_fd: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb_fd is not None: - viperlib.snprintf(fb_fd, 1024, "未找到 .py 文件: %s", pattern) - VLogger.warning(fb_fd, "Reachable") - stdlib.free(pattern) - stdlib.free(find_data) - stdlib.free(sha1_arr) - stdlib.free(mod_arr) - stdlib.free(worklist) - return -1 - - while True: - fname: str = find_data.cFileName - if fname is not None: - fname_len: t.CSizeT = string.strlen(fname) - if fname_len > 3: - is_py: int = 0 - if fname[fname_len - 3] == '.' and fname[fname_len - 2] == 'p' and fname[fname_len - 1] == 'y': - is_py = 1 - if is_py != 0: - full_path: bytes = stdlib.malloc(dir_len + fname_len + 2) - if full_path is not None: - viperlib.snprintf(full_path, dir_len + fname_len + 2, "%s/%s", source_dir, fname) - sf: fileio.File | t.CPtr = fileio.File(full_path, fileio.MODE.R) - if not sf.closed: - sbuf: bytes = stdlib.malloc(SRC_BUF_SIZE_R) - if sbuf is not None: - br: LONG = sf.read_all(sbuf, SRC_BUF_SIZE_R) - sf.close() - if br > 0: - if br < SRC_BUF_SIZE_R: - sbuf[br] = 0 - else: - sbuf[SRC_BUF_SIZE_R - 1] = 0 - # 解析 AST 获取 _imported_modules - lx: ast.Lexer | t.CPtr = ast.new_lexer(mb) - if lx is not None: - ast._lexer_init(lx, sbuf, mb) - tokens: ast.Token | t.CPtr = ast.tokenize(lx) - tree: ast.AST | t.CPtr = ast.parse_tokens(mb, tokens) - if tree is not None: - tr: HandlesTranslator.Translator | t.CPtr = HandlesTranslator.Translator() - if tr is not None: - tr._declare_only = 2 - # 源文件包名:fname 是顶级文件名(无目录分隔符),包为 None - tr.CurrentPackage = HandlesImports.compute_package_from_relpath(mb, fname) - HandlesStruct.reset_visible_structs(mb, 0) - tr.translate(tree) - # 获取 _imported_modules - if tr._imported_modules is not None: - im_len: t.CSizeT = string.strlen(tr._imported_modules) - if im_len > 0 and wl_len + im_len + 1 < 8192: - string.strcpy(worklist + wl_len, tr._imported_modules) - wl_len += im_len - worklist[wl_len] = ' ' - wl_len += 1 - worklist[wl_len] = '\0' - # 计算 App 源文件 SHA1,填充依赖到内存存储器 - # worklist 遍历时,LookupIncludesDeps 能找到 App 源文件的依赖 - app_sha1_r: str = IncludesScanner.compute_file_sha1(mb, full_path) - if app_sha1_r is not None: - PopulateIncludesDeps(app_sha1_r, tr._imported_modules) - stdlib.free(app_sha1_r) - # 释放 Translator 资源 - if tr._global_names is not None: - stdlib.free(tr._global_names) - if tr._nonlocal_names is not None: - stdlib.free(tr._nonlocal_names) - stdlib.free(sbuf) - else: - stdlib.free(sbuf) - else: - sf.close() - stdlib.free(full_path) - - if win32file.FindNextFileA(handle, find_data) == 0: - break - win32base.FindClose(handle) - stdlib.free(pattern) - stdlib.free(find_data) - - # 去掉末尾多余空格 - if wl_len > 0 and worklist[wl_len - 1] == ' ': - worklist[wl_len - 1] = '\0' - wl_len -= 1 - - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "源文件直接依赖: '%s'", worklist) - VLogger.debug(fb, "Reachable") - - # 2.5. 全局预加入基础容器模块(_list/_dict/json) - # - # 这些模块定义了 list/dict 等内建容器的泛型模板。 - # 使用 list[...]/dict[...] 语法时需要这些模块被翻译并注册模板。 - # 即使源文件和 includes 文件没有显式 import _list,也预加入以确保可达。 - # 这对应 TPC 的 _inject_auto_imports 机制(TPC 在翻译前自动注入 import _list)。 - # _list - if HandlesImports.is_module_imported(worklist, "_list") == 0: - bsha1_l: str = _FindSha1ByModName(sha1_arr, mod_arr, map_count, "_list") - if bsha1_l is not None: - if wl_len + 7 < 8192: - if wl_len > 0: - worklist[wl_len] = ' ' - wl_len += 1 - string.strcpy(worklist + wl_len, "_list") - wl_len += 5 - worklist[wl_len] = ' ' - wl_len += 1 - worklist[wl_len] = '\0' - # _dict - if HandlesImports.is_module_imported(worklist, "_dict") == 0: - bsha1_d: str = _FindSha1ByModName(sha1_arr, mod_arr, map_count, "_dict") - if bsha1_d is not None: - if wl_len + 7 < 8192: - if wl_len > 0: - worklist[wl_len] = ' ' - wl_len += 1 - string.strcpy(worklist + wl_len, "_dict") - wl_len += 5 - worklist[wl_len] = ' ' - wl_len += 1 - worklist[wl_len] = '\0' - # json - if HandlesImports.is_module_imported(worklist, "json") == 0: - bsha1_j: str = _FindSha1ByModName(sha1_arr, mod_arr, map_count, "json") - if bsha1_j is not None: - if wl_len + 6 < 8192: - if wl_len > 0: - worklist[wl_len] = ' ' - wl_len += 1 - string.strcpy(worklist + wl_len, "json") - wl_len += 4 - worklist[wl_len] = ' ' - wl_len += 1 - worklist[wl_len] = '\0' - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "预加入容器模块后: '%s'", worklist) - VLogger.debug(fb, "Reachable") - - # 3. 工作列表算法:递归收集可达 SHA1 - processed: bytes = stdlib.malloc(8192) - if processed is None: - stdlib.free(sha1_arr) - stdlib.free(mod_arr) - stdlib.free(worklist) - return -1 - processed[0] = '\0' - proc_len: t.CSizeT = 0 - - wl_pos: t.CSizeT = 0 - wl_iter: int = 0 - while wl_pos < wl_len: - wl_iter += 1 - # 提取一个模块名(到空格或末尾) - name_start: t.CSizeT = wl_pos - while wl_pos < wl_len and worklist[wl_pos] != ' ': - wl_pos += 1 - name_len: t.CSizeT = wl_pos - name_start - if wl_pos < wl_len: - wl_pos += 1 - if name_len == 0: - continue - - # 复制模块名 - mod_buf: bytes = stdlib.malloc(name_len + 1) - if mod_buf is None: - continue - string.strncpy(mod_buf, worklist + name_start, name_len) - mod_buf[name_len] = '\0' - - # 检查是否已处理 - already: int = 0 - if HandlesImports.is_module_imported(processed, mod_buf) != 0: - already = 1 - if already == 0: - # 加入 processed(嵌套 if 拆分 + 用 = 代替 += 绕过 TPC AUGASGN bug) - if processed is not None: - if proc_len + name_len + 1 < 8192: - string.strcpy(processed + proc_len, mod_buf) - proc_len = proc_len + name_len - processed[proc_len] = ' ' - proc_len = proc_len + 1 - processed[proc_len] = '\0' - - # 查找 SHA1 - found_sha1: str = _FindSha1ByModName(sha1_arr, mod_arr, map_count, mod_buf) - if found_sha1 is not None: - # 加入 reachable_set - reachable_count = _AddSha1ToSet(reachable_set, reachable_count, found_sha1) - - # 从内存查找依赖(不读 deps.txt 过程文件) - # Phase B+ 前用 declare_only 翻译所有 includes 文件,提取 _imported_modules 存入内存 - deps_str: str = LookupIncludesDeps(found_sha1) - if deps_str is not None: - dl: t.CSizeT = string.strlen(deps_str) - if dl > 0: - if wl_len + dl + 2 < 8192: - if wl_len > 0 and worklist[wl_len - 1] != ' ': - worklist[wl_len] = ' ' - wl_len = wl_len + 1 - string.strcpy(worklist + wl_len, deps_str) - wl_len = wl_len + dl - worklist[wl_len] = ' ' - wl_len = wl_len + 1 - worklist[wl_len] = '\0' - # deps_str 为空字符串视为无依赖(合法情况,如叶子模块) - else: - # 依赖未在内存中找到 - # 按需过滤: 检查是否是 App 源文件(source_dir 下的 .py 文件) - # App 源文件不需要加入 reachable_set(只用于 includes 过滤),跳过 - sd_len_ff: t.CSizeT = string.strlen(source_dir) - mb_len_ff: t.CSizeT = string.strlen(mod_buf) - app_mod_path: bytes = stdlib.malloc(sd_len_ff + mb_len_ff + 6) - is_app_src: int = 0 - if app_mod_path is not None: - viperlib.snprintf(app_mod_path, sd_len_ff + mb_len_ff + 6, "%s/%s.py", source_dir, mod_buf) - af: fileio.File | t.CPtr = fileio.File(app_mod_path, fileio.MODE.R) - if not af.closed: - is_app_src = 1 - af.close() - stdlib.free(app_mod_path) - if is_app_src != 0: - # App 源文件,跳过(不 fast-fail) - fb_skip: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb_skip is not None: - viperlib.snprintf(fb_skip, 1024, "跳过 App 源文件: %s (sha1=%s)", mod_buf, found_sha1) - VLogger.debug(fb_skip, "Reachable") - else: - # fast-fail: includes 文件依赖未在内存中找到,Phase 1a-pre 未正确填充 - fb_ff: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb_ff is not None: - viperlib.snprintf(fb_ff, 1024, "依赖未找到 fast-fail: 模块 %s (sha1=%s) 的依赖未在内存中注册", mod_buf, found_sha1) - VLogger.error(fb_ff, "Reachable") - stdlib.free(sha1_arr) - stdlib.free(mod_arr) - stdlib.free(worklist) - stdlib.free(processed) - stdlib.free(mod_buf) - return -1 - stdlib.free(mod_buf) - stdlib.free(sha1_arr) - stdlib.free(mod_arr) - stdlib.free(worklist) - stdlib.free(processed) - - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "可达 SHA1: %d 个", reachable_count) - VLogger.debug(fb, "Reachable") - return reachable_count - - -# ============================================================ -# BuildCombinedIR - 组合本地 stub + 依赖 stubs + 本地 text → 完整 IR -# -# 按需加载:读取 deps.txt 获取导入模块名,通过内存存储器查找 SHA1, -# 仅加载实际使用的依赖 stub(而非全部扫描)。 -# _sha1_map.txt 仅作为人类可读输出,程序内部不读取。 -# ============================================================ -def BuildCombinedIR(temp_dir: str, local_sha1: str, - out_buf: bytes, out_size: t.CSizeT) -> t.CSizeT: - """组合本地 stub + 依赖 stubs + 本地 text → out_buf(按需加载)""" - if temp_dir is None or local_sha1 is None or out_buf is None or out_size == 0: - return 0 - - td_len: t.CSizeT = string.strlen(temp_dir) - out_buf[0] = '\0' - out_pos: t.CSizeT = 0 - - # 1. 读取并追加本地 stub.ll(含 header) - stub_path: str = _sliced_path(temp_dir, td_len, local_sha1, "stub.ll") - if stub_path is None: - return 0 - sf: fileio.File | t.CPtr = fileio.File(stub_path, fileio.MODE.R) - if sf.closed: - stdlib.free(stub_path) - return 0 - stub_content: bytes = stdlib.malloc(STUB_READ_BUF_SIZE) - if stub_content is None: - sf.close() - stdlib.free(stub_path) - return 0 - stub_br: t.CInt64T = sf.read_all(stub_content, STUB_READ_BUF_SIZE) - sf.close() - stdlib.free(stub_path) - if stub_br <= 0: - stdlib.free(stub_content) - return 0 - if stub_br < STUB_READ_BUF_SIZE: - stub_content[stub_br] = '\0' - else: - stub_content[STUB_READ_BUF_SIZE - 1] = '\0' - slen: t.CSizeT = stub_br - # 修复本地 stub.ll 中字符串常量的非法 IR: - # llvmlite OUTPUT_STUB 模式输出 "= external unnamed_addr constant" 的非法形式。 - # 简单方案:搜索 "= external unnamed_addr constant" 并将 external 替换为 8 个空格。 - fix_pos: t.CSizeT = 0 - while fix_pos + 30 < slen: - ext_ptr: t.CPtr = string.strstr(stub_content + fix_pos, "= external unnamed_addr constant") - if ext_ptr is None: - break - # ext_ptr 指向 "= external ..." 中的 '=' - # 'external' 开始于 ext_ptr + 2 - ext_off: t.CSizeT = t.CSizeT(t.CUInt64T(ext_ptr) - t.CUInt64T(stub_content)) + 2 - if ext_off + 8 <= slen: - stub_content[ext_off] = ' ' - stub_content[ext_off + 1] = ' ' - stub_content[ext_off + 2] = ' ' - stub_content[ext_off + 3] = ' ' - stub_content[ext_off + 4] = ' ' - stub_content[ext_off + 5] = ' ' - stub_content[ext_off + 6] = ' ' - stub_content[ext_off + 7] = ' ' - fix_pos = ext_off + 8 - # 直接复制修复后的 stub 内容 - if out_pos + slen + 2 < out_size: - string.strcpy(out_buf + out_pos, stub_content) - out_pos += slen - if out_buf[out_pos - 1] != '\n': - out_buf[out_pos] = '\n' - out_pos += 1 - out_buf[out_pos] = '\0' - stdlib.free(stub_content) - - # 2. 按需加载依赖 stubs(根据 deps.txt 过滤,而非扫描全部) - # 先加载依赖 stub(含 type 定义),确保 type 定义在本地 text.ll 的 define 块之前 - # 2a. 构建 includes SHA1 → module_name 映射(从全局内存存储器) - sha1_arr: bytes = stdlib.malloc(MAX_INCLUDES * 17) - mod_arr: bytes = stdlib.malloc(MAX_INCLUDES * 64) - inc_count: int = 0 - if sha1_arr is not None and mod_arr is not None: - inc_count = _BuildIncludesSha1Map(temp_dir, td_len, sha1_arr, mod_arr) - - # 2b. 读取 deps.txt 获取导入模块名集合 - deps_buf: str = None - deps_loaded: int = 0 - deps_path: str = _sliced_path(temp_dir, td_len, local_sha1, "deps.txt") - if deps_path is not None: - df_deps: fileio.File | t.CPtr = fileio.File(deps_path, fileio.MODE.R) - if not df_deps.closed: - deps_buf = stdlib.malloc(4096) - if deps_buf is not None: - deps_br: t.CInt64T = df_deps.read_all(deps_buf, 4096) - if deps_br > 0: - if deps_br < 4096: - deps_buf[deps_br] = '\0' - else: - deps_buf[4095] = '\0' - deps_loaded = 1 - df_deps.close() - stdlib.free(deps_path) - - # 2c. 递归扫描 temp_dir 中所有 .stub.ll,按需加载 - all_sha1_arr: str = stdlib.malloc(MAX_INCLUDES_SHA1 * 17) - all_count: int = 0 - if all_sha1_arr is not None: - string.memset(all_sha1_arr, 0, MAX_INCLUDES_SHA1 * 17) - all_count = _collect_stub_sha1s(temp_dir, td_len, Config.Sha1SliceLevel, all_sha1_arr, 0, MAX_INCLUDES_SHA1) - if all_count > 0: - dep_buf: bytes = stdlib.malloc(STUB_READ_BUF_SIZE) - if dep_buf is not None: - si: int = 0 - while si < all_count: - dep_sha1: str = all_sha1_arr + t.CSizeT(si) * 17 - if string.strcmp(dep_sha1, local_sha1) != 0: - should_load: int = 0 - # 检查是否在 includes 映射中 - is_include: int = 0 - if inc_count > 0: - for ii in range(inc_count): - idx_ii: t.CSizeT = t.CSizeT(ii) * 17 - if string.strcmp(sha1_arr + idx_ii, dep_sha1) == 0: - is_include = 1 - if deps_loaded != 0: - idx_mi: t.CSizeT = t.CSizeT(ii) * 64 - dep_mod_name: str = mod_arr + idx_mi - if HandlesImports.is_module_imported(deps_buf, dep_mod_name) != 0: - should_load = 1 - else: - # 传递性依赖:deps.txt 只记录直接导入(如 ast), - # 但包的 __init__.py 内部 from .lexer import Lexer - # 会让 IR 引用 ast.lexer 子模块类型。 - # 检查 dep_mod_name 是否是已导入包的子模块 - # (如 ast.lexer 是 ast 的子模块) - if _is_submodule_of_imported(deps_buf, dep_mod_name) != 0: - should_load = 1 - break - if is_include == 0: - # 非 includes stub(用户文件),总是加载 - should_load = 1 - if should_load != 0: - out_pos = _LoadAndAppendStub(temp_dir, td_len, dep_sha1, dep_buf, out_buf, out_size, out_pos) - out_pos = _LoadAndAppendTextDeclares(temp_dir, td_len, dep_sha1, dep_buf, out_buf, out_size, out_pos) - si += 1 - stdlib.free(dep_buf) - stdlib.free(all_sha1_arr) - - # 2d. 验证 deps.txt 中所有依赖模块的 stub 文件都存在(fail-fast) - # 避免到 llc 才报 undefined value 错误。 - # 仅验证在 includes 映射中找到的模块(t/c 等内部库无 SHA1 映射,自动跳过)。 - if deps_loaded != 0 and inc_count > 0: - dep_total: t.CSizeT = string.strlen(deps_buf) - dp: t.CSizeT = 0 - while dp < dep_total: - # 跳过前导空格 - while dp < dep_total: - if deps_buf[dp] != ' ': - break - dp += 1 - if dp >= dep_total: - break - # 提取模块名(到下一个空格或末尾) - ms: t.CSizeT = dp - while dp < dep_total: - if deps_buf[dp] == ' ': - break - dp += 1 - ml: t.CSizeT = dp - ms - if ml == 0: - continue - # 复制模块名到临时缓冲区并 null 终止 - mod_nm: str = stdlib.malloc(ml + 1) - if mod_nm is None: - continue - string.strncpy(mod_nm, deps_buf + ms, ml) - mod_nm[ml] = '\0' - # 在 includes 映射中查找模块对应的 SHA1 - found_s: str = None - for mi2 in range(inc_count): - idx_m2: t.CSizeT = t.CSizeT(mi2) * 64 - if string.strcmp(mod_arr + idx_m2, mod_nm) == 0: - idx_s2: t.CSizeT = t.CSizeT(mi2) * 17 - found_s = sha1_arr + idx_s2 - break - if found_s is not None: - # 检查 stub 文件是否存在 - chk_path: str = _sliced_path(temp_dir, td_len, found_s, "stub.ll") - if chk_path is not None: - chk_f: fileio.File | t.CPtr = fileio.File(chk_path, fileio.MODE.R) - if chk_f.closed: - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "依赖模块 '%s' (sha1=%s) 的 stub 文件不存在: %s,立即终止编译", mod_nm, found_s, chk_path) - VLogger.error(fb, "BuildCombinedIR") - sys.exit(1) - chk_f.close() - stdlib.free(chk_path) - stdlib.free(mod_nm) - - # 3. 读取并追加本地 text.ll(行级去重,跳过 stub.ll 中已存在的定义) - text_path: str = _sliced_path(temp_dir, td_len, local_sha1, "text.ll") - if text_path is None: - return out_pos - tf: fileio.File | t.CPtr = fileio.File(text_path, fileio.MODE.R) - if tf.closed: - stdlib.free(text_path) - # text.ll 不存在的情况,继续 - else: - text_content: bytes = stdlib.malloc(STUB_READ_BUF_SIZE) - if text_content is None: - tf.close() - stdlib.free(text_path) - else: - text_br: t.CInt64T = tf.read_all(text_content, STUB_READ_BUF_SIZE) - tf.close() - stdlib.free(text_path) - if text_br > 0: - if text_br < STUB_READ_BUF_SIZE: - text_content[text_br] = '\0' - else: - text_content[STUB_READ_BUF_SIZE - 1] = '\0' - # 行级去重追加(与 _LoadAndAppendStub 相同逻辑) - tx_pos: t.CSizeT = 0 - tx_skip: int = 1 - while tx_pos < text_br: - tx_ls: t.CSizeT = tx_pos - while tx_pos < text_br: - if text_content[tx_pos] == '\n': - break - tx_pos += 1 - tx_ll: t.CSizeT = tx_pos - tx_ls - if tx_pos < text_br: - tx_pos += 1 - if tx_skip != 0: - if tx_ll == 0: - continue - tx_c0: int = text_content[tx_ls] - if tx_c0 == ';': - continue - if tx_c0 == 't' and tx_ll >= 6: - if string.strncmp(text_content + tx_ls, "target", 6) == 0: - continue - if tx_c0 == 's' and tx_ll >= 15: - if string.strncmp(text_content + tx_ls, "source_filename", 15) == 0: - continue - tx_skip = 0 - # 去重:declare(用 _IsFuncDeclaredOrDefined 避免误匹配 call 语句) - if tx_ll >= 8 and string.strncmp(text_content + tx_ls, "declare ", 8) == 0: - tx_at: t.CSizeT = tx_ls + 8 - while tx_at < tx_ls + tx_ll: - if text_content[tx_at] == '@': - break - tx_at += 1 - if tx_at < tx_ls + tx_ll: - tx_lp: t.CSizeT = tx_at + 1 - while tx_lp < tx_ls + tx_ll: - if text_content[tx_lp] == '(': - break - tx_lp += 1 - if tx_lp < tx_ls + tx_ll: - tx_sv: t.CChar = text_content[tx_lp + 1] - text_content[tx_lp + 1] = '\0' - if _IsFuncDeclaredOrDefined(out_buf, text_content + tx_at) != 0: - text_content[tx_lp + 1] = tx_sv - continue - text_content[tx_lp + 1] = tx_sv - # 去重:define(注释掉 out_buf 中已有的 declare,避免 declare/define 冲突) - if tx_ll >= 7 and string.strncmp(text_content + tx_ls, "define ", 7) == 0: - tx_at_d: t.CSizeT = tx_ls + 7 - while tx_at_d < tx_ls + tx_ll: - if text_content[tx_at_d] == '@': - break - tx_at_d += 1 - if tx_at_d < tx_ls + tx_ll: - tx_lp_d: t.CSizeT = tx_at_d + 1 - while tx_lp_d < tx_ls + tx_ll: - if text_content[tx_lp_d] == '(': - break - tx_lp_d += 1 - if tx_lp_d < tx_ls + tx_ll: - tx_sv_d: t.CChar = text_content[tx_lp_d + 1] - text_content[tx_lp_d + 1] = '\0' - _CommentOutDeclareInBuf(out_buf, text_content + tx_at_d) - text_content[tx_lp_d + 1] = tx_sv_d - # 处理:@global = ... - # stub 中可能是 external 声明或完整定义,以 text 中的定义为准 - # 找到 stub 中同名全局变量行并注释掉,然后追加 text 中的 - if tx_ll > 0 and text_content[tx_ls] == '@': - tx_eq: t.CSizeT = tx_ls + 1 - while tx_eq < tx_ls + tx_ll: - if text_content[tx_eq] == '=': - break - tx_eq += 1 - if tx_eq < tx_ls + tx_ll: - tx_sv2: t.CChar = text_content[tx_eq + 1] - text_content[tx_eq + 1] = '\0' - _CommentOutGlobalInBuf(out_buf, text_content + tx_ls) - text_content[tx_eq + 1] = tx_sv2 - # 去重:%type = ... - if tx_ll > 0 and text_content[tx_ls] == '%': - tx_eq2: t.CSizeT = tx_ls + 1 - while tx_eq2 < tx_ls + tx_ll: - if text_content[tx_eq2] == '=': - break - tx_eq2 += 1 - if tx_eq2 < tx_ls + tx_ll: - tx_sv3: t.CChar = text_content[tx_eq2 + 1] - text_content[tx_eq2 + 1] = '\0' - if string.strstr(out_buf, text_content + tx_ls) is not None: - text_content[tx_eq2 + 1] = tx_sv3 - continue - text_content[tx_eq2 + 1] = tx_sv3 - # 追加 - if out_pos + tx_ll + 2 < out_size: - string.strncpy(out_buf + out_pos, text_content + tx_ls, tx_ll) - out_pos += tx_ll - out_buf[out_pos] = '\n' - out_pos += 1 - out_buf[out_pos] = '\0' - stdlib.free(text_content) - - if deps_buf is not None: - stdlib.free(deps_buf) - if sha1_arr is not None: - stdlib.free(sha1_arr) - if mod_arr is not None: - stdlib.free(mod_arr) - - return out_pos diff --git a/TransPyV/App/lib/core/VLogger.py b/TransPyV/App/lib/core/VLogger.py deleted file mode 100644 index 316115c..0000000 --- a/TransPyV/App/lib/core/VLogger.py +++ /dev/null @@ -1,291 +0,0 @@ -import t, c -from stdint import * -import stdio -import stdlib -import memhub -import sys -import w32.win32console as w32cmd -import w32.win32file as w32file -import w32.win32base as win32base - - -# ============================================================ -# VLogger - 原生日志系统(Windows 控制台彩色输出) -# -# 输出格式与 TPC (lib/core/VLogger.py) 对齐: -# ├ INFO: message -# ├ INFO[category]: message -# ├ WARN: message -# ├ ERROR: message -# ├ SUCCESS: message -# ├ DEBUG: message -# ╠ CRITICAL: message (红底白字,致命错误) -# ╠ CRITICAL[category]: message -# -# 分段着色:前缀符号(├/╠) 用级别色,LEVEL 标签用亮色,消息用默认色 -# CRITICAL 级别使用 ╠ 前缀和红底白字标签,与 TPC critical 对齐 -# ============================================================ - -# 日志级别 -class LogLevel(t.CEnum): - DEBUG = 0 - INFO = 1 - WARNING = 2 - ERROR = 3 - SUCCESS = 4 - CRITICAL = 5 - - -# Win32 控制台前景色属性 -FOREGROUND_BLUE: t.CDefine = 0x0001 -FOREGROUND_GREEN: t.CDefine = 0x0002 -FOREGROUND_RED: t.CDefine = 0x0004 -FOREGROUND_INTENSITY: t.CDefine = 0x0008 -FOREGROUND_WHITE: t.CDefine = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE -FOREGROUND_CYAN: t.CDefine = FOREGROUND_BLUE | FOREGROUND_GREEN -FOREGROUND_YELLOW: t.CDefine = FOREGROUND_RED | FOREGROUND_GREEN -FOREGROUND_MAGENTA: t.CDefine = FOREGROUND_RED | FOREGROUND_BLUE - -# Win32 控制台背景色属性 -BACKGROUND_RED: t.CDefine = 0x0040 -BACKGROUND_GREEN: t.CDefine = 0x0020 -BACKGROUND_BLUE: t.CDefine = 0x0010 -BACKGROUND_INTENSITY: t.CDefine = 0x0080 -BACKGROUND_WHITE: t.CDefine = BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE - - -@t.NoVTable -class Logger: - _level: int - _console_handle: win32base.HANDLE - _use_color: int - __mbuddy__: memhub.MemBuddy | t.CPtr - - def __init__(self, level: int = 1): - self._level = level - self._console_handle = w32file.GetStdHandle(w32file.STD_OUTPUT_HANDLE) - self._use_color = 1 - self.__mbuddy__ = _mbuddy - - def _set_color(self, attr: WORD) -> int: - uc: int = self._use_color - if uc: - ch: win32base.HANDLE = self._console_handle - ret: int = w32cmd.SetConsoleTextAttribute(ch, attr) - return ret - return 0 - - def _reset_color(self) -> int: - if self._use_color: - return w32cmd.SetConsoleTextAttribute(self._console_handle, FOREGROUND_WHITE) - return 0 - - # ============================================================ - # _log - 核心日志输出(分段着色) - # - # 格式: ├ LEVEL: msg 或 ├ LEVEL[category]: msg - # 分三段着色: - # 1. 前缀符号 ├ (sym_color) - # 2. LEVEL 标签 (level_color) - # 3. 消息内容 (默认白色) - # ============================================================ - def _log(self, level: int, prefix_sym: str, level_str: str, msg: str, - sym_color: WORD, level_color: WORD, - category: str = "") -> int: - # 前缀符号着色 - self._set_color(sym_color) - stdio.printf("%s ", prefix_sym) - # LEVEL 标签着色 - self._set_color(level_color) - stdio.printf("%s", level_str) - self._reset_color() - # category 可选 - if category is not None and category[0] != 0: - stdio.printf(" [%s]", category) - stdio.printf(": %s\n", msg) - return 0 - - def debug(self, msg: str, category: str = "") -> int: - return self._log(LogLevel.DEBUG, "├", "DEBUG", msg, - FOREGROUND_INTENSITY, FOREGROUND_INTENSITY, category) - - def info(self, msg: str, category: str = "") -> int: - ret: int = self._log(LogLevel.INFO, "├", "INFO", msg, - FOREGROUND_GREEN, - FOREGROUND_GREEN | FOREGROUND_INTENSITY, category) - return ret - - def warning(self, msg: str, category: str = "") -> int: - return self._log(LogLevel.WARNING, "├", "WARN", msg, - FOREGROUND_YELLOW, - FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY, - category) - - def error(self, msg: str, category: str = "") -> int: - ret: int = self._log(LogLevel.ERROR, "├", "ERROR", msg, - FOREGROUND_RED, - FOREGROUND_RED | FOREGROUND_INTENSITY, category) - # 错误立即终止进程(避免错误后继续执行导致连锁崩溃) - sys.exit(1) - return ret - - def success(self, msg: str, category: str = "") -> int: - return self._log(LogLevel.SUCCESS, "├", "SUCCESS", msg, - FOREGROUND_GREEN, - FOREGROUND_GREEN | FOREGROUND_INTENSITY, category) - - def critical(self, msg: str, category: str = "") -> int: - # CRITICAL 使用 ╠ 前缀(红底白字标签,对齐 TPC critical 风格) - return self._log(LogLevel.CRITICAL, "╠", "CRITICAL", msg, - FOREGROUND_RED, - BACKGROUND_RED | FOREGROUND_WHITE | FOREGROUND_INTENSITY, - category) - - def set_level(self, level: int) -> int: - self._level = level - return 0 - - # ============================================================ - # 高级日志方法 - # ============================================================ - - def banner(self, msg: str) -> int: - """输出分节标题(蓝色高亮,与 TPC banner 风格对齐)。""" - self._set_color(FOREGROUND_BLUE | FOREGROUND_INTENSITY) - stdio.printf("\n=== %s ===\n\n", msg) - self._reset_color() - return 0 - - def compile_error(self, msg: str, file: str = "", line: int = 0) -> int: - """格式化编译错误输出(红底白字标题 + 位置 + 错误信息)。""" - self._set_color(BACKGROUND_RED | FOREGROUND_WHITE | FOREGROUND_INTENSITY) - stdio.printf(" 编译错误 ") - self._set_color(FOREGROUND_RED | FOREGROUND_INTENSITY) - stdio.printf("\n") - if file is not None: - if file[0] != 0 and line > 0: - stdio.printf(" 位置: %s:%d\n", file, line) - elif file[0] != 0: - stdio.printf(" 文件: %s\n", file) - stdio.printf(" 错误: %s\n", msg) - self._reset_color() - return 0 - - def compile_warning(self, msg: str, file: str = "", line: int = 0) -> int: - """格式化编译警告输出(黄底黑字标题 + 位置 + 警告信息)。""" - self._set_color(BACKGROUND_RED | BACKGROUND_GREEN | FOREGROUND_INTENSITY) - stdio.printf(" 编译警告 ") - self._set_color(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY) - stdio.printf("\n") - if file is not None: - if file[0] != 0 and line > 0: - stdio.printf(" 位置: %s:%d\n", file, line) - elif file[0] != 0: - stdio.printf(" 文件: %s\n", file) - stdio.printf(" 警告: %s\n", msg) - self._reset_color() - return 0 - - -# 全局 mbuddy 指针(由 lib.InitLib 注入) -_mbuddy: memhub.MemBuddy | t.CPtr - -# 全局 logger 指针 -_g_logger: Logger | t.CPtr - -# 全局格式化缓冲区(用于带变量的日志消息,1024 字节) -_fmt_buf: t.CChar | t.CPtr - - -def fmt_buf() -> t.CChar | t.CPtr: - """获取全局格式化缓冲区(1024 字节)。 - - 用法: - buf: t.CChar | t.CPtr = VLogger.fmt_buf() - if buf is not None: - viperlib.snprintf(buf, 1024, "翻译: %s (sha1=%s)", rp, sha1) - log.info(buf, "Phase1") - """ - global _fmt_buf - if _fmt_buf is None: - _fmt_buf = stdlib.malloc(1024) - return _fmt_buf - - -def get_logger() -> Logger | t.CPtr: - """获取全局 logger 实例。若不存在则通过 _mbuddy 分配并初始化。""" - global _g_logger - if _g_logger is None: - if _mbuddy is None: - return None - raw: t.CVoid | t.CPtr = _mbuddy.alloc(Logger.__sizeof__()) - if raw is None: - return None - _g_logger = raw - _g_logger.__before_init__() - _g_logger.__init__(LogLevel.INFO) - return _g_logger - - -def set_logger(logger: Logger | t.CPtr) -> int: - """设置全局 logger 实例。""" - global _g_logger - _g_logger = logger - return 0 - - -# ============================================================ -# 模块级便捷函数(与 TPC 的 lib.core.VLogger 对齐) -# -# 调用方式: VLogger.info("msg", "category") -# 无需先 get_logger(),方便各模块直接使用 -# ============================================================ - -def info(msg: str, category: str = "") -> int: - """输出 INFO 级别日志。""" - log: Logger | t.CPtr = get_logger() - if log is not None: - return log.info(msg, category) - return 0 - - -def warning(msg: str, category: str = "") -> int: - """输出 WARN 级别日志。""" - log: Logger | t.CPtr = get_logger() - if log is not None: - return log.warning(msg, category) - return 0 - - -def error(msg: str, category: str = "") -> int: - """输出 ERROR 级别日志并立即终止进程。""" - log: Logger | t.CPtr = get_logger() - if log is not None: - return log.error(msg, category) - # logger 不可用时也直接退出 - sys.exit(1) - return 0 - - -def success(msg: str, category: str = "") -> int: - """输出 SUCCESS 级别日志。""" - log: Logger | t.CPtr = get_logger() - if log is not None: - return log.success(msg, category) - return 0 - - -def critical(msg: str, category: str = "") -> int: - """输出 CRITICAL 级别日志(致命错误,红底白字)。""" - log: Logger | t.CPtr = get_logger() - if log is not None: - return log.critical(msg, category) - return 0 - - -def debug(msg: str, category: str = "") -> int: - """输出 DEBUG 级别日志。""" - log: Logger | t.CPtr = get_logger() - if log is not None: - return log.debug(msg, category) - return 0 diff --git a/TransPyV/App/lib/core/__init__.py b/TransPyV/App/lib/core/__init__.py deleted file mode 100644 index bc8c2f7..0000000 --- a/TransPyV/App/lib/core/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -import t, c -from stdint import * - -# ============================================================ -# core 包入口 -# -# 子模块通过绝对导入使用(import lib.core.X as X), -# 此 __init__.py 不做 re-export,避免引入未使用的依赖。 -# ============================================================ diff --git a/TransPyV/App/main.py b/TransPyV/App/main.py deleted file mode 100644 index a891c7d..0000000 --- a/TransPyV/App/main.py +++ /dev/null @@ -1,560 +0,0 @@ -import t, c -from stdint import * -import stdio -import string -import stdlib -import memhub -import argparse -import w32.win32console as w32cmd -import w32.fileio as fileio -import w32.win32file -import w32.win32base -import sys -import ast -import lib -import lib.core.VLogger as VLogger -import lib.core.Handles.HandlesTranslator as HandlesTranslator -import lib.core.Handles.HandlesStruct as HandlesStruct -import lib.core.Handles.HandlesExprCall as HandlesExprCall -import lib.core.Handles.HandlesType as HandlesType -import lib.core.BuildPipeline as BuildPipeline -import lib.core.IncludesScanner as IncludesScanner -import lib.core.StubMerger as StubMerger -import lib.core.Phase1 as Phase1 -import lib.core.Phase2 as Phase2 -import lib.Projectrans.Config as Config -import lib.Projectrans.Utils as Utils -import llvmlite -import subprocess -import viperlib -import hashlib - - -# 内存大小: fl_bytes=264 (33*8), POOL_SIZE-fl_bytes 必须是 2 的幂以避免浪费 -# 1073742088 - 264 = 1073741824 (1024MB usable = 2^30) -# 注意: POOL_SIZE 必须是 2^30+264=1073742088,否则 _largest_pow2_le 会取 2^29=512MB -# Phase1 翻译 87 个 includes 文件 + Phase2 翻译 30 个测试文件,512MB 不足导致 Phase2 崩溃 -POOL_SIZE: t.CDefine = 1073742088 -# 语言编码页 -CODE_PAGE: t.CDefine = 65001 -# 源代码缓冲区大小(1MB) -SRC_BUF_SIZE: t.CDefine = 1048576 - - -# ============================================================ -# main: 命令行入口 -# -# 解析参数 → 加载配置 → AST 解析 → LLVM IR 翻译 → 编译管线 → 可选执行 -# ============================================================ -def main() -> int: - w32cmd.SetConsoleOutputCP(CODE_PAGE) - w32cmd.SetConsoleCP(CODE_PAGE) - # 初始化 mbuddy 内存池 - arena: bytes = stdlib.malloc(POOL_SIZE) - if arena is None: - stdio.printf("FAIL: malloc for arena failed\n") - return 1 - mb: memhub.MemBuddy | t.CPtr = memhub.MemBuddy(arena, POOL_SIZE) - if mb is None: - stdio.printf("FAIL: MemBuddy init failed\n") - return 1 - - # 设置全局 mbuddy 指针(sys 和 argparse 都需要) - sys._mbuddy = mb - argparse._mbuddy = mb - ast._mbuddy = mb - lib._mbuddy = (memhub.MemBuddy | t.CPtr)(mb) - Config._mbuddy = (memhub.MemBuddy | t.CPtr)(mb) - Utils._mbuddy = (memhub.MemBuddy | t.CPtr)(mb) - HandlesTranslator._mbuddy = mb - BuildPipeline._mbuddy = (memhub.MemBuddy | t.CPtr)(mb) - IncludesScanner._mbuddy = (memhub.MemBuddy | t.CPtr)(mb) - StubMerger._mbuddy = (memhub.MemBuddy | t.CPtr)(mb) - Phase1._mbuddy = (memhub.MemBuddy | t.CPtr)(mb) - Phase2._mbuddy = (memhub.MemBuddy | t.CPtr)(mb) - subprocess._mbuddy = mb - hashlib._mbuddy = (memhub.MemBuddy | t.CPtr)(mb) - VLogger._mbuddy = (memhub.MemBuddy | t.CPtr)(mb) - lib.InitLib((memhub.MemBuddy | t.CPtr)(mb)) - - # 初始化 VLogger 并打印启动日志 - log: VLogger.Logger | t.CPtr = VLogger.get_logger() - if log is not None: - log.info("TransPyV 启动") - - # 初始化命令行参数(Windows: GetCommandLineA, POSIX: /proc/self/cmdline) - sys._init_argv() - - # 创建参数解析器 - parser: argparse.ArgumentParser | t.CPtr = argparse.ArgumentParser( - "TransPyV", "TransPyV 命令行参数解析", pool=mb) - - # 注册参数(与 Projectrans.py main() 一致) - parser.add_argument("--project", None, argparse.STRING, 0, None, False, - argparse.STORE, "project.json 路径(默认查找当前目录)") - parser.add_argument("--src", None, argparse.STRING, 0, None, False, - argparse.STORE, "源文件目录(覆盖 project.json)") - parser.add_argument("--temp", None, argparse.STRING, 0, None, False, - argparse.STORE, "声明接口临时目录(覆盖 project.json)") - parser.add_argument("--output", None, argparse.STRING, 0, None, False, - argparse.STORE, "输出目录(覆盖 project.json)") - parser.add_argument("--phase", None, argparse.STRING, 0, None, False, - argparse.STORE, "阶段: 1=生成声明, 2=翻译+编译, all=全部") - parser.add_argument("--cc", None, argparse.STRING, 0, None, False, - argparse.STORE, "LLVM 编译器命令(覆盖 project.json)") - parser.add_argument("--clean", None, argparse.BOOL, 0, None, False, - argparse.STORE_TRUE, "清理 output 和 temp 目录") - parser.add_argument("--run", None, argparse.BOOL, 0, None, False, - argparse.STORE_TRUE, "编译成功后立即执行生成的可执行文件") - parser.add_argument("--rebuild-includes", None, argparse.BOOL, 0, None, False, - argparse.STORE_TRUE, "删除 includes.binary 预编译缓存并重新编译所有 includes") - parser.add_argument("--clear-cache", None, argparse.BOOL, 0, None, False, - argparse.STORE_TRUE, "清除 .transpyc_cache 全局缓存") - - # 解析命令行参数 - args: argparse.ParsedArgs | t.CPtr = parser.parse_args(sys._argc, sys._argv) - if args is None: - if log is not None: - log.error("参数解析失败", "argparse") - return 1 - - # 打印解析结果 - if log is not None: - log.banner("TransPyV 参数解析结果") - - # 字符串参数 - project: str = args.get_str("project") - if project is not None: - stdio.printf(" --project: %s\n", project) - else: - stdio.printf(" --project: (未指定)\n") - - src: str = args.get_str("src") - if src is not None: - stdio.printf(" --src: %s\n", src) - else: - stdio.printf(" --src: (未指定)\n") - - temp: str = args.get_str("temp") - if temp is not None: - stdio.printf(" --temp: %s\n", temp) - else: - stdio.printf(" --temp: (未指定)\n") - - output: str = args.get_str("output") - if output is not None: - stdio.printf(" --output: %s\n", output) - else: - stdio.printf(" --output: (未指定)\n") - - phase: str = args.get_str("phase") - if phase is not None: - stdio.printf(" --phase: %s\n", phase) - else: - stdio.printf(" --phase: (未指定,默认 all)\n") - - cc: str = args.get_str("cc") - if cc is not None: - stdio.printf(" --cc: %s\n", cc) - else: - stdio.printf(" --cc: (未指定)\n") - - # 布尔参数 - _gb_clean: INT = args.get_bool("clean") - if _gb_clean: - stdio.printf(" --clean: True\n") - else: - stdio.printf(" --clean: False\n") - - if args.get_bool("run"): - stdio.printf(" --run: True\n") - else: - stdio.printf(" --run: False\n") - - if args.get_bool("rebuild-includes"): - stdio.printf(" --rebuild-includes: True\n") - else: - stdio.printf(" --rebuild-includes: False\n") - - if args.get_bool("clear-cache"): - stdio.printf(" --clear-cache: True\n") - else: - stdio.printf(" --clear-cache: False\n") - - stdio.printf("\n参数解析完成。\n") - - # 加载 project.vpj 配置 - proj_loaded: int = 0 - proj_path: str = project - if proj_path is not None: - if log is not None: - log.banner("工程配置") - cfg_ret: int = Config.Load_project_config(proj_path) - if cfg_ret == 0: - proj_loaded = 1 - else: - if log is not None: - warn_buf: str = stdlib.malloc(256) - if warn_buf is not None: - viperlib.snprintf(warn_buf, 256, "无法加载 project.vpj: %s", proj_path) - log.warning(warn_buf, "config") - stdlib.free(warn_buf) - else: - # 尝试默认路径 project.vpj(当前目录和上级目录) - proj_path = "project.vpj" - if Config.Load_project_config(proj_path) == 0: - proj_loaded = 1 - else: - proj_path = "../project.vpj" - if Config.Load_project_config(proj_path) == 0: - proj_loaded = 1 - if proj_loaded == 1: - # 提取 project.vpj 所在目录,将相对路径解析为基于该目录的路径 - proj_len: t.CSizeT = string.strlen(proj_path) - slash_pos: t.CSizeT = proj_len - for i in range(proj_len): - idx: t.CSizeT = proj_len - 1 - i - ch: t.CChar = proj_path[idx] - if ch == '/' or ch == '\\': - slash_pos = idx - break - proj_dir: str = "" - if slash_pos > 0 and slash_pos < proj_len: - proj_dir = stdlib.malloc(slash_pos + 1) - if proj_dir is not None: - string.memcpy(proj_dir, proj_path, slash_pos) - proj_dir[slash_pos] = '\0' - Config.resolve_paths(proj_dir) - Config.print_config() - - # === --clean: 清理 temp 和 output 目录 === - if _gb_clean: - if log is not None: - log.info("清理临时目录...", "clean") - if Config.TempDir is not None: - n: int = Utils.CleanDir(Config.TempDir) - if log is not None: - fb: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb is not None: - viperlib.snprintf(fb, 1024, "%s: 删除 %d 个文件", Config.TempDir, n) - log.info(fb, "clean") - if Config.OutputDir is not None: - n2: int = Utils.CleanDir(Config.OutputDir) - if log is not None: - fb2: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb2 is not None: - viperlib.snprintf(fb2, 1024, "%s: 删除 %d 个文件", Config.OutputDir, n2) - log.info(fb2, "clean") - - # === --phase 参数控制 === - # phase=1: 仅 stub 分离(生成 .stub.ll/.text.ll),不编译 - # phase=2: 仅 stub 合并 + 编译(跳过 stub 分离) - # phase=all: 两者都执行(默认) - phase_mode: str = phase - if phase_mode is None: - phase_mode = "all" - do_phase1: int = 0 - do_phase2: int = 0 - # 注意: 使用 string.strcmp 而非 ==,避免编译器 == 语义 bug - if string.strcmp(phase_mode, "1") == 0 or string.strcmp(phase_mode, "all") == 0: - do_phase1 = 1 - if string.strcmp(phase_mode, "2") == 0 or string.strcmp(phase_mode, "all") == 0: - do_phase2 = 1 - if log is not None: - fb3: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb3 is not None: - viperlib.snprintf(fb3, 1024, "模式: %s (phase1=%d phase2=%d)", phase_mode, do_phase1, do_phase2) - log.info(fb3, "phase") - - # === Phase1: 扫描 includes(按需翻译)=== - # 对 includes 目录中每个 .py 文件,若 stub 不存在则翻译并分离 stub - if do_phase1 != 0 and Config.IncludesDir is not None: - ph1_temp: str = Config.TempDir - if ph1_temp is None: - ph1_temp = "." - Phase1.RunPhase1(mb, Config.IncludesDir, ph1_temp, log) - # 如果仅 Phase1(不执行 Phase2),直接退出 - if do_phase2 == 0: - if log is not None: - log.info("Phase1 完成,退出", "phase") - return 0 - - # AST 解析:如果指定了 --src 或 --project,读取文件并解析为 AST 树 - src_path: str = args.get_str("src") - - # === 多文件项目模式 === - # 当 --project 指定但 --src 未指定时,扫描 source_dir 下所有 .py 文件编译 - if src_path is None and project is not None and Config.SourceDir is not None: - mf_temp: str = Config.TempDir if Config.TempDir is not None else "." - mf_output: str = Config.OutputDir if Config.OutputDir is not None else "." - mf_cc: str = Config.CompilerCmd if Config.CompilerCmd is not None else "llc" - mf_cc_flags: str = Config.CompilerFlags if Config.CompilerFlags is not None else "-filetype=obj -relocation-model=pic" - mf_linker: str = Config.LinkerCmd if Config.LinkerCmd is not None else "clang++" - mf_linker_flags: str = Config.LinkerFlags if Config.LinkerFlags is not None else "-lmsvcrt -lucrt -lpthread -lmingwex -lkernel32 -lgcc -Wl,--allow-multiple-definition" - mf_linker_out: str = Config.LinkerOutput if Config.LinkerOutput is not None else "app.exe" - mf_includes_bin: str = Config.get_includes_binary_dir() - - mf_ret: int = Phase2.RunMultiFileProject( - mb, Config.SourceDir, mf_temp, mf_output, - mf_cc, mf_cc_flags, mf_linker, mf_linker_flags, mf_linker_out, - mf_includes_bin, Config.IncludesDir, do_phase1, do_phase2, log, args) - argparse.release(args) - if log is not None: - log.success("TransPyV 完成") - return mf_ret - - # === 单文件模式:--src 指定时使用指定文件;--project 但无 SourceDir 时回退 === - if src_path is None and project is not None: - if Config.SourceDir is not None: - # 构造入口路径: SourceDir/main.py - sd_len: t.CSizeT = string.strlen(Config.SourceDir) - path_buf: bytes = stdlib.malloc(sd_len + 16) - if path_buf is not None: - viperlib.snprintf(path_buf, sd_len + 16, "%s/main.py", Config.SourceDir) - src_path = path_buf - if log is not None: - fb4: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb4 is not None: - viperlib.snprintf(fb4, 1024, "入口文件: %s", src_path) - log.info(fb4, "project") - if src_path is not None: - if log is not None: - log.banner("AST 解析") - # 打开文件 - f: fileio.File | t.CPtr = fileio.File(src_path, fileio.MODE.R) - if f.closed: - if log is not None: - fb5: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb5 is not None: - viperlib.snprintf(fb5, 1024, "无法打开文件: %s", src_path) - log.error(fb5, "fileio") - argparse.release(args) - return 1 - # 分配源代码缓冲区 - src_buf: bytes = stdlib.malloc(SRC_BUF_SIZE) - if src_buf is None: - if log is not None: - log.error("malloc for src_buf failed", "memhub") - f.close() - argparse.release(args) - return 1 - # 读取文件内容 - bytes_read: LONG = f.read_all(src_buf, SRC_BUF_SIZE) - f.close() - if bytes_read < 0: - if log is not None: - fb6: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb6 is not None: - viperlib.snprintf(fb6, 1024, "读取文件失败 (错误码: %d)", bytes_read) - log.error(fb6, "fileio") - argparse.release(args) - return 1 - # 添加 null 终止符,确保 strlen 和 SHA1 计算正确 - if bytes_read < SRC_BUF_SIZE: - src_buf[bytes_read] = 0 - else: - src_buf[SRC_BUF_SIZE - 1] = 0 - if log is not None: - log.info("文件读取完成", "fileio") - fb7: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb7 is not None: - viperlib.snprintf(fb7, 1024, "读取 %d 字节", bytes_read) - log.info(fb7, "fileio") - # 解析 AST(拆分为词法+语法两阶段,便于调试) - ast._init_tables(mb) - lx: ast.Lexer | t.CPtr = ast.new_lexer(mb) - ast._lexer_init(lx, src_buf, mb) - tokens: ast.Token | t.CPtr = ast.tokenize(lx) - tree: ast.AST | t.CPtr = ast.parse_tokens(mb, tokens) - if tree is None: - if log is not None: - log.error("AST 解析失败", "ast") - argparse.release(args) - return 1 - - # === 翻译 AST → LLVM IR === - if log is not None: - log.banner("LLVM IR 翻译") - tr: HandlesTranslator.Translator | t.CPtr = HandlesTranslator.Translator() - result: int = tr.translate(tree) - if result == 0: - IR_BUF_SIZE: t.CSizeT = 262144 - ir_buf: bytes = stdlib.malloc(IR_BUF_SIZE) - if ir_buf is not None: - tr.dump_ir(ir_buf, IR_BUF_SIZE, llvmlite.OUTPUT_FULL) - - # === 编译管线: .ll → .obj → .exe === - if log is not None: - log.banner("编译管线") - - # module_name 用源代码内容的 SHA1(前 16 字符),与 Projectrans.py 一致 - # output_name 从文件名推导(如 test.py -> test.exe),保持可读性 - module_name: str = Utils.compute_sha1(mb, src_buf) - if module_name is None: - module_name = "main" - output_name: str = "test_prog.exe" - # 从文件名提取 output_name(去掉路径和 .py 扩展名) - src_len: t.CSizeT = string.strlen(src_path) - if src_len > 0: - # 找到最后一个 / 或 \ 之后的部分 - base_start: t.CSizeT = src_len - i: t.CSizeT = src_len - while i > 0: - i -= 1 - ch: t.CChar = src_path[i] - if ch == '/' or ch == '\\': - base_start = i + 1 - break - if i == 0: - base_start = 0 - # 找到 .py 扩展名 - base_end: t.CSizeT = src_len - j: t.CSizeT = base_start - while j < src_len: - if src_path[j] == '.': - base_end = j - break - j += 1 - # 输出名 = 文件名 + ".exe" - name_len: t.CSizeT = base_end - base_start - if name_len > 0: - out_len: t.CSizeT = name_len + 5 - output_name = stdlib.malloc(out_len) - if output_name is not None: - # 手动复制文件名并追加 .exe(viperlib.snprintf 不支持 %.*s,string 无 strcat) - string.strncpy(output_name, src_path + base_start, name_len) - output_name[name_len] = '.' - output_name[name_len + 1] = 'e' - output_name[name_len + 2] = 'x' - output_name[name_len + 3] = 'e' - output_name[name_len + 4] = '\0' - # 使用 project.vpj 中的配置 - temp_dir: str = Config.TempDir if Config.TempDir is not None else "." - output_dir: str = Config.OutputDir if Config.OutputDir is not None else "." - # 设置全局 temp_dir(供跨模块 CDefine 查找使用) - HandlesType.set_temp_dir(temp_dir) - cc_cmd: str = Config.CompilerCmd if Config.CompilerCmd is not None else "llc" - cc_flags: str = "-filetype=obj -relocation-model=pic" - linker_cmd: str = Config.LinkerCmd if Config.LinkerCmd is not None else "clang++" - linker_flags: str = "-lmsvcrt -lucrt -lpthread -lmingwex -lkernel32 -lgcc -Wl,--allow-multiple-definition" - # --project 模式且未显式指定 --src 时:使用 config 中的 linker_output(如 TransPyV.exe) - # 显式指定 --src 时:使用从文件名推导的 output_name(如 test.exe),避免覆盖正在运行的 exe - if project is not None and Config.LinkerOutput is not None and args.get_str("src") is None: - linker_output: str = Config.LinkerOutput - else: - linker_output: str = output_name - - # 计算 includes.binary 目录路径(链接时附加预编译 .obj) - includes_binary_dir: str = Config.get_includes_binary_dir() - - ir_len: t.CSizeT = string.strlen(ir_buf) - - # (--phase 参数已在配置加载后处理,此处直接使用 do_phase1/do_phase2) - - # === Phase1 stub 分离:使用 OUTPUT_STUB/TEXT 模式分别生成 stub.ll 和 text.ll === - if do_phase1 != 0 and temp_dir is not None and module_name is not None: - if log is not None: - log.banner("stub 分离") - SF_IR_SIZE: t.CSizeT = 262144 - td_len_sf: t.CSizeT = string.strlen(temp_dir) - # 保存 stub.ll - sf_stub_buf: bytes = stdlib.malloc(SF_IR_SIZE) - if sf_stub_buf is not None: - tr.dump_ir(sf_stub_buf, SF_IR_SIZE, llvmlite.OUTPUT_STUB) - sf_stub_len: t.CSizeT = string.strlen(sf_stub_buf) - sf_stub_path: str = StubMerger._sliced_path(temp_dir, td_len_sf, module_name, "stub.ll") - if sf_stub_path is not None: - sf_f: fileio.File | t.CPtr = fileio.File(sf_stub_path, fileio.MODE.W) - if not sf_f.closed: - sf_f.write(sf_stub_buf, sf_stub_len) - sf_f.close() - stdlib.free(sf_stub_path) - stdlib.free(sf_stub_buf) - # 保存 text.ll - sf_text_buf: bytes = stdlib.malloc(SF_IR_SIZE) - if sf_text_buf is not None: - tr.dump_ir(sf_text_buf, SF_IR_SIZE, llvmlite.OUTPUT_TEXT) - sf_text_len: t.CSizeT = string.strlen(sf_text_buf) - sf_text_path: str = StubMerger._sliced_path(temp_dir, td_len_sf, module_name, "text.ll") - if sf_text_path is not None: - sf_tf: fileio.File | t.CPtr = fileio.File(sf_text_path, fileio.MODE.W) - if not sf_tf.closed: - sf_tf.write(sf_text_buf, sf_text_len) - sf_tf.close() - stdlib.free(sf_text_path) - stdlib.free(sf_text_buf) - - # phase=1 模式:仅生成 stub,不执行编译 - if do_phase2 == 0: - if log is not None: - log.success("Phase1 完成(仅 stub 分离,跳过编译)") - argparse.release(args) - return 0 - - # === Phase2: 组合本地 stub + 依赖 stubs + 本地 text → 完整 IR === - final_ir: bytes = ir_buf - final_ir_len: t.CSizeT = ir_len - if temp_dir is not None and module_name is not None: - if log is not None: - log.banner("IR 组合") - SF_COMBINED_SIZE: t.CSizeT = 4194304 # 4MB - combined_buf: bytes = stdlib.malloc(SF_COMBINED_SIZE) - if combined_buf is not None: - combined_len: t.CSizeT = StubMerger.BuildCombinedIR(temp_dir, module_name, combined_buf, SF_COMBINED_SIZE) - if combined_len > 0: - final_ir = combined_buf - final_ir_len = combined_len - else: - if log is not None: - log.warning("BuildCombinedIR 失败,使用原始 IR", "stub") - stdlib.free(combined_buf) - - br: BuildPipeline.BuildResult | t.CPtr = BuildPipeline.run_pipeline( - final_ir, final_ir_len, temp_dir, output_dir, module_name, - cc_cmd, cc_flags, linker_cmd, linker_flags, linker_output, - includes_binary_dir - ) - if br is not None and br.Success == 1: - if log is not None: - log.success("编译管线完成") - fb8: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb8 is not None: - viperlib.snprintf(fb8, 1024, "输出: %s/%s", output_dir, linker_output) - log.info(fb8) - # --run 模式:执行生成的可执行文件 - if args.get_bool("run"): - exe_path: bytes = stdlib.malloc(string.strlen(output_dir) + string.strlen(linker_output) + 2) - if exe_path is not None: - viperlib.snprintf(exe_path, 256, "%s/%s", output_dir, linker_output) - if log is not None: - fb9: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb9 is not None: - viperlib.snprintf(fb9, 1024, "执行: %s", exe_path) - log.info(fb9, "run") - r: subprocess.CompletedProcess | t.CPtr = subprocess.run(exe_path, False, False) - if r is not None: - if log is not None: - fb10: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb10 is not None: - viperlib.snprintf(fb10, 1024, "退出码: %d", r.returncode) - log.info(fb10, "run") - else: - if log is not None: - log.error("编译管线失败", "pipeline") - if br is not None and br.ErrorMsg is not None: - fb11: t.CChar | t.CPtr = VLogger.fmt_buf() - if fb11 is not None: - viperlib.snprintf(fb11, 1024, "编译管线失败: %s", br.ErrorMsg) - log.error(fb11, "FATAL") - sys.exit(1) - else: - if log is not None: - log.error("malloc for IR buffer failed", "memhub") - else: - if log is not None: - log.error("翻译失败", "translator") - - argparse.release(args) - if log is not None: - log.success("TransPyV 完成") - return 0 diff --git a/TransPyV/Test/App/asm_test.py b/TransPyV/Test/App/asm_test.py deleted file mode 100644 index d09ac4b..0000000 --- a/TransPyV/Test/App/asm_test.py +++ /dev/null @@ -1,47 +0,0 @@ -import stdio -import t, c - - -# ============================================================ -# c.Asm 内联汇编测试 -# ============================================================ - -def asm_test() -> int: - # 1. 简单无操作数汇编(nop + clobber) - c.Asm("nop", op=[t.ASM_DESCR.CLOBBER_MEMORY]) - stdio.printf("asm: nop ok\n") - - # 2. 仅汇编文本无 clobber - c.Asm("nop") - stdio.printf("asm: nop2 ok\n") - - # 3. 多 clobber - c.Asm("nop", op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_CC]) - stdio.printf("asm: multi-clobber ok\n") - - # 4. 带输入操作数的汇编(读取 CPU ID) - # 使用 f-string 内联 c.AsmInp - # mov eax, 输入值; nop(保持简单,不使用会产生异常的指令) - val: int = 42 - c.Asm(f"""mov eax, {c.AsmInp(val, t.ASM_DESCR.REG_ANY)} -nop""", op=[t.ASM_DESCR.CLOBBER_RAX]) - stdio.printf("asm: input ok val=%d\n", val) - - # 5. 带输出操作数的汇编 - # c.AsmOut 获取结果 - result: int = 0 - c.Asm(f"""mov {c.AsmOut(result, t.ASM_DESCR.OUTPUT_REG)}, 123 -nop""", op=[t.ASM_DESCR.CLOBBER_RAX]) - stdio.printf("asm: output result=%d\n", result) - - # 6. 带输入和输出操作数 - # result2 = val + 1 - result2: int = 0 - input_val: int = 10 - c.Asm(f"""mov eax, {c.AsmInp(input_val, t.ASM_DESCR.REG_ANY)} -add eax, 1 -mov {c.AsmOut(result2, t.ASM_DESCR.OUTPUT_REG)}, eax -nop""", op=[t.ASM_DESCR.CLOBBER_RAX]) - stdio.printf("asm: in+out result2=%d (expect 11)\n", result2) - - return 0 diff --git a/TransPyV/Test/App/attr_test.py b/TransPyV/Test/App/attr_test.py deleted file mode 100644 index 4bc8cad..0000000 --- a/TransPyV/Test/App/attr_test.py +++ /dev/null @@ -1,234 +0,0 @@ -import t, c -from stdint import * -import stdio -import string - - -# ============================================================ -# c.Attribute 装饰器测试 -# -# 测试 @c.Attribute(...) 对函数属性的设置: -# - t.attr.always_inline() -> alwaysinline -# - t.attr.noinline() -> noinline -# - t.attr.noreturn() -> noreturn -# - t.attr.pure() -> readonly (LLVM 函数属性) -# - t.attr.llvm.nounwind -> nounwind -# ============================================================ - - -# Test 1: always_inline 属性 -@c.Attribute(t.attr.always_inline()) -def AlwaysInlineFunc(x: t.CInt) -> t.CInt: - return x * 2 - - -# Test 2: noinline 属性 -@c.Attribute(t.attr.noinline()) -def NoInlineFunc(x: t.CInt) -> t.CInt: - return x + 100 - - -# Test 3: noreturn 属性(函数确实不返回) -@c.Attribute(t.attr.noreturn()) -def NoReturnFunc() -> t.CInt: - stdio.printf("NoReturnFunc called (does not return)\n") - return 0 - - -# Test 4: 普通函数对照(无装饰器) -def NormalFunc(x: t.CInt) -> t.CInt: - return x * 3 - - -# Test 5: 多属性组合 -@c.Attribute(t.attr.always_inline(), t.attr.pure()) -def MultiAttrFunc(x: t.CInt) -> t.CInt: - return x + 1 - - -# Test 6: 无括号属性引用 t.attr.packed -@c.Attribute(t.attr.packed) -def PackedAttrFunc(x: t.CInt) -> t.CInt: - return x - 1 - - -def test_always_inline() -> t.CInt: - stdio.printf("--- Test 1: c.Attribute(always_inline) ---\n") - r: t.CInt = AlwaysInlineFunc(21) - stdio.printf("AlwaysInlineFunc(21)=%d (expect 42)\n", r) - if r == 42: - stdio.printf("AlwaysInlineFunc OK\n") - else: - stdio.printf("AlwaysInlineFunc FAIL\n") - return 0 - - -def test_noinline() -> t.CInt: - stdio.printf("--- Test 2: c.Attribute(noinline) ---\n") - r: t.CInt = NoInlineFunc(5) - stdio.printf("NoInlineFunc(5)=%d (expect 105)\n", r) - if r == 105: - stdio.printf("NoInlineFunc OK\n") - else: - stdio.printf("NoInlineFunc FAIL\n") - return 0 - - -def test_noreturn() -> t.CInt: - stdio.printf("--- Test 3: c.Attribute(noreturn) ---\n") - stdio.printf("NoReturnFunc declared with noreturn attr\n") - stdio.printf("NoReturnFunc OK (not called to avoid UB)\n") - return 0 - - -def test_normal() -> t.CInt: - stdio.printf("--- Test 4: normal function (no attr) ---\n") - r: t.CInt = NormalFunc(7) - stdio.printf("NormalFunc(7)=%d (expect 21)\n", r) - if r == 21: - stdio.printf("NormalFunc OK\n") - else: - stdio.printf("NormalFunc FAIL\n") - return 0 - - -def test_multi_attr() -> t.CInt: - stdio.printf("--- Test 5: c.Attribute(always_inline, pure) ---\n") - r: t.CInt = MultiAttrFunc(10) - stdio.printf("MultiAttrFunc(10)=%d (expect 11)\n", r) - if r == 11: - stdio.printf("MultiAttrFunc OK\n") - else: - stdio.printf("MultiAttrFunc FAIL\n") - return 0 - - -def test_packed_attr() -> t.CInt: - stdio.printf("--- Test 6: c.Attribute(packed) ---\n") - r: t.CInt = PackedAttrFunc(10) - stdio.printf("PackedAttrFunc(10)=%d (expect 9)\n", r) - if r == 9: - stdio.printf("PackedAttrFunc OK\n") - else: - stdio.printf("PackedAttrFunc FAIL\n") - return 0 - - -# Test 7: t.attr.llvm.nounwind 属性 -@c.Attribute(t.attr.llvm.nounwind) -def NoUnwindFunc(x: t.CInt) -> t.CInt: - return x + 1 - - -# Test 8: t.attr.llvm.noredzone 属性 -@c.Attribute(t.attr.llvm.noredzone) -def NoRedZoneFunc(x: t.CInt) -> t.CInt: - return x + 2 - - -# Test 9: t.attr.llvm.willreturn 属性 -@c.Attribute(t.attr.llvm.willreturn) -def WillReturnFunc(x: t.CInt) -> t.CInt: - return x + 3 - - -# Test 10: t.attr.llvm.mustprogress 属性 -@c.Attribute(t.attr.llvm.mustprogress) -def MustProgressFunc(x: t.CInt) -> t.CInt: - return x + 4 - - -# Test 11: t.attr.const() -> readnone -@c.Attribute(t.attr.const()) -def ConstFunc(x: t.CInt) -> t.CInt: - return x * 0 + 42 - - -# Test 12: 多属性组合(alwaysinline + nounwind + noredzone) -@c.Attribute(t.attr.always_inline(), t.attr.llvm.nounwind, t.attr.llvm.noredzone) -def TripleAttrFunc(x: t.CInt) -> t.CInt: - return x + 5 - - -def test_nounwind() -> t.CInt: - stdio.printf("--- Test 7: c.Attribute(llvm.nounwind) ---\n") - r: t.CInt = NoUnwindFunc(10) - stdio.printf("NoUnwindFunc(10)=%d (expect 11)\n", r) - if r == 11: - stdio.printf("NoUnwindFunc OK\n") - else: - stdio.printf("NoUnwindFunc FAIL\n") - return 0 - - -def test_noredzone() -> t.CInt: - stdio.printf("--- Test 8: c.Attribute(llvm.noredzone) ---\n") - r: t.CInt = NoRedZoneFunc(10) - stdio.printf("NoRedZoneFunc(10)=%d (expect 12)\n", r) - if r == 12: - stdio.printf("NoRedZoneFunc OK\n") - else: - stdio.printf("NoRedZoneFunc FAIL\n") - return 0 - - -def test_willreturn() -> t.CInt: - stdio.printf("--- Test 9: c.Attribute(llvm.willreturn) ---\n") - r: t.CInt = WillReturnFunc(10) - stdio.printf("WillReturnFunc(10)=%d (expect 13)\n", r) - if r == 13: - stdio.printf("WillReturnFunc OK\n") - else: - stdio.printf("WillReturnFunc FAIL\n") - return 0 - - -def test_mustprogress() -> t.CInt: - stdio.printf("--- Test 10: c.Attribute(llvm.mustprogress) ---\n") - r: t.CInt = MustProgressFunc(10) - stdio.printf("MustProgressFunc(10)=%d (expect 14)\n", r) - if r == 14: - stdio.printf("MustProgressFunc OK\n") - else: - stdio.printf("MustProgressFunc FAIL\n") - return 0 - - -def test_const_attr() -> t.CInt: - stdio.printf("--- Test 11: c.Attribute(const) ---\n") - r: t.CInt = ConstFunc(99) - stdio.printf("ConstFunc(99)=%d (expect 42)\n", r) - if r == 42: - stdio.printf("ConstFunc OK\n") - else: - stdio.printf("ConstFunc FAIL\n") - return 0 - - -def test_triple_attr() -> t.CInt: - stdio.printf("--- Test 12: c.Attribute(always_inline, nounwind, noredzone) ---\n") - r: t.CInt = TripleAttrFunc(10) - stdio.printf("TripleAttrFunc(10)=%d (expect 15)\n", r) - if r == 15: - stdio.printf("TripleAttrFunc OK\n") - else: - stdio.printf("TripleAttrFunc FAIL\n") - return 0 - - -def attr_test() -> t.CInt: - stdio.printf("=== attr_test: c.Attribute 装饰器测试 ===\n\n") - test_always_inline() - test_noinline() - test_noreturn() - test_normal() - test_multi_attr() - test_packed_attr() - test_nounwind() - test_noredzone() - test_willreturn() - test_mustprogress() - test_const_attr() - test_triple_attr() - stdio.printf("\n=== attr_test 完成 ===\n") - return 0 diff --git a/TransPyV/Test/App/augassign_test.py b/TransPyV/Test/App/augassign_test.py deleted file mode 100644 index 20b52ce..0000000 --- a/TransPyV/Test/App/augassign_test.py +++ /dev/null @@ -1,58 +0,0 @@ -import stdio -import t, c - - -# ============================================================ -# AugAssign 测试:+= -= *= /= %= &= |= ^= <<= >>= -# ============================================================ - -g_count: int = 0 - - -def test_local() -> int: - x: int = 10 - x += 5 - stdio.printf("local +=: %d\n", x) - x -= 3 - stdio.printf("local -=: %d\n", x) - x *= 2 - stdio.printf("local *=: %d\n", x) - x /= 4 - stdio.printf("local /=: %d\n", x) - x %= 7 - stdio.printf("local %%=: %d\n", x) - return 0 - - -def test_global_aug() -> int: - global g_count - g_count += 1 - stdio.printf("global +=: %d\n", g_count) - g_count += 10 - stdio.printf("global +=: %d\n", g_count) - g_count -= 3 - stdio.printf("global -=: %d\n", g_count) - return 0 - - -def test_bitops() -> int: - b: int = 0xFF - b &= 0x0F - stdio.printf("bit &=: %d\n", b) - b |= 0x30 - stdio.printf("bit |=: %d\n", b) - b ^= 0xFF - stdio.printf("bit ^=: %d\n", b) - b = 1 - b <<= 4 - stdio.printf("bit <<=: %d\n", b) - b >>= 2 - stdio.printf("bit >>=: %d\n", b) - return 0 - - -def augassign_test() -> int: - test_local() - test_global_aug() - test_bitops() - return 0 diff --git a/TransPyV/Test/App/closure_test.py b/TransPyV/Test/App/closure_test.py deleted file mode 100644 index c2c876e..0000000 --- a/TransPyV/Test/App/closure_test.py +++ /dev/null @@ -1,45 +0,0 @@ -import stdio -import t, c - - -# ============================================================ -# 闭包 + nonlocal/global 测试 -# ============================================================ - -# 全局变量 -g_count: int = 0 - - -# global 关键字测试:修改全局变量 -def test_global() -> int: - global g_count - g_count = g_count + 1 - return g_count - - -# nonlocal 关键字测试:嵌套函数修改外层局部变量 -def make_counter() -> t.CPtr: - count: int = 0 - - # 内部函数(闭包)捕获 count - def counter() -> int: - nonlocal count - count = count + 1 - return count - - return counter - - -def closure_test() -> int: - # global 测试 - stdio.printf("global: %d\n", test_global()) - stdio.printf("global: %d\n", test_global()) - stdio.printf("global: %d\n", test_global()) - - # nonlocal/闭包测试 - f: t.CPtr = make_counter() - stdio.printf("closure: %d\n", f()) - stdio.printf("closure: %d\n", f()) - stdio.printf("closure: %d\n", f()) - - return 0 diff --git a/TransPyV/Test/App/deco_test.py b/TransPyV/Test/App/deco_test.py deleted file mode 100644 index 9af6396..0000000 --- a/TransPyV/Test/App/deco_test.py +++ /dev/null @@ -1,183 +0,0 @@ -import stdio -import t, c -import string - - -# ============================================================ -# deco_test - t/c 装饰器测试 -# -# 测试 t.CDefine / t.CExport / t.CInline / t.CExtern / t.State -# ============================================================ - - -# Test 1: t.CDefine - 常量定义 -MAX_VALUE: t.CDefine = 256 -PI_APPROX: t.CDefine = 314 -# Test 10: t.CDefine 作为 t.CArray 的 count -ARR_SIZE: t.CDefine = 8 - - -# Test 2: t.CExport - 导出函数标记 -def ExportedAdd(a: t.CInt, b: t.CInt) -> t.CInt | t.CExport: - return a + b - - -# Test 3: t.CInline - 内联函数标记 -def InlineSquare(x: t.CInt) -> t.CInt | t.CInline: - return x * x - - -# Test 4: 普通函数(无装饰器,作为对照) -def NormalSub(a: t.CInt, b: t.CInt) -> t.CInt: - return a - b - - -# Test 5: t.CExport 与 t.CInline 组合 -def ExportedInlineCube(x: t.CInt) -> t.CInt | t.CExport | t.CInline: - return x * x * x - - -# Test 6: t.CExport 返回指针 -def ExportedFindChar(s: str, ch: t.CInt) -> str | t.CExport: - return string.strchr(s, ch) - - -def test_cdefine(): - stdio.printf("--- Test 1: t.CDefine ---\n") - stdio.printf("MAX_VALUE=%d (expect 256)\n", MAX_VALUE) - stdio.printf("PI_APPROX=%d (expect 314)\n", PI_APPROX) - if MAX_VALUE == 256: - stdio.printf("MAX_VALUE OK\n") - else: - stdio.printf("MAX_VALUE FAIL\n") - if PI_APPROX == 314: - stdio.printf("PI_APPROX OK\n") - else: - stdio.printf("PI_APPROX FAIL\n") - - -def test_cexport(): - stdio.printf("--- Test 2: t.CExport ---\n") - r: t.CInt = ExportedAdd(3, 4) - stdio.printf("ExportedAdd(3,4)=%d (expect 7)\n", r) - if r == 7: - stdio.printf("ExportedAdd OK\n") - else: - stdio.printf("ExportedAdd FAIL\n") - - -def test_cinline(): - stdio.printf("--- Test 3: t.CInline ---\n") - r: t.CInt = InlineSquare(5) - stdio.printf("InlineSquare(5)=%d (expect 25)\n", r) - if r == 25: - stdio.printf("InlineSquare OK\n") - else: - stdio.printf("InlineSquare FAIL\n") - - -def test_deco_normal(): - stdio.printf("--- Test 4: normal function ---\n") - r: t.CInt = NormalSub(10, 3) - stdio.printf("NormalSub(10,3)=%d (expect 7)\n", r) - if r == 7: - stdio.printf("NormalSub OK\n") - else: - stdio.printf("NormalSub FAIL\n") - - -def test_export_inline(): - stdio.printf("--- Test 5: t.CExport | t.CInline ---\n") - r: t.CInt = ExportedInlineCube(3) - stdio.printf("ExportedInlineCube(3)=%d (expect 27)\n", r) - if r == 27: - stdio.printf("ExportedInlineCube OK\n") - else: - stdio.printf("ExportedInlineCube FAIL\n") - - -def test_export_ptr(): - stdio.printf("--- Test 6: t.CExport return ptr ---\n") - p: str = ExportedFindChar("Hello", 108) # 'l' = 108 - if p is not None: - stdio.printf("ExportedFindChar found, char=%d (expect 108)\n", c.Deref(p)) - if c.Deref(p) == 108: - stdio.printf("ExportedFindChar OK\n") - else: - stdio.printf("ExportedFindChar FAIL\n") - else: - stdio.printf("ExportedFindChar NOT FOUND (FAIL)\n") - - -# Test 7: t.CExtern | t.CExport - 外部声明函数(pass 体) -# 声明一个外部函数,翻译器应生成 declare 而非 define -def ExternalDecl(x: t.CInt) -> t.CInt | t.CExtern | t.CExport: pass - - -# Test 8: t.State - 状态声明(等价于 CExtern | CExport) -def StateDecl(x: t.CInt) -> t.CInt | t.State: pass - - -# Test 9: t.State 返回 void -def StateVoidDecl() -> t.State: pass - - -def test_extern_decl(): - stdio.printf("--- Test 7: t.CExtern | t.CExport ---\n") - # 外部声明函数,不调用(应由链接器解析符号) - stdio.printf("ExternalDecl declared (not called)\n") - stdio.printf("ExternalDecl OK\n") - - -def test_state_decl(): - stdio.printf("--- Test 8: t.State ---\n") - stdio.printf("StateDecl declared (not called)\n") - stdio.printf("StateDecl OK\n") - - -def test_state_void_decl(): - stdio.printf("--- Test 9: t.State (void) ---\n") - stdio.printf("StateVoidDecl declared (not called)\n") - stdio.printf("StateVoidDecl OK\n") - - -# Test 10: t.CDefine 作为 t.CArray count -# ARR_SIZE: t.CDefine = 8 已在文件顶部定义 -def test_cdefine_array_count(): - stdio.printf("--- Test 10: t.CArray[elem, CDefine] ---\n") - # 使用 CDefine 常量名作为数组 count - arr: t.CArray[t.CInt, ARR_SIZE] - i: t.CInt - # 初始化: arr[i] = i * 10 - for i in range(ARR_SIZE): - arr[i] = i * 10 - # 求和验证: 0+10+20+...+70 = 280 - total: t.CInt = 0 - for i in range(ARR_SIZE): - total += arr[i] - stdio.printf("ARR_SIZE=%d (expect 8)\n", ARR_SIZE) - stdio.printf("arr sum=%d (expect 280)\n", total) - stdio.printf("arr[0]=%d (expect 0)\n", arr[0]) - stdio.printf("arr[7]=%d (expect 70)\n", arr[7]) - if ARR_SIZE == 8 and total == 280 and arr[0] == 0 and arr[7] == 70: - stdio.printf("CArray CDefine count OK\n") - else: - stdio.printf("CArray CDefine count FAIL\n") - - -def deco_test() -> int: - stdio.printf("=== deco_test: t/c 装饰器测试 ===\n\n") - - test_cdefine() - test_cexport() - test_cinline() - test_deco_normal() - test_export_inline() - test_export_ptr() - test_extern_decl() - test_state_decl() - test_state_void_decl() - test_cdefine_array_count() - - stdio.printf("\n=== deco_test 完成 ===\n") - return 0 diff --git a/TransPyV/Test/App/deref_min_test.py b/TransPyV/Test/App/deref_min_test.py deleted file mode 100644 index 9bc3210..0000000 --- a/TransPyV/Test/App/deref_min_test.py +++ /dev/null @@ -1,9 +0,0 @@ -import stdio -import t, c - - -def deref_min_test() -> int: - s: str = "hello" - v: int = c.Deref(s) - stdio.printf("deref: %d\n", v) - return 0 diff --git a/TransPyV/Test/App/deref_test.py b/TransPyV/Test/App/deref_test.py deleted file mode 100644 index b4483cc..0000000 --- a/TransPyV/Test/App/deref_test.py +++ /dev/null @@ -1,13 +0,0 @@ -import stdio -import t, c - - -def deref_test() -> int: - s: str = "hello" - sp: str = s - slen: int = 0 - while c.Deref(sp) != 0: - slen = slen + 1 - sp = sp + 1 - stdio.printf("ptr: len(hello)=%d\n", slen) - return 0 diff --git a/TransPyV/Test/App/eq_test.py b/TransPyV/Test/App/eq_test.py deleted file mode 100644 index d3c315d..0000000 --- a/TransPyV/Test/App/eq_test.py +++ /dev/null @@ -1,144 +0,0 @@ -import stdio -import t, c -import string - - -# ============================================================ -# eq_test - ==、!=、is、is not、None 比较测试 -# -# 验证比较表达式的翻译,特别是 None 常量和 is/is not 操作符 -# ============================================================ - - -def test_int_eq(): - stdio.printf("--- Test 1: int == / != ---\n") - - a: t.CInt = 42 - b: t.CInt = 42 - c3: t.CInt = 99 - - if a == b: - stdio.printf("int == int (same) OK\n") - else: - stdio.printf("int == int (same) FAIL\n") - - if a != c3: - stdio.printf("int != int (diff) OK\n") - else: - stdio.printf("int != int (diff) FAIL\n") - - if not (a == c3): - stdio.printf("not (int == diff) OK\n") - else: - stdio.printf("not (int == diff) FAIL\n") - - -def test_int_cmp(): - stdio.printf("--- Test 2: int < > <= >= ---\n") - - a: t.CInt = 5 - b: t.CInt = 10 - - if a < b: - stdio.printf("int < OK\n") - else: - stdio.printf("int < FAIL\n") - - if b > a: - stdio.printf("int > OK\n") - else: - stdio.printf("int > FAIL\n") - - if a <= 5: - stdio.printf("int <= OK\n") - else: - stdio.printf("int <= FAIL\n") - - if b >= 10: - stdio.printf("int >= OK\n") - else: - stdio.printf("int >= FAIL\n") - - -def test_ptr_is_none(): - stdio.printf("--- Test 3: ptr is None / is not None ---\n") - - # strchr 找到字符返回非空指针,找不到返回 None - p: str = string.strchr("Hello", 108) # 'l' = 108 - if p is not None: - stdio.printf("strchr found, is not None OK\n") - else: - stdio.printf("strchr found, is not None FAIL\n") - - p2: str = string.strchr("Hello", 122) # 'z' = 122, not found - if p2 is None: - stdio.printf("strchr not found, is None OK\n") - else: - stdio.printf("strchr not found, is None FAIL\n") - - -def test_ptr_assign_none(): - stdio.printf("--- Test 4: assign None and compare ---\n") - - p: str = None - if p is None: - stdio.printf("None assign, is None OK\n") - else: - stdio.printf("None assign, is None FAIL\n") - - if p is not None: - stdio.printf("None assign, is not None FAIL\n") - else: - stdio.printf("None assign, is not None OK\n") - - -def test_ptr_eq_none(): - stdio.printf("--- Test 5: ptr == None / != None ---\n") - - p: str = string.strstr("Hello World", "World") - if p != None: - stdio.printf("strstr found, != None OK\n") - else: - stdio.printf("strstr found, != None FAIL\n") - - p2: str = string.strstr("Hello", "xyz") - if p2 == None: - stdio.printf("strstr not found, == None OK\n") - else: - stdio.printf("strstr not found, == None FAIL\n") - - -def test_bool_logic(): - stdio.printf("--- Test 6: bool and/or ---\n") - - a: t.CInt = 1 - b: t.CInt = 0 - - if a and b: - stdio.printf("1 and 0 = true FAIL\n") - else: - stdio.printf("1 and 0 = false OK\n") - - if a or b: - stdio.printf("1 or 0 = true OK\n") - else: - stdio.printf("1 or 0 = true FAIL\n") - - if not b: - stdio.printf("not 0 = true OK\n") - else: - stdio.printf("not 0 = true FAIL\n") - - -def eq_test() -> int: - stdio.printf("=== eq_test: ==、!=、is、None 比较测试 ===\n\n") - - test_int_eq() - test_int_cmp() - test_ptr_is_none() - test_ptr_assign_none() - test_ptr_eq_none() - test_bool_logic() - - stdio.printf("\n=== eq_test 完成 ===\n") - return 0 diff --git a/TransPyV/Test/App/float_test.py b/TransPyV/Test/App/float_test.py deleted file mode 100644 index 100f4f0..0000000 --- a/TransPyV/Test/App/float_test.py +++ /dev/null @@ -1,84 +0,0 @@ -import stdio -import t, c - - -# ============================================================ -# 联合体(t.CUnion)含浮点字段 -# ============================================================ - -class DataUnion(t.CUnion): - i: t.CInt - f: t.CFloat - l: t.CInt64T - - -# ============================================================ -# 主函数 -# ============================================================ -def float_test() -> int: - # ============================================================ - # 测试 1: 基本浮点变量(float / double) - # ============================================================ - f: t.CFloat = 3.14 - stdio.printf("float: f=%f\n", f) - - d: t.CDouble = 3.141592653589793 - stdio.printf("double: d=%lf\n", d) - - # 重新赋值 - f = 2.5 - stdio.printf("float: f=%f\n", f) - - # ============================================================ - # 测试 2: 联合体浮点字段 - # ============================================================ - u: DataUnion - u.f = 3.14 - stdio.printf("union: u.f=%f\n", u.f) - - # 写入 i 字段后,f 的值已被覆盖 - u.i = 42 - stdio.printf("union: u.i=%d (after f overwritten)\n", u.i) - - # ============================================================ - # 测试 3: 联合体共享内存验证(float 与 int 共享) - # ============================================================ - u2: DataUnion - u2.i = 0 - u2.f = 1.0 - # 写入 f 后,i 的值应不再是 0 - if u2.i != 0: - stdio.printf("union: float overwrites int verified\n") - - # ============================================================ - # 测试 4: 浮点算术运算(fadd/fsub/fmul/fdiv/frem) - # ============================================================ - a: t.CFloat = 1.5 - b: t.CFloat = 2.5 - stdio.printf("arith: %.2f + %.2f = %.2f\n", a, b, a + b) - stdio.printf("arith: %.2f - %.2f = %.2f\n", a, b, a - b) - stdio.printf("arith: %.2f * %.2f = %.2f\n", a, b, a * b) - stdio.printf("arith: %.2f / %.2f = %.2f\n", a, b, a / b) - - # ============================================================ - # 测试 5: double 算术运算 - # ============================================================ - x: t.CDouble = 10.0 - y: t.CDouble = 3.0 - stdio.printf("arith: %.4lf + %.4lf = %.4lf\n", x, y, x + y) - stdio.printf("arith: %.4lf - %.4lf = %.4lf\n", x, y, x - y) - stdio.printf("arith: %.4lf * %.4lf = %.4lf\n", x, y, x * y) - stdio.printf("arith: %.4lf / %.4lf = %.4lf\n", x, y, x / y) - - # ============================================================ - # 测试 6: 浮点取模 (frem) - # ============================================================ - stdio.printf("arith: 10.0 %% 3.0 = %.4lf\n", x % y) - - # ============================================================ - # 测试 7: int 与 float 混合运算(int 自动转 float) - # ============================================================ - n: t.CInt = 3 - stdio.printf("arith: %d + %.2f = %.2f\n", n, a, n + a) - - return 0 diff --git a/TransPyV/Test/App/flow_test.py b/TransPyV/Test/App/flow_test.py deleted file mode 100644 index 89114ac..0000000 --- a/TransPyV/Test/App/flow_test.py +++ /dev/null @@ -1,23 +0,0 @@ -import stdio -import t, c - - -def flow_test() -> int: - i: int = 0 - total: int = 0 - while i < 5: - total = total + i - i = i + 1 - stdio.printf("while: total=%d i=%d\n", total, i) - - for k in range(10): - if k == 3: - break - stdio.printf("break: k=%d\n", k) - - for m in range(5): - if m == 2: - continue - stdio.printf("continue: m=%d\n", m) - - return 0 diff --git a/TransPyV/Test/App/for_test.py b/TransPyV/Test/App/for_test.py deleted file mode 100644 index e178457..0000000 --- a/TransPyV/Test/App/for_test.py +++ /dev/null @@ -1,8 +0,0 @@ -import stdio -import t, c - - -def for_test() -> int: - for j in range(5): - stdio.printf("for: j=%d\n", j) - return 0 diff --git a/TransPyV/Test/App/func_test.py b/TransPyV/Test/App/func_test.py deleted file mode 100644 index 21a3d4b..0000000 --- a/TransPyV/Test/App/func_test.py +++ /dev/null @@ -1,68 +0,0 @@ -import stdio -import t, c - - -def add(a: int, b: int) -> int: - return a + b - - -def mul(a: int, b: int) -> int: - return a * b - - -def square(x: int) -> int: - return mul(x, x) - - -def factorial(n: int) -> int: - if n <= 1: - return 1 - return n * factorial(n - 1) - - -def greet(greeting: str, name: str, times: int) -> int: - i: int = 0 - while i < times: - stdio.printf("%s, %s!\n", greeting, name) - i = i + 1 - return times - - -def sub(a: int, b: int) -> int: - return a - b - - -def func_test() -> int: - r1: int = add(3, 4) - stdio.printf("add(3,4)=%d\n", r1) - - r2: int = mul(5, 6) - stdio.printf("mul(5,6)=%d\n", r2) - - r3: int = square(7) - stdio.printf("square(7)=%d\n", r3) - - r5: int = factorial(5) - stdio.printf("factorial(5)=%d\n", r5) - - # ============================================================ - # 测试: 函数乱序传参(关键字参数) - # ============================================================ - # 乱序传参:b=4, a=3 等价于 add(3, 4) - r6: int = add(b=4, a=3) - stdio.printf("add(b=4,a=3)=%d\n", r6) - - # 乱序传参:a=10, b=3 等价于 sub(10, 3) - r7: int = sub(b=3, a=10) - stdio.printf("sub(b=3,a=10)=%d\n", r7) - - # 混合传参:位置参数 + 关键字参数 - # greeting="Hello" 是位置参数,name="World" 和 times=2 是关键字 - r8: int = greet("Hello", name="World", times=2) - stdio.printf("greet mixed: returned=%d\n", r8) - - # 全关键字乱序传参 - r9: int = greet(times=1, name="TransPyC", greeting="Hi") - stdio.printf("greet kwargs: returned=%d\n", r9) - - return 0 diff --git a/TransPyV/Test/App/func_vtable_test.py b/TransPyV/Test/App/func_vtable_test.py deleted file mode 100644 index 854ab7c..0000000 --- a/TransPyV/Test/App/func_vtable_test.py +++ /dev/null @@ -1,116 +0,0 @@ -import stdio -import t, c - - -# ============================================================ -# 场景 A: @t.NoVTable 类 + 函数级 @t.CVTable -# -# NoVTableClass 标记 @t.NoVTable(类级别禁用虚表) -# 但 VirtualMethod 标记 @t.CVTable → 该方法单独进入虚表 -# NormalMethod 无装饰器 → 不进入虚表 -# 预期: 虚表 1 个方法 (VirtualMethod) -# ============================================================ -@t.NoVTable -class NoVTableClass: - val: t.CInt - - def __init__(self, v: t.CInt): - self.val = v - - @t.CVTable - def VirtualMethod(self) -> t.CInt: - return self.val + 10 - - def NormalMethod(self) -> t.CInt: - return self.val + 20 - - -# ============================================================ -# 场景 B: @t.CVTable 类 + 函数级 @t.NoVTable -# -# CVTableClass 标记 @t.CVTable(所有方法进入虚表) -# KeptMethod 无装饰器 → 进入虚表 -# ExcludedMethod 标记 @t.NoVTable → 排除出虚表 -# 预期: 虚表 1 个方法 (KeptMethod) -# ============================================================ -@t.CVTable -class CVTableClass: - val: t.CInt - - def __init__(self, v: t.CInt): - self.val = v - - def KeptMethod(self) -> t.CInt: - return self.val + 30 - - @t.NoVTable - def ExcludedMethod(self) -> t.CInt: - return self.val + 40 - - -# ============================================================ -# 场景 C: 默认类(无装饰器无继承)+ 函数级 @t.CVTable -# -# DefaultClass 无装饰器(默认无虚表) -# VirtualMethod 标记 @t.CVTable → 单独进入虚表 -# NormalMethod 无装饰器 → 不进入虚表 -# 预期: 虚表 1 个方法 (VirtualMethod) -# ============================================================ -class DefaultClass: - val: t.CInt - - def __init__(self, v: t.CInt): - self.val = v - - @t.CVTable - def VirtualMethod(self) -> t.CInt: - return self.val + 50 - - def NormalMethod(self) -> t.CInt: - return self.val + 60 - - -def func_vtable_test() -> int: - stdio.printf("funcvt: === Test Start ===\n") - - # 场景 A: NoVTableClass - nvt: NoVTableClass = NoVTableClass(5) - a1: int = nvt.VirtualMethod() - stdio.printf("funcvt: A.VirtualMethod()=%d (expected 15)\n", a1) - if a1 != 15: - stdio.printf("[FAIL] A.VirtualMethod()=%d expected 15\n", a1) - return 1 - a2: int = nvt.NormalMethod() - stdio.printf("funcvt: A.NormalMethod()=%d (expected 25)\n", a2) - if a2 != 25: - stdio.printf("[FAIL] A.NormalMethod()=%d expected 25\n", a2) - return 1 - - # 场景 B: CVTableClass - cvt: CVTableClass = CVTableClass(7) - b1: int = cvt.KeptMethod() - stdio.printf("funcvt: B.KeptMethod()=%d (expected 37)\n", b1) - if b1 != 37: - stdio.printf("[FAIL] B.KeptMethod()=%d expected 37\n", b1) - return 1 - b2: int = cvt.ExcludedMethod() - stdio.printf("funcvt: B.ExcludedMethod()=%d (expected 47)\n", b2) - if b2 != 47: - stdio.printf("[FAIL] B.ExcludedMethod()=%d expected 47\n", b2) - return 1 - - # 场景 C: DefaultClass - dfc: DefaultClass = DefaultClass(9) - c1: int = dfc.VirtualMethod() - stdio.printf("funcvt: C.VirtualMethod()=%d (expected 59)\n", c1) - if c1 != 59: - stdio.printf("[FAIL] C.VirtualMethod()=%d expected 59\n", c1) - return 1 - c2: int = dfc.NormalMethod() - stdio.printf("funcvt: C.NormalMethod()=%d (expected 69)\n", c2) - if c2 != 69: - stdio.printf("[FAIL] C.NormalMethod()=%d expected 69\n", c2) - return 1 - - stdio.printf("funcvt: === All Tests Passed ===\n") - return 0 diff --git a/TransPyV/Test/App/inherit_test.py b/TransPyV/Test/App/inherit_test.py deleted file mode 100644 index 52bc20e..0000000 --- a/TransPyV/Test/App/inherit_test.py +++ /dev/null @@ -1,121 +0,0 @@ -import stdio -import t, c - - -# ============================================================ -# 继承测试:字段展平 + vtable 继承 + 方法覆盖 -# ============================================================ - - -# ============================================================ -# 基类 Animal(有虚方法) -# ============================================================ -@t.CVTable -class Animal: - name: t.CInt - - def __init__(self, n: t.CInt): - self.name = n - - def GetName(self) -> t.CInt: - return self.name - - def Speak(self) -> t.CInt: - return 0 - - -# ============================================================ -# 子类 Dog(继承 Animal,覆盖 Speak,新增字段和方法) -# ============================================================ -class Dog(Animal): - breed: t.CInt - - def __init__(self, n: t.CInt, b: t.CInt): - self.name = n - self.breed = b - - def Speak(self) -> t.CInt: - return 1 - - def GetBreed(self) -> t.CInt: - return self.breed - - -# ============================================================ -# 子类 Cat(继承 Animal,不覆盖 Speak,新增字段和方法) -# ============================================================ -class Cat(Animal): - color: t.CInt - - def __init__(self, n: t.CInt, col: t.CInt): - self.name = n - self.color = col - - def GetColor(self) -> t.CInt: - return self.color - - -# ============================================================ -# 主函数 -# ============================================================ -def inherit_test() -> int: - # ============================================================ - # 测试 1: 基类 Animal - # ============================================================ - stdio.printf("inherit: === Test 1: Base Class ===\n") - a: Animal = Animal(42) - aname: int = a.GetName() - stdio.printf("inherit: a.GetName()=%d (expected 42)\n", aname) - if aname != 42: - stdio.printf("[FAIL] a.GetName()=%d expected 42\n", aname) - return 1 - aspeak: int = a.Speak() - stdio.printf("inherit: a.Speak()=%d (expected 0)\n", aspeak) - if aspeak != 0: - stdio.printf("[FAIL] a.Speak()=%d expected 0\n", aspeak) - return 1 - - # ============================================================ - # 测试 2: 子类 Dog(覆盖 Speak,继承 GetName) - # ============================================================ - stdio.printf("inherit: === Test 2: Dog (override Speak) ===\n") - d: Dog = Dog(100, 7) - dname: int = d.GetName() - stdio.printf("inherit: d.GetName()=%d (expected 100)\n", dname) - if dname != 100: - stdio.printf("[FAIL] d.GetName()=%d expected 100\n", dname) - return 1 - dspeak: int = d.Speak() - stdio.printf("inherit: d.Speak()=%d (expected 1)\n", dspeak) - if dspeak != 1: - stdio.printf("[FAIL] d.Speak()=%d expected 1\n", dspeak) - return 1 - dbreed: int = d.GetBreed() - stdio.printf("inherit: d.GetBreed()=%d (expected 7)\n", dbreed) - if dbreed != 7: - stdio.printf("[FAIL] d.GetBreed()=%d expected 7\n", dbreed) - return 1 - - # ============================================================ - # 测试 3: 子类 Cat(不覆盖 Speak,继承 GetName) - # ============================================================ - stdio.printf("inherit: === Test 3: Cat (inherit Speak) ===\n") - ct: Cat = Cat(200, 3) - cname: int = ct.GetName() - stdio.printf("inherit: ct.GetName()=%d (expected 200)\n", cname) - if cname != 200: - stdio.printf("[FAIL] ct.GetName()=%d expected 200\n", cname) - return 1 - cspeak: int = ct.Speak() - stdio.printf("inherit: ct.Speak()=%d (expected 0)\n", cspeak) - if cspeak != 0: - stdio.printf("[FAIL] ct.Speak()=%d expected 0\n", cspeak) - return 1 - ccolor: int = ct.GetColor() - stdio.printf("inherit: ct.GetColor()=%d (expected 3)\n", ccolor) - if ccolor != 3: - stdio.printf("[FAIL] ct.GetColor()=%d expected 3\n", ccolor) - return 1 - - stdio.printf("inherit: === All Tests Passed ===\n") - return 0 diff --git a/TransPyV/Test/App/llvmir_test.py b/TransPyV/Test/App/llvmir_test.py deleted file mode 100644 index c7e44a7..0000000 --- a/TransPyV/Test/App/llvmir_test.py +++ /dev/null @@ -1,247 +0,0 @@ -import t, c -from stdint import * -import stdio - - -# ============================================================ -# c.LLVMIR / c.LInp / c.LOut 内联 LLVM IR 测试 -# -# 测试 c.LLVMIR 内联 LLVM IR 指令的生成和执行 -# - c.LInp(expr) 标记输入操作数 -# - c.LOut(expr) 标记输出操作数 -# ============================================================ - - -# Test 1: 基本加法 add -def test_add() -> t.CInt: - stdio.printf("--- Test 1: LLVMIR add ---\n") - a: t.CInt = 10 - b: t.CInt = 20 - r: t.CInt = c.LLVMIR(f"add i32 {c.LInp(a)}, {c.LInp(b)}", t.CInt) - stdio.printf("add(10, 20)=%d (expect 30)\n", r) - if r == 30: - stdio.printf("LLVMIR add OK\n") - else: - stdio.printf("LLVMIR add FAIL\n") - return 0 - - -# Test 2: 基本减法 sub -def test_sub() -> t.CInt: - stdio.printf("--- Test 2: LLVMIR sub ---\n") - a: t.CInt = 50 - b: t.CInt = 20 - r: t.CInt = c.LLVMIR(f"sub i32 {c.LInp(a)}, {c.LInp(b)}", t.CInt) - stdio.printf("sub(50, 20)=%d (expect 30)\n", r) - if r == 30: - stdio.printf("LLVMIR sub OK\n") - else: - stdio.printf("LLVMIR sub FAIL\n") - return 0 - - -# Test 3: 基本乘法 mul -def test_mul() -> t.CInt: - stdio.printf("--- Test 3: LLVMIR mul ---\n") - a: t.CInt = 6 - b: t.CInt = 7 - r: t.CInt = c.LLVMIR(f"mul i32 {c.LInp(a)}, {c.LInp(b)}", t.CInt) - stdio.printf("mul(6, 7)=%d (expect 42)\n", r) - if r == 42: - stdio.printf("LLVMIR mul OK\n") - else: - stdio.printf("LLVMIR mul FAIL\n") - return 0 - - -# Test 4: 基本除法 sdiv -def test_sdiv() -> t.CInt: - stdio.printf("--- Test 4: LLVMIR sdiv ---\n") - a: t.CInt = 100 - b: t.CInt = 4 - r: t.CInt = c.LLVMIR(f"sdiv i32 {c.LInp(a)}, {c.LInp(b)}", t.CInt) - stdio.printf("sdiv(100, 4)=%d (expect 25)\n", r) - if r == 25: - stdio.printf("LLVMIR sdiv OK\n") - else: - stdio.printf("LLVMIR sdiv FAIL\n") - return 0 - - -# Test 5: 位运算 and -def test_and() -> t.CInt: - stdio.printf("--- Test 5: LLVMIR and ---\n") - a: t.CInt = 255 - b: t.CInt = 15 - r: t.CInt = c.LLVMIR(f"and i32 {c.LInp(a)}, {c.LInp(b)}", t.CInt) - stdio.printf("and(255, 15)=%d (expect 15)\n", r) - if r == 15: - stdio.printf("LLVMIR and OK\n") - else: - stdio.printf("LLVMIR and FAIL\n") - return 0 - - -# Test 6: 位运算 or -def test_or() -> t.CInt: - stdio.printf("--- Test 6: LLVMIR or ---\n") - a: t.CInt = 240 - b: t.CInt = 15 - r: t.CInt = c.LLVMIR(f"or i32 {c.LInp(a)}, {c.LInp(b)}", t.CInt) - stdio.printf("or(240, 15)=%d (expect 255)\n", r) - if r == 255: - stdio.printf("LLVMIR or OK\n") - else: - stdio.printf("LLVMIR or FAIL\n") - return 0 - - -# Test 7: 位运算 xor -def test_xor() -> t.CInt: - stdio.printf("--- Test 7: LLVMIR xor ---\n") - a: t.CInt = 255 - b: t.CInt = 15 - r: t.CInt = c.LLVMIR(f"xor i32 {c.LInp(a)}, {c.LInp(b)}", t.CInt) - stdio.printf("xor(255, 15)=%d (expect 240)\n", r) - if r == 240: - stdio.printf("LLVMIR xor OK\n") - else: - stdio.printf("LLVMIR xor FAIL\n") - return 0 - - -# Test 8: 左移 shl -def test_shl() -> t.CInt: - stdio.printf("--- Test 8: LLVMIR shl ---\n") - a: t.CInt = 1 - b: t.CInt = 4 - r: t.CInt = c.LLVMIR(f"shl i32 {c.LInp(a)}, {c.LInp(b)}", t.CInt) - stdio.printf("shl(1, 4)=%d (expect 16)\n", r) - if r == 16: - stdio.printf("LLVMIR shl OK\n") - else: - stdio.printf("LLVMIR shl FAIL\n") - return 0 - - -# Test 9: LOut 输出赋值 -def test_lout() -> t.CInt: - stdio.printf("--- Test 9: LLVMIR LOut ---\n") - a: t.CInt = 10 - b: t.CInt = 20 - out_val: t.CInt = 0 - c.LLVMIR(f"{c.LOut(out_val)} = add i32 {c.LInp(a)}, {c.LInp(b)}", t.CInt) - stdio.printf("LOut add(10, 20)=%d (expect 30)\n", out_val) - if out_val == 30: - stdio.printf("LLVMIR LOut OK\n") - else: - stdio.printf("LLVMIR LOut FAIL\n") - return 0 - - -# Test 10: icmp eq 比较 -# 注意: TransPyV 用 sext i1 to i32 扩展布尔结果,true -> -1 -def test_icmp_eq() -> t.CInt: - stdio.printf("--- Test 10: LLVMIR icmp eq ---\n") - a: t.CInt = 5 - b: t.CInt = 5 - r: t.CInt = c.LLVMIR(f"icmp eq i32 {c.LInp(a)}, {c.LInp(b)}", t.CInt) - stdio.printf("icmp eq(5, 5)=%d (expect nonzero)\n", r) - if r != 0: - stdio.printf("LLVMIR icmp eq OK\n") - else: - stdio.printf("LLVMIR icmp eq FAIL\n") - return 0 - - -# Test 11: icmp ne 比较 -def test_icmp_ne() -> t.CInt: - stdio.printf("--- Test 11: LLVMIR icmp ne ---\n") - a: t.CInt = 5 - b: t.CInt = 3 - r: t.CInt = c.LLVMIR(f"icmp ne i32 {c.LInp(a)}, {c.LInp(b)}", t.CInt) - stdio.printf("icmp ne(5, 3)=%d (expect nonzero)\n", r) - if r != 0: - stdio.printf("LLVMIR icmp ne OK\n") - else: - stdio.printf("LLVMIR icmp ne FAIL\n") - return 0 - - -# Test 12: icmp slt 比较 -def test_icmp_slt() -> t.CInt: - stdio.printf("--- Test 12: LLVMIR icmp slt ---\n") - a: t.CInt = 3 - b: t.CInt = 5 - r: t.CInt = c.LLVMIR(f"icmp slt i32 {c.LInp(a)}, {c.LInp(b)}", t.CInt) - stdio.printf("icmp slt(3, 5)=%d (expect nonzero)\n", r) - if r != 0: - stdio.printf("LLVMIR icmp slt OK\n") - else: - stdio.printf("LLVMIR icmp slt FAIL\n") - return 0 - - -# Test 13: srem 取余 -def test_srem() -> t.CInt: - stdio.printf("--- Test 13: LLVMIR srem ---\n") - a: t.CInt = 17 - b: t.CInt = 5 - r: t.CInt = c.LLVMIR(f"srem i32 {c.LInp(a)}, {c.LInp(b)}", t.CInt) - stdio.printf("srem(17, 5)=%d (expect 2)\n", r) - if r == 2: - stdio.printf("LLVMIR srem OK\n") - else: - stdio.printf("LLVMIR srem FAIL\n") - return 0 - - -# Test 14: lshr 逻辑右移 -def test_lshr() -> t.CInt: - stdio.printf("--- Test 14: LLVMIR lshr ---\n") - a: t.CInt = 256 - b: t.CInt = 2 - r: t.CInt = c.LLVMIR(f"lshr i32 {c.LInp(a)}, {c.LInp(b)}", t.CInt) - stdio.printf("lshr(256, 2)=%d (expect 64)\n", r) - if r == 64: - stdio.printf("LLVMIR lshr OK\n") - else: - stdio.printf("LLVMIR lshr FAIL\n") - return 0 - - -# Test 15: 嵌套在表达式中使用 -def test_nested() -> t.CInt: - stdio.printf("--- Test 15: LLVMIR nested in expression ---\n") - a: t.CInt = 10 - b: t.CInt = 20 - # c.LLVMIR 结果参与后续运算 - llvmir_result: t.CInt = c.LLVMIR(f"add i32 {c.LInp(a)}, {c.LInp(b)}", t.CInt) - final_result: t.CInt = llvmir_result + 10 - stdio.printf("(LLVMIR add(10,20)) + 10 = %d (expect 40)\n", final_result) - if final_result == 40: - stdio.printf("LLVMIR nested OK\n") - else: - stdio.printf("LLVMIR nested FAIL\n") - return 0 - - -def llvmir_test() -> t.CInt: - stdio.printf("=== llvmir_test: c.LLVMIR 内联 LLVM IR 测试 ===\n\n") - test_add() - test_sub() - test_mul() - test_sdiv() - test_and() - test_or() - test_xor() - test_shl() - test_lout() - test_icmp_eq() - test_icmp_ne() - test_icmp_slt() - test_srem() - test_lshr() - test_nested() - stdio.printf("\n=== llvmir_test 完成 ===\n") - return 0 diff --git a/TransPyV/Test/App/namespace_defs.py b/TransPyV/Test/App/namespace_defs.py deleted file mode 100644 index 24e8e63..0000000 --- a/TransPyV/Test/App/namespace_defs.py +++ /dev/null @@ -1,60 +0,0 @@ -import stdio -import t, c - - -# ============================================================ -# 命名空间隔离测试:定义类模块 -# -# 本文件定义供其他文件 import 使用的类,验证跨模块命名空间隔离: -# - 裸名 Class(): 需要 from namespace_defs import Class -# - 模块限定 namespace_defs.Class(): 需要 import namespace_defs -# ============================================================ - - -# ============================================================ -# 带虚表的类 Widget -# ============================================================ -@t.CVTable -class Widget: - id: t.CInt - - def __init__(self, i: t.CInt): - self.id = i - - def GetId(self) -> t.CInt: - return self.id - - def Render(self) -> t.CInt: - return 100 - - -# ============================================================ -# 子类 Gadget(继承 Widget,覆盖 Render) -# ============================================================ -class Gadget(Widget): - extra: t.CInt - - def __init__(self, i: t.CInt, e: t.CInt): - self.id = i - self.extra = e - - def Render(self) -> t.CInt: - return 200 - - def GetExtra(self) -> t.CInt: - return self.extra - - -# ============================================================ -# 普通结构体 PlainStruct(无虚表) -# ============================================================ -class PlainStruct: - x: t.CInt - y: t.CInt - - def __init__(self, ax: t.CInt, ay: t.CInt): - self.x = ax - self.y = ay - - def Sum(self) -> t.CInt: - return self.x + self.y diff --git a/TransPyV/Test/App/namespace_test.py b/TransPyV/Test/App/namespace_test.py deleted file mode 100644 index 396a901..0000000 --- a/TransPyV/Test/App/namespace_test.py +++ /dev/null @@ -1,111 +0,0 @@ -import stdio -import t, c -import namespace_defs -from namespace_defs import Widget, Gadget, PlainStruct - - -# ============================================================ -# 命名空间隔离测试 -# -# 验证跨模块类访问必须通过 import: -# - Test 1: from X import Class → 裸名 Class() 构造 -# - Test 2: import X → 模块限定 X.Class() 构造 -# - Test 3: 类型注解使用导入的类 -# - Test 4: 继承类的虚分派(跨模块继承) -# ============================================================ - - -def namespace_test() -> int: - stdio.printf("nsisol: === Test Start ===\n") - - # ============================================================ - # Test 1: from X import Class → 裸名 Class() 构造 - # ============================================================ - stdio.printf("nsisol: === Test 1: from-import bare constructor ===\n") - - w: Widget = Widget(42) - wid: int = w.GetId() - stdio.printf("nsisol: w.GetId()=%d (expected 42)\n", wid) - if wid != 42: - stdio.printf("[FAIL] w.GetId()=%d expected 42\n", wid) - return 1 - - wrender: int = w.Render() - stdio.printf("nsisol: w.Render()=%d (expected 100)\n", wrender) - if wrender != 100: - stdio.printf("[FAIL] w.Render()=%d expected 100\n", wrender) - return 1 - - g: Gadget = Gadget(7, 9) - grender: int = g.Render() - stdio.printf("nsisol: g.Render()=%d (expected 200)\n", grender) - if grender != 200: - stdio.printf("[FAIL] g.Render()=%d expected 200\n", grender) - return 1 - - gextra: int = g.GetExtra() - stdio.printf("nsisol: g.GetExtra()=%d (expected 9)\n", gextra) - if gextra != 9: - stdio.printf("[FAIL] g.GetExtra()=%d expected 9\n", gextra) - return 1 - - # ============================================================ - # Test 2: import X → 模块限定 X.Class() 构造 - # ============================================================ - stdio.printf("nsisol: === Test 2: module-qualified constructor ===\n") - - ps: PlainStruct = PlainStruct(10, 20) - psum: int = ps.Sum() - stdio.printf("nsisol: ps.Sum()=%d (expected 30)\n", psum) - if psum != 30: - stdio.printf("[FAIL] ps.Sum()=%d expected 30\n", psum) - return 1 - - ps2: namespace_defs.PlainStruct = namespace_defs.PlainStruct(5, 6) - psum2: int = ps2.Sum() - stdio.printf("nsisol: ps2.Sum()=%d (expected 11)\n", psum2) - if psum2 != 11: - stdio.printf("[FAIL] ps2.Sum()=%d expected 11\n", psum2) - return 1 - - # ============================================================ - # Test 3: 类型注解使用导入的类 - # ============================================================ - stdio.printf("nsisol: === Test 3: type annotation with imported class ===\n") - - annot_w: Widget = Widget(99) - annot_id: int = annot_w.GetId() - stdio.printf("nsisol: annot_w.GetId()=%d (expected 99)\n", annot_id) - if annot_id != 99: - stdio.printf("[FAIL] annot_w.GetId()=%d expected 99\n", annot_id) - return 1 - - # ============================================================ - # Test 4: 跨模块继承的虚分派 - # ============================================================ - stdio.printf("nsisol: === Test 4: cross-module inheritance vtable ===\n") - - # Gadget 继承 Widget,覆盖 Render - # Widget.Render()=100, Gadget.Render()=200 - base: Widget = Widget(1) - derived: Gadget = Gadget(2, 3) - base_r: int = base.Render() - deriv_r: int = derived.Render() - stdio.printf("nsisol: base.Render()=%d (expected 100)\n", base_r) - if base_r != 100: - stdio.printf("[FAIL] base.Render()=%d expected 100\n", base_r) - return 1 - stdio.printf("nsisol: derived.Render()=%d (expected 200)\n", deriv_r) - if deriv_r != 200: - stdio.printf("[FAIL] derived.Render()=%d expected 200\n", deriv_r) - return 1 - - # 继承的方法:Gadget 继承 Widget.GetId - gname: int = derived.GetId() - stdio.printf("nsisol: derived.GetId()=%d (expected 2)\n", gname) - if gname != 2: - stdio.printf("[FAIL] derived.GetId()=%d expected 2\n", gname) - return 1 - - stdio.printf("nsisol: === All Tests Passed ===\n") - return 0 diff --git a/TransPyV/Test/App/new_test.py b/TransPyV/Test/App/new_test.py deleted file mode 100644 index 1cb9600..0000000 --- a/TransPyV/Test/App/new_test.py +++ /dev/null @@ -1,119 +0,0 @@ -import stdio -import t, c - - -# ============================================================ -# __new__ 函数测试:验证 __new__ 在创建 OOP 结构体前被调用, -# 返回的指针作为结构体存储空间。 -# -# __new__ 签名默认和 __init__ 一样(self + args),返回 Ptr(struct_ty)。 -# 如果 __new__ 返回 self,则使用默认 alloca 作为存储空间。 -# ============================================================ - - -# ============================================================ -# Test 1: __new__ 返回 self(默认 alloca) -# 验证 __new__ 被调用且不破坏 __init__ 正常功能 -# ============================================================ -class WithNew: - value: t.CInt - - def __new__(self, v: t.CInt): - stdio.printf("new: WithNew.__new__ called\n") - return self - - def __init__(self, v: t.CInt): - stdio.printf("new: WithNew.__init__ called\n") - self.value = v - - def GetValue(self) -> t.CInt: - return self.value - - -# ============================================================ -# Test 2: __new__ 不接受额外参数(仅 self) -# 验证 __new__ 签名可以与 __init__ 不同 -# ============================================================ -class WithNewNoArgs: - value: t.CInt - - def __new__(self): - stdio.printf("new: WithNewNoArgs.__new__ called\n") - return self - - def __init__(self, v: t.CInt): - self.value = v - - def GetValue(self) -> t.CInt: - return self.value - - -# ============================================================ -# Test 3: __new__ + @t.CVTable 虚表类 -# 验证 __new__ 与虚表机制兼容(__new__ 不进入虚表) -# ============================================================ -@t.CVTable -class WithNewVTable: - value: t.CInt - - def __new__(self, v: t.CInt): - stdio.printf("new: WithNewVTable.__new__ called\n") - return self - - def __init__(self, v: t.CInt): - self.value = v - - def GetValue(self) -> t.CInt: - return self.value - - def Speak(self) -> t.CInt: - return self.value + 1 - - -def new_test() -> int: - stdio.printf("new: === Test Start ===\n") - - # ============================================================ - # Test 1: __new__ 返回 self - # ============================================================ - stdio.printf("new: === Test 1: __new__ returns self ===\n") - - w: WithNew = WithNew(42) - v: int = w.GetValue() - stdio.printf("new: w.GetValue()=%d (expected 42)\n", v) - if v != 42: - stdio.printf("[FAIL] w.GetValue()=%d expected 42\n", v) - return 1 - - # ============================================================ - # Test 2: __new__ 不接受额外参数 - # ============================================================ - stdio.printf("new: === Test 2: __new__ no extra args ===\n") - - n: WithNewNoArgs = WithNewNoArgs(99) - nv: int = n.GetValue() - stdio.printf("new: n.GetValue()=%d (expected 99)\n", nv) - if nv != 99: - stdio.printf("[FAIL] n.GetValue()=%d expected 99\n", nv) - return 1 - - # ============================================================ - # Test 3: __new__ + 虚表类 - # ============================================================ - stdio.printf("new: === Test 3: __new__ + vtable ===\n") - - vt: WithNewVTable = WithNewVTable(10) - vtv: int = vt.GetValue() - stdio.printf("new: vt.GetValue()=%d (expected 10)\n", vtv) - if vtv != 10: - stdio.printf("[FAIL] vt.GetValue()=%d expected 10\n", vtv) - return 1 - - vts: int = vt.Speak() - stdio.printf("new: vt.Speak()=%d (expected 11)\n", vts) - if vts != 11: - stdio.printf("[FAIL] vt.Speak()=%d expected 11\n", vts) - return 1 - - stdio.printf("new: === All Tests Passed ===\n") - return 0 diff --git a/TransPyV/Test/App/oop_test.py b/TransPyV/Test/App/oop_test.py deleted file mode 100644 index ebf66dd..0000000 --- a/TransPyV/Test/App/oop_test.py +++ /dev/null @@ -1,129 +0,0 @@ -import stdio -import t, c - - -# ============================================================ -# OOP 测试:存在方法的 class 自动升级为 OOP 结构体 -# ============================================================ - -# ============================================================ -# 测试 1: 基本方法(无 __init__,__before_init__ 零值填充) -# ============================================================ -class Point: - x: t.CInt - y: t.CInt - - def MoveTo(self, nx: t.CInt, ny: t.CInt) -> t.CInt: - self.x = nx - self.y = ny - return 0 - - def GetX(self) -> t.CInt: - return self.x - - def GetY(self) -> t.CInt: - return self.y - - -# ============================================================ -# 测试 2: 带默认值的 OOP 结构体(__before_init__ 应用默认值) -# ============================================================ -class Counter: - count: t.CInt = 0 - step: t.CInt = 1 - - def Increment(self) -> t.CInt: - self.count = self.count + self.step - return self.count - - def Reset(self) -> t.CInt: - self.count = 0 - return 0 - - -# ============================================================ -# 测试 3: __init__ 构造函数 -# ============================================================ -class Rect: - width: t.CInt - height: t.CInt - - def __init__(self, w: t.CInt, h: t.CInt): - self.width = w - self.height = h - - def Area(self) -> t.CInt: - return self.width * self.height - - -# ============================================================ -# 主函数 -# ============================================================ -def oop_test() -> int: - # ============================================================ - # 测试 1: 基本方法调用 - # ============================================================ - stdio.printf("oop: === Test 1: Basic Methods ===\n") - p: Point = Point() - p.MoveTo(10, 20) - stdio.printf("oop: p.x=%d p.y=%d\n", p.GetX(), p.GetY()) - - if p.GetX() != 10: - stdio.printf("[FAIL] p.GetX()=%d expected 10\n", p.GetX()) - return 1 - if p.GetY() != 20: - stdio.printf("[FAIL] p.GetY()=%d expected 20\n", p.GetY()) - return 1 - - # 修改字段后再次调用方法 - p.MoveTo(100, 200) - stdio.printf("oop: after move p.x=%d p.y=%d\n", p.GetX(), p.GetY()) - if p.GetX() != 100: - return 1 - - # ============================================================ - # 测试 2: 默认值 + 方法 - # ============================================================ - stdio.printf("oop: === Test 2: Defaults + Methods ===\n") - cnt: Counter = Counter() - stdio.printf("oop: initial count=%d step=%d\n", cnt.count, cnt.step) - if cnt.count != 0: - stdio.printf("[FAIL] cnt.count=%d expected 0\n", cnt.count) - return 1 - if cnt.step != 1: - stdio.printf("[FAIL] cnt.step=%d expected 1\n", cnt.step) - return 1 - - r1: int = cnt.Increment() - r2: int = cnt.Increment() - r3: int = cnt.Increment() - stdio.printf("oop: after 3 increments: %d %d %d\n", r1, r2, r3) - if r1 != 1 or r2 != 2 or r3 != 3: - stdio.printf("[FAIL] increments: %d %d %d\n", r1, r2, r3) - return 1 - - cnt.Reset() - r4: int = cnt.Increment() - stdio.printf("oop: after reset+increment: %d\n", r4) - if r4 != 1: - return 1 - - # ============================================================ - # 测试 3: __init__ 构造函数 - # ============================================================ - stdio.printf("oop: === Test 3: __init__ ===\n") - rect: Rect = Rect(3, 4) - area: int = rect.Area() - stdio.printf("oop: rect %dx%d area=%d\n", rect.width, rect.height, area) - if area != 12: - stdio.printf("[FAIL] area=%d expected 12\n", area) - return 1 - if rect.width != 3: - stdio.printf("[FAIL] width=%d expected 3\n", rect.width) - return 1 - if rect.height != 4: - stdio.printf("[FAIL] height=%d expected 4\n", rect.height) - return 1 - - stdio.printf("oop: === All OOP Tests Passed ===\n") - return 0 diff --git a/TransPyV/Test/App/opovl_test.py b/TransPyV/Test/App/opovl_test.py deleted file mode 100644 index 3a68afc..0000000 --- a/TransPyV/Test/App/opovl_test.py +++ /dev/null @@ -1,253 +0,0 @@ -import stdio -import stdlib -import t, c -import testcheck - - -# ============================================================ -# 运算符重载测试 -# -# 验证: 当 lhs 是结构体指针时,二元/比较运算触发 dunder 方法调用 -# 支持: __add__/__sub__/__mul__/__div__/__mod__/__and__/__or__/__xor__ -# __lshift__/__rshift__/__floordiv__ (BinOp) -# __eq__/__ne__/__lt__/__le__/__gt__/__ge__ (Compare) -# -# 三种测试场景: -# 1. Counter/BitBox: dunder 返回 t.CInt(值类型变量触发重载) -# 2. Vec2: dunder 返回 Vec2|t.CPtr(堆分配结构体,指针类型变量触发重载) -# 3. 原生整数运算回退 -# ============================================================ - - -# ============================================================ -# Counter: 演示 __add__/__mul__/__sub__ + 比较重载 -# dunder 返回 t.CInt -# ============================================================ -class Counter: - val: t.CInt - - def __init__(self, v: t.CInt): - self.val = v - - def __add__(self, n: t.CInt) -> t.CInt: - return self.val + n - - def __sub__(self, n: t.CInt) -> t.CInt: - return self.val - n - - def __mul__(self, n: t.CInt) -> t.CInt: - return self.val * n - - def __div__(self, n: t.CInt) -> t.CInt: - return self.val / n - - def __mod__(self, n: t.CInt) -> t.CInt: - return self.val % n - - def __eq__(self, n: t.CInt) -> t.CInt: - if self.val == n: - return 1 - return 0 - - def __ne__(self, n: t.CInt) -> t.CInt: - if self.val != n: - return 1 - return 0 - - def __lt__(self, n: t.CInt) -> t.CInt: - if self.val < n: - return 1 - return 0 - - def __le__(self, n: t.CInt) -> t.CInt: - if self.val <= n: - return 1 - return 0 - - def __gt__(self, n: t.CInt) -> t.CInt: - if self.val > n: - return 1 - return 0 - - def __ge__(self, n: t.CInt) -> t.CInt: - if self.val >= n: - return 1 - return 0 - - -# ============================================================ -# BitBox: 演示位运算重载 -# dunder 返回 t.CInt -# ============================================================ -class BitBox: - flags: t.CInt - - def __init__(self, v: t.CInt): - self.flags = v - - def __and__(self, mask: t.CInt) -> t.CInt: - return self.flags & mask - - def __or__(self, mask: t.CInt) -> t.CInt: - return self.flags | mask - - def __xor__(self, mask: t.CInt) -> t.CInt: - return self.flags ^ mask - - def __lshift__(self, n: t.CInt) -> t.CInt: - return self.flags << n - - def __rshift__(self, n: t.CInt) -> t.CInt: - return self.flags >> n - - -# ============================================================ -# Vec2: 演示结构体运算重载 -# -# __new__ + stdlib.malloc 在堆上分配内存,使 Vec2|t.CPtr 变量 -# 能正确工作(dunder 方法返回堆上新对象)。 -# -# __new__ 返回 malloc 的堆指针作为结构体存储空间, -# 后续 __init__ 在堆指针上初始化字段。 -# ============================================================ -class Vec2: - x: t.CInt - y: t.CInt - - def __new__(self, x0: t.CInt, y0: t.CInt): - r: Vec2 | t.CPtr = stdlib.malloc(Vec2.__sizeof__()) - return r - - def __init__(self, x0: t.CInt, y0: t.CInt): - self.x = x0 - self.y = y0 - - def __add__(self, other: Vec2 | t.CPtr) -> Vec2 | t.CPtr: - r: Vec2 | t.CPtr = Vec2(0, 0) - r.x = self.x + other.x - r.y = self.y + other.y - return r - - def __sub__(self, other: Vec2 | t.CPtr) -> Vec2 | t.CPtr: - r: Vec2 | t.CPtr = Vec2(0, 0) - r.x = self.x - other.x - r.y = self.y - other.y - return r - - def __eq__(self, other: Vec2 | t.CPtr) -> t.CInt: - if self.x == other.x: - if self.y == other.y: - return 1 - return 0 - - def __ne__(self, other: Vec2 | t.CPtr) -> t.CInt: - if self.x != other.x: - return 1 - if self.y != other.y: - return 1 - return 0 - - -# ============================================================ -# 主测试入口 -# ============================================================ -def opovl_test() -> int: - testcheck.begin("Operator Overload Tests") - - # ============================================================ - # 测试 1: Counter + int 触发 __add__ - # ============================================================ - testcheck.section("Counter __add__") - cnt: Counter = Counter(10) - sum_val: int = cnt + 5 - testcheck.check(sum_val == 15, "cnt(10)+5=15", "cnt+5 expected 15 got ??") - - # ============================================================ - # 测试 2: Counter - int / * int / / int / % int - # ============================================================ - testcheck.section("Counter __sub__/__mul__/__div__/__mod__") - sub_val: int = cnt - 3 - mul_val: int = cnt * 3 - div_val: int = cnt / 3 - mod_val: int = cnt % 3 - testcheck.check(sub_val == 7, "cnt-3=7", "cnt-3 expected 7") - testcheck.check(mul_val == 30, "cnt*3=30", "cnt*3 expected 30") - testcheck.check(div_val == 3, "cnt/3=3", "cnt/3 expected 3") - testcheck.check(mod_val == 1, "cnt%3=1", "cnt%3 expected 1") - - # ============================================================ - # 测试 3: Counter 比较重载 (==, !=, <, <=, >, >=) - # ============================================================ - testcheck.section("Counter compare overloads") - eq_10: int = cnt == 10 - ne_10: int = cnt != 10 - lt_20: int = cnt < 20 - le_10: int = cnt <= 10 - gt_5: int = cnt > 5 - ge_10: int = cnt >= 10 - testcheck.check(eq_10 == 1, "cnt==10:1", "cnt==10 expected 1") - testcheck.check(ne_10 == 0, "cnt!=10:0", "cnt!=10 expected 0") - testcheck.check(lt_20 == 1, "cnt<20:1", "cnt<20 expected 1") - testcheck.check(le_10 == 1, "cnt<=10:1", "cnt<=10 expected 1") - testcheck.check(gt_5 == 1, "cnt>5:1", "cnt>5 expected 1") - testcheck.check(ge_10 == 1, "cnt>=10:1", "cnt>=10 expected 1") - - # ============================================================ - # 测试 4: BitBox 位运算重载 - # ============================================================ - testcheck.section("BitBox bitwise overloads") - bb: BitBox = BitBox(0xFF) - and_val: int = bb & 0x0F - or_val: int = bb | 0x100 - xor_val: int = bb ^ 0x55 - lsh_val: int = bb << 4 - rsh_val: int = bb >> 4 - testcheck.check(and_val == 0x0F, "bb&0x0F=15", "bb&0x0F expected 15") - testcheck.check(or_val == 0x1FF, "bb|0x100=511", "bb|0x100 expected 511") - testcheck.check(xor_val == 0xAA, "bb^0x55=170", "bb^0x55 expected 170") - testcheck.check(lsh_val == 0xFF0, "bb<<4=4080", "bb<<4 expected 4080") - testcheck.check(rsh_val == 0x0F, "bb>>4=15", "bb>>4 expected 15") - - # ============================================================ - # 测试 5: 原生整数运算不受影响(回退路径) - # ============================================================ - testcheck.section("Native int binop") - x: int = 7 + 8 - y: int = 10 - 3 - z: int = 4 * 5 - testcheck.check(x == 15, "7+8=15", "7+8 expected 15") - testcheck.check(y == 7, "10-3=7", "10-3 expected 7") - testcheck.check(z == 20, "4*5=20", "4*5 expected 20") - - # ============================================================ - # 测试 6: 原生整数比较不受影响 - # ============================================================ - testcheck.section("Native int compare") - testcheck.check(3 < 5, "3<5", "3<5 broken") - testcheck.check(10 == 10, "10==10", "10==10 broken") - - # ============================================================ - # 测试 7: Vec2 结构体运算重载 - # ============================================================ - testcheck.section("Vec2 struct overloads") - a: Vec2 | t.CPtr = Vec2(3, 4) - b: Vec2 | t.CPtr = Vec2(1, 2) - c: Vec2 | t.CPtr = a + b - d: Vec2 | t.CPtr = a - b - testcheck.check(c.x == 4, "a+b x=4", "a+b x expected 4") - testcheck.check(c.y == 6, "a+b y=6", "a+b y expected 6") - testcheck.check(d.x == 2, "a-b x=2", "a-b x expected 2") - testcheck.check(d.y == 2, "a-b y=2", "a-b y expected 2") - - # ============================================================ - # 测试 8: Vec2 比较重载 - # ============================================================ - testcheck.section("Vec2 compare overloads") - p: Vec2 | t.CPtr = Vec2(5, 5) - q: Vec2 | t.CPtr = Vec2(5, 5) - eq_v: int = p == q - ne_v: int = p != q - testcheck.check(eq_v == 1, "(5,5)==(5,5):1", "p==q expected 1") - testcheck.check(ne_v == 0, "(5,5)!=(5,5):0", "p!=q expected 0") - - return testcheck.end() diff --git a/TransPyV/Test/App/ptr_only_test.py b/TransPyV/Test/App/ptr_only_test.py deleted file mode 100644 index 5050881..0000000 --- a/TransPyV/Test/App/ptr_only_test.py +++ /dev/null @@ -1,26 +0,0 @@ -import stdio -import t, c - - -def ptr_only_test() -> int: - s: str = "hello" - sp: str = s - slen: int = 0 - while c.Deref(sp) != 0: - slen = slen + 1 - sp = sp + 1 - stdio.printf("ptr: len(hello)=%d\n", slen) - - x: int = 65 - px: str = c.Addr(x) - c.DerefAs(px, 88) - stdio.printf("ptr: after DerefAs x=%d\n", x) - - p2: str = "ABC" - total_ch: int = 0 - while c.Deref(p2) != 0: - total_ch = total_ch + c.Deref(p2) - p2 = p2 + 1 - stdio.printf("ptr: sum(A,B,C)=%d\n", total_ch) - - return 0 diff --git a/TransPyV/Test/App/ptr_test.py b/TransPyV/Test/App/ptr_test.py deleted file mode 100644 index cf6fb02..0000000 --- a/TransPyV/Test/App/ptr_test.py +++ /dev/null @@ -1,111 +0,0 @@ -import stdio -import t, c - - -# ============================================================ -# 简单指针 + 逻辑测试 -# ============================================================ - -def ptr_test() -> int: - # 逻辑测试:if 语句 - x: int = 10 - if x: - stdio.printf("if: x is truthy\n") - - if 1 == 1: - stdio.printf("if: 1==1 is truthy\n") - - # While 循环 + 累加 - i: int = 0 - total: int = 0 - while i < 5: - total = total + i - i = i + 1 - stdio.printf("while: total=%d i=%d\n", total, i) - - # For 循环 - for j in range(5): - stdio.printf("for: j=%d\n", j) - - # Break 测试 - for k in range(10): - if k == 3: - break - stdio.printf("break: k=%d\n", k) - - # Continue 测试 - for m in range(5): - if m == 2: - continue - stdio.printf("continue: m=%d\n", m) - - # 布尔运算 and(短路求值) - if x > 5 and x < 100: - stdio.printf("bool: x>5 and x<100 is true\n") - - # 布尔运算 or(短路求值) - if x > 100 or x > 5: - stdio.printf("bool: x>100 or x>5 is true\n") - - # ============================================================ - # 指针 + c.Deref / c.DerefAs 测试 - # ============================================================ - - # 字符串遍历: while c.Deref(p) != 0 - s: str = "hello" - sp: str = s - slen: int = 0 - while c.Deref(sp) != 0: - slen = slen + 1 - sp = sp + 1 - stdio.printf("ptr: len(hello)=%d\n", slen) - - # c.DerefAs 写入字符(使用 c.Addr 获取栈变量地址,字符串字面量是只读的) - v: int = 65 # 'A' - px: str = c.Addr(v) - c.DerefAs(px, 88) # *px = 88 - stdio.printf("ptr: after DerefAs v=%d\n", v) - - # 遍历字符串并累加字符值 - p2: str = "ABC" - total_ch: int = 0 - while c.Deref(p2) != 0: - total_ch = total_ch + c.Deref(p2) - p2 = p2 + 1 - stdio.printf("ptr: sum(A,B,C)=%d\n", total_ch) - - # ============================================================ - # c.Load 测试: *a = *b(加载源指针的值,存储到目标指针) - # ============================================================ - - # 基本复制: v2 = v1 - v1: int = 42 - v2: int = 0 - c.Load(c.Addr(v2), c.Addr(v1)) - stdio.printf("ptr: c.Load v2=%d (expected 42)\n", v2) - if v2 != 42: - stdio.printf("[FAIL] c.Load expected 42 got %d\n", v2) - return 1 - - # 覆盖已有值: v3 = v4 - v3: int = 100 - v4: int = 200 - c.Load(c.Addr(v3), c.Addr(v4)) - stdio.printf("ptr: c.Load overwrite v3=%d (expected 200)\n", v3) - if v3 != 200: - stdio.printf("[FAIL] c.Load overwrite expected 200 got %d\n", v3) - return 1 - - # 验证源不被修改: v5 保持原值 - v5: int = 999 - v6: int = 0 - c.Load(c.Addr(v6), c.Addr(v5)) - stdio.printf("ptr: c.Load src unchanged v5=%d v6=%d (expected 999, 999)\n", v5, v6) - if v5 != 999: - stdio.printf("[FAIL] c.Load src changed v5=%d\n", v5) - return 1 - if v6 != 999: - stdio.printf("[FAIL] c.Load dst expected 999 got %d\n", v6) - return 1 - - return 0 diff --git a/TransPyV/Test/App/simple_test.py b/TransPyV/Test/App/simple_test.py deleted file mode 100644 index bc5c64e..0000000 --- a/TransPyV/Test/App/simple_test.py +++ /dev/null @@ -1,6 +0,0 @@ -import stdio - -def simple_test() -> int: - stdio.printf("hello\n") - return 0 - diff --git a/TransPyV/Test/App/string_min_test.py b/TransPyV/Test/App/string_min_test.py deleted file mode 100644 index 5be13ea..0000000 --- a/TransPyV/Test/App/string_min_test.py +++ /dev/null @@ -1,9 +0,0 @@ -import stdio -import t, c -import string - - -def string_min_test() -> int: - l: t.CSizeT = string.strlen("Hello") - stdio.printf("strlen(Hello)=%lu\n", l) - return 0 diff --git a/TransPyV/Test/App/string_test.py b/TransPyV/Test/App/string_test.py deleted file mode 100644 index 3880db4..0000000 --- a/TransPyV/Test/App/string_test.py +++ /dev/null @@ -1,106 +0,0 @@ -import stdio -import t, c -import string - - -# ============================================================ -# string_test - string.py 库函数测试 -# -# 测试 strlen / strcmp / strncmp / atoi / strchr / strstr -# ============================================================ - - -def test_strlen(): - stdio.printf("--- Test 1: strlen ---\n") - - l1: t.CSizeT = string.strlen("Hello") - stdio.printf("strlen(Hello)=%lu (expect 5)\n", l1) - - l2: t.CSizeT = string.strlen("") - stdio.printf("strlen()=%lu (expect 0)\n", l2) - - l3: t.CSizeT = string.strlen("Hello, World!") - stdio.printf("strlen(Hello, World!)=%lu (expect 13)\n", l3) - - -def test_strcmp(): - stdio.printf("--- Test 2: strcmp ---\n") - - r1: t.CInt = string.strcmp("abc", "abc") - stdio.printf("strcmp(abc,abc)=%d (expect 0)\n", r1) - - r2: t.CInt = string.strcmp("abc", "abd") - stdio.printf("strcmp(abc,abd)=%d (expect <0)\n", r2) - - r3: t.CInt = string.strcmp("abd", "abc") - stdio.printf("strcmp(abd,abc)=%d (expect >0)\n", r3) - - -def test_strncmp(): - stdio.printf("--- Test 3: strncmp ---\n") - - r1: t.CInt = string.strncmp("abcdef", "abcXYZ", 3) - stdio.printf("strncmp(abcdef,abcXYZ,3)=%d (expect 0)\n", r1) - - r2: t.CInt = string.strncmp("abcdef", "abcXYZ", 4) - stdio.printf("strncmp(abcdef,abcXYZ,4)=%d (expect <0)\n", r2) - - -def test_atoi(): - stdio.printf("--- Test 4: atoi ---\n") - - n1: t.CInt = string.atoi("123") - stdio.printf("atoi(123)=%d (expect 123)\n", n1) - - n2: t.CInt = string.atoi("-456") - stdio.printf("atoi(-456)=%d (expect -456)\n", n2) - - n3: t.CInt = string.atoi(" 789") - stdio.printf("atoi( 789)=%d (expect 789)\n", n3) - - -def test_strchr(): - stdio.printf("--- Test 5: strchr ---\n") - - # strchr 返回指向字符的指针,不为 None 表示找到 - p: str = string.strchr("Hello", 108) # 'l' = 108 - if p is not None: - stdio.printf("strchr(Hello,'l') found, char=%d (expect 108)\n", c.Deref(p)) - else: - stdio.printf("strchr(Hello,'l') NOT FOUND (FAIL)\n") - - p2: str = string.strchr("Hello", 122) # 'z' = 122 - if p2 is None: - stdio.printf("strchr(Hello,'z') not found OK\n") - else: - stdio.printf("strchr(Hello,'z') FAIL (should be None)\n") - - -def test_strstr(): - stdio.printf("--- Test 6: strstr ---\n") - - p: str = string.strstr("Hello World", "World") - if p is not None: - stdio.printf("strstr(Hello,World) found OK\n") - else: - stdio.printf("strstr(Hello,World) NOT FOUND (FAIL)\n") - - p2: str = string.strstr("Hello World", "xyz") - if p2 is None: - stdio.printf("strstr(Hello,xyz) not found OK\n") - else: - stdio.printf("strstr(Hello,xyz) FAIL (should be None)\n") - - -def string_test() -> int: - stdio.printf("=== string_test: string.py 库函数测试 ===\n\n") - - test_strlen() - test_strcmp() - test_strncmp() - test_atoi() - test_strchr() - test_strstr() - - stdio.printf("\n=== string_test 完成 ===\n") - return 0 diff --git a/TransPyV/Test/App/struct_test.py b/TransPyV/Test/App/struct_test.py deleted file mode 100644 index 2b883e0..0000000 --- a/TransPyV/Test/App/struct_test.py +++ /dev/null @@ -1,235 +0,0 @@ -import stdio -import t, c - - -# ============================================================ -# 纯内存结构体(class)测试 -# ============================================================ - -class Point: - x: t.CInt - y: t.CInt - - -class Box: - width: t.CInt - height: t.CInt - depth: t.CInt - - -class Size: - w: t.CInt = 100 - h: t.CInt = 200 - - -# ============================================================ -# 枚举(t.CEnum)测试 -# ============================================================ - -class State(t.CEnum): - Idle: t.State - Run: t.State - Stop: t.State - - -class Color(t.CEnum): - Red: t.State = 10 - Green: t.State - Blue: t.State = 20 - Yellow: t.State - - -class MixedType(t.CEnum): - Small: t.CInt8T - Big: t.CInt64T - Medium: t.CInt16T - - -# ============================================================ -# 联合体(t.CUnion)测试 -# ============================================================ - -class DataUnion(t.CUnion): - i: t.CInt - f: t.CFloat - l: t.CInt64T - - -# ============================================================ -# 主函数 -# ============================================================ -def struct_test() -> int: - # ============================================================ - # 测试 1: 结构体字段读写 - # ============================================================ - p: Point = Point() - p.x = 10 - p.y = 20 - stdio.printf("struct: p.x=%d p.y=%d\n", p.x, p.y) - - # 修改字段 - p.x = 100 - p.y = 200 - stdio.printf("struct: modified p.x=%d p.y=%d\n", p.x, p.y) - - # 字段运算 - sum_xy: int = p.x + p.y - stdio.printf("struct: sum=%d\n", sum_xy) - - # ============================================================ - # 测试 2: 多字段结构体 - # ============================================================ - b: Box - b.width = 3 - b.height = 4 - b.depth = 5 - vol: int = b.width * b.height * b.depth - stdio.printf("struct: volume=%d\n", vol) - - # ============================================================ - # 测试 3: t.CArray 数组遍历 - # ============================================================ - arr: t.CArray[t.CInt, 5] - arr[0] = 100 - arr[1] = 200 - arr[2] = 300 - arr[3] = 400 - arr[4] = 500 - - arr_total: int = 0 - for i in range(5): - arr_total = arr_total + arr[i] - stdio.printf("array: total=%d\n", arr_total) - - # 修改数组元素 - arr[2] = 999 - stdio.printf("array: arr[2]=%d\n", arr[2]) - - # ============================================================ - # 测试 4: 指针遍历(字符串) - # ============================================================ - s: str = "hello" - sp: str = s - slen: int = 0 - while c.Deref(sp) != 0: - slen = slen + 1 - sp = sp + 1 - stdio.printf("ptr: len(hello)=%d\n", slen) - - # 累加字符值 - p2: str = "ABC" - total_ch: int = 0 - while c.Deref(p2) != 0: - total_ch = total_ch + c.Deref(p2) - p2 = p2 + 1 - stdio.printf("ptr: sum(A,B,C)=%d\n", total_ch) - - # ============================================================ - # 测试 5: 结构体构造函数 Point() / Point(x, y) - # ============================================================ - # 无参数构造:零初始化 - z: Point = Point() - stdio.printf("ctor: z.x=%d z.y=%d\n", z.x, z.y) - - # 带参数构造:按位置赋值 - p3: Point = Point(7, 8) - stdio.printf("ctor: p3.x=%d p3.y=%d\n", p3.x, p3.y) - - # 多字段构造 - bx: Box = Box(10, 20, 30) - stdio.printf("ctor: bx.w=%d bx.h=%d bx.d=%d\n", bx.width, bx.height, bx.depth) - - # ============================================================ - # 测试 6: 结构体关键字参数(乱序传参) - # ============================================================ - # 全关键字乱序 - p4: Point = Point(y=20, x=10) - stdio.printf("kw: p4.x=%d p4.y=%d\n", p4.x, p4.y) - - # 混合:位置 + 关键字 - p5: Point = Point(5, y=15) - stdio.printf("kw: p5.x=%d p5.y=%d\n", p5.x, p5.y) - - # 多字段关键字乱序 - bx2: Box = Box(depth=30, width=10, height=20) - stdio.printf("kw: bx2.w=%d bx2.h=%d bx2.d=%d\n", bx2.width, bx2.height, bx2.depth) - - # ============================================================ - # 测试 7: 结构体默认赋值 - # ============================================================ - # 无参数构造:使用默认值 - sz: Size = Size() - stdio.printf("def: sz.w=%d sz.h=%d\n", sz.w, sz.h) - - # 位置参数覆盖默认值 - sz2: Size = Size(5, 6) - stdio.printf("def: sz2.w=%d sz2.h=%d\n", sz2.w, sz2.h) - - # 关键字参数覆盖默认值(乱序) - sz3: Size = Size(h=999, w=888) - stdio.printf("def: sz3.w=%d sz3.h=%d\n", sz3.w, sz3.h) - - # 混合:位置参数 + 默认值(w=7 覆盖默认值,h 保持默认值 200) - sz4: Size = Size(7) - stdio.printf("def: sz4.w=%d sz4.h=%d\n", sz4.w, sz4.h) - - # ============================================================ - # 测试 8: 枚举自动赋值(Idle=0, Run=1, Stop=2) - # ============================================================ - s_idle: int = State.Idle - s_run: int = State.Run - s_stop: int = State.Stop - stdio.printf("enum: Idle=%d Run=%d Stop=%d\n", s_idle, s_run, s_stop) - - # ============================================================ - # 测试 9: 枚举手动赋值(Red=10, Green=11, Blue=20, Yellow=21) - # ============================================================ - c_red: int = Color.Red - c_green: int = Color.Green - c_blue: int = Color.Blue - c_yellow: int = Color.Yellow - stdio.printf("enum: Red=%d Green=%d Blue=%d Yellow=%d\n", - c_red, c_green, c_blue, c_yellow) - - # ============================================================ - # 测试 10: 枚举混用数字类型(基准类型应为 i64) - # ============================================================ - m_small: int = MixedType.Small - m_big: int = MixedType.Big - m_medium: int = MixedType.Medium - stdio.printf("enum: Small=%d Big=%d Medium=%d\n", m_small, m_big, m_medium) - - # 枚举参与运算 - s_sum: int = State.Idle + State.Run + State.Stop - stdio.printf("enum: sum(Idle,Run,Stop)=%d\n", s_sum) - - # 枚举比较 - if State.Idle == 0: - stdio.printf("enum: Idle==0 true\n") - if Color.Red == 10: - stdio.printf("enum: Red==10 true\n") - if State.Run != State.Stop: - stdio.printf("enum: Run!=Stop true\n") - - # ============================================================ - # 测试 11: 联合体字段读写 - # ============================================================ - u: DataUnion - u.i = 42 - stdio.printf("union: u.i=%d\n", u.i) - - # 写入 l 字段(覆盖 i 的内存,因为 l 是 i64) - u.l = 20015998343868 - stdio.printf("union: u.l=%lld\n", u.l) - - # ============================================================ - # 测试 12: 联合体共享内存验证 - # ============================================================ - u2: DataUnion - u2.i = 1 - # 写入 l 后,i 的值已被覆盖(不再是 1) - u2.l = 100 - if u2.i != 1: - stdio.printf("union: shared memory verified\n") - - return 0 diff --git a/TransPyV/Test/App/test_main.py b/TransPyV/Test/App/test_main.py deleted file mode 100644 index 9608995..0000000 --- a/TransPyV/Test/App/test_main.py +++ /dev/null @@ -1,113 +0,0 @@ -import stdio -import t, c -import testcheck -from stdint import * -from asm_test import asm_test -from attr_test import attr_test -from augassign_test import augassign_test -from closure_test import closure_test -from deco_test import deco_test -from deref_min_test import deref_min_test -from deref_test import deref_test -from eq_test import eq_test -from float_test import float_test -from flow_test import flow_test -from for_test import for_test -from func_test import func_test -from llvmir_test import llvmir_test -from oop_test import oop_test -from ptr_only_test import ptr_only_test -from ptr_test import ptr_test -from simple_test import simple_test -from string_min_test import string_min_test -from string_test import string_test -from struct_test import struct_test -from type_bit_test import type_bit_test -from vtable_test import vtable_test -from inherit_test import inherit_test -from func_vtable_test import func_vtable_test -from virtual_dispatch_test import virtual_dispatch_test -from new_test import new_test -from namespace_test import namespace_test -from testcheck_test import testcheck_test -from opovl_test import opovl_test -from circ_test import circ_test -# from generic_test import generic_test # 屏蔽泛型模块(GenericTest 运行时崩溃,待修复) - - -def main() -> int: - stdio.printf("===== TransPyV Test Suite =====\n\n") - - r: int = 0 - - stdio.fflush(None) - r = asm_test() - stdio.fflush(None) - r = attr_test() - stdio.fflush(None) - r = augassign_test() - stdio.fflush(None) - r = closure_test() - stdio.fflush(None) - r = deco_test() - stdio.fflush(None) - r = deref_min_test() - stdio.fflush(None) - r = deref_test() - stdio.fflush(None) - r = eq_test() - stdio.fflush(None) - r = float_test() - stdio.fflush(None) - r = flow_test() - stdio.fflush(None) - r = for_test() - stdio.fflush(None) - r = func_test() - stdio.fflush(None) - r = llvmir_test() - stdio.fflush(None) - r = oop_test() - stdio.fflush(None) - r = ptr_only_test() - stdio.fflush(None) - r = ptr_test() - stdio.fflush(None) - r = simple_test() - stdio.fflush(None) - r = string_min_test() - stdio.fflush(None) - r = string_test() - stdio.fflush(None) - r = struct_test() - stdio.fflush(None) - r = type_bit_test() - stdio.fflush(None) - r = vtable_test() - stdio.fflush(None) - r = inherit_test() - stdio.fflush(None) - r = func_vtable_test() - stdio.fflush(None) - r = virtual_dispatch_test() - stdio.fflush(None) - r = new_test() - stdio.fflush(None) - r = namespace_test() - stdio.fflush(None) - r = testcheck_test() - stdio.fflush(None) - r = opovl_test() - stdio.fflush(None) - r = circ_test() - stdio.fflush(None) - - # 屏蔽泛型模块(GenericTest 运行时崩溃,待修复) - # stdio.printf("[TM] before generic_test\n") - # stdio.fflush(None) - # r = generic_test() - # stdio.printf("[TM] after generic_test r=%d\n", r) - # stdio.fflush(None) - - stdio.printf("\n===== Test Suite Complete =====\n") - return r \ No newline at end of file diff --git a/TransPyV/Test/App/testcheck_test.py b/TransPyV/Test/App/testcheck_test.py deleted file mode 100644 index 2540bdb..0000000 --- a/TransPyV/Test/App/testcheck_test.py +++ /dev/null @@ -1,37 +0,0 @@ -import stdio -import t, c -import string -import testcheck - - -# ============================================================ -# testcheck_test - 测试 includes/testcheck 库导入与调用 -# -# 验证命名空间隔离下,import testcheck + 模块限定函数调用能正常工作。 -# 同时测试 string 库的模块限定调用。 -# ============================================================ -def testcheck_test() -> int: - testcheck.begin("testcheck_test") - - testcheck.section("Arithmetic") - a: int = 3 + 4 - testcheck.check(a == 7, "3+4=7", "3+4!=7") - - b: int = 10 - 3 - testcheck.check(b == 7, "10-3=7", "10-3!=7") - - m: int = 6 * 7 - testcheck.check(m == 42, "6*7=42", "6*7!=42") - - testcheck.section("String") - slen: int = string.strlen("hello") - testcheck.check(slen == 5, "strlen(hello)=5", "strlen(hello)!=5") - - scmp: int = string.strcmp("abc", "abc") - testcheck.check(scmp == 0, "strcmp(abc,abc)=0", "strcmp(abc,abc)!=0") - - testcheck.section("Module Import") - testcheck.info("testcheck module imported and called successfully") - testcheck.ok("import testcheck works") - - return testcheck.end() diff --git a/TransPyV/Test/App/type_bit_test.py b/TransPyV/Test/App/type_bit_test.py deleted file mode 100644 index 817020f..0000000 --- a/TransPyV/Test/App/type_bit_test.py +++ /dev/null @@ -1,26 +0,0 @@ -import stdio -import t, c - - -def type_bit_test() -> int: - ti: t.CInt = 100 - ti32: t.CInt32T = 200 - tui32: t.CUInt32T = 300 - stdio.printf("type: CInt=%d CInt32T=%d CUInt32T=%d\n", ti, ti32, tui32) - - tl: t.CLong = 1000 - tll: t.CLongLong = 2000 - ti64: t.CInt64T = 3000 - tsize: t.CSizeT = 4000 - stdio.printf("type: CLong=%d CLongLong=%d CInt64T=%d CSizeT=%d\n", tl, tll, ti64, tsize) - - ba: int = 240 - bb: int = 15 - stdio.printf("bit: 240&15=%d\n", ba & bb) - stdio.printf("bit: 240|15=%d\n", ba | bb) - stdio.printf("bit: 240^15=%d\n", ba ^ bb) - stdio.printf("bit: 240<<2=%d\n", ba << 2) - stdio.printf("bit: 240>>2=%d\n", ba >> 2) - stdio.printf("bit: 17%%5=%d\n", 17 % 5) - - return 0 diff --git a/TransPyV/Test/App/virtual_dispatch_test.py b/TransPyV/Test/App/virtual_dispatch_test.py deleted file mode 100644 index d3ca34b..0000000 --- a/TransPyV/Test/App/virtual_dispatch_test.py +++ /dev/null @@ -1,83 +0,0 @@ -import stdio -import t, c -import string -from inherit_test import Animal, Dog - - -# ============================================================ -# 虚分派测试:通过虚表指针验证虚分派机制 -# -# 本测试验证:方法调用通过对象的 __vtable__ 字段进行虚分派, -# 而非通过变量声明类型直接调用。 -# -# 测试方法: -# 1. 创建 Animal 对象 a(Animal 虚表,Speak 返回 0) -# 2. 创建 Dog 对象 d -# 3. 用内联汇编将 d 的虚表指针复制到 a -# 4. 调用 a.Speak() — 应返回 1(Dog.Speak),证明虚分派生效 -# -# 如果是直接调用(非虚分派),a.Speak() 会调用 Animal.Speak 返回 0 -# -# 注意:Animal 和 Dog 类从 inherit_test.py 导入(命名空间隔离) -# ============================================================ - - -def virtual_dispatch_test() -> int: - stdio.printf("vdispatch: === Test Start ===\n") - - # 创建对象 - a: Animal = Animal(42) - d: Dog = Dog(100, 7) - - # ============================================================ - # 测试 1: 直接分派(基线验证) - # ============================================================ - stdio.printf("vdispatch: === Test 1: Direct Dispatch ===\n") - - a_speak: int = a.Speak() - stdio.printf("vdispatch: a.Speak()=%d (expected 0)\n", a_speak) - if a_speak != 0: - stdio.printf("[FAIL] a.Speak()=%d expected 0\n", a_speak) - return 1 - - d_speak: int = d.Speak() - stdio.printf("vdispatch: d.Speak()=%d (expected 1)\n", d_speak) - if d_speak != 1: - stdio.printf("[FAIL] d.Speak()=%d expected 1\n", d_speak) - return 1 - - # ============================================================ - # 测试 2: 虚分派验证(复制虚表指针) - # - # 将 Dog 的虚表指针复制到 Animal 对象 a - # 虚表指针位于结构体偏移 0(__vtable__ 字段) - # 复制后 a.Speak() 应通过虚表分发到 Dog.Speak(返回 1) - # ============================================================ - stdio.printf("vdispatch: === Test 2: Virtual Dispatch ===\n") - - # 使用 string.memcpy 复制虚表指针(8字节,结构体偏移0) - # 将 d 的虚表指针复制到 a,使 a.Speak() 分发到 Dog.Speak - string.memcpy(c.Addr(a), c.Addr(d), 8) - - a_speak2: int = a.Speak() - stdio.printf("vdispatch: a.Speak()=%d (expected 1 after vtable copy)\n", a_speak2) - if a_speak2 != 1: - stdio.printf("[FAIL] a.Speak()=%d expected 1 after vtable copy\n", a_speak2) - return 1 - - # ============================================================ - # 测试 3: GetName 验证(未被覆盖的虚方法) - # - # Dog 没有覆盖 GetName,Dog 虚表中 GetName 槽位指向 Animal.GetName - # a.GetName() 应返回 a.name (42),证明虚表槽位一致性 - # ============================================================ - stdio.printf("vdispatch: === Test 3: GetName After VTable Copy ===\n") - - a_name: int = a.GetName() - stdio.printf("vdispatch: a.GetName()=%d (expected 42)\n", a_name) - if a_name != 42: - stdio.printf("[FAIL] a.GetName()=%d expected 42\n", a_name) - return 1 - - stdio.printf("vdispatch: === All Tests Passed ===\n") - return 0 diff --git a/TransPyV/Test/App/vtable_test.py b/TransPyV/Test/App/vtable_test.py deleted file mode 100644 index 0964412..0000000 --- a/TransPyV/Test/App/vtable_test.py +++ /dev/null @@ -1,63 +0,0 @@ -import stdio -import t, c - - -@t.CVTable -class Animal: - name: t.CInt - - def __init__(self, n: t.CInt): - self.name = n - - def GetName(self) -> t.CInt: - return self.name - - def Speak(self) -> t.CInt: - return 0 - - -@t.CVTable -class Shape: - sides: t.CInt - - def SetSides(self, n: t.CInt) -> t.CInt: - self.sides = n - return 0 - - def GetSides(self) -> t.CInt: - return self.sides - - -def vtable_test() -> int: - stdio.printf("vtable: === Test Start ===\n") - - # 测试 1: Animal 虚方法调用(无参,访问 self 字段) - a: Animal = Animal(42) - name: int = a.GetName() - stdio.printf("vtable: a.GetName()=%d (expected 42)\n", name) - if name != 42: - stdio.printf("[FAIL] a.GetName()=%d expected 42\n", name) - return 1 - - speak: int = a.Speak() - stdio.printf("vtable: a.Speak()=%d (expected 0)\n", speak) - if speak != 0: - stdio.printf("[FAIL] a.Speak()=%d expected 0\n", speak) - return 1 - - # 测试 2: Shape 虚方法调用(带参,修改 self 字段) - s: Shape = Shape() - r: int = s.SetSides(4) - stdio.printf("vtable: s.SetSides(4)=%d (expected 0)\n", r) - if r != 0: - stdio.printf("[FAIL] s.SetSides(4)=%d expected 0\n", r) - return 1 - - sides: int = s.GetSides() - stdio.printf("vtable: s.GetSides()=%d (expected 4)\n", sides) - if sides != 4: - stdio.printf("[FAIL] s.GetSides()=%d expected 4\n", sides) - return 1 - - stdio.printf("vtable: === All Tests Passed ===\n") - return 0 diff --git a/TransPyV/Test/NegativeTest/App/defs.py b/TransPyV/Test/NegativeTest/App/defs.py deleted file mode 100644 index a6b825e..0000000 --- a/TransPyV/Test/NegativeTest/App/defs.py +++ /dev/null @@ -1,20 +0,0 @@ -import stdio -import t, c - - -# ============================================================ -# 负向测试定义模块:定义 SecretClass -# -# 此文件定义 SecretClass,但 main.py 不 import 它。 -# 严格模式下 main.py 中的 SecretClass() 构造应编译失败。 -# ============================================================ - - -class SecretClass: - val: t.CInt - - def __init__(self, v: t.CInt): - self.val = v - - def GetVal(self) -> t.CInt: - return self.val diff --git a/TransPyV/Test/NegativeTest/App/main.py b/TransPyV/Test/NegativeTest/App/main.py deleted file mode 100644 index dc9a2ba..0000000 --- a/TransPyV/Test/NegativeTest/App/main.py +++ /dev/null @@ -1,21 +0,0 @@ -import stdio -import t, c -# 故意不 import defs.SecretClass — 严格模式下应编译失败 - - -# ============================================================ -# 负向测试主入口 -# -# 此文件故意不 import SecretClass,但尝试使用 SecretClass()。 -# 命名空间隔离严格模式下,SecretClass 不可见, -# 构造器路径被跳过,生成 call i32 @SecretClass(...), -# llc 报错 "use of undefined value '@SecretClass'"。 -# -# 预期:TransPyV 编译失败(exit code != 0) -# ============================================================ -def main() -> int: - # SecretClass 未导入,严格模式下不可见 - s: SecretClass = SecretClass(42) - v: int = s.GetVal() - stdio.printf("negtest: v=%d (should not reach here)\n", v) - return 0 diff --git a/TransPyV/Test/Sha1Test/App/main.py b/TransPyV/Test/Sha1Test/App/main.py deleted file mode 100644 index c7e4533..0000000 --- a/TransPyV/Test/Sha1Test/App/main.py +++ /dev/null @@ -1,62 +0,0 @@ -import t, c -from stdint import * -import stdio -import stdlib -import memhub -import hashlib - - -POOL_SIZE: t.CDefine = 16777480 - - -@t.CExport -def main() -> int: - arena: bytes = stdlib.malloc(POOL_SIZE) - if arena is None: - return 1 - mb: memhub.MemBuddy | t.CPtr = memhub.MemBuddy(arena, POOL_SIZE) - if mb is None: - return 1 - hashlib._mbuddy = (memhub.MemManager | t.CPtr)(mb) - - # 测试 "abc" 的 SHA1 - # 期望: a9993e364706816aba3e25717850c26c9cd0d89d - s: str = "abc" - stdio.printf("input: %s\n", s) - - # 计算 len(s) - n: t.CSizeT = len(s) - stdio.printf("len=%d\n", n) - - # 构造 sha1 对象 - ctx: hashlib.sha1 | t.CPtr = hashlib.sha1() - if ctx is None: - stdio.printf("ctx is None\n") - return 1 - - ctx.update(s) - - digest: bytes = mb.alloc(hashlib.SHA1_DIGEST_LEN) - if digest is None: - stdio.printf("digest alloc failed\n") - return 1 - - ctx.final(digest) - - # 打印 digest(十六进制) - stdio.printf("SHA1: ") - for i in range(hashlib.SHA1_DIGEST_LEN): - b: t.CUInt8T = digest[i] - hi: t.CInt = (b >> 4) & 0xF - lo: t.CInt = b & 0xF - if hi < 10: - stdio.printf("%c", '0' + hi) - else: - stdio.printf("%c", 'a' + (hi - 10)) - if lo < 10: - stdio.printf("%c", '0' + lo) - else: - stdio.printf("%c", 'a' + (lo - 10)) - stdio.printf("\n") - stdio.printf("expect: a9993e364706816aba3e25717850c26c9cd0d89d\n") - return 0 diff --git a/TransPyV/output/51f0144d6e8188d9.deps.json b/TransPyV/output/51f0144d6e8188d9.deps.json deleted file mode 100644 index ea6b2e1..0000000 --- a/TransPyV/output/51f0144d6e8188d9.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "06f53cc594b4ac6c", "win32sync": "06f53cc594b4ac6c", "sys": "0c67644125bea0fd", "hashlib.__sha1": "0df65b8ed15664b0", "__sha1": "0df65b8ed15664b0", "lib.core.Handles.HandlesFunctions": "1073ffca7e27aae5", "HandlesFunctions": "1073ffca7e27aae5", "lib.core.Handles.HandlesAnnAssign": "15bb32adb7093ed7", "HandlesAnnAssign": "15bb32adb7093ed7", "hashlib.__md5": "19f8024d10c828e8", "__md5": "19f8024d10c828e8", "llvmlite.__init__": "1d74d1d3a174c684", "__init__": "f3444ec56937284f", "llvmlite": "1d74d1d3a174c684", "json.__writer": "20cd49775c100a38", "__writer": "20cd49775c100a38", "ast.base": "22bc0df83b3f0e62", "base": "22bc0df83b3f0e62", "json.__parser": "240a9a4157959a9f", "__parser": "240a9a4157959a9f", "lib.core.Handles.HandlesReturn": "2703a899f26b771d", "HandlesReturn": "2703a899f26b771d", "atom": "271ea3decb810db2", "stdio": "285b6aa29a34754d", "posix": "28de517e3820658a", "lib.core.Handles.HandlesAssign": "2b59175b77f1304e", "HandlesAssign": "2b59175b77f1304e", "lib.core.Phase1": "2d523679d6b886ad", "Phase1": "2d523679d6b886ad", "llvmlite.__types": "2d8debefda779c40", "__types": "2d8debefda779c40", "hashtable": "2fbec3db55b30ad4", "lib.core.Handles.HandlesAugAssign": "31e49accebfc8aac", "HandlesAugAssign": "31e49accebfc8aac", "lib.core.Handles.HandlesStruct": "371fa89e15d8c015", "HandlesStruct": "371fa89e15d8c015", "stdlib": "3aa6057398be5673", "lib.StubGen.Converter": "3c5f1c61545644a9", "Converter": "3c5f1c61545644a9", "ast.astaux": "4337fb260448bbe2", "astaux": "4337fb260448bbe2", "lib.core.Handles.HandlesFor": "456fb516ba3c5002", "HandlesFor": "456fb516ba3c5002", "lib.Projectrans.Utils": "4650533467115342", "Utils": "4650533467115342", "lib.core.Handles.HandlesMain": "4a7b57e6bd18f65e", "HandlesMain": "4a7b57e6bd18f65e", "string": "4daf5ed3f8e421a1", "ast.match": "4dd6b3f1427d1cc5", "match": "4dd6b3f1427d1cc5", "json.__init__": "57288496f7c2d1ad", "json": "57288496f7c2d1ad", "llvmlite.__builder": "5a1d8c48f1243746", "__builder": "5a1d8c48f1243746", "lib.core.Handles.HandlesExprCall": "5c482c6aac2ba83b", "HandlesExprCall": "5c482c6aac2ba83b", "lib.core.Handles.HandlesTranslator": "62805d8ad3e9b5ba", "HandlesTranslator": "62805d8ad3e9b5ba", "lib.core.IncludesScanner": "6282c9b745a35b8f", "IncludesScanner": "6282c9b745a35b8f", "lib.core.Handles.HandlesImports": "6293eee0a5805aa5", "HandlesImports": "6293eee0a5805aa5", "lib.core.Handles.HandlesBase": "63a3d17e96a083ac", "HandlesBase": "63a3d17e96a083ac", "ast.stmts": "657e182b27c2a022", "stmts": "657e182b27c2a022", "lib.core.Handles.HandlesIf": "66de93aaeebc0601", "HandlesIf": "66de93aaeebc0601", "lib.core.Handles.HandlesExpr": "68f2617198f5757f", "HandlesExpr": "68f2617198f5757f", "llvmlite.__module": "692919c5a194ac8d", "__module": "692919c5a194ac8d", "lib.__init__": "6a19179426e9a883", "lib": "6a19179426e9a883", "llvmlite.__verify": "6b3bc463fd044545", "__verify": "6b3bc463fd044545", "hashlib.__sha512": "6ff26590374ae6fc", "__sha512": "6ff26590374ae6fc", "stdarg": "71e0a3ffcb3ebfad", "w32.fileio": "72dbbb563aa943b0", "fileio": "72dbbb563aa943b0", "lib.core.Phase2": "7ba06a9edf0fa6c7", "Phase2": "7ba06a9edf0fa6c7", "_list": "7cadfe07e983fd90", "lib.core.Handles.HandlesBody": "81eb28ba912467a6", "HandlesBody": "81eb28ba912467a6", "llvmlite.__function": "874bac141c97bae9", "__function": "874bac141c97bae9", "hashlib.__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "subprocess": "a335eb99f2e34479", "linkedlist": "a5e9a83e9db303ad", "lib.core.Handles.HandlesClassDef": "aa45364399b86a03", "HandlesClassDef": "aa45364399b86a03", "lib.core.Handles.HandlesType": "af1cc6aaab47a7d1", "HandlesType": "af1cc6aaab47a7d1", "lib.core.Handles.HandlesNonlocal": "af9484a65085bf4b", "HandlesNonlocal": "af9484a65085bf4b", "argparse": "b370d93b74bf55cc", "ast.exprs": "b543bc1dfb592119", "exprs": "b543bc1dfb592119", "ast.tokens": "b547ac4f380bddb6", "tokens": "b547ac4f380bddb6", "platmacro": "b57252077e6b596b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "lib.core.VLogger": "bdf5730851fb95f2", "VLogger": "bdf5730851fb95f2", "lib.core.Handles.HandlesExprOps": "be8c2d7b882881c8", "HandlesExprOps": "be8c2d7b882881c8", "lib.Projectrans.Config": "c0042adc0b7ec5df", "Config": "c0042adc0b7ec5df", "main": "c2010cffc6092ea2", "hashlib.__sha256": "c9d54a4158f7f5a8", "__sha256": "c9d54a4158f7f5a8", "viperio": "c9f4be41ca1cc2b4", "memhub": "ca40915f11b8b6ad", "lib.core.StubMerger": "cae1b2c5898ed6e5", "StubMerger": "cae1b2c5898ed6e5", "lib.core.Handles.HandlesVar": "cb1aa3a78af6f362", "HandlesVar": "cb1aa3a78af6f362", "ast.lexer": "e217def267d3d4a8", "lexer": "e217def267d3d4a8", "viperlib": "e307a2d809cef071", "lib.core.BuildPipeline": "e991626c0aee9d7b", "BuildPipeline": "e991626c0aee9d7b", "lib.core.Handles.HandlesEnum": "f05b14a2ad5767a7", "HandlesEnum": "f05b14a2ad5767a7", "ast.__init__": "f3444ec56937284f", "ast": "f3444ec56937284f", "stdint": "f5522571bcce7bcb", "w32.win32file": "f6b51804a0ba8ff0", "win32file": "f6b51804a0ba8ff0", "llvmlite.__values": "f9e36e2cd6fa659f", "__values": "f9e36e2cd6fa659f", "w32.win32base": "fc980acec33d69a7", "win32base": "fc980acec33d69a7", "ast.parser": "fde6db0747bdd959", "parser": "fde6db0747bdd959"} \ No newline at end of file diff --git a/TransPyV/output/66de93aaeebc0601.deps.json b/TransPyV/output/66de93aaeebc0601.deps.json deleted file mode 100644 index f47c1e0..0000000 --- a/TransPyV/output/66de93aaeebc0601.deps.json +++ /dev/null @@ -1 +0,0 @@ -{"w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "06f53cc594b4ac6c", "win32sync": "06f53cc594b4ac6c", "sys": "0c67644125bea0fd", "hashlib.__sha1": "0df65b8ed15664b0", "__sha1": "0df65b8ed15664b0", "lib.core.Handles.HandlesFunctions": "1073ffca7e27aae5", "HandlesFunctions": "1073ffca7e27aae5", "lib.core.Handles.HandlesAnnAssign": "15bb32adb7093ed7", "HandlesAnnAssign": "15bb32adb7093ed7", "hashlib.__md5": "19f8024d10c828e8", "__md5": "19f8024d10c828e8", "llvmlite.__init__": "1d74d1d3a174c684", "__init__": "f3444ec56937284f", "llvmlite": "1d74d1d3a174c684", "json.__writer": "20cd49775c100a38", "__writer": "20cd49775c100a38", "ast.base": "22bc0df83b3f0e62", "base": "22bc0df83b3f0e62", "json.__parser": "240a9a4157959a9f", "__parser": "240a9a4157959a9f", "lib.core.Handles.HandlesReturn": "2703a899f26b771d", "HandlesReturn": "2703a899f26b771d", "atom": "271ea3decb810db2", "stdio": "285b6aa29a34754d", "posix": "28de517e3820658a", "lib.core.Handles.HandlesAssign": "2b59175b77f1304e", "HandlesAssign": "2b59175b77f1304e", "lib.core.Phase1": "2d523679d6b886ad", "Phase1": "2d523679d6b886ad", "llvmlite.__types": "2d8debefda779c40", "__types": "2d8debefda779c40", "hashtable": "2fbec3db55b30ad4", "lib.core.Handles.HandlesAugAssign": "31e49accebfc8aac", "HandlesAugAssign": "31e49accebfc8aac", "lib.core.Handles.HandlesStruct": "371fa89e15d8c015", "HandlesStruct": "371fa89e15d8c015", "stdlib": "3aa6057398be5673", "lib.StubGen.Converter": "3c5f1c61545644a9", "Converter": "3c5f1c61545644a9", "ast.astaux": "4337fb260448bbe2", "astaux": "4337fb260448bbe2", "lib.core.Handles.HandlesFor": "456fb516ba3c5002", "HandlesFor": "456fb516ba3c5002", "lib.Projectrans.Utils": "4650533467115342", "Utils": "4650533467115342", "lib.core.Handles.HandlesMain": "4a7b57e6bd18f65e", "HandlesMain": "4a7b57e6bd18f65e", "string": "4daf5ed3f8e421a1", "ast.match": "4dd6b3f1427d1cc5", "match": "4dd6b3f1427d1cc5", "lib.core.Handles.HandlesWhile": "51f0144d6e8188d9", "HandlesWhile": "51f0144d6e8188d9", "json.__init__": "57288496f7c2d1ad", "json": "57288496f7c2d1ad", "llvmlite.__builder": "5a1d8c48f1243746", "__builder": "5a1d8c48f1243746", "lib.core.Handles.HandlesExprCall": "5c482c6aac2ba83b", "HandlesExprCall": "5c482c6aac2ba83b", "lib.core.Handles.HandlesTranslator": "62805d8ad3e9b5ba", "HandlesTranslator": "62805d8ad3e9b5ba", "lib.core.IncludesScanner": "6282c9b745a35b8f", "IncludesScanner": "6282c9b745a35b8f", "lib.core.Handles.HandlesImports": "6293eee0a5805aa5", "HandlesImports": "6293eee0a5805aa5", "lib.core.Handles.HandlesBase": "63a3d17e96a083ac", "HandlesBase": "63a3d17e96a083ac", "ast.stmts": "657e182b27c2a022", "stmts": "657e182b27c2a022", "lib.core.Handles.HandlesExpr": "68f2617198f5757f", "HandlesExpr": "68f2617198f5757f", "llvmlite.__module": "692919c5a194ac8d", "__module": "692919c5a194ac8d", "lib.__init__": "6a19179426e9a883", "lib": "6a19179426e9a883", "llvmlite.__verify": "6b3bc463fd044545", "__verify": "6b3bc463fd044545", "hashlib.__sha512": "6ff26590374ae6fc", "__sha512": "6ff26590374ae6fc", "stdarg": "71e0a3ffcb3ebfad", "w32.fileio": "72dbbb563aa943b0", "fileio": "72dbbb563aa943b0", "lib.core.Phase2": "7ba06a9edf0fa6c7", "Phase2": "7ba06a9edf0fa6c7", "_list": "7cadfe07e983fd90", "lib.core.Handles.HandlesBody": "81eb28ba912467a6", "HandlesBody": "81eb28ba912467a6", "llvmlite.__function": "874bac141c97bae9", "__function": "874bac141c97bae9", "hashlib.__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "subprocess": "a335eb99f2e34479", "linkedlist": "a5e9a83e9db303ad", "lib.core.Handles.HandlesClassDef": "aa45364399b86a03", "HandlesClassDef": "aa45364399b86a03", "lib.core.Handles.HandlesType": "af1cc6aaab47a7d1", "HandlesType": "af1cc6aaab47a7d1", "lib.core.Handles.HandlesNonlocal": "af9484a65085bf4b", "HandlesNonlocal": "af9484a65085bf4b", "argparse": "b370d93b74bf55cc", "ast.exprs": "b543bc1dfb592119", "exprs": "b543bc1dfb592119", "ast.tokens": "b547ac4f380bddb6", "tokens": "b547ac4f380bddb6", "platmacro": "b57252077e6b596b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "lib.core.VLogger": "bdf5730851fb95f2", "VLogger": "bdf5730851fb95f2", "lib.core.Handles.HandlesExprOps": "be8c2d7b882881c8", "HandlesExprOps": "be8c2d7b882881c8", "lib.Projectrans.Config": "c0042adc0b7ec5df", "Config": "c0042adc0b7ec5df", "main": "c2010cffc6092ea2", "hashlib.__sha256": "c9d54a4158f7f5a8", "__sha256": "c9d54a4158f7f5a8", "viperio": "c9f4be41ca1cc2b4", "memhub": "ca40915f11b8b6ad", "lib.core.StubMerger": "cae1b2c5898ed6e5", "StubMerger": "cae1b2c5898ed6e5", "lib.core.Handles.HandlesVar": "cb1aa3a78af6f362", "HandlesVar": "cb1aa3a78af6f362", "ast.lexer": "e217def267d3d4a8", "lexer": "e217def267d3d4a8", "viperlib": "e307a2d809cef071", "lib.core.BuildPipeline": "e991626c0aee9d7b", "BuildPipeline": "e991626c0aee9d7b", "lib.core.Handles.HandlesEnum": "f05b14a2ad5767a7", "HandlesEnum": "f05b14a2ad5767a7", "ast.__init__": "f3444ec56937284f", "ast": "f3444ec56937284f", "stdint": "f5522571bcce7bcb", "w32.win32file": "f6b51804a0ba8ff0", "win32file": "f6b51804a0ba8ff0", "llvmlite.__values": "f9e36e2cd6fa659f", "__values": "f9e36e2cd6fa659f", "w32.win32base": "fc980acec33d69a7", "win32base": "fc980acec33d69a7", "ast.parser": "fde6db0747bdd959", "parser": "fde6db0747bdd959"} \ No newline at end of file diff --git a/TransPyV/output/81eb28ba912467a6.deps.json b/TransPyV/output/81eb28ba912467a6.deps.json index e0db6f6..666c8e6 100644 --- a/TransPyV/output/81eb28ba912467a6.deps.json +++ b/TransPyV/output/81eb28ba912467a6.deps.json @@ -1 +1 @@ -{"w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "06f53cc594b4ac6c", "win32sync": "06f53cc594b4ac6c", "sys": "0c67644125bea0fd", "hashlib.__sha1": "0df65b8ed15664b0", "__sha1": "0df65b8ed15664b0", "lib.core.Handles.HandlesFunctions": "1073ffca7e27aae5", "HandlesFunctions": "1073ffca7e27aae5", "lib.core.Handles.HandlesAnnAssign": "15bb32adb7093ed7", "HandlesAnnAssign": "15bb32adb7093ed7", "hashlib.__md5": "19f8024d10c828e8", "__md5": "19f8024d10c828e8", "llvmlite.__init__": "1d74d1d3a174c684", "__init__": "f3444ec56937284f", "llvmlite": "1d74d1d3a174c684", "json.__writer": "20cd49775c100a38", "__writer": "20cd49775c100a38", "ast.base": "22bc0df83b3f0e62", "base": "22bc0df83b3f0e62", "json.__parser": "240a9a4157959a9f", "__parser": "240a9a4157959a9f", "lib.core.Handles.HandlesReturn": "2703a899f26b771d", "HandlesReturn": "2703a899f26b771d", "atom": "271ea3decb810db2", "stdio": "285b6aa29a34754d", "posix": "28de517e3820658a", "lib.core.Handles.HandlesAssign": "2b59175b77f1304e", "HandlesAssign": "2b59175b77f1304e", "lib.core.Phase1": "2d523679d6b886ad", "Phase1": "2d523679d6b886ad", "llvmlite.__types": "2d8debefda779c40", "__types": "2d8debefda779c40", "hashtable": "2fbec3db55b30ad4", "lib.core.Handles.HandlesAugAssign": "31e49accebfc8aac", "HandlesAugAssign": "31e49accebfc8aac", "lib.core.Handles.HandlesStruct": "371fa89e15d8c015", "HandlesStruct": "371fa89e15d8c015", "stdlib": "3aa6057398be5673", "lib.StubGen.Converter": "3c5f1c61545644a9", "Converter": "3c5f1c61545644a9", "ast.astaux": "4337fb260448bbe2", "astaux": "4337fb260448bbe2", "lib.core.Handles.HandlesFor": "456fb516ba3c5002", "HandlesFor": "456fb516ba3c5002", "lib.Projectrans.Utils": "4650533467115342", "Utils": "4650533467115342", "lib.core.Handles.HandlesMain": "4a7b57e6bd18f65e", "HandlesMain": "4a7b57e6bd18f65e", "string": "4daf5ed3f8e421a1", "ast.match": "4dd6b3f1427d1cc5", "match": "4dd6b3f1427d1cc5", "lib.core.Handles.HandlesWhile": "51f0144d6e8188d9", "HandlesWhile": "51f0144d6e8188d9", "json.__init__": "57288496f7c2d1ad", "json": "57288496f7c2d1ad", "llvmlite.__builder": "5a1d8c48f1243746", "__builder": "5a1d8c48f1243746", "lib.core.Handles.HandlesExprCall": "5c482c6aac2ba83b", "HandlesExprCall": "5c482c6aac2ba83b", "lib.core.Handles.HandlesTranslator": "62805d8ad3e9b5ba", "HandlesTranslator": "62805d8ad3e9b5ba", "lib.core.IncludesScanner": "6282c9b745a35b8f", "IncludesScanner": "6282c9b745a35b8f", "lib.core.Handles.HandlesImports": "6293eee0a5805aa5", "HandlesImports": "6293eee0a5805aa5", "lib.core.Handles.HandlesBase": "63a3d17e96a083ac", "HandlesBase": "63a3d17e96a083ac", "ast.stmts": "657e182b27c2a022", "stmts": "657e182b27c2a022", "lib.core.Handles.HandlesIf": "66de93aaeebc0601", "HandlesIf": "66de93aaeebc0601", "lib.core.Handles.HandlesExpr": "68f2617198f5757f", "HandlesExpr": "68f2617198f5757f", "llvmlite.__module": "692919c5a194ac8d", "__module": "692919c5a194ac8d", "lib.__init__": "6a19179426e9a883", "lib": "6a19179426e9a883", "llvmlite.__verify": "6b3bc463fd044545", "__verify": "6b3bc463fd044545", "hashlib.__sha512": "6ff26590374ae6fc", "__sha512": "6ff26590374ae6fc", "stdarg": "71e0a3ffcb3ebfad", "w32.fileio": "72dbbb563aa943b0", "fileio": "72dbbb563aa943b0", "lib.core.Phase2": "7ba06a9edf0fa6c7", "Phase2": "7ba06a9edf0fa6c7", "_list": "7cadfe07e983fd90", "llvmlite.__function": "874bac141c97bae9", "__function": "874bac141c97bae9", "hashlib.__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "subprocess": "a335eb99f2e34479", "linkedlist": "a5e9a83e9db303ad", "lib.core.Handles.HandlesClassDef": "aa45364399b86a03", "HandlesClassDef": "aa45364399b86a03", "lib.core.Handles.HandlesType": "af1cc6aaab47a7d1", "HandlesType": "af1cc6aaab47a7d1", "lib.core.Handles.HandlesNonlocal": "af9484a65085bf4b", "HandlesNonlocal": "af9484a65085bf4b", "argparse": "b370d93b74bf55cc", "ast.exprs": "b543bc1dfb592119", "exprs": "b543bc1dfb592119", "ast.tokens": "b547ac4f380bddb6", "tokens": "b547ac4f380bddb6", "platmacro": "b57252077e6b596b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "lib.core.VLogger": "bdf5730851fb95f2", "VLogger": "bdf5730851fb95f2", "lib.core.Handles.HandlesExprOps": "be8c2d7b882881c8", "HandlesExprOps": "be8c2d7b882881c8", "lib.Projectrans.Config": "c0042adc0b7ec5df", "Config": "c0042adc0b7ec5df", "main": "c2010cffc6092ea2", "hashlib.__sha256": "c9d54a4158f7f5a8", "__sha256": "c9d54a4158f7f5a8", "viperio": "c9f4be41ca1cc2b4", "memhub": "ca40915f11b8b6ad", "lib.core.StubMerger": "cae1b2c5898ed6e5", "StubMerger": "cae1b2c5898ed6e5", "lib.core.Handles.HandlesVar": "cb1aa3a78af6f362", "HandlesVar": "cb1aa3a78af6f362", "ast.lexer": "e217def267d3d4a8", "lexer": "e217def267d3d4a8", "viperlib": "e307a2d809cef071", "lib.core.BuildPipeline": "e991626c0aee9d7b", "BuildPipeline": "e991626c0aee9d7b", "lib.core.Handles.HandlesEnum": "f05b14a2ad5767a7", "HandlesEnum": "f05b14a2ad5767a7", "ast.__init__": "f3444ec56937284f", "ast": "f3444ec56937284f", "stdint": "f5522571bcce7bcb", "w32.win32file": "f6b51804a0ba8ff0", "win32file": "f6b51804a0ba8ff0", "llvmlite.__values": "f9e36e2cd6fa659f", "__values": "f9e36e2cd6fa659f", "w32.win32base": "fc980acec33d69a7", "win32base": "fc980acec33d69a7", "ast.parser": "fde6db0747bdd959", "parser": "fde6db0747bdd959"} \ No newline at end of file +{"w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "06f53cc594b4ac6c", "win32sync": "06f53cc594b4ac6c", "sys": "0c67644125bea0fd", "hashlib.__sha1": "0df65b8ed15664b0", "__sha1": "0df65b8ed15664b0", "lib.core.Handles.HandlesFunctions": "1073ffca7e27aae5", "HandlesFunctions": "1073ffca7e27aae5", "lib.core.Handles.HandlesAnnAssign": "15bb32adb7093ed7", "HandlesAnnAssign": "15bb32adb7093ed7", "hashlib.__md5": "19f8024d10c828e8", "__md5": "19f8024d10c828e8", "llvmlite.__init__": "1d74d1d3a174c684", "__init__": "f3444ec56937284f", "llvmlite": "1d74d1d3a174c684", "json.__writer": "20cd49775c100a38", "__writer": "20cd49775c100a38", "ast.base": "22bc0df83b3f0e62", "base": "22bc0df83b3f0e62", "json.__parser": "240a9a4157959a9f", "__parser": "240a9a4157959a9f", "stdio": "285b6aa29a34754d", "posix": "28de517e3820658a", "lib.core.Handles.HandlesAssign": "2b59175b77f1304e", "HandlesAssign": "2b59175b77f1304e", "llvmlite.__types": "2d8debefda779c40", "__types": "2d8debefda779c40", "hashtable": "2fbec3db55b30ad4", "lib.core.Handles.HandlesAugAssign": "31e49accebfc8aac", "HandlesAugAssign": "31e49accebfc8aac", "lib.core.Handles.HandlesStruct": "371fa89e15d8c015", "HandlesStruct": "371fa89e15d8c015", "stdlib": "3aa6057398be5673", "lib.StubGen.Converter": "3c5f1c61545644a9", "Converter": "3c5f1c61545644a9", "ast.astaux": "4337fb260448bbe2", "astaux": "4337fb260448bbe2", "lib.core.Handles.HandlesFor": "456fb516ba3c5002", "HandlesFor": "456fb516ba3c5002", "lib.Projectrans.Utils": "4650533467115342", "Utils": "4650533467115342", "main": "484879ffecdf2b08", "lib.core.Handles.HandlesMain": "4a7b57e6bd18f65e", "HandlesMain": "4a7b57e6bd18f65e", "lib.core.Handles.HandlesReturn": "4c644ade1f0d6d02", "HandlesReturn": "4c644ade1f0d6d02", "string": "4daf5ed3f8e421a1", "ast.match": "4dd6b3f1427d1cc5", "match": "4dd6b3f1427d1cc5", "json.__init__": "57288496f7c2d1ad", "json": "57288496f7c2d1ad", "llvmlite.__builder": "5a1d8c48f1243746", "__builder": "5a1d8c48f1243746", "lib.core.Handles.HandlesTranslator": "62805d8ad3e9b5ba", "HandlesTranslator": "62805d8ad3e9b5ba", "lib.core.Handles.HandlesImports": "6293eee0a5805aa5", "HandlesImports": "6293eee0a5805aa5", "lib.core.Handles.HandlesBase": "63a3d17e96a083ac", "HandlesBase": "63a3d17e96a083ac", "ast.stmts": "657e182b27c2a022", "stmts": "657e182b27c2a022", "llvmlite.__module": "692919c5a194ac8d", "__module": "692919c5a194ac8d", "lib.__init__": "6a19179426e9a883", "lib": "6a19179426e9a883", "llvmlite.__verify": "6b3bc463fd044545", "__verify": "6b3bc463fd044545", "hashlib.__sha512": "6ff26590374ae6fc", "__sha512": "6ff26590374ae6fc", "stdarg": "71e0a3ffcb3ebfad", "w32.fileio": "72dbbb563aa943b0", "fileio": "72dbbb563aa943b0", "_list": "7cadfe07e983fd90", "llvmlite.__function": "874bac141c97bae9", "__function": "874bac141c97bae9", "lib.core.IncludesScanner": "8d6185cf886c0334", "IncludesScanner": "8d6185cf886c0334", "lib.core.Handles.HandlesWhile": "8dc65d4c71e2936a", "HandlesWhile": "8dc65d4c71e2936a", "hashlib.__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "lib.core.StubMerger": "9dbc46e5249ed198", "StubMerger": "9dbc46e5249ed198", "subprocess": "a335eb99f2e34479", "lib.core.BuildPipeline": "a38b726f4a82545f", "BuildPipeline": "a38b726f4a82545f", "linkedlist": "a5e9a83e9db303ad", "atom": "aa246c6e6aa30484", "lib.core.Handles.HandlesClassDef": "aa45364399b86a03", "HandlesClassDef": "aa45364399b86a03", "lib.core.Handles.HandlesType": "af1cc6aaab47a7d1", "HandlesType": "af1cc6aaab47a7d1", "lib.core.Handles.HandlesNonlocal": "af9484a65085bf4b", "HandlesNonlocal": "af9484a65085bf4b", "argparse": "b370d93b74bf55cc", "ast.exprs": "b543bc1dfb592119", "exprs": "b543bc1dfb592119", "ast.tokens": "b547ac4f380bddb6", "tokens": "b547ac4f380bddb6", "platmacro": "b57252077e6b596b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "lib.core.Handles.HandlesExpr": "bde6b4cc0847ee6d", "HandlesExpr": "bde6b4cc0847ee6d", "lib.core.VLogger": "bdf5730851fb95f2", "VLogger": "bdf5730851fb95f2", "lib.core.Handles.HandlesExprOps": "be8c2d7b882881c8", "HandlesExprOps": "be8c2d7b882881c8", "lib.Projectrans.Config": "c0042adc0b7ec5df", "Config": "c0042adc0b7ec5df", "lib.core.Phase2": "c1bb03b1eae141e0", "Phase2": "c1bb03b1eae141e0", "hashlib.__sha256": "c9d54a4158f7f5a8", "__sha256": "c9d54a4158f7f5a8", "viperio": "c9f4be41ca1cc2b4", "memhub": "ca40915f11b8b6ad", "lib.core.Handles.HandlesVar": "cb1aa3a78af6f362", "HandlesVar": "cb1aa3a78af6f362", "ast.lexer": "e217def267d3d4a8", "lexer": "e217def267d3d4a8", "viperlib": "e307a2d809cef071", "lib.core.Handles.HandlesExprCall": "efefa18c5d6c2d81", "HandlesExprCall": "efefa18c5d6c2d81", "lib.core.Handles.HandlesEnum": "f05b14a2ad5767a7", "HandlesEnum": "f05b14a2ad5767a7", "ast.__init__": "f3444ec56937284f", "ast": "f3444ec56937284f", "lib.core.Handles.HandlesIf": "f4cdbca2f8802c12", "HandlesIf": "f4cdbca2f8802c12", "stdint": "f5522571bcce7bcb", "w32.win32file": "f6b51804a0ba8ff0", "win32file": "f6b51804a0ba8ff0", "llvmlite.__values": "f9e36e2cd6fa659f", "__values": "f9e36e2cd6fa659f", "lib.core.Phase1": "fc26f66203d7cbb7", "Phase1": "fc26f66203d7cbb7", "w32.win32base": "fc980acec33d69a7", "win32base": "fc980acec33d69a7", "ast.parser": "fde6db0747bdd959", "parser": "fde6db0747bdd959"} \ No newline at end of file diff --git a/TransPyV/output/af9484a65085bf4b.deps.json b/TransPyV/output/af9484a65085bf4b.deps.json index 28f0892..d01d4bb 100644 --- a/TransPyV/output/af9484a65085bf4b.deps.json +++ b/TransPyV/output/af9484a65085bf4b.deps.json @@ -1 +1 @@ -{"w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "06f53cc594b4ac6c", "win32sync": "06f53cc594b4ac6c", "sys": "0c67644125bea0fd", "hashlib.__sha1": "0df65b8ed15664b0", "__sha1": "0df65b8ed15664b0", "lib.core.Handles.HandlesFunctions": "1073ffca7e27aae5", "HandlesFunctions": "1073ffca7e27aae5", "lib.core.Handles.HandlesAnnAssign": "15bb32adb7093ed7", "HandlesAnnAssign": "15bb32adb7093ed7", "hashlib.__md5": "19f8024d10c828e8", "__md5": "19f8024d10c828e8", "llvmlite.__init__": "1d74d1d3a174c684", "__init__": "f3444ec56937284f", "llvmlite": "1d74d1d3a174c684", "json.__writer": "20cd49775c100a38", "__writer": "20cd49775c100a38", "ast.base": "22bc0df83b3f0e62", "base": "22bc0df83b3f0e62", "json.__parser": "240a9a4157959a9f", "__parser": "240a9a4157959a9f", "lib.core.Handles.HandlesReturn": "2703a899f26b771d", "HandlesReturn": "2703a899f26b771d", "atom": "271ea3decb810db2", "stdio": "285b6aa29a34754d", "posix": "28de517e3820658a", "lib.core.Handles.HandlesAssign": "2b59175b77f1304e", "HandlesAssign": "2b59175b77f1304e", "lib.core.Phase1": "2d523679d6b886ad", "Phase1": "2d523679d6b886ad", "llvmlite.__types": "2d8debefda779c40", "__types": "2d8debefda779c40", "hashtable": "2fbec3db55b30ad4", "lib.core.Handles.HandlesAugAssign": "31e49accebfc8aac", "HandlesAugAssign": "31e49accebfc8aac", "lib.core.Handles.HandlesStruct": "371fa89e15d8c015", "HandlesStruct": "371fa89e15d8c015", "stdlib": "3aa6057398be5673", "lib.StubGen.Converter": "3c5f1c61545644a9", "Converter": "3c5f1c61545644a9", "ast.astaux": "4337fb260448bbe2", "astaux": "4337fb260448bbe2", "lib.core.Handles.HandlesFor": "456fb516ba3c5002", "HandlesFor": "456fb516ba3c5002", "lib.Projectrans.Utils": "4650533467115342", "Utils": "4650533467115342", "lib.core.Handles.HandlesMain": "4a7b57e6bd18f65e", "HandlesMain": "4a7b57e6bd18f65e", "string": "4daf5ed3f8e421a1", "ast.match": "4dd6b3f1427d1cc5", "match": "4dd6b3f1427d1cc5", "lib.core.Handles.HandlesWhile": "51f0144d6e8188d9", "HandlesWhile": "51f0144d6e8188d9", "json.__init__": "57288496f7c2d1ad", "json": "57288496f7c2d1ad", "llvmlite.__builder": "5a1d8c48f1243746", "__builder": "5a1d8c48f1243746", "lib.core.Handles.HandlesExprCall": "5c482c6aac2ba83b", "HandlesExprCall": "5c482c6aac2ba83b", "lib.core.Handles.HandlesTranslator": "62805d8ad3e9b5ba", "HandlesTranslator": "62805d8ad3e9b5ba", "lib.core.IncludesScanner": "6282c9b745a35b8f", "IncludesScanner": "6282c9b745a35b8f", "lib.core.Handles.HandlesImports": "6293eee0a5805aa5", "HandlesImports": "6293eee0a5805aa5", "lib.core.Handles.HandlesBase": "63a3d17e96a083ac", "HandlesBase": "63a3d17e96a083ac", "ast.stmts": "657e182b27c2a022", "stmts": "657e182b27c2a022", "lib.core.Handles.HandlesIf": "66de93aaeebc0601", "HandlesIf": "66de93aaeebc0601", "lib.core.Handles.HandlesExpr": "68f2617198f5757f", "HandlesExpr": "68f2617198f5757f", "llvmlite.__module": "692919c5a194ac8d", "__module": "692919c5a194ac8d", "lib.__init__": "6a19179426e9a883", "lib": "6a19179426e9a883", "llvmlite.__verify": "6b3bc463fd044545", "__verify": "6b3bc463fd044545", "hashlib.__sha512": "6ff26590374ae6fc", "__sha512": "6ff26590374ae6fc", "stdarg": "71e0a3ffcb3ebfad", "w32.fileio": "72dbbb563aa943b0", "fileio": "72dbbb563aa943b0", "lib.core.Phase2": "7ba06a9edf0fa6c7", "Phase2": "7ba06a9edf0fa6c7", "_list": "7cadfe07e983fd90", "lib.core.Handles.HandlesBody": "81eb28ba912467a6", "HandlesBody": "81eb28ba912467a6", "llvmlite.__function": "874bac141c97bae9", "__function": "874bac141c97bae9", "hashlib.__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "subprocess": "a335eb99f2e34479", "linkedlist": "a5e9a83e9db303ad", "lib.core.Handles.HandlesClassDef": "aa45364399b86a03", "HandlesClassDef": "aa45364399b86a03", "lib.core.Handles.HandlesType": "af1cc6aaab47a7d1", "HandlesType": "af1cc6aaab47a7d1", "argparse": "b370d93b74bf55cc", "ast.exprs": "b543bc1dfb592119", "exprs": "b543bc1dfb592119", "ast.tokens": "b547ac4f380bddb6", "tokens": "b547ac4f380bddb6", "platmacro": "b57252077e6b596b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "lib.core.VLogger": "bdf5730851fb95f2", "VLogger": "bdf5730851fb95f2", "lib.core.Handles.HandlesExprOps": "be8c2d7b882881c8", "HandlesExprOps": "be8c2d7b882881c8", "lib.Projectrans.Config": "c0042adc0b7ec5df", "Config": "c0042adc0b7ec5df", "main": "c2010cffc6092ea2", "hashlib.__sha256": "c9d54a4158f7f5a8", "__sha256": "c9d54a4158f7f5a8", "viperio": "c9f4be41ca1cc2b4", "memhub": "ca40915f11b8b6ad", "lib.core.StubMerger": "cae1b2c5898ed6e5", "StubMerger": "cae1b2c5898ed6e5", "lib.core.Handles.HandlesVar": "cb1aa3a78af6f362", "HandlesVar": "cb1aa3a78af6f362", "ast.lexer": "e217def267d3d4a8", "lexer": "e217def267d3d4a8", "viperlib": "e307a2d809cef071", "lib.core.BuildPipeline": "e991626c0aee9d7b", "BuildPipeline": "e991626c0aee9d7b", "lib.core.Handles.HandlesEnum": "f05b14a2ad5767a7", "HandlesEnum": "f05b14a2ad5767a7", "ast.__init__": "f3444ec56937284f", "ast": "f3444ec56937284f", "stdint": "f5522571bcce7bcb", "w32.win32file": "f6b51804a0ba8ff0", "win32file": "f6b51804a0ba8ff0", "llvmlite.__values": "f9e36e2cd6fa659f", "__values": "f9e36e2cd6fa659f", "w32.win32base": "fc980acec33d69a7", "win32base": "fc980acec33d69a7", "ast.parser": "fde6db0747bdd959", "parser": "fde6db0747bdd959"} \ No newline at end of file +{"w32.win32process": "067c78e9f121dce3", "win32process": "067c78e9f121dce3", "w32.win32sync": "06f53cc594b4ac6c", "win32sync": "06f53cc594b4ac6c", "sys": "0c67644125bea0fd", "hashlib.__sha1": "0df65b8ed15664b0", "__sha1": "0df65b8ed15664b0", "lib.core.Handles.HandlesFunctions": "1073ffca7e27aae5", "HandlesFunctions": "1073ffca7e27aae5", "lib.core.Handles.HandlesAnnAssign": "15bb32adb7093ed7", "HandlesAnnAssign": "15bb32adb7093ed7", "hashlib.__md5": "19f8024d10c828e8", "__md5": "19f8024d10c828e8", "llvmlite.__init__": "1d74d1d3a174c684", "__init__": "f3444ec56937284f", "llvmlite": "1d74d1d3a174c684", "json.__writer": "20cd49775c100a38", "__writer": "20cd49775c100a38", "ast.base": "22bc0df83b3f0e62", "base": "22bc0df83b3f0e62", "json.__parser": "240a9a4157959a9f", "__parser": "240a9a4157959a9f", "stdio": "285b6aa29a34754d", "posix": "28de517e3820658a", "lib.core.Handles.HandlesAssign": "2b59175b77f1304e", "HandlesAssign": "2b59175b77f1304e", "llvmlite.__types": "2d8debefda779c40", "__types": "2d8debefda779c40", "hashtable": "2fbec3db55b30ad4", "lib.core.Handles.HandlesAugAssign": "31e49accebfc8aac", "HandlesAugAssign": "31e49accebfc8aac", "lib.core.Handles.HandlesStruct": "371fa89e15d8c015", "HandlesStruct": "371fa89e15d8c015", "stdlib": "3aa6057398be5673", "lib.StubGen.Converter": "3c5f1c61545644a9", "Converter": "3c5f1c61545644a9", "ast.astaux": "4337fb260448bbe2", "astaux": "4337fb260448bbe2", "lib.core.Handles.HandlesFor": "456fb516ba3c5002", "HandlesFor": "456fb516ba3c5002", "lib.Projectrans.Utils": "4650533467115342", "Utils": "4650533467115342", "main": "484879ffecdf2b08", "lib.core.Handles.HandlesMain": "4a7b57e6bd18f65e", "HandlesMain": "4a7b57e6bd18f65e", "lib.core.Handles.HandlesReturn": "4c644ade1f0d6d02", "HandlesReturn": "4c644ade1f0d6d02", "string": "4daf5ed3f8e421a1", "ast.match": "4dd6b3f1427d1cc5", "match": "4dd6b3f1427d1cc5", "json.__init__": "57288496f7c2d1ad", "json": "57288496f7c2d1ad", "llvmlite.__builder": "5a1d8c48f1243746", "__builder": "5a1d8c48f1243746", "lib.core.Handles.HandlesTranslator": "62805d8ad3e9b5ba", "HandlesTranslator": "62805d8ad3e9b5ba", "lib.core.Handles.HandlesImports": "6293eee0a5805aa5", "HandlesImports": "6293eee0a5805aa5", "lib.core.Handles.HandlesBase": "63a3d17e96a083ac", "HandlesBase": "63a3d17e96a083ac", "ast.stmts": "657e182b27c2a022", "stmts": "657e182b27c2a022", "llvmlite.__module": "692919c5a194ac8d", "__module": "692919c5a194ac8d", "lib.__init__": "6a19179426e9a883", "lib": "6a19179426e9a883", "llvmlite.__verify": "6b3bc463fd044545", "__verify": "6b3bc463fd044545", "hashlib.__sha512": "6ff26590374ae6fc", "__sha512": "6ff26590374ae6fc", "stdarg": "71e0a3ffcb3ebfad", "w32.fileio": "72dbbb563aa943b0", "fileio": "72dbbb563aa943b0", "_list": "7cadfe07e983fd90", "lib.core.Handles.HandlesBody": "81eb28ba912467a6", "HandlesBody": "81eb28ba912467a6", "llvmlite.__function": "874bac141c97bae9", "__function": "874bac141c97bae9", "lib.core.IncludesScanner": "8d6185cf886c0334", "IncludesScanner": "8d6185cf886c0334", "lib.core.Handles.HandlesWhile": "8dc65d4c71e2936a", "HandlesWhile": "8dc65d4c71e2936a", "hashlib.__init__": "96837bcc64032444", "hashlib": "96837bcc64032444", "lib.core.StubMerger": "9dbc46e5249ed198", "StubMerger": "9dbc46e5249ed198", "subprocess": "a335eb99f2e34479", "lib.core.BuildPipeline": "a38b726f4a82545f", "BuildPipeline": "a38b726f4a82545f", "linkedlist": "a5e9a83e9db303ad", "atom": "aa246c6e6aa30484", "lib.core.Handles.HandlesClassDef": "aa45364399b86a03", "HandlesClassDef": "aa45364399b86a03", "lib.core.Handles.HandlesType": "af1cc6aaab47a7d1", "HandlesType": "af1cc6aaab47a7d1", "argparse": "b370d93b74bf55cc", "ast.exprs": "b543bc1dfb592119", "exprs": "b543bc1dfb592119", "ast.tokens": "b547ac4f380bddb6", "tokens": "b547ac4f380bddb6", "platmacro": "b57252077e6b596b", "w32.win32console": "bbdf3bbd4c3bc28c", "win32console": "bbdf3bbd4c3bc28c", "lib.core.Handles.HandlesExpr": "bde6b4cc0847ee6d", "HandlesExpr": "bde6b4cc0847ee6d", "lib.core.VLogger": "bdf5730851fb95f2", "VLogger": "bdf5730851fb95f2", "lib.core.Handles.HandlesExprOps": "be8c2d7b882881c8", "HandlesExprOps": "be8c2d7b882881c8", "lib.Projectrans.Config": "c0042adc0b7ec5df", "Config": "c0042adc0b7ec5df", "lib.core.Phase2": "c1bb03b1eae141e0", "Phase2": "c1bb03b1eae141e0", "hashlib.__sha256": "c9d54a4158f7f5a8", "__sha256": "c9d54a4158f7f5a8", "viperio": "c9f4be41ca1cc2b4", "memhub": "ca40915f11b8b6ad", "lib.core.Handles.HandlesVar": "cb1aa3a78af6f362", "HandlesVar": "cb1aa3a78af6f362", "ast.lexer": "e217def267d3d4a8", "lexer": "e217def267d3d4a8", "viperlib": "e307a2d809cef071", "lib.core.Handles.HandlesExprCall": "efefa18c5d6c2d81", "HandlesExprCall": "efefa18c5d6c2d81", "lib.core.Handles.HandlesEnum": "f05b14a2ad5767a7", "HandlesEnum": "f05b14a2ad5767a7", "ast.__init__": "f3444ec56937284f", "ast": "f3444ec56937284f", "lib.core.Handles.HandlesIf": "f4cdbca2f8802c12", "HandlesIf": "f4cdbca2f8802c12", "stdint": "f5522571bcce7bcb", "w32.win32file": "f6b51804a0ba8ff0", "win32file": "f6b51804a0ba8ff0", "llvmlite.__values": "f9e36e2cd6fa659f", "__values": "f9e36e2cd6fa659f", "lib.core.Phase1": "fc26f66203d7cbb7", "Phase1": "fc26f66203d7cbb7", "w32.win32base": "fc980acec33d69a7", "win32base": "fc980acec33d69a7", "ast.parser": "fde6db0747bdd959", "parser": "fde6db0747bdd959"} \ No newline at end of file diff --git a/TransPyV/project.json b/TransPyV/project.json index f923695..bdf4f80 100644 --- a/TransPyV/project.json +++ b/TransPyV/project.json @@ -22,7 +22,7 @@ "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, + "slice_level": 3, "sha1_slice_level": 1, "target": "llvm", "strict_mode": true diff --git a/TransPyV/temp/067c78e9f121dce3.pyi b/TransPyV/temp/067c78e9f121dce3.pyi deleted file mode 100644 index f4f767c..0000000 --- a/TransPyV/temp/067c78e9f121dce3.pyi +++ /dev/null @@ -1,136 +0,0 @@ -""" -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/TransPyV/temp/06f53cc594b4ac6c.pyi b/TransPyV/temp/06f53cc594b4ac6c.pyi deleted file mode 100644 index 8b5a8cf..0000000 --- a/TransPyV/temp/06f53cc594b4ac6c.pyi +++ /dev/null @@ -1,109 +0,0 @@ -""" -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/TransPyV/temp/0df65b8ed15664b0.pyi b/TransPyV/temp/0df65b8ed15664b0.pyi deleted file mode 100644 index e33dc69..0000000 --- a/TransPyV/temp/0df65b8ed15664b0.pyi +++ /dev/null @@ -1,30 +0,0 @@ -""" -Auto-generated Python stub file from hashlib.__sha1.py -Module: hashlib.__sha1 -""" - - -import string -import t, c - -SHA1_BLOCK_LEN: t.CDefine = 64 -SHA1_DIGEST_LEN: t.CDefine = 20 - -def sha1_rotl(x: t.CUInt32T, n: t.CInt) -> t.CUInt32T: pass - -def sha1_f1(b: t.CUInt32T, c: t.CUInt32T, d: t.CUInt32T) -> t.CUInt32T: pass - -def sha1_f2(b: t.CUInt32T, c: t.CUInt32T, d: t.CUInt32T) -> t.CUInt32T: pass - -def sha1_f3(b: t.CUInt32T, c: t.CUInt32T, d: t.CUInt32T) -> t.CUInt32T: pass - - -@t.Object -class sha1: - state: t.CArray[t.CUInt32T, 5] - count: t.CUInt64T - 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: t.CArray[t.CUInt8T, SHA1_DIGEST_LEN]) -> t.CInt: pass \ No newline at end of file diff --git a/TransPyV/temp/19f8024d10c828e8.pyi b/TransPyV/temp/19f8024d10c828e8.pyi deleted file mode 100644 index a25a2e4..0000000 --- a/TransPyV/temp/19f8024d10c828e8.pyi +++ /dev/null @@ -1,35 +0,0 @@ -""" -Auto-generated Python stub file from hashlib.__md5.py -Module: hashlib.__md5 -""" - - -import string -import t, c - -MD5_BLOCK_LEN: t.CDefine = 64 # 分组块大小 -MD5_DIGEST_LEN: t.CDefine = 16 # 摘要输出长度 - -def md5_F(x: t.CUInt32T, y: t.CUInt32T, z: t.CUInt32T) -> t.CUInt32T: pass - -def md5_G(x: t.CUInt32T, y: t.CUInt32T, z: t.CUInt32T) -> t.CUInt32T: pass - -def md5_H(x: t.CUInt32T, y: t.CUInt32T, z: t.CUInt32T) -> t.CUInt32T: pass - -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 | t.CArray[t.CUInt32T, 64] -md5_S: t.CExtern | t.CArray[t.CInt, 64] - -@t.Object -class md5: - state: t.CArray[t.CUInt32T, 4] - count: t.CUInt64T - 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: t.CArray[t.CUInt8T, MD5_DIGEST_LEN]) -> t.CInt: pass \ No newline at end of file diff --git a/TransPyV/temp/20cd49775c100a38.pyi b/TransPyV/temp/20cd49775c100a38.pyi deleted file mode 100644 index df04de7..0000000 --- a/TransPyV/temp/20cd49775c100a38.pyi +++ /dev/null @@ -1,22 +0,0 @@ -""" -Auto-generated Python stub file from json.__writer.py -Module: json.__writer -""" - - -import t, c -from stdint import * -import memhub -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: memhub.MemManager | t.CPtr) -> t.CSizeT: pass - -def write(pool: memhub.MemManager | t.CPtr, val: JsonValue | t.CPtr, pretty: bool) -> t.CChar | t.CPtr: pass diff --git a/TransPyV/temp/240a9a4157959a9f.pyi b/TransPyV/temp/240a9a4157959a9f.pyi deleted file mode 100644 index c230800..0000000 --- a/TransPyV/temp/240a9a4157959a9f.pyi +++ /dev/null @@ -1,38 +0,0 @@ -""" -Auto-generated Python stub file from json.__parser.py -Module: json.__parser -""" - - -import t, c -from stdint import * -import memhub -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: memhub.MemManager | t.CPtr - def __init__(self: ParseState, src: t.CChar | t.CPtr, pool: memhub.MemManager | 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: memhub.MemManager | t.CPtr, src: t.CChar | t.CPtr) -> JsonValue | t.CPtr: pass diff --git a/TransPyV/temp/271ea3decb810db2.pyi b/TransPyV/temp/271ea3decb810db2.pyi deleted file mode 100644 index 3d637bf..0000000 --- a/TransPyV/temp/271ea3decb810db2.pyi +++ /dev/null @@ -1,26 +0,0 @@ -""" -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/TransPyV/temp/4337fb260448bbe2.pyi b/TransPyV/temp/4337fb260448bbe2.pyi deleted file mode 100644 index 7ed88bd..0000000 --- a/TransPyV/temp/4337fb260448bbe2.pyi +++ /dev/null @@ -1,73 +0,0 @@ -""" -Auto-generated Python stub file from ast.astaux.py -Module: ast.astaux -""" - - -import t, c -from stdint import * -import memhub -import string -from .base import AST, ASTKind, _init_ast, _copy_str, _set_parent_list, _emit, _emit_str, _emit_int, _dump_list - -class ExceptHandler(AST): - type: AST | t.CPtr - name: str - def __new__(self: ExceptHandler, pool: memhub.MemManager | t.CPtr, type: AST | t.CPtr, name: str) -> t.CInt: pass - def __init__(self: ExceptHandler, pool: memhub.MemManager | t.CPtr, type: AST | t.CPtr, name: str) -> t.CInt: pass - def kind(self: ExceptHandler) -> t.CInt: pass - def type_name(self: ExceptHandler) -> str: pass - def dump(self: ExceptHandler, buf: bytes, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass -class Arguments(AST): - args: list[AST | t.CPtr] | t.CPtr - vararg: AST | t.CPtr - kwarg: AST | t.CPtr - defaults: list[AST | t.CPtr] | t.CPtr - kw_defaults: list[AST | t.CPtr] | t.CPtr - def __new__(self: Arguments, pool: memhub.MemManager | t.CPtr, args: list[AST | t.CPtr] | t.CPtr, vararg: AST | t.CPtr, kwarg: AST | t.CPtr, defaults: list[AST | t.CPtr] | t.CPtr, kw_defaults: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass - def __init__(self: Arguments, pool: memhub.MemManager | t.CPtr, args: list[AST | t.CPtr] | t.CPtr, vararg: AST | t.CPtr, kwarg: AST | t.CPtr, defaults: list[AST | t.CPtr] | t.CPtr, kw_defaults: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass - def kind(self: Arguments) -> t.CInt: pass - def type_name(self: Arguments) -> str: pass - def dump(self: Arguments, buf: bytes, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass -class Arg(AST): - arg: str - annotation: AST | t.CPtr - def __new__(self: Arg, pool: memhub.MemManager | t.CPtr, arg: str, annotation: AST | t.CPtr) -> t.CInt: pass - def __init__(self: Arg, pool: memhub.MemManager | t.CPtr, arg: str, annotation: AST | t.CPtr) -> t.CInt: pass - def kind(self: Arg) -> t.CInt: pass - def type_name(self: Arg) -> str: pass - def dump(self: Arg, buf: bytes, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass -class Keyword(AST): - arg: str - value: AST | t.CPtr - def __new__(self: Keyword, pool: memhub.MemManager | t.CPtr, arg: str, value: AST | t.CPtr) -> t.CInt: pass - def __init__(self: Keyword, pool: memhub.MemManager | t.CPtr, arg: str, value: AST | t.CPtr) -> t.CInt: pass - def kind(self: Keyword) -> t.CInt: pass - def type_name(self: Keyword) -> str: pass - def dump(self: Keyword, buf: bytes, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass -class Alias(AST): - name: str - asname: str - def __new__(self: Alias, pool: memhub.MemManager | t.CPtr, name: str, asname: str) -> t.CInt: pass - def __init__(self: Alias, pool: memhub.MemManager | t.CPtr, name: str, asname: str) -> t.CInt: pass - def kind(self: Alias) -> t.CInt: pass - def type_name(self: Alias) -> str: pass - def dump(self: Alias, buf: bytes, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass -class WithItem(AST): - context_expr: AST | t.CPtr - optional_vars: AST | t.CPtr - def __new__(self: WithItem, pool: memhub.MemManager | t.CPtr, context_expr: AST | t.CPtr, optional_vars: AST | t.CPtr) -> t.CInt: pass - def __init__(self: WithItem, pool: memhub.MemManager | t.CPtr, context_expr: AST | t.CPtr, optional_vars: AST | t.CPtr) -> t.CInt: pass - def kind(self: WithItem) -> t.CInt: pass - def type_name(self: WithItem) -> str: pass - def dump(self: WithItem, buf: bytes, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass -class Comprehension(AST): - target: AST | t.CPtr - iter: AST | t.CPtr - ifs: list[AST | t.CPtr] | t.CPtr - is_async: t.CInt - def __new__(self: Comprehension, pool: memhub.MemManager | t.CPtr, target: AST | t.CPtr, iter: AST | t.CPtr, ifs: list[AST | t.CPtr] | t.CPtr, is_async: t.CInt) -> t.CInt: pass - def __init__(self: Comprehension, pool: memhub.MemManager | t.CPtr, target: AST | t.CPtr, iter: AST | t.CPtr, ifs: list[AST | t.CPtr] | t.CPtr, is_async: t.CInt) -> t.CInt: pass - def kind(self: Comprehension) -> t.CInt: pass - def type_name(self: Comprehension) -> str: pass - def dump(self: Comprehension, buf: bytes, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass \ No newline at end of file diff --git a/TransPyV/temp/4dd6b3f1427d1cc5.pyi b/TransPyV/temp/4dd6b3f1427d1cc5.pyi deleted file mode 100644 index dd15aa2..0000000 --- a/TransPyV/temp/4dd6b3f1427d1cc5.pyi +++ /dev/null @@ -1,82 +0,0 @@ -""" -Auto-generated Python stub file from ast.match.py -Module: ast.match -""" - - -import t, c -from stdint import * -import memhub -import string -from .base import AST, ASTKind, _init_ast, _copy_str, _set_parent_list, _emit, _emit_str, _emit_int, _dump_list - -class MatchCase(AST): - pattern: AST | t.CPtr - guard: AST | t.CPtr - def __new__(self: MatchCase, pool: memhub.MemManager | t.CPtr, pattern: AST | t.CPtr, guard: AST | t.CPtr) -> t.CInt: pass - def __init__(self: MatchCase, pool: memhub.MemManager | t.CPtr, pattern: AST | t.CPtr, guard: AST | t.CPtr) -> t.CInt: pass - def kind(self: MatchCase) -> t.CInt: pass - def type_name(self: MatchCase) -> str: pass - def dump(self: MatchCase, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass -class MatchValue(AST): - value: AST | t.CPtr - def __new__(self: MatchValue, pool: memhub.MemManager | t.CPtr, value: AST | t.CPtr) -> t.CInt: pass - def __init__(self: MatchValue, pool: memhub.MemManager | t.CPtr, value: AST | t.CPtr) -> t.CInt: pass - def kind(self: MatchValue) -> t.CInt: pass - def type_name(self: MatchValue) -> str: pass - def dump(self: MatchValue, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass -class MatchSingleton(AST): - value: AST | t.CPtr - def __new__(self: MatchSingleton, pool: memhub.MemManager | t.CPtr, value: AST | t.CPtr) -> t.CInt: pass - def __init__(self: MatchSingleton, pool: memhub.MemManager | t.CPtr, value: AST | t.CPtr) -> t.CInt: pass - def kind(self: MatchSingleton) -> t.CInt: pass - def type_name(self: MatchSingleton) -> str: pass - def dump(self: MatchSingleton, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass -class MatchSequence(AST): - patterns: list[AST | t.CPtr] | t.CPtr - def __new__(self: MatchSequence, pool: memhub.MemManager | t.CPtr, patterns: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass - def __init__(self: MatchSequence, pool: memhub.MemManager | t.CPtr, patterns: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass - def kind(self: MatchSequence) -> t.CInt: pass - def type_name(self: MatchSequence) -> str: pass - def dump(self: MatchSequence, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass -class MatchMapping(AST): - keys: list[AST | t.CPtr] | t.CPtr - patterns: list[AST | t.CPtr] | t.CPtr - rest: str - def __new__(self: MatchMapping, pool: memhub.MemManager | t.CPtr, keys: list[AST | t.CPtr] | t.CPtr, patterns: list[AST | t.CPtr] | t.CPtr, rest: str) -> t.CInt: pass - def __init__(self: MatchMapping, pool: memhub.MemManager | t.CPtr, keys: list[AST | t.CPtr] | t.CPtr, patterns: list[AST | t.CPtr] | t.CPtr, rest: str) -> t.CInt: pass - def kind(self: MatchMapping) -> t.CInt: pass - def type_name(self: MatchMapping) -> str: pass - def dump(self: MatchMapping, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass -class MatchClass(AST): - cls: AST | t.CPtr - patterns: list[AST | t.CPtr] | t.CPtr - kwd_attrs: list[AST | t.CPtr] | t.CPtr - kwd_patterns: list[AST | t.CPtr] | t.CPtr - def __new__(self: MatchClass, pool: memhub.MemManager | t.CPtr, cls: AST | t.CPtr, patterns: list[AST | t.CPtr] | t.CPtr, kwd_attrs: list[AST | t.CPtr] | t.CPtr, kwd_patterns: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass - def __init__(self: MatchClass, pool: memhub.MemManager | t.CPtr, cls: AST | t.CPtr, patterns: list[AST | t.CPtr] | t.CPtr, kwd_attrs: list[AST | t.CPtr] | t.CPtr, kwd_patterns: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass - def kind(self: MatchClass) -> t.CInt: pass - def type_name(self: MatchClass) -> str: pass - def dump(self: MatchClass, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass -class MatchStar(AST): - name: str - def __new__(self: MatchStar, pool: memhub.MemManager | t.CPtr, name: str) -> t.CInt: pass - def __init__(self: MatchStar, pool: memhub.MemManager | t.CPtr, name: str) -> t.CInt: pass - def kind(self: MatchStar) -> t.CInt: pass - def type_name(self: MatchStar) -> str: pass - def dump(self: MatchStar, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass -class MatchAs(AST): - pattern: AST | t.CPtr - name: str - def __new__(self: MatchAs, pool: memhub.MemManager | t.CPtr, pattern: AST | t.CPtr, name: str) -> t.CInt: pass - def __init__(self: MatchAs, pool: memhub.MemManager | t.CPtr, pattern: AST | t.CPtr, name: str) -> t.CInt: pass - def kind(self: MatchAs) -> t.CInt: pass - def type_name(self: MatchAs) -> str: pass - def dump(self: MatchAs, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass -class MatchOr(AST): - patterns: list[AST | t.CPtr] | t.CPtr - def __new__(self: MatchOr, pool: memhub.MemManager | t.CPtr, patterns: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass - def __init__(self: MatchOr, pool: memhub.MemManager | t.CPtr, patterns: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass - def kind(self: MatchOr) -> t.CInt: pass - def type_name(self: MatchOr) -> str: pass - def dump(self: MatchOr, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass \ No newline at end of file diff --git a/TransPyV/temp/51f0144d6e8188d9.doc.json b/TransPyV/temp/51f0144d6e8188d9.doc.json deleted file mode 100644 index a63fb44..0000000 --- a/TransPyV/temp/51f0144d6e8188d9.doc.json +++ /dev/null @@ -1 +0,0 @@ -{"WhileHandle": "while 循环语句处理器:继承 Mixin 获得 Trans 回指针", "WhileHandle.Handle": "翻译 while 循环语句"} \ No newline at end of file diff --git a/TransPyV/temp/51f0144d6e8188d9.pyi b/TransPyV/temp/51f0144d6e8188d9.pyi deleted file mode 100644 index eb71aad..0000000 --- a/TransPyV/temp/51f0144d6e8188d9.pyi +++ /dev/null @@ -1,25 +0,0 @@ -""" -Auto-generated Python stub file from lib.core.Handles.HandlesWhile.py -Module: lib.core.Handles.HandlesWhile -""" - - -import t, c -from stdint import * -import ast -import llvmlite -import memhub -import string -import stdio -import viperlib -import lib.core.Handles.HandlesBase as HandlesBase -import lib.core.Handles.HandlesTranslator as HT -import lib.core.Handles.HandlesExpr as HandlesExpr -import lib.core.Handles.HandlesBody as HandlesBody - -@t.NoVTable -class WhileHandle(HandlesBase.Mixin): - def __init__(self: WhileHandle, trans: HT.Translator | t.CPtr) -> t.CInt: pass - def Handle(self: WhileHandle, node: ast.AST | t.CPtr) -> int: pass - -def NewWhileHandle(pool: memhub.MemBuddy | t.CPtr, trans: HT.Translator | t.CPtr) -> WhileHandle | t.CPtr: pass diff --git a/TransPyV/temp/57288496f7c2d1ad.pyi b/TransPyV/temp/57288496f7c2d1ad.pyi deleted file mode 100644 index 0624d9a..0000000 --- a/TransPyV/temp/57288496f7c2d1ad.pyi +++ /dev/null @@ -1,71 +0,0 @@ -""" -Auto-generated Python stub file from json.__init__.py -Module: json.__init__ -""" - - -import t, c -from stdint import * -import memhub -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: memhub.MemManager | 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: memhub.MemManager | t.CPtr) -> JsonValue | t.CPtr: pass - -def bool_val(pool: memhub.MemManager | t.CPtr, val: bool) -> JsonValue | t.CPtr: pass - -def int_val(pool: memhub.MemManager | t.CPtr, val: t.CInt64T) -> JsonValue | t.CPtr: pass - -def float_val(pool: memhub.MemManager | t.CPtr, val: t.CDouble) -> JsonValue | t.CPtr: pass - -def string_val(pool: memhub.MemManager | t.CPtr, val: t.CChar | t.CPtr) -> JsonValue | t.CPtr: pass - -def array(pool: memhub.MemManager | t.CPtr) -> JsonValue | t.CPtr: pass - -def object(pool: memhub.MemManager | t.CPtr) -> JsonValue | t.CPtr: pass - -def array_append(pool: memhub.MemManager | t.CPtr, arr: JsonValue | t.CPtr, item: JsonValue | t.CPtr) -> t.CInt: pass - -def object_set(pool: memhub.MemManager | 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/TransPyV/temp/6446627d4f07a1b5.pyi b/TransPyV/temp/6446627d4f07a1b5.pyi deleted file mode 100644 index d7bcff4..0000000 --- a/TransPyV/temp/6446627d4f07a1b5.pyi +++ /dev/null @@ -1,86 +0,0 @@ -""" -Auto-generated Python stub file from w32.winsock2.py -Module: w32.winsock2 -""" - - -import t, c -from stdint import * -from w32.win32base import * - -WINSOCK_VERSION: t.CDefine = 0x0202 # 2.2 -AF_INET: t.CDefine = 2 -AF_INET6: t.CDefine = 23 -SOCK_STREAM: t.CDefine = 1 # TCP -SOCK_DGRAM: t.CDefine = 2 # UDP -SOCK_RAW: t.CDefine = 3 # 原始套接字 -IPPROTO_TCP: t.CDefine = 6 -IPPROTO_UDP: t.CDefine = 17 -SOL_SOCKET: t.CDefine = 0xFFFF # WinSock2 值 -SO_RCVTIMEO: t.CDefine = 0x1006 # WinSock2 值 -SO_SNDTIMEO: t.CDefine = 0x1005 # WinSock2 值 -SO_REUSEADDR: t.CDefine = 0x0004 # WinSock2 值 -INADDR_ANY: t.CDefine = 0 -SOCKET_ERROR: t.CDefine = -1 -INVALID_SOCKET: t.CDefine = 0xFFFFFFFF # WinSock2: ~0 -MSG_NOSIGNAL: t.CDefine = 0 # Windows 不支持,设为 0 -SD_SEND: t.CDefine = 1 -SD_RECV: t.CDefine = 0 -SD_BOTH: t.CDefine = 2 - -class WSASocketAddr: - family: u16 - port: u16 - addr: u32 - zero: u64 -class WSAData: - wVersion: WORD - wHighVersion: WORD - szDescription: BYTE - szSystemStatus: BYTE - iMaxSockets: u16 - iMaxUdpDg: u16 - lpVendorInfo: CHARPTR -class WSAHostEnt: - h_name: CHARPTR - h_aliases: CHARPTR - h_addrtype: SHORT - h_length: SHORT - h_addr_list: CHARPTR -class WinTimeVal: - tv_sec: LONG - tv_usec: LONG - -def WSAStartup(wVersionRequested: WORD, lpWSAData: WSAData | t.CPtr) -> INT | t.State: pass - -def WSACleanup() -> INT | t.State: pass - -def WSAGetLastError() -> INT | t.State: pass - -def socket(family: INT, type: INT, protocol: INT) -> u64 | t.State: pass - -def closesocket(s: u64) -> INT | t.State: pass - -def connect(s: u64, name: WSASocketAddr | t.CPtr, namelen: INT) -> INT | t.State: pass - -def send(s: u64, buf: t.CVoid | t.CPtr, len: INT, flags: INT) -> INT | t.State: pass - -def recv(s: u64, buf: t.CVoid | t.CPtr, len: INT, flags: INT) -> INT | t.State: pass - -def bind(s: u64, name: WSASocketAddr | t.CPtr, namelen: INT) -> INT | t.State: pass - -def listen(s: u64, backlog: INT) -> INT | t.State: pass - -def accept(s: u64, addr: WSASocketAddr | t.CPtr, addrlen: INT | t.CPtr) -> u64 | t.State: pass - -def setsockopt(s: u64, level: INT, optname: INT, optval: t.CVoid | t.CPtr, optlen: INT) -> INT | t.State: pass - -def shutdown(s: u64, how: INT) -> INT | t.State: pass - -def gethostbyname(name: t.CChar | t.CConst | t.CPtr) -> WSAHostEnt | t.CPtr | t.State: pass - -def ntohs(netshort: u16) -> u16 | t.State: pass - -def htons(hostshort: u16) -> u16 | t.State: pass - -def inet_addr(cp: t.CChar | t.CConst | t.CPtr) -> u32 | t.State: pass diff --git a/TransPyV/temp/657e182b27c2a022.pyi b/TransPyV/temp/657e182b27c2a022.pyi deleted file mode 100644 index 430e06f..0000000 --- a/TransPyV/temp/657e182b27c2a022.pyi +++ /dev/null @@ -1,226 +0,0 @@ -""" -Auto-generated Python stub file from ast.stmts.py -Module: ast.stmts -""" - - -import t, c -from stdint import * -import memhub -import string -from .base import AST, ASTKind, ASTCtx, OpKind, _init_ast, _copy_str, _set_parent_list, _emit, _emit_str, _emit_int, _dump_list, FLAG_IS_ASYNC - -@t.CVTable -class Module(AST): - def __new__(self: Module, pool: memhub.MemManager | t.CPtr) -> t.CInt: pass - def __init__(self: Module, pool: memhub.MemManager | t.CPtr) -> t.CInt: pass - def kind(self: Module) -> t.CInt: pass - def type_name(self: Module) -> str: pass - def dump(self: Module, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass -class Assign(AST): - targets: list[AST | t.CPtr] | t.CPtr - value: AST | t.CPtr - def __new__(self: Assign, pool: memhub.MemManager | t.CPtr, targets: list[AST | t.CPtr] | t.CPtr, value: AST | t.CPtr) -> t.CInt: pass - def __init__(self: Assign, pool: memhub.MemManager | t.CPtr, targets: list[AST | t.CPtr] | t.CPtr, value: AST | t.CPtr) -> t.CInt: pass - def kind(self: Assign) -> t.CInt: pass - def type_name(self: Assign) -> str: pass - def dump(self: Assign, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass -class If(AST): - test: AST | t.CPtr - orelse: list[AST | t.CPtr] | t.CPtr - def __new__(self: If, pool: memhub.MemManager | t.CPtr, test: AST | t.CPtr, orelse: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass - def __init__(self: If, pool: memhub.MemManager | t.CPtr, test: AST | t.CPtr, orelse: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass - def kind(self: If) -> t.CInt: pass - def type_name(self: If) -> str: pass - def dump(self: If, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass -class For(AST): - target: AST | t.CPtr - iter: AST | t.CPtr - orelse: list[AST | t.CPtr] | t.CPtr - flags: t.CInt - def __new__(self: For, pool: memhub.MemManager | t.CPtr, target: AST | t.CPtr, iter: AST | t.CPtr, orelse: list[AST | t.CPtr] | t.CPtr, is_async: t.CInt) -> t.CInt: pass - def __init__(self: For, pool: memhub.MemManager | t.CPtr, target: AST | t.CPtr, iter: AST | t.CPtr, orelse: list[AST | t.CPtr] | t.CPtr, is_async: t.CInt) -> t.CInt: pass - def kind(self: For) -> t.CInt: pass - def type_name(self: For) -> str: pass - def dump(self: For, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass -class While(AST): - test: AST | t.CPtr - orelse: list[AST | t.CPtr] | t.CPtr - def __new__(self: While, pool: memhub.MemManager | t.CPtr, test: AST | t.CPtr, orelse: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass - def __init__(self: While, pool: memhub.MemManager | t.CPtr, test: AST | t.CPtr, orelse: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass - def kind(self: While) -> t.CInt: pass - def type_name(self: While) -> str: pass - def dump(self: While, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass -class Return(AST): - value: AST | t.CPtr - def __new__(self: Return, pool: memhub.MemManager | t.CPtr, value: AST | t.CPtr) -> t.CInt: pass - def __init__(self: Return, pool: memhub.MemManager | t.CPtr, value: AST | t.CPtr) -> t.CInt: pass - def kind(self: Return) -> t.CInt: pass - def type_name(self: Return) -> str: pass - def dump(self: Return, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass -class Expr(AST): - value: AST | t.CPtr - def __new__(self: Expr, pool: memhub.MemManager | t.CPtr, value: AST | t.CPtr) -> t.CInt: pass - def __init__(self: Expr, pool: memhub.MemManager | t.CPtr, value: AST | t.CPtr) -> t.CInt: pass - def kind(self: Expr) -> t.CInt: pass - def type_name(self: Expr) -> str: pass - def dump(self: Expr, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass -class FunctionDef(AST): - name: str - args: AST | t.CPtr - decorator_list: list[AST | t.CPtr] | t.CPtr - returns: AST | t.CPtr - flags: t.CInt - def __new__(self: FunctionDef, pool: memhub.MemManager | t.CPtr, name: str, args: AST | t.CPtr, decorator_list: list[AST | t.CPtr] | t.CPtr, returns: AST | t.CPtr, is_async: t.CInt) -> t.CInt: pass - def __init__(self: FunctionDef, pool: memhub.MemManager | t.CPtr, name: str, args: AST | t.CPtr, decorator_list: list[AST | t.CPtr] | t.CPtr, returns: AST | t.CPtr, is_async: t.CInt) -> t.CInt: pass - def kind(self: FunctionDef) -> t.CInt: pass - def type_name(self: FunctionDef) -> str: pass - def dump(self: FunctionDef, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass -class Expression(AST): - body: AST | t.CPtr - def __new__(self: Expression, pool: memhub.MemManager | t.CPtr, body: AST | t.CPtr) -> t.CInt: pass - def __init__(self: Expression, pool: memhub.MemManager | t.CPtr, body: AST | t.CPtr) -> t.CInt: pass - def kind(self: Expression) -> t.CInt: pass - def type_name(self: Expression) -> str: pass - def dump(self: Expression, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass -class Interactive(AST): - body: AST | t.CPtr - def __new__(self: Interactive, pool: memhub.MemManager | t.CPtr, body: AST | t.CPtr) -> t.CInt: pass - def __init__(self: Interactive, pool: memhub.MemManager | t.CPtr, body: AST | t.CPtr) -> t.CInt: pass - def kind(self: Interactive) -> t.CInt: pass - def type_name(self: Interactive) -> str: pass - def dump(self: Interactive, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass -class FunctionType(AST): - argtypes: list[AST | t.CPtr] | t.CPtr - returns: AST | t.CPtr - def __new__(self: FunctionType, pool: memhub.MemManager | t.CPtr, argtypes: list[AST | t.CPtr] | t.CPtr, returns: AST | t.CPtr) -> t.CInt: pass - def __init__(self: FunctionType, pool: memhub.MemManager | t.CPtr, argtypes: list[AST | t.CPtr] | t.CPtr, returns: AST | t.CPtr) -> t.CInt: pass - def kind(self: FunctionType) -> t.CInt: pass - def type_name(self: FunctionType) -> str: pass - def dump(self: FunctionType, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass -class ClassDef(AST): - name: str - bases: list[AST | t.CPtr] | t.CPtr - keywords: list[AST | t.CPtr] | t.CPtr - decorator_list: list[AST | t.CPtr] | t.CPtr - type_params: list[str] | t.CPtr - def __new__(self: ClassDef, pool: memhub.MemManager | t.CPtr, name: str, bases: list[AST | t.CPtr] | t.CPtr, keywords: list[AST | t.CPtr] | t.CPtr, decorator_list: list[AST | t.CPtr] | t.CPtr, type_params: list[str] | t.CPtr = None) -> t.CInt: pass - def __init__(self: ClassDef, pool: memhub.MemManager | t.CPtr, name: str, bases: list[AST | t.CPtr] | t.CPtr, keywords: list[AST | t.CPtr] | t.CPtr, decorator_list: list[AST | t.CPtr] | t.CPtr, type_params: list[str] | t.CPtr = None) -> t.CInt: pass - def kind(self: ClassDef) -> t.CInt: pass - def type_name(self: ClassDef) -> str: pass - def dump(self: ClassDef, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass -class Delete(AST): - targets: list[AST | t.CPtr] | t.CPtr - def __new__(self: Delete, pool: memhub.MemManager | t.CPtr, targets: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass - def __init__(self: Delete, pool: memhub.MemManager | t.CPtr, targets: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass - def kind(self: Delete) -> t.CInt: pass - def type_name(self: Delete) -> str: pass - def dump(self: Delete, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass -class AugAssign(AST): - target: AST | t.CPtr - op: t.CInt - value: AST | t.CPtr - def __new__(self: AugAssign, pool: memhub.MemManager | t.CPtr, target: AST | t.CPtr, op: t.CInt, value: AST | t.CPtr) -> t.CInt: pass - def __init__(self: AugAssign, pool: memhub.MemManager | t.CPtr, target: AST | t.CPtr, op: t.CInt, value: AST | t.CPtr) -> t.CInt: pass - def kind(self: AugAssign) -> t.CInt: pass - def type_name(self: AugAssign) -> str: pass - def dump(self: AugAssign, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass -class AnnAssign(AST): - target: AST | t.CPtr - annotation: AST | t.CPtr - value: AST | t.CPtr - simple: t.CInt - def __new__(self: AnnAssign, pool: memhub.MemManager | t.CPtr, target: AST | t.CPtr, annotation: AST | t.CPtr, value: AST | t.CPtr, simple: t.CInt) -> t.CInt: pass - def __init__(self: AnnAssign, pool: memhub.MemManager | t.CPtr, target: AST | t.CPtr, annotation: AST | t.CPtr, value: AST | t.CPtr, simple: t.CInt) -> t.CInt: pass - def kind(self: AnnAssign) -> t.CInt: pass - def type_name(self: AnnAssign) -> str: pass - def dump(self: AnnAssign, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass -class With(AST): - items: list[AST | t.CPtr] | t.CPtr - flags: t.CInt - def __new__(self: With, pool: memhub.MemManager | t.CPtr, items: list[AST | t.CPtr] | t.CPtr, is_async: t.CInt) -> t.CInt: pass - def __init__(self: With, pool: memhub.MemManager | t.CPtr, items: list[AST | t.CPtr] | t.CPtr, is_async: t.CInt) -> t.CInt: pass - def kind(self: With) -> t.CInt: pass - def type_name(self: With) -> str: pass - def dump(self: With, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass -class Raise(AST): - exc: AST | t.CPtr - cause: AST | t.CPtr - def __new__(self: Raise, pool: memhub.MemManager | t.CPtr, exc: AST | t.CPtr, cause: AST | t.CPtr) -> t.CInt: pass - def __init__(self: Raise, pool: memhub.MemManager | t.CPtr, exc: AST | t.CPtr, cause: AST | t.CPtr) -> t.CInt: pass - def kind(self: Raise) -> t.CInt: pass - def type_name(self: Raise) -> str: pass - def dump(self: Raise, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass -class Try(AST): - handlers: list[AST | t.CPtr] | t.CPtr - orelse: list[AST | t.CPtr] | t.CPtr - finalbody: list[AST | t.CPtr] | t.CPtr - def __new__(self: Try, pool: memhub.MemManager | t.CPtr, handlers: list[AST | t.CPtr] | t.CPtr, orelse: list[AST | t.CPtr] | t.CPtr, finalbody: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass - def __init__(self: Try, pool: memhub.MemManager | t.CPtr, handlers: list[AST | t.CPtr] | t.CPtr, orelse: list[AST | t.CPtr] | t.CPtr, finalbody: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass - def kind(self: Try) -> t.CInt: pass - def type_name(self: Try) -> str: pass - def dump(self: Try, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass -class Assert(AST): - test: AST | t.CPtr - msg: AST | t.CPtr - def __new__(self: Assert, pool: memhub.MemManager | t.CPtr, test: AST | t.CPtr, msg: AST | t.CPtr) -> t.CInt: pass - def __init__(self: Assert, pool: memhub.MemManager | t.CPtr, test: AST | t.CPtr, msg: AST | t.CPtr) -> t.CInt: pass - def kind(self: Assert) -> t.CInt: pass - def type_name(self: Assert) -> str: pass - def dump(self: Assert, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass -class Global(AST): - names: list[AST | t.CPtr] | t.CPtr - def __new__(self: Global, pool: memhub.MemManager | t.CPtr, names: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass - def __init__(self: Global, pool: memhub.MemManager | t.CPtr, names: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass - def kind(self: Global) -> t.CInt: pass - def type_name(self: Global) -> str: pass - def dump(self: Global, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass -class Nonlocal(AST): - names: list[AST | t.CPtr] | t.CPtr - def __new__(self: Nonlocal, pool: memhub.MemManager | t.CPtr, names: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass - def __init__(self: Nonlocal, pool: memhub.MemManager | t.CPtr, names: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass - def kind(self: Nonlocal) -> t.CInt: pass - def type_name(self: Nonlocal) -> str: pass - def dump(self: Nonlocal, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass -class Pass(AST): - def __new__(self: Pass, pool: memhub.MemManager | t.CPtr) -> t.CInt: pass - def __init__(self: Pass, pool: memhub.MemManager | t.CPtr) -> t.CInt: pass - def kind(self: Pass) -> t.CInt: pass - def type_name(self: Pass) -> str: pass - def dump(self: Pass, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass -class Break(AST): - def __new__(self: Break, pool: memhub.MemManager | t.CPtr) -> t.CInt: pass - def __init__(self: Break, pool: memhub.MemManager | t.CPtr) -> t.CInt: pass - def kind(self: Break) -> t.CInt: pass - def type_name(self: Break) -> str: pass - def dump(self: Break, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass -class Continue(AST): - def __new__(self: Continue, pool: memhub.MemManager | t.CPtr) -> t.CInt: pass - def __init__(self: Continue, pool: memhub.MemManager | t.CPtr) -> t.CInt: pass - def kind(self: Continue) -> t.CInt: pass - def type_name(self: Continue) -> str: pass - def dump(self: Continue, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass -class Import(AST): - names: list[AST | t.CPtr] | t.CPtr - def __new__(self: Import, pool: memhub.MemManager | t.CPtr, names: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass - def __init__(self: Import, pool: memhub.MemManager | t.CPtr, names: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass - def kind(self: Import) -> t.CInt: pass - def type_name(self: Import) -> str: pass - def dump(self: Import, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass -class ImportFrom(AST): - module: str - names: list[AST | t.CPtr] | t.CPtr - level: t.CInt - def __new__(self: ImportFrom, pool: memhub.MemManager | t.CPtr, module: str, names: list[AST | t.CPtr] | t.CPtr, level: t.CInt) -> t.CInt: pass - def __init__(self: ImportFrom, pool: memhub.MemManager | t.CPtr, module: str, names: list[AST | t.CPtr] | t.CPtr, level: t.CInt) -> t.CInt: pass - def kind(self: ImportFrom) -> t.CInt: pass - def type_name(self: ImportFrom) -> str: pass - def dump(self: ImportFrom, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass -class Match(AST): - subject: AST | t.CPtr - cases: list[AST | t.CPtr] | t.CPtr - def __new__(self: Match, pool: memhub.MemManager | t.CPtr, subject: AST | t.CPtr, cases: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass - def __init__(self: Match, pool: memhub.MemManager | t.CPtr, subject: AST | t.CPtr, cases: list[AST | t.CPtr] | t.CPtr) -> t.CInt: pass - def kind(self: Match) -> t.CInt: pass - def type_name(self: Match) -> str: pass - def dump(self: Match, buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT: pass \ No newline at end of file diff --git a/TransPyV/temp/66de93aaeebc0601.doc.json b/TransPyV/temp/66de93aaeebc0601.doc.json deleted file mode 100644 index 046af31..0000000 --- a/TransPyV/temp/66de93aaeebc0601.doc.json +++ /dev/null @@ -1 +0,0 @@ -{"IfHandle": "if/elif/else 语句处理器:继承 Mixin 获得 Trans 回指针", "IfHandle.Handle": "翻译 if/elif/else 语句"} \ No newline at end of file diff --git a/TransPyV/temp/66de93aaeebc0601.pyi b/TransPyV/temp/66de93aaeebc0601.pyi deleted file mode 100644 index 2981cf3..0000000 --- a/TransPyV/temp/66de93aaeebc0601.pyi +++ /dev/null @@ -1,25 +0,0 @@ -""" -Auto-generated Python stub file from lib.core.Handles.HandlesIf.py -Module: lib.core.Handles.HandlesIf -""" - - -import t, c -from stdint import * -import ast -import llvmlite -import memhub -import string -import stdio -import viperlib -import lib.core.Handles.HandlesBase as HandlesBase -import lib.core.Handles.HandlesTranslator as HT -import lib.core.Handles.HandlesExpr as HandlesExpr -import lib.core.Handles.HandlesBody as HandlesBody - -@t.NoVTable -class IfHandle(HandlesBase.Mixin): - def __init__(self: IfHandle, trans: HT.Translator | t.CPtr) -> t.CInt: pass - def Handle(self: IfHandle, node: ast.AST | t.CPtr) -> int: pass - -def NewIfHandle(pool: memhub.MemBuddy | t.CPtr, trans: HT.Translator | t.CPtr) -> IfHandle | t.CPtr: pass diff --git a/TransPyV/temp/6ff26590374ae6fc.pyi b/TransPyV/temp/6ff26590374ae6fc.pyi deleted file mode 100644 index 1b1bba1..0000000 --- a/TransPyV/temp/6ff26590374ae6fc.pyi +++ /dev/null @@ -1,39 +0,0 @@ -""" -Auto-generated Python stub file from hashlib.__sha512.py -Module: hashlib.__sha512 -""" - - -import t, c - -SHA512_BLOCK_LEN: t.CDefine = 128 -SHA512_DIGEST_LEN: t.CDefine = 64 - -def sha512_ror(x: t.CUInt64T, n: int) -> t.CUInt64T: pass - -def sha512_shr(x: t.CUInt64T, n: int) -> t.CUInt64T: pass - -def sha512_Ch(x: t.CUInt64T, y: t.CUInt64T, z: t.CUInt64T) -> t.CUInt64T: pass - -def sha512_Maj(x: t.CUInt64T, y: t.CUInt64T, z: t.CUInt64T) -> t.CUInt64T: pass - -def sha512_BigSigma0(x: t.CUInt64T) -> t.CUInt64T: pass - -def sha512_BigSigma1(x: t.CUInt64T) -> t.CUInt64T: pass - -def sha512_Sigma0(x: t.CUInt64T) -> t.CUInt64T: pass - -def sha512_Sigma1(x: t.CUInt64T) -> t.CUInt64T: pass - - -sha512_K: t.CExtern | t.CArray[t.CUInt64T, 80] - -@t.Object -class sha512: - 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: t.CArray[t.CUInt8T, SHA512_BLOCK_LEN]) -> t.CInt: pass - def update(self: sha512, s: str) -> t.CInt: pass - def final(self: sha512, out: t.CArray[t.CUInt8T, SHA512_DIGEST_LEN]) -> t.CInt: pass \ No newline at end of file diff --git a/TransPyV/temp/71e0a3ffcb3ebfad.pyi b/TransPyV/temp/71e0a3ffcb3ebfad.pyi deleted file mode 100644 index 574b20e..0000000 --- a/TransPyV/temp/71e0a3ffcb3ebfad.pyi +++ /dev/null @@ -1,20 +0,0 @@ -""" -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/TransPyV/temp/72e2d5ccb7cedcf1.pyi b/TransPyV/temp/72e2d5ccb7cedcf1.pyi deleted file mode 100644 index 5fceb08..0000000 --- a/TransPyV/temp/72e2d5ccb7cedcf1.pyi +++ /dev/null @@ -1,91 +0,0 @@ -""" -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/TransPyV/temp/81eb28ba912467a6.pyi b/TransPyV/temp/81eb28ba912467a6.pyi deleted file mode 100644 index aa52e34..0000000 --- a/TransPyV/temp/81eb28ba912467a6.pyi +++ /dev/null @@ -1,35 +0,0 @@ -""" -Auto-generated Python stub file from lib.core.Handles.HandlesBody.py -Module: lib.core.Handles.HandlesBody -""" - - -import t, c -from stdint import * -import ast -import llvmlite -import memhub -import string -import stdio -import viperlib -import lib.core.Handles.HandlesTranslator as HT -import lib.core.Handles.HandlesExpr as HandlesExpr -import lib.core.Handles.HandlesExprCall as HandlesExprCall -import lib.core.Handles.HandlesFunctions as HandlesFunctions -import lib.core.Handles.HandlesClassDef as HandlesClassDef - -def translate_stmt(trans: HT.Translator | t.CPtr, node: ast.AST | t.CPtr) -> int: pass - -def translate_global(trans: HT.Translator | t.CPtr, node: ast.AST | t.CPtr) -> int: pass - -def translate_nonlocal(trans: HT.Translator | t.CPtr, node: ast.AST | t.CPtr) -> int: pass - -def translate_expr_stmt(trans: HT.Translator | t.CPtr, node: ast.AST | t.CPtr) -> int: pass - -def pre_scan_allocas(trans: HT.Translator | t.CPtr, node: ast.AST | t.CPtr) -> int: pass - -def translate_break(trans: HT.Translator | t.CPtr) -> int: pass - -def translate_continue(trans: HT.Translator | t.CPtr) -> int: pass - -def get_stmt_kind_name(node: ast.AST | t.CPtr) -> str: pass diff --git a/TransPyV/temp/96837bcc64032444.pyi b/TransPyV/temp/96837bcc64032444.pyi deleted file mode 100644 index 46e78bd..0000000 --- a/TransPyV/temp/96837bcc64032444.pyi +++ /dev/null @@ -1,13 +0,0 @@ -""" -Auto-generated Python stub file from hashlib.__init__.py -Module: hashlib.__init__ -""" - -import t -import c - - -from .__md5 import md5, MD5_DIGEST_LEN -from .__sha1 import sha1, SHA1_DIGEST_LEN -from .__sha256 import sha256, SHA256_DIGEST_LEN -from .__sha512 import sha512, SHA512_DIGEST_LEN \ No newline at end of file diff --git a/TransPyV/temp/_phase1_manifest.json b/TransPyV/temp/_phase1_manifest.json index f07200b..b2b9363 100644 --- a/TransPyV/temp/_phase1_manifest.json +++ b/TransPyV/temp/_phase1_manifest.json @@ -1 +1 @@ -{"D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\Projectrans\\Config.py": {"sha1": "c0042adc0b7ec5df", "mtime": 1785332415.2264168, "size": 14060}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\Projectrans\\Utils.py": {"sha1": "4650533467115342", "mtime": 1785332415.2054548, "size": 4900}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\StubGen\\Converter.py": {"sha1": "3c5f1c61545644a9", "mtime": 1785332415.2120533, "size": 35262}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\__init__.py": {"sha1": "6a19179426e9a883", "mtime": 1785332415.1753137, "size": 820}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\BuildPipeline.py": {"sha1": "e991626c0aee9d7b", "mtime": 1785338517.4840038, "size": 23557}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesAnnAssign.py": {"sha1": "15bb32adb7093ed7", "mtime": 1785332415.1796682, "size": 22584}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesAssign.py": {"sha1": "2b59175b77f1304e", "mtime": 1785343736.8740923, "size": 24369}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesAugAssign.py": {"sha1": "31e49accebfc8aac", "mtime": 1784751046.0461829, "size": 12874}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesBase.py": {"sha1": "63a3d17e96a083ac", "mtime": 1785332415.2080498, "size": 8740}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesBody.py": {"sha1": "81eb28ba912467a6", "mtime": 1784566611.8626723, "size": 8538}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesClassDef.py": {"sha1": "aa45364399b86a03", "mtime": 1785345709.6485052, "size": 142863}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesEnum.py": {"sha1": "f05b14a2ad5767a7", "mtime": 1784741624.7278736, "size": 8520}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesExpr.py": {"sha1": "68f2617198f5757f", "mtime": 1785352882.3350165, "size": 144462}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesExprCall.py": {"sha1": "5c482c6aac2ba83b", "mtime": 1785332415.2151341, "size": 250062}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesExprOps.py": {"sha1": "be8c2d7b882881c8", "mtime": 1784791452.111348, "size": 12796}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesFor.py": {"sha1": "456fb516ba3c5002", "mtime": 1785332415.1896677, "size": 17319}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesFunctions.py": {"sha1": "1073ffca7e27aae5", "mtime": 1785332415.2064638, "size": 45439}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesIf.py": {"sha1": "66de93aaeebc0601", "mtime": 1784909392.040444, "size": 5211}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesImports.py": {"sha1": "6293eee0a5805aa5", "mtime": 1785332415.2416043, "size": 25274}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesMain.py": {"sha1": "4a7b57e6bd18f65e", "mtime": 1785332415.1935978, "size": 21362}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesNonlocal.py": {"sha1": "af9484a65085bf4b", "mtime": 1784540868.0555332, "size": 5336}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesReturn.py": {"sha1": "2703a899f26b771d", "mtime": 1785332415.1835012, "size": 5496}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesStruct.py": {"sha1": "371fa89e15d8c015", "mtime": 1785352932.9305031, "size": 48672}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesTranslator.py": {"sha1": "62805d8ad3e9b5ba", "mtime": 1785332415.2370398, "size": 18196}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesType.py": {"sha1": "af1cc6aaab47a7d1", "mtime": 1785350678.7589717, "size": 60329}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesVar.py": {"sha1": "cb1aa3a78af6f362", "mtime": 1785332415.2565334, "size": 15697}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesWhile.py": {"sha1": "51f0144d6e8188d9", "mtime": 1784566611.8311827, "size": 4787}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\IncludesScanner.py": {"sha1": "6282c9b745a35b8f", "mtime": 1785332415.2009153, "size": 12723}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Phase1.py": {"sha1": "2d523679d6b886ad", "mtime": 1785347467.5013578, "size": 51449}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Phase2.py": {"sha1": "7ba06a9edf0fa6c7", "mtime": 1785351377.19578, "size": 51540}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\StubMerger.py": {"sha1": "cae1b2c5898ed6e5", "mtime": 1785389144.9056978, "size": 91558}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\VLogger.py": {"sha1": "bdf5730851fb95f2", "mtime": 1785332415.2542837, "size": 10068}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\main.py": {"sha1": "c2010cffc6092ea2", "mtime": 1785332415.2064638, "size": 26351}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\_list.py": {"sha1": "7cadfe07e983fd90", "mtime": 1785338614.5410473, "size": 3238}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\argparse.py": {"sha1": "b370d93b74bf55cc", "mtime": 1785347242.759819, "size": 18275}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\ast\\__init__.py": {"sha1": "f3444ec56937284f", "mtime": 1785332415.2553575, "size": 3421}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\ast\\astaux.py": {"sha1": "4337fb260448bbe2", "mtime": 1784006094.7981195, "size": 11489}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\ast\\base.py": {"sha1": "22bc0df83b3f0e62", "mtime": 1785332415.1850114, "size": 14992}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\ast\\exprs.py": {"sha1": "b543bc1dfb592119", "mtime": 1785332415.2436252, "size": 40886}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\ast\\lexer.py": {"sha1": "e217def267d3d4a8", "mtime": 1785332415.2310088, "size": 24109}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\ast\\match.py": {"sha1": "4dd6b3f1427d1cc5", "mtime": 1782961799.8492737, "size": 12309}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\ast\\parser.py": {"sha1": "fde6db0747bdd959", "mtime": 1785348036.106818, "size": 87525}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\ast\\stmts.py": {"sha1": "657e182b27c2a022", "mtime": 1783929993.759902, "size": 37926}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\ast\\tokens.py": {"sha1": "b547ac4f380bddb6", "mtime": 1783165480.469121, "size": 13722}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\atom.py": {"sha1": "271ea3decb810db2", "mtime": 1782226548.693161, "size": 1290}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\hashlib\\__init__.py": {"sha1": "96837bcc64032444", "mtime": 1777902641.540433, "size": 186}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\hashlib\\__md5.py": {"sha1": "19f8024d10c828e8", "mtime": 1784356818.7075372, "size": 5847}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\hashlib\\__sha1.py": {"sha1": "0df65b8ed15664b0", "mtime": 1784356827.656474, "size": 4516}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\hashlib\\__sha256.py": {"sha1": "c9d54a4158f7f5a8", "mtime": 1782266203.9352357, "size": 5332}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\hashlib\\__sha512.py": {"sha1": "6ff26590374ae6fc", "mtime": 1782266223.3380039, "size": 7162}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\hashtable.py": {"sha1": "2fbec3db55b30ad4", "mtime": 1785337460.8923311, "size": 9701}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\json\\__init__.py": {"sha1": "57288496f7c2d1ad", "mtime": 1783239811.8873823, "size": 7653}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\json\\__parser.py": {"sha1": "240a9a4157959a9f", "mtime": 1782826918.100951, "size": 7517}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\json\\__writer.py": {"sha1": "20cd49775c100a38", "mtime": 1782826901.8906734, "size": 3784}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\linkedlist.py": {"sha1": "a5e9a83e9db303ad", "mtime": 1785337078.812168, "size": 17137}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\llvmlite\\__init__.py": {"sha1": "1d74d1d3a174c684", "mtime": 1785332415.2151341, "size": 17031}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\llvmlite\\__builder.py": {"sha1": "5a1d8c48f1243746", "mtime": 1785342190.6646752, "size": 51186}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\llvmlite\\__function.py": {"sha1": "874bac141c97bae9", "mtime": 1785342172.222551, "size": 30049}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\llvmlite\\__module.py": {"sha1": "692919c5a194ac8d", "mtime": 1785332415.2502255, "size": 23144}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\llvmlite\\__types.py": {"sha1": "2d8debefda779c40", "mtime": 1785332415.2141044, "size": 18976}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\llvmlite\\__values.py": {"sha1": "f9e36e2cd6fa659f", "mtime": 1784566611.8301415, "size": 6739}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\llvmlite\\__verify.py": {"sha1": "6b3bc463fd044545", "mtime": 1784566611.82952, "size": 14751}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\memhub.py": {"sha1": "ca40915f11b8b6ad", "mtime": 1785336321.3175714, "size": 21931}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\platmacro.py": {"sha1": "b57252077e6b596b", "mtime": 1785332415.2187803, "size": 1266}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\posix.py": {"sha1": "28de517e3820658a", "mtime": 1785335629.2014928, "size": 10586}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\stdarg.py": {"sha1": "71e0a3ffcb3ebfad", "mtime": 1781258888.113146, "size": 277}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\stdint.py": {"sha1": "f5522571bcce7bcb", "mtime": 1782383975.8824987, "size": 4356}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\stdio.py": {"sha1": "285b6aa29a34754d", "mtime": 1785332415.1829746, "size": 561}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\stdlib.py": {"sha1": "3aa6057398be5673", "mtime": 1785319487.0321114, "size": 374}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\string.py": {"sha1": "4daf5ed3f8e421a1", "mtime": 1785332415.2233481, "size": 11037}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\subprocess.py": {"sha1": "a335eb99f2e34479", "mtime": 1785319401.2041914, "size": 7841}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\sys.py": {"sha1": "0c67644125bea0fd", "mtime": 1785325556.7317626, "size": 5606}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\viperio.py": {"sha1": "c9f4be41ca1cc2b4", "mtime": 1782812279.506002, "size": 1556}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\viperlib.py": {"sha1": "e307a2d809cef071", "mtime": 1785318582.5499828, "size": 56783}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\w32\\fileio.py": {"sha1": "72dbbb563aa943b0", "mtime": 1785332415.1891341, "size": 13751}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\w32\\win32base.py": {"sha1": "fc980acec33d69a7", "mtime": 1785332415.2228394, "size": 2653}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\w32\\win32console.py": {"sha1": "bbdf3bbd4c3bc28c", "mtime": 1781200703.5338137, "size": 5604}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\w32\\win32file.py": {"sha1": "f6b51804a0ba8ff0", "mtime": 1782531158.744144, "size": 8424}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\w32\\win32process.py": {"sha1": "067c78e9f121dce3", "mtime": 1781200703.5409546, "size": 4802}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\w32\\win32sync.py": {"sha1": "06f53cc594b4ac6c", "mtime": 1782297500.2581685, "size": 4726}} \ No newline at end of file +{"D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\Projectrans\\Config.vp": {"sha1": "c0042adc0b7ec5df", "mtime": 1785332415.2264168, "size": 14060}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\Projectrans\\Utils.vp": {"sha1": "4650533467115342", "mtime": 1785332415.2054548, "size": 4900}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\StubGen\\Converter.vp": {"sha1": "3c5f1c61545644a9", "mtime": 1785332415.2120533, "size": 35262}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\__init__.vp": {"sha1": "6a19179426e9a883", "mtime": 1785332415.1753137, "size": 820}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\BuildPipeline.vp": {"sha1": "a38b726f4a82545f", "mtime": 1785397411.8500457, "size": 23570}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesAnnAssign.vp": {"sha1": "15bb32adb7093ed7", "mtime": 1785332415.1796682, "size": 22584}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesAssign.vp": {"sha1": "2b59175b77f1304e", "mtime": 1785343736.8740923, "size": 24369}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesAugAssign.vp": {"sha1": "31e49accebfc8aac", "mtime": 1784751046.0461829, "size": 12874}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesBase.vp": {"sha1": "63a3d17e96a083ac", "mtime": 1785332415.2080498, "size": 8740}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesBody.vp": {"sha1": "81eb28ba912467a6", "mtime": 1784566611.8626723, "size": 8538}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesClassDef.vp": {"sha1": "aa45364399b86a03", "mtime": 1785345709.6485052, "size": 142863}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesEnum.vp": {"sha1": "f05b14a2ad5767a7", "mtime": 1784741624.7278736, "size": 8520}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesExpr.vp": {"sha1": "bde6b4cc0847ee6d", "mtime": 1785398911.198053, "size": 145938}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesExprCall.vp": {"sha1": "efefa18c5d6c2d81", "mtime": 1785397182.7094119, "size": 261395}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesExprOps.vp": {"sha1": "be8c2d7b882881c8", "mtime": 1784791452.111348, "size": 12796}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesFor.vp": {"sha1": "456fb516ba3c5002", "mtime": 1785332415.1896677, "size": 17319}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesFunctions.vp": {"sha1": "1073ffca7e27aae5", "mtime": 1785332415.2064638, "size": 45439}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesIf.vp": {"sha1": "f4cdbca2f8802c12", "mtime": 1785390159.3673935, "size": 5626}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesImports.vp": {"sha1": "6293eee0a5805aa5", "mtime": 1785332415.2416043, "size": 25274}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesMain.vp": {"sha1": "4a7b57e6bd18f65e", "mtime": 1785332415.1935978, "size": 21362}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesNonlocal.vp": {"sha1": "af9484a65085bf4b", "mtime": 1784540868.0555332, "size": 5336}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesReturn.vp": {"sha1": "4c644ade1f0d6d02", "mtime": 1785394149.332443, "size": 6334}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesStruct.vp": {"sha1": "371fa89e15d8c015", "mtime": 1785352932.9305031, "size": 48672}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesTranslator.vp": {"sha1": "62805d8ad3e9b5ba", "mtime": 1785332415.2370398, "size": 18196}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesType.vp": {"sha1": "af1cc6aaab47a7d1", "mtime": 1785350678.7589717, "size": 60329}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesVar.vp": {"sha1": "cb1aa3a78af6f362", "mtime": 1785332415.2565334, "size": 15697}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesWhile.vp": {"sha1": "8dc65d4c71e2936a", "mtime": 1785390170.5239043, "size": 5202}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\IncludesScanner.vp": {"sha1": "8d6185cf886c0334", "mtime": 1785398707.0211506, "size": 13021}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Phase1.vp": {"sha1": "fc26f66203d7cbb7", "mtime": 1785398809.9049404, "size": 51449}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Phase2.vp": {"sha1": "c1bb03b1eae141e0", "mtime": 1785398659.7543666, "size": 50899}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\StubMerger.vp": {"sha1": "9dbc46e5249ed198", "mtime": 1785398798.4501393, "size": 92415}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\VLogger.vp": {"sha1": "bdf5730851fb95f2", "mtime": 1785332415.2542837, "size": 10068}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\main.vp": {"sha1": "484879ffecdf2b08", "mtime": 1785398833.4931703, "size": 27267}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\_list.vp": {"sha1": "7cadfe07e983fd90", "mtime": 1785338614.5410473, "size": 3238}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\argparse.vp": {"sha1": "b370d93b74bf55cc", "mtime": 1785347242.759819, "size": 18275}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\ast\\__init__.vp": {"sha1": "f3444ec56937284f", "mtime": 1785332415.2553575, "size": 3421}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\ast\\astaux.vp": {"sha1": "4337fb260448bbe2", "mtime": 1784006094.7981195, "size": 11489}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\ast\\base.vp": {"sha1": "22bc0df83b3f0e62", "mtime": 1785332415.1850114, "size": 14992}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\ast\\exprs.vp": {"sha1": "b543bc1dfb592119", "mtime": 1785332415.2436252, "size": 40886}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\ast\\lexer.vp": {"sha1": "e217def267d3d4a8", "mtime": 1785332415.2310088, "size": 24109}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\ast\\match.vp": {"sha1": "4dd6b3f1427d1cc5", "mtime": 1782961799.8492737, "size": 12309}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\ast\\parser.vp": {"sha1": "fde6db0747bdd959", "mtime": 1785348036.106818, "size": 87525}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\ast\\stmts.vp": {"sha1": "657e182b27c2a022", "mtime": 1783929993.759902, "size": 37926}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\ast\\tokens.vp": {"sha1": "b547ac4f380bddb6", "mtime": 1783165480.469121, "size": 13722}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\atom.vp": {"sha1": "aa246c6e6aa30484", "mtime": 1785389628.701967, "size": 1198}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\hashlib\\__init__.vp": {"sha1": "96837bcc64032444", "mtime": 1777902641.540433, "size": 186}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\hashlib\\__md5.vp": {"sha1": "19f8024d10c828e8", "mtime": 1784356818.7075372, "size": 5847}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\hashlib\\__sha1.vp": {"sha1": "0df65b8ed15664b0", "mtime": 1784356827.656474, "size": 4516}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\hashlib\\__sha256.vp": {"sha1": "c9d54a4158f7f5a8", "mtime": 1782266203.9352357, "size": 5332}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\hashlib\\__sha512.vp": {"sha1": "6ff26590374ae6fc", "mtime": 1782266223.3380039, "size": 7162}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\hashtable.vp": {"sha1": "2fbec3db55b30ad4", "mtime": 1785337460.8923311, "size": 9701}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\json\\__init__.vp": {"sha1": "57288496f7c2d1ad", "mtime": 1783239811.8873823, "size": 7653}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\json\\__parser.vp": {"sha1": "240a9a4157959a9f", "mtime": 1782826918.100951, "size": 7517}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\json\\__writer.vp": {"sha1": "20cd49775c100a38", "mtime": 1782826901.8906734, "size": 3784}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\linkedlist.vp": {"sha1": "a5e9a83e9db303ad", "mtime": 1785337078.812168, "size": 17137}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\llvmlite\\__init__.vp": {"sha1": "1d74d1d3a174c684", "mtime": 1785332415.2151341, "size": 17031}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\llvmlite\\__builder.vp": {"sha1": "5a1d8c48f1243746", "mtime": 1785342190.6646752, "size": 51186}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\llvmlite\\__function.vp": {"sha1": "874bac141c97bae9", "mtime": 1785342172.222551, "size": 30049}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\llvmlite\\__module.vp": {"sha1": "692919c5a194ac8d", "mtime": 1785332415.2502255, "size": 23144}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\llvmlite\\__types.vp": {"sha1": "2d8debefda779c40", "mtime": 1785332415.2141044, "size": 18976}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\llvmlite\\__values.vp": {"sha1": "f9e36e2cd6fa659f", "mtime": 1784566611.8301415, "size": 6739}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\llvmlite\\__verify.vp": {"sha1": "6b3bc463fd044545", "mtime": 1784566611.82952, "size": 14751}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\memhub.vp": {"sha1": "ca40915f11b8b6ad", "mtime": 1785336321.3175714, "size": 21931}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\platmacro.vp": {"sha1": "b57252077e6b596b", "mtime": 1785332415.2187803, "size": 1266}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\posix.vp": {"sha1": "28de517e3820658a", "mtime": 1785335629.2014928, "size": 10586}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\stdarg.vp": {"sha1": "71e0a3ffcb3ebfad", "mtime": 1781258888.113146, "size": 277}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\stdint.vp": {"sha1": "f5522571bcce7bcb", "mtime": 1782383975.8824987, "size": 4356}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\stdio.vp": {"sha1": "285b6aa29a34754d", "mtime": 1785332415.1829746, "size": 561}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\stdlib.vp": {"sha1": "3aa6057398be5673", "mtime": 1785319487.0321114, "size": 374}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\string.vp": {"sha1": "4daf5ed3f8e421a1", "mtime": 1785332415.2233481, "size": 11037}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\subprocess.vp": {"sha1": "a335eb99f2e34479", "mtime": 1785319401.2041914, "size": 7841}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\sys.vp": {"sha1": "0c67644125bea0fd", "mtime": 1785325556.7317626, "size": 5606}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\viperio.vp": {"sha1": "c9f4be41ca1cc2b4", "mtime": 1782812279.506002, "size": 1556}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\viperlib.vp": {"sha1": "e307a2d809cef071", "mtime": 1785318582.5499828, "size": 56783}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\w32\\fileio.vp": {"sha1": "72dbbb563aa943b0", "mtime": 1785332415.1891341, "size": 13751}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\w32\\win32base.vp": {"sha1": "fc980acec33d69a7", "mtime": 1785332415.2228394, "size": 2653}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\w32\\win32console.vp": {"sha1": "bbdf3bbd4c3bc28c", "mtime": 1781200703.5338137, "size": 5604}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\w32\\win32file.vp": {"sha1": "f6b51804a0ba8ff0", "mtime": 1782531158.744144, "size": 8424}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\w32\\win32process.vp": {"sha1": "067c78e9f121dce3", "mtime": 1781200703.5409546, "size": 4802}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\w32\\win32sync.vp": {"sha1": "06f53cc594b4ac6c", "mtime": 1782297500.2581685, "size": 4726}} \ No newline at end of file diff --git a/TransPyV/temp/_sha1_map.txt b/TransPyV/temp/_sha1_map.txt index fb30c62..d319891 100644 --- a/TransPyV/temp/_sha1_map.txt +++ b/TransPyV/temp/_sha1_map.txt @@ -1,80 +1,80 @@ -067c78e9f121dce3:includes/w32\win32process.py -06f53cc594b4ac6c:includes/w32\win32sync.py -0c67644125bea0fd:includes/sys.py -0df65b8ed15664b0:includes/hashlib\__sha1.py -1073ffca7e27aae5:lib/core/Handles/HandlesFunctions.py -15bb32adb7093ed7:lib/core/Handles/HandlesAnnAssign.py -19f8024d10c828e8:includes/hashlib\__md5.py -1d74d1d3a174c684:includes/llvmlite\__init__.py -20cd49775c100a38:includes/json\__writer.py -22bc0df83b3f0e62:includes/ast\base.py -240a9a4157959a9f:includes/json\__parser.py -2703a899f26b771d:lib/core/Handles/HandlesReturn.py -271ea3decb810db2:includes/atom.py -285b6aa29a34754d:includes/stdio.py -28de517e3820658a:includes/posix.py -2b59175b77f1304e:lib/core/Handles/HandlesAssign.py -2d523679d6b886ad:lib/core/Phase1.py -2d8debefda779c40:includes/llvmlite\__types.py -2fbec3db55b30ad4:includes/hashtable.py -31e49accebfc8aac:lib/core/Handles/HandlesAugAssign.py -371fa89e15d8c015:lib/core/Handles/HandlesStruct.py -3aa6057398be5673:includes/stdlib.py -3c5f1c61545644a9:lib/StubGen/Converter.py -4337fb260448bbe2:includes/ast\astaux.py -456fb516ba3c5002:lib/core/Handles/HandlesFor.py -4650533467115342:lib/Projectrans/Utils.py -4a7b57e6bd18f65e:lib/core/Handles/HandlesMain.py -4daf5ed3f8e421a1:includes/string.py -4dd6b3f1427d1cc5:includes/ast\match.py -51f0144d6e8188d9:lib/core/Handles/HandlesWhile.py -57288496f7c2d1ad:includes/json\__init__.py -5a1d8c48f1243746:includes/llvmlite\__builder.py -5c482c6aac2ba83b:lib/core/Handles/HandlesExprCall.py -62805d8ad3e9b5ba:lib/core/Handles/HandlesTranslator.py -6282c9b745a35b8f:lib/core/IncludesScanner.py -6293eee0a5805aa5:lib/core/Handles/HandlesImports.py -63a3d17e96a083ac:lib/core/Handles/HandlesBase.py -657e182b27c2a022:includes/ast\stmts.py -66de93aaeebc0601:lib/core/Handles/HandlesIf.py -68f2617198f5757f:lib/core/Handles/HandlesExpr.py -692919c5a194ac8d:includes/llvmlite\__module.py -6a19179426e9a883:lib/__init__.py -6b3bc463fd044545:includes/llvmlite\__verify.py -6ff26590374ae6fc:includes/hashlib\__sha512.py -71e0a3ffcb3ebfad:includes/stdarg.py -72dbbb563aa943b0:includes/w32\fileio.py -7ba06a9edf0fa6c7:lib/core/Phase2.py -7cadfe07e983fd90:includes/_list.py -81eb28ba912467a6:lib/core/Handles/HandlesBody.py -874bac141c97bae9:includes/llvmlite\__function.py -96837bcc64032444:includes/hashlib\__init__.py -a335eb99f2e34479:includes/subprocess.py -a5e9a83e9db303ad:includes/linkedlist.py -aa45364399b86a03:lib/core/Handles/HandlesClassDef.py -af1cc6aaab47a7d1:lib/core/Handles/HandlesType.py -af9484a65085bf4b:lib/core/Handles/HandlesNonlocal.py -b370d93b74bf55cc:includes/argparse.py -b543bc1dfb592119:includes/ast\exprs.py -b547ac4f380bddb6:includes/ast\tokens.py -b57252077e6b596b:includes/platmacro.py -bbdf3bbd4c3bc28c:includes/w32\win32console.py -bdf5730851fb95f2:lib/core/VLogger.py -be8c2d7b882881c8:lib/core/Handles/HandlesExprOps.py -c0042adc0b7ec5df:lib/Projectrans/Config.py -c2010cffc6092ea2:main.py -c9d54a4158f7f5a8:includes/hashlib\__sha256.py -c9f4be41ca1cc2b4:includes/viperio.py -ca40915f11b8b6ad:includes/memhub.py -cae1b2c5898ed6e5:lib/core/StubMerger.py -cb1aa3a78af6f362:lib/core/Handles/HandlesVar.py -e217def267d3d4a8:includes/ast\lexer.py -e307a2d809cef071:includes/viperlib.py -e991626c0aee9d7b:lib/core/BuildPipeline.py -f05b14a2ad5767a7:lib/core/Handles/HandlesEnum.py -f3444ec56937284f:includes/ast\__init__.py -f5522571bcce7bcb:includes/stdint.py -f6b51804a0ba8ff0:includes/w32\win32file.py -f9e36e2cd6fa659f:includes/llvmlite\__values.py -fc980acec33d69a7:includes/w32\win32base.py -fde6db0747bdd959:includes/ast\parser.py +067c78e9f121dce3:includes/w32\win32process.vp +06f53cc594b4ac6c:includes/w32\win32sync.vp +0c67644125bea0fd:includes/sys.vp +0df65b8ed15664b0:includes/hashlib\__sha1.vp +1073ffca7e27aae5:lib/core/Handles/HandlesFunctions.vp +15bb32adb7093ed7:lib/core/Handles/HandlesAnnAssign.vp +19f8024d10c828e8:includes/hashlib\__md5.vp +1d74d1d3a174c684:includes/llvmlite\__init__.vp +20cd49775c100a38:includes/json\__writer.vp +22bc0df83b3f0e62:includes/ast\base.vp +240a9a4157959a9f:includes/json\__parser.vp +285b6aa29a34754d:includes/stdio.vp +28de517e3820658a:includes/posix.vp +2b59175b77f1304e:lib/core/Handles/HandlesAssign.vp +2d8debefda779c40:includes/llvmlite\__types.vp +2fbec3db55b30ad4:includes/hashtable.vp +31e49accebfc8aac:lib/core/Handles/HandlesAugAssign.vp +371fa89e15d8c015:lib/core/Handles/HandlesStruct.vp +3aa6057398be5673:includes/stdlib.vp +3c5f1c61545644a9:lib/StubGen/Converter.vp +4337fb260448bbe2:includes/ast\astaux.vp +456fb516ba3c5002:lib/core/Handles/HandlesFor.vp +4650533467115342:lib/Projectrans/Utils.vp +484879ffecdf2b08:main.vp +4a7b57e6bd18f65e:lib/core/Handles/HandlesMain.vp +4c644ade1f0d6d02:lib/core/Handles/HandlesReturn.vp +4daf5ed3f8e421a1:includes/string.vp +4dd6b3f1427d1cc5:includes/ast\match.vp +57288496f7c2d1ad:includes/json\__init__.vp +5a1d8c48f1243746:includes/llvmlite\__builder.vp +62805d8ad3e9b5ba:lib/core/Handles/HandlesTranslator.vp +6293eee0a5805aa5:lib/core/Handles/HandlesImports.vp +63a3d17e96a083ac:lib/core/Handles/HandlesBase.vp +657e182b27c2a022:includes/ast\stmts.vp +692919c5a194ac8d:includes/llvmlite\__module.vp +6a19179426e9a883:lib/__init__.vp +6b3bc463fd044545:includes/llvmlite\__verify.vp +6ff26590374ae6fc:includes/hashlib\__sha512.vp +71e0a3ffcb3ebfad:includes/stdarg.vp +72dbbb563aa943b0:includes/w32\fileio.vp +7cadfe07e983fd90:includes/_list.vp +81eb28ba912467a6:lib/core/Handles/HandlesBody.vp +874bac141c97bae9:includes/llvmlite\__function.vp +8d6185cf886c0334:lib/core/IncludesScanner.vp +8dc65d4c71e2936a:lib/core/Handles/HandlesWhile.vp +96837bcc64032444:includes/hashlib\__init__.vp +9dbc46e5249ed198:lib/core/StubMerger.vp +a335eb99f2e34479:includes/subprocess.vp +a38b726f4a82545f:lib/core/BuildPipeline.vp +a5e9a83e9db303ad:includes/linkedlist.vp +aa246c6e6aa30484:includes/atom.vp +aa45364399b86a03:lib/core/Handles/HandlesClassDef.vp +af1cc6aaab47a7d1:lib/core/Handles/HandlesType.vp +af9484a65085bf4b:lib/core/Handles/HandlesNonlocal.vp +b370d93b74bf55cc:includes/argparse.vp +b543bc1dfb592119:includes/ast\exprs.vp +b547ac4f380bddb6:includes/ast\tokens.vp +b57252077e6b596b:includes/platmacro.vp +bbdf3bbd4c3bc28c:includes/w32\win32console.vp +bde6b4cc0847ee6d:lib/core/Handles/HandlesExpr.vp +bdf5730851fb95f2:lib/core/VLogger.vp +be8c2d7b882881c8:lib/core/Handles/HandlesExprOps.vp +c0042adc0b7ec5df:lib/Projectrans/Config.vp +c1bb03b1eae141e0:lib/core/Phase2.vp +c9d54a4158f7f5a8:includes/hashlib\__sha256.vp +c9f4be41ca1cc2b4:includes/viperio.vp +ca40915f11b8b6ad:includes/memhub.vp +cb1aa3a78af6f362:lib/core/Handles/HandlesVar.vp +e217def267d3d4a8:includes/ast\lexer.vp +e307a2d809cef071:includes/viperlib.vp +efefa18c5d6c2d81:lib/core/Handles/HandlesExprCall.vp +f05b14a2ad5767a7:lib/core/Handles/HandlesEnum.vp +f3444ec56937284f:includes/ast\__init__.vp +f4cdbca2f8802c12:lib/core/Handles/HandlesIf.vp +f5522571bcce7bcb:includes/stdint.vp +f6b51804a0ba8ff0:includes/w32\win32file.vp +f9e36e2cd6fa659f:includes/llvmlite\__values.vp +fc26f66203d7cbb7:lib/core/Phase1.vp +fc980acec33d69a7:includes/w32\win32base.vp +fde6db0747bdd959:includes/ast\parser.vp diff --git a/TransPyV/temp/_shared_sym.json b/TransPyV/temp/_shared_sym.json index 39bbdd808b011919549538687f00032b315334a3..35b5b659bf11d7347b2399dc768268d1fcb7a82d 100644 GIT binary patch delta 100263 zcma&v1$Y(5`v>~&#O1_}2Mf}oEd&Wtpio>3#hnmkg9Hfw_tRYD0=mx~uI3EO*|m{gzAX}60~+fUTa&@g!ZnJ zm(y&7y83!uDjJFkCAUbfl-zQ3R;d}@JZGtYByY9Jc~k3>;WZG2Y8Tgd1qI;8wXI$& z_u|L66z_`J__0gz>1CrIJf~7<4{f-^=RiROSF7T)%tSv#eOe_36w&I|^QrA??iHU9 z)2nh^T!m_tt0pAG#2XEo^E9Z4_M(Z;MZI!z?P;HM_gRdE(9ZYq`S?p&UTywJ^R1w% zhkQ;)$Pg<}KOgMR`~G5Tt}Xu7XG{=s6uRyck%1r4{d{LN!;d3-eCMr}IU4ataiLL@ z5B2ophkE)~MeK{7{)PRG*sVjoqBK`;|F)q<2s)EiW4Qm1q3<==4Az!M|K)GbOkZ$| z=Vb?W)rL&-pNF=hCAVtDvi#?vFQ6HA9rw>^7WRH?`wZc8j@To4-u}QF+J>-zUX>`Z z7Fs``=@4Va)Oa6ir}hRkEn3PCOpfUpq{Z|M{*lRYs`1o;;UDv;+kQTihsOoe|0ZpCT*!1k6ylo_ za&9ovrS44BYUG8)w?QbCcqf^DOrHEzs5belu)65(+8HfuK@36@{tVL+{tS^HhsDkYD>JVhV*M@wPVeX?@oG@CL8a+C;ng zxT2ir%A<(tJm;?Y6TZ!9o~0b+m)cmb@;sNbsvao{+nN^<$*&hQ2k@T@n8z70IVGu0 z4_Tf3mxAU+${oxu=16uRCk>;PYS!K+(0@;l(`K%msD!*05Je)oL zl6Q|WKVV85-n^>$PZr)rt69x_!JqxuTBAI{3U_>NenBPZQ;(jRym^T_<|IC~zIkna zD($m|=07|#=^BvwiHO^+?6^@$yc<@s5RCbf%Xq{)L z*_<-8@G`SMFGx$yhIiJe1^g8@wKJAJRjwD2wbXL+NVcFe8Y7iIx)`D7t+K*Anyu^1 zscllxNuzlEmFE8J<2JnL>yRq^(f5Jg{Lhum~oX*4<)8nYEQ#>j|aXy@_Hz%+>V@CPSPhB~Rm)>BW$O78(Bdx-# z^Sc|&Z&`)5qDI-96mQ<5F|DS&UFNcUmPYY-Nt~Qt#^dY1O9iyx)yQ z5-GGV&0l({!R_=0(pPs95Bt`lFZqHU=0q0VPE&T8YbmTFrR+>I8otYXgN@X)rGM}1 z%^P;6S-V$7#x>eJc6T<%dZ{^jGV};eJ%W}tzYDIn|t4)Esplm43^n16J{`~{n*r>aw(irIRE zR={pOWa~K!IepZe$9~pBemzFr>#aVKSHhp>d)$0eDavEF&`!g4l782hzoW|e=^L$B z{Jp2los}dR)$BAa{S5hg^f%^v$`<)MJvh`eOX;(e{p3kMVFW2o*<^8H-sc;SAM6X58}ks`Mc&3?y1f9 z&D&+Z(T*hT%tL)@*`d%x?ap83o$i#%6Z2&;b?In`G}l~wIpf@|CrCnlrPM$ zP5pb)p|n{ub8>T)X1Z*dHGzkQ*?f43cV;s``-*l50k_Rxc&T~a#d2kCP4q_X!h@YE z-~EbO*Q{!^L6%74_^0;xw=?JQ)nVT{41@D-`<#evPOFH+?8G;ITjPg zXdnLYUvtMI$vu=0CS}d=jvbg3ou#I@rz&Qt{dy?;agf=`2FWrq>nsyRJf0Yq$fMqw zyBEoFr>ET9Jw>?}QtnG_EDkSqsmzWew9(L<4!l0|x>>puIqc3vMI3WaQ4uGpi0F!e zPIgvb2pqmq#HI06gTp>H8b~Xau0X%Cq0yTH=IRy#!8z%|H5SU4NOQb z(Jd?aBlWdWXqKP5Ua6|Xhd*bQPDKjRigLG15%&}oTC67uEy+svSLLLMVnLFlE8=gT8Ni%!v>Zwj!?#spPBjPCfMUuopCKhUDGX|ZxfMtY^8qd$Lj zF(QoL46>vl(~)djqIM|Q@`EC0r=JqM39+~o_MEbtsWaUQvrI8X^%DIyocb+=*PZ1U z!v74n^kKJRdFun#>PYPFTAQaif)VY@&1Op*#gDgUmKfgiIrA2UVtE5Bv_zCiEbqt5 z92?Da>Q}95^~A)4xcJ11y((0br!D#ry7h9$Xf~i1AGzAmn^#{UC+5@&qitq|qb={j z%%d{vob~48r#US=Y<*;Vt?)|6KpOt^;zd8C*}Yih7^~;MkG~@8$Tg0iFmbqCn3aFQ zBim@tEtY#mQ)D0aFT%f=Y6;>midlMUsa8uVg^Q+i#PJ)eElFAvr)7)6^eO)BwStAT zF$F9+B8VEJSirpeLHe9B5%sl6g)Co*$V=ESOeSfpWl_i9l`_G%{2t@%jI4f-#ggod> z+;lHuySZ{)Oy$b4@d?q172;#!D^!%LvNoOeQeUoqKVmxTAFuaiv0oYyFDoTRH0>Wo zOky&mHc$UMq7Lu+XGAKS5idLQdl`(AjZi-MuZZEuCHhmr8rEafp|u+|tQ8oKs%p8V zy{cvHYhq`=Yhyp0^IYRA+gQs{b+{PTZ)j_+&E(0*&)SI&)`E)2&ChhQ zmZt4bCc4nsT1?@29jv#tt6i;+7`shXqfVw(>}kzZFm)u!ny7u;%bG2wE}f?1McH`k zJTWC&KRwgzqm@gP$u&y;Fh5SSs@7g&s%}vy9pY206Hw%U+aZa(!ecs*EjY{?$RG8w zjyBzn&p$1@6aU}g`=h>;A~9KPwOwher830PhQb5>xzJ!@FeyR{ z4YiIkLbc)zm^pMtMY*&asX%b(7&mJ;Ft%63Zx4Um00UL~68#f*GTt zu^KeXO6zJ$e(4b z*w0Wb?VVq<4^+8h#t4YQ#6}_tt#jNO%9k9bEv4Iw@G88{P31$rdA-%-rIwUg#Hh!} zVl0b44?boc&RXh8uvazeK?M$AgJcAM^j2}t&vl+QCaPutPdi~9;5A>>M`w%m#C6Wm zaKe~V_f$HC6w7qtq;&{8s;8-Nhqg{iBX;j1`t2#&Fn>4Z=ds?!h9r`d{l@A-CfNa0 zhbY*OTk2SCJi}`4u22(}w!~|}XRZE0K53=YxIWm+rg98Xwdp@tJ1T6b9+a06=FQ)} zw5ISvzgh#e3siwEIu3;a;p)A6(Rk z;ajUXN^;r{6xN16w~h$N%yCrKDk!!_0qozt@=_O#>H>LQplu0T&`*XSIe#5w8_&+_ zAxjm61ltC(jj6o9$#$DP=qGoYMlF6-LV38=8pCrwrn4!kLlOr5gS{&DSNJx2pi`+T zqO~8wY`qk%=v><|V<5sG?eH$bYtOTpc&9AeKvS6kVjBylT}FukaucXE&(>23fvon|Had{e6n0Ad`Vh+8V25pFerDcsswG&fw97Wy9V8BS1$W!% zyi1=2KkRFZ%lP^mrb9)Ygq9>M6zG9;F#WB`S@sBOS9168UMAuZ4`T zavxTDkQ`N{r(1tuZ0sP}d9!Jspe0YRR`ElS=(l{!4C@O@uJ`Uk3#=(x)NJcyg;gFT zug|Tbei}B%I-kvu0ldgNI?vl0MJFYJ3#?)M%Q0R9yw$6Nsl&~PZ00dKy)oCih~*9v z%ZNF1nzQJhfih#YEbCnMTE>f=5}!GV5`=A|>qnyGN%Lq35H(mf5_Uvdxom5w!kXwo zVk6i%jq>!c+4MZmxiyLP(-Vk|f)+3-dx3Qd%N)#?h1sg}J+mms;Z6>jL#w~gdX@2i zN?W#@tHsB~REe(~S2a4JV)aTfvBn6KZd;V%#mZWyv4v@}p~PA1sx-Mh7@Kk^ul=!Q z0+YewKql5W1^V*FpIDNamL`_P$Slr-imbH-@UG=8laWtsQHRz#M$(-xUUQwJmbrR- zuei!F2~{dquAUGdU0pwaN#K;o#NV!S^fOt9hz%D~bs-Q?XVWQvA8wK|3wVhbf+W z)Zwoc-RBsWAEX5xa4Zm0Vwe(q$T3Vz;RINFaM&@*osu%klwzj2#~o8eoR~U%(m@w# zXf`6>^3!@gF*WIoJ|%`s>N&@9ky6ZW@C65LER>H1LP=VDu4A#g%;azN1rc-T`<+J| zAJ?f+L2c#_j)@|9Y!6z}5m!8uyRLd9*T!FS+;tax`MTq=m=aYecSElNRW?a0c+0WN zowE8J#|~pEQET_RgH9x=vZ6v=?>bJ3DY017?mKpiDU`|AKXgn$LUFpl|8z{kME)r) zofy%XuMtgW6Fz*%BZmti;&?7X;vUNoQAE#1w7oSAbO!OBPaFeHaU(^iEhziPjc1NY z{M=gVuY+Vb26I%F2v2-Q;p1hv-pMKanJH5Sd3J5FQKtvfOuGK#7-d=^Q+RfA8r}!; z{UOd^Iw&~CnzqXn?(QzGn+4La%Q4k-Oh$V4`67N!EARV~HlWKg(zD~!C6YjXK%u!) zicp@j#gS^dC6jq<2l>0tFh2CPqa&M58^mizDV9w=54S3E9W-vEWyc!Av0PLpm~VUI z=+5>G;o<)}>a*kYH=fR{jAZVmGQD+-VfSTGzU5^rqNHr>#asPN7f|ZGa|~e-LwR&t zyC`6req}E}RDE8mb3UszR8}QtgTJWCdr4H*Q;%+S_kTnO@$1alk4@CmM6IB)CRLLz zDvjVR0;t_Xy`6R0YCSryN`QM|X*X)+em>6D?9@>Hcvk5Dt)7`*IqFF8QXlBqbI;R( z(`W=*Hv?JdFgjzkxLZc7ux>%lP@a3zQQJ$cFic;xS2V0Oa?*^8@=gKH2CTInefV+6 zd(nw(pp5Zt@PFHsM(IJ$p=^Pkx7BvpEVRf!u>E>qh3&E(#JWhMl`1xcB_?Nk_RBDS z#O#b@H}#}F|D^L_qiV*Q?a91`%Vhq;IE#NNSt#U)fCPA z+UgA9ITmLtc62!UbYzWF!}G6p()G$S?x`wS>UsB6OqQA}ri^Qumxs%9cDV$3>>s_n z*X}%2-dpz+m8XozpBI(qEvAg}{6@%=d@4_L#6EUsS5{_(Y{*u1-tP)l?s7O|S&I?8 z?#-}LtgTGu+s(b=xmesIPUjRhS}!C$(&@3%?ncNJoL#_~##WBtM|#U`O{}YQ2aTNK z?m9BP)QfuVs2c9>W^AcJd~_ja@50aAi&ZI0eg58Jz0$MSxfm*DE|%?Z6m4X?9y*3$ z<%nIcsO`QY&WQ+d@4^eeGy7r~H(O8m4u8eon@&6Q4oZc2^Y`}S>x(-lBO#4c5_#+h z=V(5=dr*~Pv6ZUzs!EULRF17yu}bACi8ONZd^W|eO&Y&ZQz^i6`j~EN4@Wv3UUZ^` zp%mS)xjKe#8%SNKAc)0 zn#^}DV5MBL%ZZZ$ea5(H5y)pPaK^D_GTIkM3yO8`cEc7^2^$tVhx1RlwJOhD8|H1) zTOJ~E7dg9zWxDdW0J>q3?UKip#rizOapk|Iu3)EK@=%gr8yp~eEOGX$ao=4W-JJN- zJw^TSv3rU(#Ajm4*w~)yOM#=$f9Ds*k1Ta|DIA%eUsEc&keD*EN2SX{lTjf#v|mLH zuz!WqpTEkXc5IQZ@5OO|(i0j@9UIoqT{^YHfOND&6wh7mtjNab8O5Q?n1eXTQVWVX zbY;uj84Bj#*4e0M6vs1Tj;ox#!p^@pvs`!HGW?5*-gHT3wJkcolskGUM(5Ix%nq)t zcDk@2?yYlnQ%4Zru*R8=U~yVd?KGX%zBp$~_3t)L^s|ole?Dna0S-R{4>Myzwd97}G2n-a0=#fzu4fn3l-!FFnFb zeM8}!Wq4bUaK{-6KPbc7d4&6)rSJn;T=4}&t0&E@xue`-u%ruTOZS( zGDY%#Q`|dmOEtZfk-guKOgDv$7fqzf@YqNPo$+0?4K@{);iF}E-CWx>(?0VHvp#U#^N|f@- z+fF-tN?ErH-39aWv+omAxF^QT2G~FLcyvm6WG+vS69olxXDy!+TB{*mX1b+mCBJDoz(lsJ~uG}-AKji$tm%7ofCyQe-2x676mv#o8mXSn04SoM^mlxB84r8s&t zaoXvM6_qK@`x+InUldbF$(KhLiqJ9&+0#UjxU=84h+ZL4y+K9oVx?(Ci`(BKkw!hu zpBcsR%asZ_wDl!r0U9-3ArU8Lyt=G?g(z1n%+`#T?U&K^HO5pT z_pfZ9f`r@F(zVN%mF?p&apMZz0J>GhJ{=R{=EV;&azgo$V!o+rAB&jBcWL75YWDFW z87|o`sjg4p4wAT5o>$8r#-E(C4KZDwCihS7EsE2X0$<+J1ch;*k|@3CbLZ8x!ZE5FxR0J#bpZ5 z9hf^siMo`cl1$;bD|4r)@;RlbCsTOt)Z8f=)}s_{WD3vSo47wkixJ3&HnfL$?C9cT zTF)Kbf6|Iw-XNLGbC>sCvN5LdGKIeL6ZhxDZLRc1_A#bR8L969MPzDY`+U<18Sb$g z*m`-X@p?*eT5Y5h z&wRCtw{tdgk~}puV%)8LD8+8dPPY5;!wL3gY^zZpoGluO-Hm%Wks9~1Oe0Pe^OGdm z7qS<6W^tBi#E4yD`QG*nR&=sFLo{Og{6_cW#IjCM?VSsMJ~@B1Oyk)GV#*jTH=Zn; z$vF6l&MSI@$WO~KkoDEmh|@%49^yWu=oc^h&}N*Wr@>>2Vtt~yse#PANI&~9rcLHI zPSBHJM($buM&It*-`vAk5x+W8#Y^v?_e4E zpAGNvK>H-6g-F5iv}1n3bzHPtsyWy`Q5h`r5A(<`)~s0eNon>)%3_&fghvXoM+({>7U#ah>;skGW#l-INMn-?;pU2kth}YkUYVX2c2@LKL#A?i!qMGG z#H$BwY~WtFDNRfXpsMH6Em`fwC=u)QPgUwXBlD(~2_E_%8OZRi4z(ctdIq8z>0 zn5n$=Xu76gM7w*fWsJR_*9t02JmR)imgPI!a{*k`BQH+nHH135f}bvC-Ays>H{{RgA9|E$Gn1{OPPtO~{ z0eoEsWpU0!{ZjEvP+|V)G98#6eQQr;rRSl#sXXsbdl4S;104lkU$zfm)#qtcd)$$m zr@6kj2Pmx5JXGDCpPu9Tk(#SFz4k!Qr&f_I=)PY@bNA7TU$K9|*sTn?d0>d4ZMteN zvmXB$4T>cRa z6^drc${apJ&y0uck;^@WHPnN}s~JK2D44EX(1C*5kPmx82gQ_3PS5IB=k}-e=WH&e zrswswCeQ4O!Zbavcwpalg!0P06Y_@Mr4BRch<&b?dQ(qU=a^l8guLf-`yj=Shaa@X zaPgFW$P4>5rHl-S@}>%wKSia9hv`L4*1xoOm1n(Y3)|#V_#*u6Yg)YXuj~V8uPsUw zPx23cP3J$0WWeS(_7}7}7LnpH{YK|KmeE&BdTU?CGIP!J?vdiCslN=>NXzkZ&=X8a z^X2L3Ngu~h_dRH>X#aqcihKZoQi!q0AAXKF)@HtJVmvv5yzXO^t z13hIl@y`PtDqAvNJ{V2W#$(I$HURF3i`__45Z%C~IP5{Rp$^+cZ!M;Xt$rz{EYPnm zVl`+p8r#|xUfoF3m^7H{jr>gWkDNanv5d@sTI1Y1|8wh(QW zziZ%!r_sZB6;J@h2k=`-wstH|F9oAzemIIs5j{_&dXa2v&nD>!aG#w|?QQ#otMGum*aNcmd~5 zIhw6_;7H6id4MgAsWO3hALrpG6i;U=h4@zkZJpW7g`D2Zsm`-XQ1H7lH2+_R+JgAu zLG;YbUcFp;S;t#jFxXaEVRvPa<~_t#P+^uuvM%C%sGO=)Li#Lvm?m$iZ65nx;ZHda3MNcg@zFO04zp+_*2wsZOx=**2R@fdrNW1~lw~I%eLwV%o z$Uxp@COyG)TTdn4ipl9lsi^t4v(P1?KAJk)R#;&*{ zYE6P2gB7o(%V;z+!@m^|3vn!TPyHL>$Y4vC@!6q{dkCGEPD##%IWiF#8}4|h|832e zML6bQqNv5u8ifS%*=CuSLT-x^Zv^|b;vKDyuiR6OY>q536@JLnnwPihanb31t+c`p z$7mmRdO2TQ$Z?xpSG0>d)f@p_tF1>4$e|@%{F!5=tSv1ezu1;$D^hK#L$|8LIzafm zx{ho%V!6EaA!hN_=Z=A_^C})z&+!jaSD{H#`B$G&_G$GUgV=~wXq*%5(Q^3~+`9&j zLo9rS?3dI;DV!b+NMe;&$Zf7%3A$8!rYhwg*_iHlchVDvHE~>LW8_3Owzkqu9aq?j z6>@8<+01d3oz|0z&FgttDn?Y|Omjys_E3)#ht3BdQ(Q(cYKJ+RIN9}y@HIdott#J43mPO(8UIy3#Ah!u~IiY=jPZwF^f z*3jKZ8n07fA|I{uOiYMDs+!_RV;`>NH&PsURUGf0|740;D~4QF8gy4!EAIk~>gyO} zYAC~P9^tY59BHQZGTbi1>B@K_Z_?i}#FQw*9UkeUQyn8rLu9zqBYoiklzx&7$4xNI zcYx!%DO&~=@F?Q(K$_)h8IFfQD5;p`PlKq4T{66oNBSd!9m7l~Wq4s3zHMw|0^gA4 z7|x94n?8gd`nV$#;RzBWeE3kR@82>UPmoYJ-4RISiNmN8KI=p~;V}}U5-o>QC9Et6duI_)Ecz#FgMuqwv5D1=D@YzeO;ulte8g-9a}BC=phX_F}AqUUxC3u8*f( zS^m_Xi4M94pvTDqdrh3DF*U5gK=xlA-Qm64uZz&(Ql(`g2sWeTG+%yNw8`({w1s50EM zGte_PK78#=#|+a58EN#0S&pZsX);Lf4Ad+Y-D5MZRA!Yp-D~#A{)(!7a5k;sg)+To zPcdpX*|c6p8r@|MmA_X8={=?HTzV|%j11B{2?dSjhqD~M{6wZ>fa$7?#FO?$)6y8) zhi}Sq%rf1Rk)A!rSU593G0!pF^h&1C`;b^OTeBTAO@SNU>qBU+Q=FPBQijVuB-bQ8 z-RQ%`dO9_q_HX6ai9JPj2wmc&8X32Iz4^HXj{fXR87poG8=Zw_=-|IDpe1^}kO~+o zlgN9*MjE|QQ`kZy77rCsEIkjR%DI2I*wKdVTPLrC>iOu=10P;wiK7dWyZaGpXIjkrpX({+QVAaXMrO} zAopHj8)@P)QlCG)p{CN=1U>HddWCJQSHMQPx3`Nf;X3DA=;8dZjdHgyt~<*bi3hK= zFIU;hE9{Gnvb7NtY97ohuCa|pUEMc*3$3-yMF`!Zxr@Kz1Y&*(=L9cyq_y5qXX$$r zw$e@$V^cSAyk5lLmUWh4MdgI%^|6yq_ulrEsp-yGUS^#FU9^tnopjI3$Z;du`LQuU z(Or3iO7s9z(M@vTg3hR2sO${($`2CVi$AF5eC82EeToOgIg{3O`qUXj#mU?p=ipjO zBj;_@P;1@PSvZ1~+r$TSb^gn;HpzAuC$1Ix(!(Y9x;dw^yLzyAeve)~4CNy3ukOya z?BmV(TL>T1gDTKg2Jm$~op0GleL`F!p!&%-b#e#bA-rDnNJWkjPnFfEvfc_iwOONw z=gKJTfsE4zCOGN+Wa}2up}DoLUWlkdOp;S&HMYq0ip%@j&q>abbh@br;c7mw)!X@! z&C)}}B?wx4@m34HV2*{P1@YmpRA&daO;07RL-cGysf?!Z;o*Ip@$82!;`%+`+Q<15 zd#R^B+}HVvMQxQABwBv)UfIL@JBPDITlE^^ip0mM&OcZmJw#lCXf?q3fX&fEI=6GC z;Efw67tO>5(Oh@wak$#f6FR&%gC5EBWW>)MoRhrN8+tNab?4cgD49Hoq-E5Gr#XN3 z=1nVDMsSS4yg#QaWLkK%<(8Mc&6)%re^ddyyYoe{FuaGrb8|qK;*Vspbx` zP2*Vcc?OR5Nj#*kWw5Ea495Y3!fAAp$p5Zu8D{D#!*SF=_%gbQoAdEQKQe*$$f64>C+k~=nr6tz((Xu8Xpf{GgA@9u_K5F2um@M-{OMfh zrn#NzE17h%o)neZ+JGvxQHJky7r_@cq)P3V;k!J-r!}&SGM$s*r#-@lHMWd1U6bM8 zFL@%2l zNIYVd+}e_%_J9ViW0R58)=zAwJ1QhU?>RBYH0qWEt3>p zCrZv8sraAiw0G_PpkScpH`X#h@lEkq4vL#b$xq29F_H&p55{2)_xDKo`vl7=`npe& zTw?LCL4nDZ(~9pPk3{s!&MCz=%_Agzy5+j!JJcP*>G6eNu0AUmq~*=D{7TJ|8}44B zG8qus&^F&`?jph?dbEliI4Gfc^Y$&iOc>mDcpDxa z6xf2Vt*qF2-tOKp)bIJtkk$k}jU|GsS# zh7E4c=R8&D#jwTn21={WcE9YWta|pju)jEcwIY9!MSEx`7g_Eqz8SJuv27MuLOslP zt_%@RkQB(VSeb8@3=tc};^h__^UanaV&$Q6wKA(L+Z5mVB3Pq`Y5bV)LYYQ9TGVzO zR>@Z~g!*TqwqyfBmUxu2|3E~L_GFW#rs6SrZ+$c%(>F)Yhh4+RTP=raQ<*FKgg8^~ z^tEL=OEtCvd`-&et$gcIdIdgthh?I^`L{}wYguf}gLheeQ+&6%tDv3OZ5gTf?#`cG zlD26t*63atBDSK<`{}hZxsTZ|gGIZnK4=+D9qXmu8}M|{?8BB_itl-M`KV4hyQ0_B z_o9rUCwu5ch~t*!`ODyYNydn$d`_OU%w*+u$Zg#Bsz+((PFqHC@m3`DKk*Fi&TlN~ z;+{7Jh$m~7ow1A+-}OO@(02nY{J^JSZTRf7mT_F%^QK^N(`w8)%UE3TKspi7=RD;U z_q~mrVHWz9S!!h;Z{FjAWjM#>JERu#sejQjUOpP7=MS*;XxpG;+aArE^Fu}G@m+j$ z1*tI#omZZ|dQdsn;_}@gmqt|Ve6HmOzBN2TBoiSSYw2@TbfI>UIMkbPsMiP9G4$4) z=Ler0ywzR$8o;NQEyKd~VStfzBqhZdTwIZ)D;)v6-glPtaD6;rq`IZ25*Niqsy5%h zf7Hi&)b#LYA_qW%uLXU8kiVFH?99Hs~gDaV}Ea`qeVrlqplVhaGzR zJj%1Q4tqvp68DEtp6}qTZ&)JPn;mi-YYa@pZcH?L`J0yRtjJD%n2Ya8P@ff#6HrUg zc+(M@+Oz1fVN;&w)U zMzPElZqnMi^BaAzVyBT?AKJL9H?nN)k!j+gjdVmT*4*Ps;>ll`KgPo#ebki&F}&C+KjQ5k)#wK*C?o+x7tM0pL}R3)4ewW!;PO}yyV~X zrIJBLv_2YpZ;1kV$A2tcST?1>iz&vM7rBQ%r`-EA`A&%uLrYPTZ+u~)Z?|dk5g>{& zuDS;DA6{BIDqg&`w=*VxtY%bvm-2~-Fa~SxP9$38-VnhB_<=NM1keiP}MGizu1f?;?FE#Z4(K6gmIgNpN&4kbvNJ&3$?-deVjho z=H7(G16N|VCe{_L@ErDPA0KP8MtZ&5M`t|0deP^=y!XpC(MQChO!qER+s?M(>yTWA+>QKh^Vlj-TDtF7LFCW$}6vIhK}tO7WVm=@jSs#RpnTaDE zl^Mv(d$J+9QlKE_l~P;QEP7&XGD7r)M*b|4g>Z6Ug|VG z-WaQkIl2!ir;1w-v3&>ljY;&m9b=~^b|!RK3+638w6L)8&u$MM8H6x>(vei}lmX@*MutLb})- zJwhM-i@bFAe>vN&N9cop5#e6!NgvZ!3VzX(=w|`O3zZh!%nszcKCzB?|9n6!+M)7R z*Lx=g?n2L1u%`cy(*toh`#IV=*7F=;CjYCVb(DUNpwT%(0NsixO67<42EG)Rskdx&j`pf~N?b`~iWa?@E@QLk zQ(RmI@0m%L1YKV{efd}0oT;XBr^NUjw|Z()id;N`@U=6|bWMgw$#4v)wWRINNeZJ> zbkdr{+wXLaWND}5X`L8GQj9pkY^FJ9(CqY!I`kxsk8%pTfkfVVkCW%;;dSuM99dkV z)@vW$RYVc=5l24tfO7~Eif?ZqRCK0chv+R#qhN6A@LxA`~D zk)|Qvc($K7@h~Fkh37NW!johQkCvo!mq_lqOc%SmpLKR(|C|!rw7jOMS6C#Od7dsQ zk3C0k3Oi4WBt|p4x0@N~o&8yD8H@L)(A4z$Y=7SWGJT70-vxTHHbIXynj1|iihpp? zInry!X&O}yw>jAyJ()NkH=2!>zc84q!i>mL~%gXw10} zdt)TWDS(kY`#WbZR^%JGw0{LKRF+=G6`xTI<=elfxA-V2){3a#&L5nUi~uekdD;IX z-G4!8*dVG!*tVJzE6357KVmD==jSU_jEm0y*qyk<9c#8tX2Z_Njwrq+GX9L{N#f;U z*K2x|b%fP6hRIO*NiBMha;!3sM_+Wtc;?{g_2^dD47+UtQj3r6oqHZJ)c@ugvHFYg z^l8rKJSQI7E*i=0W?%-0b+6~6Q<`nm4kh{}w&oZ?KHSKmBKOaGhh`f=AZ zy2sGe%j}Y$PW<(vr5&&6Z5}HpdwxTc1$~Uk)PDloavxvwC>dMOVs6Xt`kKe_cVnHF z%&?;rxtu=NbJNc}*gx!?s8*D_T4+FVm(P#?;mXLz)7;kDFM^TVn2#78SdQ;V><5k{D3Z+dhmkWVrjVbtiqx!YT{n#c39 zYn_SOf-BDLPQQ6UAK>UUPr~y6&-9UGc-hp2ER>$J!DzF-y2H$}D-~kBf zNQ8oDP!Y5R?Z9v_0(=D)gJa-0_ygPpL7j+TPys{}F0~DQwgn@=NU#hn2gkt)@H_Ye z_;)4(Kv_@@dVf*86X*<5Kp!x<3;N#_{N!LhSO?aF1K=RI2y($Ka2vb?uRu^& zA{Z0_Q6L&r1oc3D&g56<{UU z33h=K;3W73TnB%He~7lKiIzhR0i{71P!H56($rHV_SAh5)DMgSF0cZu1lz$5B28`I zOW{S|I>+Gq&D-eNzR!L{+!gRIcnk2sXtgM)0HQ&C(11vr;oUd3cfTymHnA6;BdE#L zE%GzbV)RE}Wu`%5yj>lNEW^NLFa>atgT60`(Ywd@o7=k9AbKr04ZZ0aF<9^ zd(fwIG4mG)dI<{05k){fP#>ru1!RIOup8_Fzk)pQ6g-PlQa(`qs9@C}6as}o6%YfO zfTl#6`VEO1^hZ!CNC#uVDzF;t1iOedwP0_V;U@%LrH>5HiyY?Dl}?Us^Q~he6Kgk1 zqVVP*6$}9LKsMM5_JLnP9`H^kd_c)$tbcYXR=VISup8_F7r;eu8{7de zz)KKDZKZ~T65vBn4OA!6)PGWCQ=XhpqmYgWf6|wD3TE{qW`o1v2*HodiyXqw&yGxS z-9*?e;M1S*1*Je~&eHT|qbC0_g*lUbI8N&n&P8tOfhPesB@wf?MD=_#6BK{HS`WKar+R zOOrJ%ji54MEEqRPY~Fn53~K$82ss7rf_uO+n6QHCpa$p#;=p7u1!S0LUC#jaY1ziWx?m59%v6b02QQw5nv>dramLFr(1}i zMPLKi2y($CkOyuMY3iXdp6j2Nd+Y4)Tab2i^f4>3_PvKtQXgOiHt-?%2vh+vpaEzI z+JW{U0VIMnFa%5llfV|R75oCO1Mi`P4=4-D4Ml^r$IlL6I2ZwzfTiFNI1KW@4d643 z@CBtnY0v~T1u94Z)4>ezHP{Zm2S0$t+ff!Q^Zq=!7{+y#^Xl|W@s57Y;3KwA(8;=v#=7>oxK zKqklnE5J&y9qa(dz;SRHd^ZvU>Rb4E8$1QiK+q^67?cF1KrK)kv;l2FU(gS@Ksv|- zSzrZN3ATeB;1oCwegdwm@GiIqUV>L3U^Ed3ihw8(4Jv{Lpdsi4I)lET9~cY9fq5Vs ztOM)8DR3Ix8IAt;8-6|qFF+`5F=`kn2}*%lpf>0LI)eTn6}Uh;m<=+(Qji0-fUQKD z+G3pC7%w6y7x3frBGY^$X@jH>UWpCThAP=XUGO=G2MJ(0m;rVH4cq`XL0CEw4yuD1 zAQ2=14(5Xs;G_tn;TjGL7(FJ3CP$R!>DR2W;tS6nALeT7dW*#G06zDohJZq#FsKTu zfhM3S=mC0ypE(a^XDR3Ix1NTAr zL?QyjfU2Me=n2Mw@n98L4bFhG;34=EgiRvCK@|`~xYUmL*$IpWW58;#27Cj~fCu0q z2%k(ufEwUa5DR*NNnkQq2iAjJa0xsG&wy(B@B{cA`~hBqSHLur2m!7lFbYJ2il6~#2s(g{ zAO-XRxKgHzx%_z_$Izk@%(bMONA(Oy~gC(=|)_4#rST@qoXKvjB>^O`lq3qR=l9Q|Et zV+1z=9YH6M40?lMU^tiprh@rk0ay#xf!$ya_!(RSZ@|Bx$Q&XHGz5)6Z=ky1G%y`( z0-M1Fa1lHPPXK+SkoH2LDyRlJgD$`Y(!naQ8k`3gz$5S&&_9SmMS&WbN(0&@;%5)g z6HEXT!3MAqH8C^OHD*{5|{~QfgNBc zc)JMK&cRQZybAD574;r?30?twd{7MpP7n!7gEF8xr~#UQrl1q(?1K3EiK>F(Um*bVl83*aKS z4eo${z;h7Di6BrI6af`MCD0Hw0$o8jkO~HXX<#~VErCnHR$y zH3JJM4ayK{>SGdTdrc736!ZoCz+8|CG_V_d1J2CH^8bRL*NHTB_A*(DvVejZ2nP|M zGN=OTVTIQRoiN!Mi~^&9;AUGU@Djf7J;w8 zCa@VC0*ApR@GZClegiMTD-gPr2m_@-nWZ@V)WgsEpabX#dIJ?q1e3rDuo4^q2f>fv z3U~~jfY2Nw3={>$Ky^?9Gy}~+9N|*q@pC8`24;f{umY?E2f#sa349Cgg9qRp_<(w@ zO8>ML?KMG3PzuxqpMx%-D@X%F2)btFy+(F<`hWv%dU(p>q@~yA21S(0?k$t%|U0-1*jkei~u9SG%y`31dG6W zumS7`2S6^k1a5;n;01WO%0&jRCQKj-6a|$*6;K~E0Bu1#5DyZ-V2}nTfQcXr%mXXI zDzF3W1joS%@Eze&zsJwp;0|~O{wC5?>sqYpbNXX+o)T-A?245$hkf<~Y{=l~Ky5*Px8f=OU9 z$Oas&25Z1Bpn;R%6xeu}_NhPM7rynN{ZkbG6f^^!K^LHc6fgpe1k=EDun;T) z>%j)F7wiLPz*%q={0#1a``{IL4FY@9x>17wJ~*Hj0A)Z~P!rSwEx{L{7l;FcK^m9< zCW0(5k4RI)H_6q$8$o+EV5c!kyrE9l%cJfi@Bw%Y-hk2@i88>rpC;ZY^?1#_tt%PP zy}>Xr9N;BD`DP> zV{&!;tO0t0STGSx0_(vBa1rE!SKu|sZb5JmxQz$`C6kF#AQF=WKxt40R0GvPBj9Qb zJAuxiKS%`=!6dK%ECgG?R&Wd)2S0;r;4kn91bs~egQB1qs01p5MxZh1^mPo`89)1j zR4@@t0t>)GunBAiN5E13W_4sSR}iggHJC_Ki=L8ey)1&tfmAR6Tme6Uayy8RK}}E# zGzTp}SI`ag0e!(JFdEDNGXcK$s8-9sy88;#i@`>)3G4?4z&UUpTm!#=2jC&F?j&rW z8mJDsfUY1Nj0LN}YH$Hu1W$qM8I0UT6ab%rIv^1wflQDE4uV7AF1QCQ8es*WfjS@w zB!d}XCfEYDg73ih;H9|A`U*b_?j{O>MxZem2nGQT=7YUpANU1a2OsPq6i^(L0F6Nt zFbE6=OTbd_4LC!%)ED^q5|r6Xlm*>E50DA6z)5flJO$5yV;|uJpMsho2_%CIFb5m~ zN5OC4cTi|QQP>6Bf_7ju7z37r72qPs1#iJSQ0@TnG3Wp~f>B^JSOHdo@4)xqZ}1O@ zJV+D(wGN{H)yB{6pa+-?rhxTe1Gogf1^;ZehS#S>g0Hv><&hPQD71H z3LF3j!3}T|cpWFaK@kuIDuK$N0cZ%if$ks;3<2{%HdqH->*0BD0XzmzK)?wi5EKH1 zL3L0AbO0T}ATSur1hc?0upDS$H~0};0l$Mk!0Qv}e{b;9bdm@Gg+O6Y1;l_xpfTtM zx`P2=AQ%hAfjM9Mjjrc z5mXVRfgu1dN2uokUWZVB0S~}K5PF&j0~J9f&;fKjjpZMMpDwT-YyjuM1@Hts1=eo} z8>j}VgT|l<=mvoDSXA`qt8|fzDl1D=(B@9pVDU^eHxC? z_j~&E+lG$^eaI+Y3!zUueG=%CNuMnGoJpU>^r@!LO8VSNpWEp3Bz>Nu&ujE~ojyD1 z(@dYw=(C?bN9ps!Ha~oA$gkFaJD>2Ba^n;-1J_Q&r*YsZ_R7)|Do0J7qXz#A2Y^PVgxdM|H2Ud6 zrdI(+5V9J?1V^|5i|WcNYVjXw1iowsJ}U`FHhEf92?+dk=GkN;C_utoPP+gUjSWWf z@n}bV4e$gN)^Yfcd*DNK=7lx(%GwHh9VLJe!jueu+YXXIon+>U>Z+PLq=cZtK1%y9 zjHAr>C);ZsO#&orlJIxS6u(bVQF&!~T~Se!00?U%?IJ=M>7HCwx~55hgn^HC8w_w7 zgJxEiRMeL`Y8RB)D=VqU2rR5)w0r8o9iXS`jOFDOh?Zc&6b5!L!1^tyt1q7Is99D> ztOOEA^EiVCa^U3p@`}=V<<*Xg@=EX$P@Fj9f2Dv9(j`x+u-Dd3b(A#;ur}(SeDt#l zOQJ1XZ5ci$;hd_`XA+X5B}2gN>Ub?qtEVV6UOL;nZgpiaH23$orQ9k zD2!BRANUhXYL9-i`t=L$x8>OL%7q@$wCtPR&qJ70k~;(8!g!bu@~>W0F5#6gDe4rm z)tc?;AuP3sCiFtdlLS}D5>_^ZnIbSYVPQjI?{WQz0ycYZ{YM#^TXHRgPZWo|a4w@z zyg1S=3>N3Pg+Agim-0bJxj?ozZF&18CDWEpdwYf6Vq>qczu46)^b%Wog#$F&%qy(c zXiuPUA|JL@8Qnl@-9ov%EwpJBp)$b{llt{5oGLV0N}bm$APN@B?CgF%LY1Yc^8qGz zx^RPq5(~029Zc#g^5iMi*V+Bzh4MPPU$B^?kS|P7TefUfDm;>DASOvP3{!+O2tyJL zz=a`V^hJ6TUsE1vczY-6{?%#dcEWeS^aW2hU?WXmiRru2^gUqu_Lx4e83ylA(>Krb zop1VXo6%qpzH9>bn?9dY3~Z+9TV(n!G<};*-+xWtLDLsJ(~$DsT(s`s%>1&voRX5f zQMtvr_J)%Dk|ym3AhiEcNkq*veB(@CvFW?Y^gU+!+DxCve1mtW={w!@tuuZ1n!e`w zlz$O%ztargP}6t1>ATSMZ8Cjtn7*T?FK&S$WtQoyH+^@SzPAitgLc&LYVivV=J}>? zmFc_9^ldeLUzk3>MF#H()3@04U1|CrGJPKipT|x<;|(R=_RdaT4maQ(s)WKE2m@pT zAQ9UL@|J|acSy&*3tYo?!i@|EweUGi-+I&clIi=*^!Y^?9NDICvFTf9`tCP3hxe9WZ^to`#eH)3?m@Z8Uvvn7$u88w{3&0fuj` z>04|1{%!iUnZ934U$U3MTWI>KP2UF7_q^%bZ}>8`0B?hNgy}oY^j&EB4o*b*ZQIHJ zejBB>lS*w`6h6XNYx*{uzV}SuZ>BFH+Tb|F^sO*`|1f=9Oy7s5&qFbI(-kT;5%GKz zxXSe1X8K+;eFscmC^LA+nZ9MFZ@uaJkLmlw^m(c}Z-bU@c(r+^Z?)3QS*->AT7Fy=wXnn!eCj;&o8*PZVDAtuTEXP2Ve~?{m}V8)rnEYx;^z-*u+% zS?S{*@1m-kDTdHYe1xyS^c9)D%T3<{rtdw|_k-z+$}*&kGkwLT?;6whxar%KHPT@D z%>>408?c$Cufp`*D1E%`U1g+g_T4;qn-cH6dnZ_G?&c%6DM{XYD8TRL_H9an_lFdC z@os(%VLqn7zPtHT+mvMQPbuK_Zz5BCOC81a&~HE6$vw6!BWz#nD(&5N2 z(&jiChyJ!qiB`Aq8^Kh--wCq9E9ku7|P2W=T|pre-HziLkNaMGltQ6Vk}XV zRIRAC*C3L=h=&X(+<1)iXI{s`7WHce5!qCj$xkqaca&XRRaH@iexQ{M}|{NPI8_ z$c|rd3?7BI3Uc!udD*$69Hm*K3NrA{Sybc#Z4i;sVaC#?LJxamLWe)fDyk6gWfrZd zDlMvAZpVTtj9BOhL#D-@gKvFL35$y$B0Aj=M9Ce9KKU*z{4_0!sOaQFP<4#l*(OVh z?4_kB2!%N4grsv0JZ-~58&o2qQx8ED?;g3e9TwSZv22Vb20F|T3`t!wR8*{5QI3?v z6Av9F2%b0#PoDgXF-zjb!Znc?=$t_?q*@pRJx};RiJF#7M0DIBn>zLUM0d&z6h%>4 zePu~eT~$$?y_j|lQi+c&@JKkn^?EjJU>bqw=9>U5y@n-w4?ohMsLwI&>?gI&$TKEwmHrG!&W7V-0C(ZnSa-+3<#TJl9yN3 zS;$pBw@n$KE+F(E@q%pWq?%>5qR$bfwm?Wp4;K_Z6d#QzhJ;7kl*E`bi8<7bSx{+b zHuG=Wlp(=_q(8Pc493B`l^As?F$P)~i9i$3IR1T`q9!;2K1H=O448SvLHR6gMl+9Z zSC}_}wc=*}%5Ejv26t(@lEVMqjf@pj6q47OaSLyJ%rf`Xi-<(tmkCKjB#EzpTQYA* z`FFdLkXS)d!Yo;FQfmU2!tJ2*k;PKc%!BtRs%=6u&)B03CwJ){CB|zeNlD`gpDOXZ zdXM54EdT-3zU?*3>Q^|Nb@%!nWwuv6(K9}4FL;H2nB-l&R|yOk0G}eNGB6tjf6-ng zHDxXFMWUjGNRjHA43kn5Xqk)zH>h7xS$SnC2Ej^GqR)rQ5Usp>Cck+ft=77f%KPB zYL{cf(uIHSM@o{{4aBbye>mUzk>V`@Lro!G0vaR8f~BPDs@n3p@~TQ~^68!E^N*Bl zubW9yoRn1lu@YdrxtUM+SjmqThyXOisv1Kx(D`oo7&}L|H1n+=D+yk=5Wij<-k&Ie ziU15OvR7AEtSPdWP?Sc5BR+wC^si=q?kC9hzld?TO!57nC_#||;8#tLJ5xQ@8eH#v zq71X$-OT^^M2RC81)dpkH*xz_*P!_pEq7E@gO~=El20M|e!@lbmp)aP?S4U@!nc2_ z_(uwazhtVfwJ&q%T;F|)B7KCo6kfPbQKes$W&%HZ9}4A>W?sHeS!jC}U2mU~==&TI z_g`L7#{)l8A~t@e46wb}%)LKT5^b+E^P!(9skYae`GU`sAt7%Nsb^JvU9rf}o6UUU zeuae>H);P9Ldq*wQ!?H}z|KQHQ$iyMqHQzS2%849WCP}XosH_zl?|JuI}J8j%aSeD zwhM*6Um0TC-OL-w-P_FnvtLQGeca4H+pnBu+tfp-3n-~@*fEG5 zBI0iZr{J+e(KRFWlCj?W-tZdfrBYzCwcxKW6~)%Sg@5}c8nsso5Bv&v-xfZd z+<+E-@mI=dTTlysp4`wD{?k{=Sl@^iMC51BF6MuJrKAVKQ&fyi^!(f=ExLu*e68f# z)E0jK*GfiQ9Fck#XWNUGuax7DKP}Q@=+nQ&gP-%2qQn5BB?>|kjvHG~az^6GSe^Op}Q zgChjqPeO}G-x3n|?+4Kr$F}geZxqFAEXhcbsXgl(B_LD)yzM0`>&vkiksNEjk@>s* z8zstX3UMS#j)%Tcd~H)&_^01sxhNAC!m|!3p^hq!EZc(!T!i0#g8iCk3*=01;naX zg8#RQ-)sT!Ds@yi>hxTRlC+O3ag>d;+w(_`%FfCw9hKouVJTi6r7af48^<61R`IbR z@a(r#p3QvEw`gTcTX^tcB_((%C7?fz1p3r4?XWU9Ocs&vv{lG$h8QNwTKFZ0mH3b{ zq8}hf09oiy99H5YB!j#%v3Ql&it$GBDBmfu5!D0_kSsb@t8U?Q zzEhIU6}a%slH$Cava-^wg6zCf$4H0X>N1JZPcq7OC?Ko@xjTs#ge_K?f*s#=Om!6< z9juKl_N1kU%-qgl0>}m9@(klJbs0wbHSgjujhP_}@P%3H;?F zinnJ263EB@tVHlnjwpVj!GV<@Iif@bZ|ILhANpyRQ8tqJ<|9fBANIZCqY8juQEf#P zW<*4xR|(?1xS7xUUP+9-ide!d(K~6it6K23vobVZ&_DwuDd#z;JCedKgis$=__;@w z$V9?ujU+DAU7U{MnLj8A{)QCL@`*>4FfS>J#~f3l0!1A9mcx29kfWHc;ofmn8MbUa z$(D*Jk+~+L(PMd&_GJ|cVFpr$L}iy1J4$j&i}Uh|b29Cvn5~2gO^n*c4yh#VT1QbT zha?CRUEgz!O+><5sQ4lW3Vl#=-rmCR`~d?vT$EZo-}{5&A9g#%(VX*Vmfq{~60OJxTAN!M%mh>MYcgcm5 zP7_F(i?iLq-bF=H*Z|WM>6{69T__Mz#iK*@l%TiJXqt+%$Dvrne zs`$pXQ7l5Jb;)W9o%*Yi7}7x~-~6i*YWql+^AO}v;Mrf5%+P%#&kL&uM`fvA7W~&= zp{k-mCjF))%JJ~)7Jlk)N_zA`5j$2{7IF+$K;Q5iw3lyN_+!6e*(?$O;EvyvA#q2D zXCPWG3|Web9c5VGI13#_%I`|1*AGM##n=6g8Cv+$`TXA$l{fyb1SJVTfG)vaM&>Z) zIQcagwI89`{GmkTxR7YSlFZ0c%PY@wl+J;on9&J3O++)S6HGvjV@1^}M^Oo^MU0Y> zSw&RIDSx>OcOlmVS_(hA6AW~QI(rGt8HV;{&vT5j7vwmwf0&b*V=slyASkr{yO4_z zOD?ReJm^o10baZK=s%SVq5RohXzMF0kbS)G2_by$Z%S;u719{6++Hg)SmU5oBNDU0 z13OWB{!{|Jf+*rhJVd5M`I+gIS;CVsSa}X20v}O6Sgkm#q_l-E{7Z=+5>EI~OUgSV zr9PJ|>-zb>6h9@3m;y_x>aoxi^k&NV$A2lQUX1Y3e8S&~;!M>LDPY#$N^o>65n%GD z!MdroycqeX4F%+k*Z!@fcqI@zioXwj>DL?Dp1+l#D1i)s5sw=y3MJW=x@*H=7UPvl z0%S34$Y+6rML2lDspYkGqLI0DCDC9giwS(Q2V;DK2lK)<#?W0Gwz6=un^4=$kbFh5 zd21OION6^rCzi*1uwgRMeN)t^OSYBa3HrtIQD{aJ)ruEYAXl&BdZp)*8EGc0AnU;SMP4I9&E~?pZUhT>Jf;*sgc(N#4_%8m9CrkGd-7AV0 z4q%Gx73ustPp0zI2QZZWF1~C4ONgS8*xoqs)T)y6p#B;Kb=EGv-W#MZ4q!eu1me69 z<=z3zSD8dv3J~PRYE2Wc7{0@cMfh8Q#1&7|#3U~k>Sd>5mPEYTi}^+hfPY;LZAw{} zeK&crB*h`>UPNQ1&>Xw?b}u&A2KOf~mKZIQAE+naSj}nLE}rGhQfzR~^zM*LeIch+ zid-h!;BN6|G0|sG-u#6uW7Q=oWT6{cv^hNAhoyzC zCRn7uWuqho|F+IT`JFy2%(iA1f5wN2HC($7vV?-N`Leu07gN>;VBuU zcJURyELy7U_-oZbrtqMFY+!hkb~!~vCKl!}9M0{LEIiBEspLLO&}_$w+4f58wAEyk zp#i$%<9UcLQx$>It`!M^YAlo>IS=vqzAQA=71kJRk!nFvAw=-U{n4A( z^JC%=;uAlX=(UmLCyE&TVCqQu)i&xGwTkpIH2lLD)|fk z%-443F8-#!EX9NVjCtKfLQ{w!mj6KnckSZ20W4vFXeoTh>X-XDTEN=NyZHNoELZ-Igkauj-^Ck3Sd>>giAo}N zmTIzS0vc3QRa1&hDCoD)JDe-hk3-lnuaAi@iccDZW+wdULIy7!#DZ-f@8U}bVPHoQ zuO7s*z4lAuPl;Igb>f2{ju!x5tOo5cFvp&&SvE#`l~APjz%D*66zM(SOfN4CWq$Dj zFt7+aIM@j&FBOO0rU0^@AlCW$tnmAXl6tQ7*%0kw5@*vPvSRh)!rek9A8MiVOX%eO`_ z?+8KSM_EFnfYvMp@sA=fY6i7(k4P3xZbCF#{OCv)5D`Q&B}4HV94|N-n6CtA_?N>= zh!3vddye?R1YdovqqNA%w>J_IMYr<5i2<%)D2QSKkt!+Yh+QJMxPzUhQ!1Y zGSnJWNjJzPtEY z(a_}6kiBR&%r?B0KN`(agEEMS%susyeSb6?LdYNmtq$&Bg$?!00TG7|9~x;ap?uH; zG_nIFHpsq2fvk}vi%ddwAk6xQ+D5nX&lEN~XdEHQHdIFrWh^;p5&_9fR0p2JSVGWL z0+Pij0g;3o7)$h?PQVW$_y@5}@vovKIN3*>(#k(%Y{-orkN; zFKjj;$f#6CfWYKdUZ}E|;d2Q?My6o#MQ*Ts$Sx>#CQ=I0gIGip|dSmw9# z4JykVzJOTB2DJ;8lI4PBQ7b>HqH&zj$|GXf@Sw%SN(QQWMo)_Y^6XZ=Duzw8Ep6rh ziDBus;#R&thQWe{h{;M7@f5+|S<=LoeUnyBq-4grv`JJDKQ|U??Rl+Si-q2`qLtqq z3$>)G70)2Cw7?poCR>Yw#O|Vd=7pG_(0cR|ncG~O(Gm*_}TX{?Z z8*jV5l`ln}{IHj=yQi$|-P^X6IxV6zAlS(Fct(O~Be4J#jKFcMFg&Xlz$c|L7N{SVX#y6_H>I$!B-g{QMrR=#tEsm{A;k5Gi(I1{LJlsLEE8af36k-6FV**T@TIVCySBOP`WtfbeDiS*Vw_k1xr7zfsT{ty-(DRA1ag099ug>?I|RY9rbF zd5DbkCIsgBx?1$@DjkXO`HvxNip{@`Pa2B07ShHq8p^V5VQu{Jp)98$ikKogX0w70 z2SwMX0mr9k3IV2z(O@`|X~$nYW63pQ7{fA>MEDlXwx8#iM23&lfQ+mx7>2Pgp^dK^ zhOscYjlVpM>6`1{Q)cJZq75Hy<=+p(j#N6yfpJwPiyY`&nrZ26JZm@$^Ek#cGFVKk zYX$f(KwcemW{ZMES@U(nSz@>-a|0!cUi(9!RK*A(DjWe+mO>{r>gDiomL8Qui3qev zB?2v{jgQE{PME+3=-3ibMw$u^{%R(Rj>)h<8ja{h6>I(4C}k>tIfHpci>e){OVMjs zqiW@q5aXZW1aXfMEYy=KR-jTc^lI14x~?l<;ee%%vk_&r@by{HTPjAdfVhd2n-DWM zbq2L25Q(C!`J*G)z(E4wRfcPwl~uCd`SuYkHhLOKFw&}{H3EtR@t90(AWUoHX_+k3 zHmi-FmC5pxW)qKIN>eb0h~YX-bE)yCGTDgqc^2VQoE@>zvzFE`MkB%)K#?hNM%P;D2dfg%bwV1Qe*#2y#;z?A`CNjN_MBAoJ6PX?BTr|Px zRB<|fjz!vJqq7QWMhk~DHCdoEI}z*orp;`<;|g-mHhxn!Q&V-gR%)T0f;LR%1NKVdiw?hrwLmI3Im_1EIrm-6N7TLqe_<37H`98U^_LJle9#XMQ%&{F2Xxo_hzt zjgdJpddbWinKP=O*pZh%GAF~>_`8{w%TXQB=Cb-0!iRUjiG*+{I|?r!5x zj6}iS+s5~kdw&}bFJO7L2iy3m1t{o8+W7eeEH~^i%FuHoWriN7z!PnJYXOUkeu@Gg zyJ7%&NT4Hm&?x2;_YBc^6$oyqt93P5O~T1;0v&R{V-yRE#45gI1-6{F5OIbiM$vNn zD3%oV0s$AAKm=aYBX|rE1ieh?3rsYBa}*mKw3UE&I)Q(TVktqd6Y#$}5F4hMqp`+( zlYrkjfsWB^F#8_?>8>4B@myG~NLA@AfJK56D8Zyxy-S3XJ0YY3itq=S)KIp!@jpki zG~4@aeDD~YH|!ujJY715B@Dtf?`8_N=wi?zuNi~-LH@UlVL8-650U#}8&4R^Mv!~j zSgDNy9>s4M%T(K^ZT#V}s6@CQk7X01_mjkz#>yPbf~$Q_kT2T!$Z=hABXMX@7j3Ec&L8gqm7M6dHeu{U_8sP9YZ%I_vbd=I-Vs4{z@|L882ku2oy3R zd|+3*s!993jVDjQ+V-zDK6e5eZu8j9FP;F&p1b+I6VPhCck`VS*c4yC-H<>JO7h1h zFy>QUSyqLY2zK*H6H#=7c5}x>5Qp#P>nCCpBWgF_LU0uI-ia*Di-8#m$ok1FiaAeu z1k}^A3(Ln&VzJ@zMC^Y$bjPY13=vcW@w<7|B$jxJKn*BbR#PSHWaXL*+X8v^g6wRJ zEcwM{#ie!_brXS>LV^NxK~`9dNQtir;=fH|F=7R$Nka=iok^HV4B5@ICbNVwLr7d$ zhsfj+g^O{HqtOsRNG(GMP($?q%JFQhFi@K)o);%G7M4Yl4HoDLOz23BV^!!couKDa^;Pr_(becNa&C;#7Ui(7tKV4D|yz>Y_;4 z{wbIf#_#3rqYPTId7vkNv6RI~e+!V}jf7xQ;NM_FBBz0*OGq3Z@7V)>ccLQy}3~yO4MR;rw8tVXwq$TH4=&+cuLW z2CtQT&gdi`g|$lvH-Om0(!0?ElLz?L&1Mmi5~^J$*pVV(%3>r*gte;#4k>WKiLiF9 zz(KMV7cRou^@QtB7ae6TMbU_Rk2eWSMU^n- z<)G2yye0><@T_?(bl?iCpX}mBhIY?xehFy2iAKA3H@~frB^5p((pN1;+BBpcsLSzz z6{JiYEoV*Mo(jF#y?4PZc=TuIHdKje4W}y)Rr9CFdN{U^IBu0d_ zCkZ!T`I>6o%2SsiYBfrNwPyrP87?H!dYH;IVJ_-i0<`}~>5g(?`mNV_WC?|}7X)Vw z&LPBNTjz|D0PSUgt*gO}I*Z&G3D8~@a?5c45lFK%_?+2Hjr_0RB%DjmDb+C{ZwW>V zjz2b=C55~rc+gt1GA*%1N`UsBU_yY}w$W@NL|EG)aA!1| zhk1vznK2q|m&%PlLbyEwN1fGZ^1ww#%C7Q}L|XcaK+3-IsYF^j3y?7(`vrKJeZ>m9 zB_R z5hAP|6*wf=1t-GVF@Zz+tvFsek9mdsA|j-2Xy7QqQzSt9ov>b_+39GSwjw+94V^;! zOGu-ZXq6Tv0h&iUwfyqhN^@upnU8Yx)WObd0UYH`LCw3JpEI8^8!nc3oW@uh?#tz3 z8R|zYezoN*a4V<27!Yc&{s3wL^f9OK!>JAZHiQ^Khbu^`5(k?t)0D(q|%`KxDPp?YKi8)zHc z&i@8oh$!qd5L;;?_{4=Q&^EN4&s&I*R?z6hk-ogPeg#F8;Y?L&l}o`{a==oFpODVv9+(Q=(!)L^JBcG5h2B~B}7=k`S`G@$eLgGM;UDURAt=i=g$ zK{?(@NlmD8N|rBi+9aY56paW;!4<$7yWE?%rUWHSGZt=`Q7woP_RN>0+Ek|iH1!h{ z@Y3nbf5Z$YC$e-xoRK{64CXgtmXj0NI3dmmzVr;{pE{d3gUmkT&Pr{KCiEN5V1tLu zbH;*}e;iV0spL6{v;|I9bh&O>`NT7szwPvPKKo1-8R0B>p(e=oub2EyAPiqj(tXWL z=!5&?XR?IwB~Fw@tpSR~iLh2g1aj1}Ozjv^`KuW4RDE_Yc8U>Gx|}{p46j;@ts;k0 zie;KNq{Qnp{cen}01UgxDT5SCnMcTA(G=7goM$!RKJlW$qH@ z6%R`c2XeTH_y^XM;wh5SoNNh1DHx;=FJ%Lx@3zq7=XRhuNHq8AG?b34d^ehu=m#w5 z4$-KI21t9@Lf0WG)!zVVkG1os&cTk+lkNNqa-V7EkwtL-)6QoWAB3%swGZ3*4m);s_P6t&?by`(vYlrXvk1Sh2>CTW4nF@J7CNF5 zG21H)cI_Jy8Hkoia05zhOXuS^6|+?JFi{1qs;XR3UhAlJCF47b*@)=xiDDq`gFEV~ zoOo?-J2jsOo>>C3;$!W6QVEOnHqr~x5xl+xMr^;Jg_f{{7`XrsTDY8!-<=0xlpgGO zyivlkLjFWV+S~Y`#R+o$s)L2bz(xoQ7VU3JMu5(5!uaAONWIjSyY zYPjbfu>0%mf<*J&!#9_*#4v&Kfw3A66U0F+rKqix#Yg)RlaXeVK=a+hgB>hYq6cE5 zO5PFGFC7#2TnCQh1Bp9KkJ6P&3*5v1;eZ7Y+*go;h}B{*L#NeG+*Y?x?vkPe4iyRQ z$60XN@9lh88B59koysN5UYuEMFU!i!a+Ks1XJ%&^rWLZ-eI>KlQj4NgDLk``MUHm@ zItsAvtu4=VH0mQ2ml083M2I=mZLLg>#{$E?8t1&+yL=dgXqU1NnciR zkCj;SOR$ztG=4H3x{ufd2+t~K30?xD@<~238bd4zeBXI2BGh{0 zPZJ28qa7USdW6{LmiH=y_57fu^&5NI1gEf3)|-kF5iIUqioS~5GBtKNr8vc&vKg{* zXi%hK+j`0#evJkT>M0~LRiuw^)z~0Hppe4j5UseVrtK1KR3yd%qgsi@vIwnUSBsNF z>=5pC<-Q5xS@$-)y% zymlsulMT-bq=pxpDnv*UA(D>5yAmnz+EQ1M22hGLLWos}ba^Jmxb^2DQpq1#!TchN zU8TuqVTwi1NRALlUmBuT)vc*E3Xl6#V%Kun9-dhVV_LWD$qWjHHV>Hm=+8UkdJ1~W&8E9>-946u{ z01)|>)l{u;5pYR08yuBvUON=ol7r>zPF0Yl9Vb*a}j9xoW6P}(Es>v{jw5Rv*eXC)|6I_o*A_yQr zmbgWLUIout1(+})Krw?d4fcxaO89_UX=8x7huZWke0wjs{vP^+u2Bm<~@@3^T zQc_7kKvawbXs=sEm@t_JGiaoN-X%9hM5`6zo$|M>66^*{N-%>`LT$BO+@~-S!4I#3 zdHr^)07;^4*K=V8^(54ml$Se`5Err2%4-)`ZKqKJMo{uv+m9##z0tH;MVK&3e^R!< zb?lzC)wuAFNtzBL@ID0^fC-VEYTo(G+e@IM_`VCFzf=PdJ_Z_DV*t%JPF-vapSy;| z_~@G182;gfsN8qXXMXa|&@bztUyN(!pPtXcygs9p#`5*&v#3BrBNH$gNsN3oKzm83 z3VJjqjL%!ck_rSaa%73Uw9Jt?(lM$ar>t~TrhYRPe=@=fQ(`w0EWQ(TKM4$U_*2t@k_yq3mV}5bfHPM=dl+u7V!&}ugs3P z>LkK4F6dF`8)*J|Ew&=Y%73*Mez}jFKGX3;TtYuamsXRSHY*#Vi(WTI4u*V zH}m%{VuM2k9^+6^WflHeL1sAS5*8gN!kX`1um>6J1{uJ7;#!tENTBJt8o8LKzPtTm zSThPeHIR4%ExbCEKf0Es1QJ%;^qpZPux~AkR|XM>nOKO`)z3kDDX}rhRtPA45jOQu z#7*<1!k=h>aa8riFeHj3aUqrj80x1$B=We6aU0VGCSKkVZxQNQiH%a-b0O4gbuZ;2 zK1vTD9x6j!i6vf9hEgLyi4dMDrU=fk&UI5~y)=XId-bUcyC9uWG+sl=8*bpk% z%THa0trRSNYSuxy9kZ9;x{l>56ND)JfxeomRpq#`C!*TR4-(zvy?oH6Y(xRv~d?vTv`U3x6FdPtg_-!d1cudj+z=AooX|Qf&K#4 z!a$-T;%n<+HCc;u=t3f)|Aw`Y&_>Vm+mx8F*@UFOi?tv*y9~zmbNBMmm%&z8to43e z(GPZlUpb%qTzMIrIAA)M9em<;B|2yU$vNo6e|#CsVT%d)tqDYcGQ0d#?X10g*yU`n z_Yxxbbpb!?ayB{X912t{lu4m+zcBzUuf7CZB9*wojhTBdf8}yETeTD6tVM#b(XWL5 z5T&Tnz5;JGfg7k|9u4dzcJAHI{l18NR(d9I}u15dCLi(bJzds!m zwnE~PjSRA`|{w#BxR!wsBXPLE?6cAHa4f*gK!2?$@wV@V)6MC+>p19<5&1oHl z0oT1G{T=5uBuT#GoYv5VDCY~$9UoyfA9%iygvkexuZDXDos*CCKu;~-)B02D^CHc;Bv9O=W!`XL|DEV-9 zS1GZI8X(`L7Efw#CU*Ixc312t@YeR-BuT!t-IXNQN4OhG3$k3E?KWQFzK5jASGYS! z6J5}KWUxNe-T6D+_mN2XPPZvC86eRbEv4T13*M0r5WD_@cjEwhrW^C=>b-p7)ojd+ z4h@cuxZR%eeuxCfr@Zy}MMf?ouxP!tdpW!Ao784o$%7Ve9Sd$dh}C-iPmJh zAs)OP{ZBX!e((cju=f^1pLsdI>IODC`Z)^7H^0-+qA_{tE!z3|xB4Q{92D<@r)e)y zfbJ_vLVib!k`eX_0p*k6It5a>%AYsx~1O4lZ?f8=~p}Zq;oBzRX@D{cA z?p~gMGZqFrO}W~k^B@3;sJt0D*}IoteKSiL^sy8FO}WHVPCdT>oUdzQ%2-69{Z6O@ zlnRl_6Hjbb6H5s=N{mMG0l|&XCU(lOj!ARP^>`mdD%gABC{|xtTMKn(g15v7ueoo6w>4T0-4_ z_)jX%f8yraUTO*=c+)?bHwnAtpSUEQ{~>SxCrcPN?nATM&X*0bC(*oe3!<5SixCY4 zBSX-r(O;&Uf|qB`(Pn=ac={W?zoku%}H}6X_mGhI=8HcVJ27`0Wa2UR6V3yUjSx>ozkYKx$eeK- zOHkcOME4~U>Z@YZL96)JZ8*LI$JX0$gf;R*zVam;l!|KioQ8iYH0xay8&A0%V;b^M zbUW$^^>yd%EWAKadr#5-2*qqDdapO@Pz*RC4MvYWbURFe1h;Kwtq~K3ox>RKkX38Z ziE0{m2TnT?>lJsf#XYSimxyQm3)PhOFIi0pBn5YfYwf@ET7p}+%30X=RHFPYaE3)L zd(tj9-HCRYdMDbY7zrtu7KY*BLz(GIA^P|w&~PW4-qW00yC2Wmgq*9JWX=&tQd`jp z<@_M01eb!U-XvScKQ`eKU^gA(gbRW9-;9=zwwFsTI*Ma+cj@@|W|@vRH?s+S%Kyr{ zkpCrj$^0YGP5vLhi^UJiN0rQ3UO4-74~<=lKZf+thQp!Y1PVr>@;uTLugSQc{Je{*y{e%?{x{RNvp8sZPvt33HdabbQ(W9He zV+}+aLqSlL+0^9-u(CYNG3`cQtP$ zmjh5!=EP_+@P_-KzoBk7-q%G%9KDY%riz$-KO28i2Po|U3{XezHwGvQp7;PY^8q$J z#-&+w7+D{FfR%KnJtjOTwZ}0J9$z7&QKJ#~UTI>VgV9xG41b7C=(+*Abk;{7LTA0@ zAq*Z!1_D!ucB5%FdXzVrie}8iJ<{E7e;AP&x*GzCov0G;Kg^~L69dKo`Jc+f z5vgt3%8oI*^NK!b@ZRt!n-=8K%Ji&J#r*LoD<1ZmIWifm6W3YJnH0=F*FJ{F8{P#+ zrz7oKkFoJ#9p^qHM)2o6j(?nT8yZAOQ*s`E9QAnH z+=rj&WjFAA(!CqxJ;}z=cvJTz%j~*4Scf?N*OOS;*o?vK7wcLKsI;)(P0a#}_F!7Z z{Dochr`Y`PekkjDtqh>GP-TV2fo0{Ur&wxOXFZCqyb14wp`edGb^M`0w(4)5rp3k6 zy?f}BQ!UN6WuZ9zM~ZVU5u9by6QevNydwcIlQbNs|oxvc}fSLNpS+;M9c zs7?#;655+V!@KpluG91l@V!dYl;_>+vhI0Sn$cM=uqx@+O#!T-AASL?KK=#f+k@VF z+6z*fy6gou<76*Cqh4eQ!`!tf(apv3^Eg{WRJjc=_Oc*-UP9%@ciMG<62se!m%31= z?tY0qLh96MFSGH(-6u9NO?gemBeip@jj1Y4b`>l~UwWBE4Rc=-y3b!OiiF22Y;a81 zE4^v2unFA?by=%D-o4NtUty)TYd+*>ZDn(Mx{Pv(YyVccatnKvC5`VYt3nUHS=WOj zq#lf*(1R7!7G|CLS9`wc;*yvhugb*0#Ur$@G4GD6`MlTUYW_^PeaiULugSQ+c#S1> z-Pv3!JnMDY+2E>Pi89}pzs?e7y0Ow~t#1 zpZ`}DMfe-tt)dscA+?@WZ?N=P9W^PJJh}wBZdv@1H!l}nY;(z?BnJ_@>{Y*7QNM7i8Q?>qkQ%)mN3d)S3Th(;FI1)oez6k?q(p+ zg%*49+j75P+uJOy!DYYTP+xZ&kul(6MP#(N`4w)ThWevgL!onT9* ztzPW!+^zSKFxf{C6n!LCP6#Oj!A*4}Bmf1Ox`hj6)+m{@$|Z4mSPd?eYF& z2TBVH-RtB+gZ^fb&Bl}=4xcEP1U-aK zh1`3oHE}$>SvK9mW;UUZNjR$oN!ZtHG+hcN4LX4&u&0byY;TPyZf%#ep0()yWSParLNfCqXBH? z9wdIr9+`Lq#0J*QdszBO-F3cgFM7o(pBlOx1=HwcMX$E5hpr3up3L&nK17C-Ka?33 zfkhNR$sy1at^e5%Wx;>-p)54tk67tREwocVMxpKe$S5=lTDR)EF0`Q^pUgsIpP2^EpvFdVAkf{^xcSqQSyb!y zA@;(3GIkNThyrL|2=t_=0zZSGUv)tUh@#5;jFq0mq6*wkaeO8di$Hfpb=rP5{q*j} zY?l>|OTc{+cF`Z_eU7yFeJ;}?0%M$k!9(R?!i;W?FQgI1U7xe*)4N=Fop`ct`U1(C z^@U892wX@3)F%SQf$oC(Vq@p1xYJ{XyYm<7zkG9>BkGK)V@n zu=^UEVI?PV_{cbf>W@Ao`vwBt4Ied!x=f-leP}(z zO1jI&8Q-$PuJ`9$jkqSpDel`Ly)ZA} z#|}%?BK12t>Ywsm7cK7J-?0_c;zEzG@jX7Ywe~cA{Snk)*BjS6j<6}|8wTos>kTum z<2E>9)0O-E@vQ-*f#8xK(6>MNp80ltg7xB2kYyh2<;mY2M{#_BRahrhnn3l$NMOJZ zvS#vsU{kw2$FUwmV;F1rktx}}NQKxN>v9HiX}&+|ai;v(shPl;KeB0wInEuc?u`S+ zAH%p}F%IZjlZ-jmS7U%p$JpTXQ?1(*?vsnl`Tvn)U7Y`)^HWdH{}27t)y`@9&)uE> zZ}_>3^Z$K6%k}_Q_0o?#a)0Ue_@DpM_3?k;uf04dD+8nJ5iS2!o{zQu>OK)F-41x& zEb|M0>ta~C?>9D=hNWMA>+7&o^Lw|$(zCyJIk5=KT;&f|(ycwVcsNcNqCmlW;Ex{J z^rZcX+0d}*L7+36p0odC(>goLH_W59{n_-{?((AZ^GZm-H^ZK zT#vxi6CHDC=6&Vw?sS6<{nZ)W+Vxm#XTvJ>_y-~zo>IH9>WTAEk8jme=b?)2&3io5 z_yJOFPVi6_{<(*mp6)W^xesK{6e8F8Hnk@fkb7*Z%HOc5V%>^>Sn&N}Q+r~yv#7tC z65wL2b7g<^IL11!^;hQ)7REY_Uh?sE+($7Dc8n7cSoiGw)Ps+JkxoXM)}85s_!lIj z|6J^;CXI482RQM0Z;z)soEi_@K3cC74N#L@8$Tclzkh%_wX@Fn*8o-6g+zI&-7MH$ z=IK%|nckbd)G3{bwFgPDHt!yZo#QRV!c{o;R@1v3#KzIRD_BJ~FmtKAmTx zVW}D=HMe1YY7{@>qx!~mQ^h>WS5>JZ^L?dkhp(E{D|?z3!01|!fGFJ4Po3&&hx4>PO|Ak)c==5Z>%U12X&!`U+f{(u}gpvNeEQIU9=voMXD7@8QjiUwc z&u}{|LPp@V{hq3wivwgruMSXSN$~vvYFvj~Co0~ImVzy}PX5$6Vg{fhNK)2NHBV4EzP&FuOL=QiUBTwQcoM5lxzdS_cj zaV!i~mr!eZG8DOiyDwBtbsetaL@%Ph?CI^5uti~NT(sM8g^frtR#|%HePOa@-U@T} z%#*kubZs~ax;|WLFbJf?xUBlD`%z+hU|YC4nGWQFBh*eqj?5<(-sK8y6v}sHVuVZRAcWqr7!1s7*2>%l;TQ&mIr_hZ8IX1W_ z?!*i70#zmkt}=Ea>P1)^tt54!`wP=9>HAxCA9Vo1k!y^)q+4~7{zukS7e9#Ulg>UY zR^|w_-w& z*b@>_*uo%31S=EOF04{+OjJ*yNwPgrO?AEbCaof{A4-lZAeyUbv9~#pR6X5&KRE3qfyhIB9j4EnE;!!PDafxTdvD+azGar zm8vE&=XhkDzzc13QT6mxbxDs89VUKe3^-_lhf~#**yE}R^4KbCusS)Tqhjpd_?&W4 ze47WW3E3_Q_C$ikA!%WP?Aya--%fD$Z8W?eDX#9eIqopkOVO^sO-D1oC{69j4UI?B zWPQO^vOAyUj-Nl2TY5UykIt$&@w#mQqpN}nh{E4aS0{DW9N7@4j401BL;5r^@F6n0 zZ$eD3*8b{H_rVkpg*%3-3Ddir4^F&fwhfhOgsbrIVREvkKwdt^ePcj9ad~ToNqP4V zQ)4^a#CJ9!ROV;H)RG=|qdIFhS~t8~ZTt1%a^UgKP-pdN`PZ0%e4$CeRg%o*pR1PZ zlDJp^Rb774tFG9O&H`}be5flaU;<(b(NZ$ zQo~3!wg)B~Z;o^y?T?MbViQfipg@hA-erU9vH}CGgXa4M7)Q1gs1cMx1X4N-A%9uP zgGZ_5#+zPly))INcTy8TQlA;6rp|Y{jZ@s$A%-ltuCG#~W&|S&xBVXR&%iz1<-KmS zY&aWaR`D-I57X??Ip^ z8ziqxkO_mUaG#0lu-=Yh+QeRtVq3xJs@DRdaNkKi-2z!ZsZW~jx07T^!0qD}$mYpN zf8%6q4!S&60PvVTZGj|A#jG`AiZN@6;5k#ATOc$VUOA;lFS`Reb}4EW@&aI6PGi=rDe}>~=&<>vFea_B2(a8RofZ7|+tMPd`l! z&+p}4!?5Y*n3yoq)kv<(>B&VYczC*ONpKZ@Y`QwE2NUS58Il*S;zhSCk+EB5xbLZy zcRL?-m}Eo>&6_>}r#SODwof|!`csf#C>C%P)`@km*a@KNZ|$WxO-61)XMzFlv!a{eqeMZB*!OJyBzv%fP-opKT*J-tvydPO1T ztk3paHvFxdBjPybtwMG3f)nqpC*F{koGQ}*SK;@ZDkm5UB?Ehea}m z#d-5EUVbsx*nOp7R42KVdu+qz$#`eaLn_g&E}Ez2b^gfD8}rn1^R?K#`D&{BGjdzB z`RbD%Wc(MqKpoxf`NR8@&|M94mCG0OY4ZJafovLZm9Y$stJmibj)m?sTGK-HoNhC- z&wTX_?J9OrkCZ!YkxV>Xg+H}OP48?qe0Y&ORP#B#N3s{5E@fYKx;mxXO!S{@sga|I zsApDOF7_^S&X5tqRmP_DrAC_1aIX>DnI}*q;nvJFp4p>P+kK`?y!YbHt)Z4ImX)z; zagW4)zZez#;bQ$X5wcz1Y#2@UTV2jy-P}ZwyWIK-mVC0oIKk@d#fD$jQ4j2+UDJCq&Z?F^?aS(jZEw?t_hKers(Tzif*kZL~1 zeG|3smUlCX{+}%Go-2|q^y{Ktw$SnCx(`5rDEz8(<;;0M+zys^y=aKs&n^=RSMfSk zwyeeWE?d?^c6CUfl#}3M#EB^juGLbFjH=|$?WSZk%2z(sKw9{uV(jBnuw!%Xvd6hB zaDLJwO)2TrUhRw$S+M8B?NjDFN>NRRN-*9chX^DzShYMn`RjHtC?BZ6F`+Oi#4AJS z+j30RPY&fH!B&D*AkeMTj&lLW#KXKOkpB41(w`nH?fww-XlWny&nkzkVz^2w6mK#{ zbl<^st2@&?@)rl1{sgNX>)qh`-p^9f%9gGuP_9 z-)Z^nJXuz76+We+M>{S5tdP8KRmg_jc%$#gdEX)yQm@*0_&+H`k~s!`z2EciquhaoAb@95Q-kxH7s{CIYU)FRN8c zdwkgBEM}x5sjk~Y97mlz#Cf1joi*&lH^y-68CNf_yo{@tX@;w$(bMp9f=KJ|9+gYd z9f;H;o&USk4TZ1tiIecr4n$+3N1>;X%A};9VdZq%5t|JE^ z3V-GTHDOdYilOURVO>V^pbOol0-`LWt)Js)N4<~h;R|KcgsbFcI%7EDCdtz;k`m6m z=p@;6@6!dsRmPI0)oTT=Y^_Y%hPCP~GdpU!;$nmEg8JgxlA7{r^TJAJe+2gK7skYi zac{@Ps-lqjz^n9^RW1{jxF`M4#cDD&JJ5ABsS?VDVICaVAeD@a2K1%Amb2)^IYm6`C725BZd`V#jIh`w8KJ$gwe>-gSSaRslF6$sa~tteXORLHtjc%1cy z`k;d`eq^0`+?O)w*f!07T*cy|hnbLF{GjQUOs;|Nj^ZFurfP0?laI z3lORp}N@1uj!n=vD6B?cr|MZ{6%w^Q*2pN!{(hRkGls zu9m}6!PUL(YL8vr^^E%$@Vzo(UU-drf4JtUUsZWjfiM)~cQBT`;y=;_+u6OT2eYOeY=iYFVdeHYbAmtz4AWH}Vaqm0i#%`?v zjiZr?a_AT$wcLqv=opG&2nzRQH#&P`xA!ZYgPFKrK_}OYRF+Q9s4P~eGjHl;$Gj7a zuG1eN3jg}1K23is*F(mV_3j2-0H>V94*AJ?*|XsGQVCx24=DjI>@)t+`@ZRYb1(bm z(wk)p;41vyn>)4ZIPvN4+@?-DXj7BaY=Ks$=mr>W(*tM=WrHTO z0{JM+i%l3_M{H0B(KhFl4emYr-agNbTQ;1eo*lhWmhUMWWv5=gvD;2fqt^2}`JRo= z&f7Dsbw2NUD%}Kpucp$U!06gzQ~ueDPQ0sz+}`zS^qbpcp9Nh)7dKT4Z~}ffUkm?haK+z-uLPf8fSXFy6TScd`5@ z(BJPk0ShYYbjj`i>bl204t%eAoY$T1JudG~bxa?2iXP}7aQB@jb!MEtNw(7ZO+D&a zuj_0_H=U$Cp$j+5binP~p3ug-gdjNBLA^_D=$2~~-p?~X#$@jQl0j3Qud5}Lx&g}ZFx;b)Y#|1G` zRTtiaQYMx49`~HS*6obm%^>miXG<2vr?o$$UT)^;BELHXEtud!)H!6>LEv=82K zQ}3gD<(ceXaJzoN&gEob`hDv34yR>Z4(_j+#+*+#R^zy~5t^YlSU&z*%7@@c{M619C)wtME||s{Z-Cy!Ld#gHjM&g}?qF zu07#D>kd5#vqUV5ydIL}J@g^9xZ5??#il`uSaW^wuo{)^Z>+hxY?v0aW|>V1!>qiMv5c~p(-nSQ+d(XMCfEx`Axs|a;ha;{E#O6{*xw-aIM^;&8X?|&DHedFldg&Igztpq)bIl{> zg)PONG1Wf&f|!^uwk(K?S!4??D9z6*$SWx;D9A6#%*n~!l4FY*PT-RKywco~ky(!H zQ91c`{@};zwZWrGi%W9z9eLTgqa3AKqYAdP%#E>m_-?4Yx}W%M`M)a8ouy$gjKV15 z;H4I=TRw>{Zjz*Fn!!;-A%bXewB+&y#gvp9Z<7cjR-;oiU{O&}3TnL}U$ssA32v?` zl#jDQl44|38kkJzal?WNC#03)akfcdSm}(brP&Ex28arhu^CT-KBu1npmaOfe>K*3C zYb=H)U$EiWa??1}QZSPpn9dpcP*AdctAuNzfcu4#YwZN+(zRFLtLu(k2vE^09=ZFb zw|np1?gWp9TR8BqEAGLjcX;CEZO3}_jpBPXZ|LpmQ9d^dIc{QPEWEHZu7&yi?$sJz zlknj&{Kvlh=XWnm|NPV`-vrjVw{`54A8SejGSnYru;)TUJF zCwDNXW>Rob<2XZSoXWOi?+16gznK2sYWT{c)~6`AQ@;3R{LkJ{gGVP{7~h08G%!`) tu195B4Ey4#uv>x>Ny>a{0c%lN44YvXiik@|Q4o?yu`sL-ea?fkx^JXv?7jd1 delta 99593 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 GxcwhC^2rVW diff --git a/TransPyV/temp/af9484a65085bf4b.pyi b/TransPyV/temp/af9484a65085bf4b.pyi deleted file mode 100644 index 3d49af5..0000000 --- a/TransPyV/temp/af9484a65085bf4b.pyi +++ /dev/null @@ -1,21 +0,0 @@ -""" -Auto-generated Python stub file from lib.core.Handles.HandlesNonlocal.py -Module: lib.core.Handles.HandlesNonlocal -""" - - -import t, c -from stdint import * -import ast -import llvmlite -import memhub -import string -import stdio -import lib.core.Handles.HandlesTranslator as HT -import lib.core.Handles.HandlesVar as HandlesVar - -def get_env_ptr_var(trans: HT.Translator | t.CPtr) -> llvmlite.Value | t.CPtr: pass - -def load_nonlocal_var(trans: HT.Translator | t.CPtr, name: str) -> llvmlite.Value | t.CPtr: pass - -def get_nonlocal_var_ptr(trans: HT.Translator | t.CPtr, name: str) -> llvmlite.Value | t.CPtr: pass diff --git a/TransPyV/temp/b547ac4f380bddb6.pyi b/TransPyV/temp/b547ac4f380bddb6.pyi deleted file mode 100644 index e960341..0000000 --- a/TransPyV/temp/b547ac4f380bddb6.pyi +++ /dev/null @@ -1,166 +0,0 @@ -""" -Auto-generated Python stub file from ast.tokens.py -Module: ast.tokens -""" - - -import t, c -from stdint import * -import memhub -import string - -class TokenType(t.CEnum): - EndMarker: t.State - NewLine: t.State - Indent: t.State - Dedent: t.State - Name: t.State - Number: t.State - String: t.State - FStringStart: t.State - FStringMiddle: t.State - FStringEnd: t.State - Op: t.State - Nl: t.State - Comment: t.State - Encoding: t.State -class Keyword(t.CEnum): - NotKeyword: t.State - False_: t.State - None_: t.State - True_: t.State - And: t.State - As: t.State - Assert: t.State - Async: t.State - Await: t.State - Break: t.State - Class: t.State - Continue: t.State - Def: t.State - Del: t.State - Elif: t.State - Else: t.State - Except: t.State - Finally: t.State - For: t.State - From: t.State - Global: t.State - If: t.State - Import: t.State - In: t.State - Is: t.State - Lambda: t.State - Nonlocal: t.State - Not: t.State - Or: t.State - Pass: t.State - Raise: t.State - Return: t.State - Try: t.State - While: t.State - With: t.State - Yield: t.State - Match: t.State - Case: t.State - Type: t.State -class TokOp(t.CEnum): - LPar: t.State - RPar: t.State - Lsqb: t.State - Rsqb: t.State - LBrace: t.State - RBrace: t.State - Comma: t.State - Colon: t.State - Dot: t.State - Semi: t.State - At: t.State - Equal: t.State - RArrow: t.State - PlusEq: t.State - MinusEq: t.State - StarEq: t.State - SlashEq: t.State - DSlashEq: t.State - PercentEq: t.State - AtEq: t.State - AmpEq: t.State - VBarEq: t.State - CaretEq: t.State - GtGtEq: t.State - LtLtEq: t.State - StarEqEq: t.State - DSlash: t.State - StarStar: t.State - LtLt: t.State - GtGt: t.State - LessEq: t.State - GreaterEq: t.State - EqEq: t.State - ExclaimEq: t.State - Less: t.State - Greater: t.State - Plus: t.State - Minus: t.State - Star: t.State - Slash: t.State - Percent: t.State - Amp: t.State - VBar: t.State - Caret: t.State - Tilde: t.State - ColonEq: t.State - Ellipsis: t.State - Bang: t.State -class Token: - type: t.CInt - op_subtype: t.CInt - kw_subtype: t.CInt - str_val: str - int_val: t.CInt64T - float_val: t.CDouble - is_float: t.CInt - is_complex: t.CInt - lineno: t.CInt - col_offset: t.CInt - end_lineno: t.CInt - end_col_offset: t.CInt - next: Token | t.CPtr - def __new__(self: Token, pool: memhub.MemManager | t.CPtr) -> t.CInt: pass -class KwEntry: - name: str - kw_id: t.CInt - next: KwEntry | t.CPtr - def __new__(self: KwEntry, pool: memhub.MemManager | t.CPtr) -> t.CInt: pass - -_kw_head: t.CExtern | KwEntry | t.CPtr -_kw_pool: t.CExtern | memhub.MemManager | t.CPtr - -def _kw_intern(pool: memhub.MemManager | t.CPtr, name: str, kw_id: t.CInt) -> t.CInt: pass - -def _kw_lookup(name: str) -> t.CInt: pass - -def _init_keywords(pool: memhub.MemManager | t.CPtr) -> t.CInt: pass - - -class OpEntry: - name: str - op_id: t.CInt - length: t.CInt - next: OpEntry | t.CPtr - def __new__(self: OpEntry, pool: memhub.MemManager | t.CPtr) -> t.CInt: pass - -_op_head: t.CExtern | OpEntry | t.CPtr - -def _op_intern(pool: memhub.MemManager | t.CPtr, name: str, op_id: t.CInt) -> t.CInt: pass - -def _init_operators(pool: memhub.MemManager | t.CPtr) -> t.CInt: pass - -def _init_tables(pool: memhub.MemManager | t.CPtr) -> t.CInt: pass - -def new_token(pool: memhub.MemManager | t.CPtr, ttype: t.CInt, lineno: t.CInt, col_offset: t.CInt) -> Token | t.CPtr: pass - -def token_set_str(pool: memhub.MemManager | t.CPtr, tok: Token | t.CPtr, src: str, start: t.CSizeT, length: t.CSizeT) -> t.CInt: pass - -def token_set_str_literal(pool: memhub.MemManager | t.CPtr, tok: Token | t.CPtr, text: str) -> t.CInt: pass diff --git a/TransPyV/temp/bbdf3bbd4c3bc28c.pyi b/TransPyV/temp/bbdf3bbd4c3bc28c.pyi deleted file mode 100644 index 70dcdbc..0000000 --- a/TransPyV/temp/bbdf3bbd4c3bc28c.pyi +++ /dev/null @@ -1,138 +0,0 @@ -""" -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/TransPyV/temp/c9d54a4158f7f5a8.pyi b/TransPyV/temp/c9d54a4158f7f5a8.pyi deleted file mode 100644 index 3e2d738..0000000 --- a/TransPyV/temp/c9d54a4158f7f5a8.pyi +++ /dev/null @@ -1,34 +0,0 @@ -""" -Auto-generated Python stub file from hashlib.__sha256.py -Module: hashlib.__sha256 -""" - - -import t, c - -SHA256_BLOCK_LEN: t.CDefine = 64 -SHA256_DIGEST_LEN: t.CDefine = 32 -sha256_K: t.CExtern | t.CArray[t.CUInt32T, 64] - -def s0(x: t.CUInt32T) -> t.CUInt32T: pass - -def s1(x: t.CUInt32T) -> t.CUInt32T: pass - -def S0(x: t.CUInt32T) -> t.CUInt32T: pass - -def S1(x: t.CUInt32T) -> t.CUInt32T: pass - -def Ch(x: t.CUInt32T, y: t.CUInt32T, z: t.CUInt32T) -> t.CUInt32T: pass - -def Maj(x: t.CUInt32T, y: t.CUInt32T, z: t.CUInt32T) -> t.CUInt32T: pass - - -@t.Object -class sha256: - state: t.CArray[t.CUInt32T, 8] - count: t.CUInt64T - 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: t.CArray[t.CUInt8T, SHA256_DIGEST_LEN]) -> t.CInt: pass \ No newline at end of file diff --git a/TransPyV/temp/c9f4be41ca1cc2b4.pyi b/TransPyV/temp/c9f4be41ca1cc2b4.pyi deleted file mode 100644 index 12ff3c2..0000000 --- a/TransPyV/temp/c9f4be41ca1cc2b4.pyi +++ /dev/null @@ -1,22 +0,0 @@ -""" -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 = 0, owned: bool = False) -> 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/TransPyV/temp/f5522571bcce7bcb.pyi b/TransPyV/temp/f5522571bcce7bcb.pyi deleted file mode 100644 index 106a202..0000000 --- a/TransPyV/temp/f5522571bcce7bcb.pyi +++ /dev/null @@ -1,100 +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.CLongLong -ULONGLONG: t.CTypedef = t.CUnsignedLongLong -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 -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 -SIZE_T: t.CTypedef = t.CSizeT -SSIZE_T: t.CTypedef = t.CPtrDiffT -PTRDIFF_T: t.CTypedef = t.CPtrDiffT -int8_t: t.CTypedef = t.CInt8T -int16_t: t.CTypedef = t.CInt16T -int32_t: t.CTypedef = t.CInt32T -int64_t: t.CTypedef = t.CInt64T -uint8_t: t.CTypedef = t.CUInt8T -uint16_t: t.CTypedef = t.CUInt16T -uint32_t: t.CTypedef = t.CUInt32T -uint64_t: t.CTypedef = t.CUInt64T -size_t: t.CTypedef = t.CSizeT -ssize_t: t.CTypedef = t.CPtrDiffT -ptrdiff_t: t.CTypedef = t.CPtrDiffT -intptr_t: t.CTypedef = t.CIntPtrT -uintptr_t: t.CTypedef = t.CUIntPtrT -wchar_t: t.CTypedef = t.CWCharT -char8_t: t.CTypedef = t.CChar8T -char16_t: t.CTypedef = t.CChar16T -char32_t: t.CTypedef = t.CChar32T -float8_t: t.CTypedef = t.CFloat8T -float16_t: t.CTypedef = t.CFloat16T -float32_t: t.CTypedef = t.CFloat32T -float64_t: t.CTypedef = t.CFloat64T -float128_t: t.CTypedef = t.CFloat128T -_Bool: t.CTypedef = t.CBool \ No newline at end of file diff --git a/TransPyV/temp/f6b51804a0ba8ff0.pyi b/TransPyV/temp/f6b51804a0ba8ff0.pyi deleted file mode 100644 index 0036d89..0000000 --- a/TransPyV/temp/f6b51804a0ba8ff0.pyi +++ /dev/null @@ -1,192 +0,0 @@ -""" -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: t.CArray[t.CChar, 260] - cAlternateFileName: t.CArray[t.CChar, 14] -class WIN32_FIND_DATAW: - dwFileAttributes: ULONG - ftCreationTime: FILETIME - ftLastAccessTime: FILETIME - ftLastWriteTime: FILETIME - nFileSizeHigh: ULONG - nFileSizeLow: ULONG - dwReserved0: ULONG - dwReserved1: ULONG - cFileName: t.CArray[t.CUInt16T, 260] - cAlternateFileName: t.CArray[t.CUInt16T, 14] - -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 - - -HANDLE_FLAG_INHERIT: t.CDefine = 0x00000001 -HANDLE_FLAG_PROTECT_FROM_CLOSE: t.CDefine = 0x00000002 - -def CreatePipe(hReadPipe: HANDLE | t.CPtr, hWritePipe: HANDLE | t.CPtr, lpPipeAttributes: SECURITY_ATTRIBUTES | t.CPtr, nSize: ULONG) -> BOOL | t.State: pass - -def SetHandleInformation(hObject: HANDLE, dwMask: ULONG, dwFlags: ULONG) -> BOOL | t.State: pass - -def DuplicateHandle(hSourceProcessHandle: HANDLE, hSourceHandle: HANDLE, hTargetProcessHandle: HANDLE, lpTargetHandle: HANDLE | t.CPtr, dwDesiredAccess: ULONG, bInheritHandle: BOOL, dwOptions: ULONG) -> BOOL | t.State: pass - - -DUPLICATE_SAME_ACCESS: t.CDefine = 0x00000002 \ No newline at end of file diff --git a/ViperQtHelloWorld/App/main.py b/ViperQtHelloWorld/App/main.vp similarity index 100% rename from ViperQtHelloWorld/App/main.py rename to ViperQtHelloWorld/App/main.vp diff --git a/includes/_dict.py b/includes/_dict.vp similarity index 100% rename from includes/_dict.py rename to includes/_dict.vp diff --git a/includes/_fakeduck.py b/includes/_fakeduck.vp similarity index 100% rename from includes/_fakeduck.py rename to includes/_fakeduck.vp diff --git a/includes/_list.py b/includes/_list.vp similarity index 100% rename from includes/_list.py rename to includes/_list.vp diff --git a/includes/_variant.py b/includes/_variant.vp similarity index 100% rename from includes/_variant.py rename to includes/_variant.vp diff --git a/includes/_withcontent.py b/includes/_withcontent.vp similarity index 100% rename from includes/_withcontent.py rename to includes/_withcontent.vp diff --git a/includes/argparse.py b/includes/argparse.vp similarity index 100% rename from includes/argparse.py rename to includes/argparse.vp diff --git a/includes/asm.py b/includes/asm.vp similarity index 100% rename from includes/asm.py rename to includes/asm.vp diff --git a/includes/ast/__init__.py b/includes/ast/__init__.vp similarity index 100% rename from includes/ast/__init__.py rename to includes/ast/__init__.vp diff --git a/includes/ast/astaux.py b/includes/ast/astaux.vp similarity index 100% rename from includes/ast/astaux.py rename to includes/ast/astaux.vp diff --git a/includes/ast/base.py b/includes/ast/base.vp similarity index 100% rename from includes/ast/base.py rename to includes/ast/base.vp diff --git a/includes/ast/exprs.py b/includes/ast/exprs.vp similarity index 100% rename from includes/ast/exprs.py rename to includes/ast/exprs.vp diff --git a/includes/ast/lexer.py b/includes/ast/lexer.vp similarity index 100% rename from includes/ast/lexer.py rename to includes/ast/lexer.vp diff --git a/includes/ast/match.py b/includes/ast/match.vp similarity index 100% rename from includes/ast/match.py rename to includes/ast/match.vp diff --git a/includes/ast/parser.py b/includes/ast/parser.vp similarity index 100% rename from includes/ast/parser.py rename to includes/ast/parser.vp diff --git a/includes/ast/stmts.py b/includes/ast/stmts.vp similarity index 100% rename from includes/ast/stmts.py rename to includes/ast/stmts.vp diff --git a/includes/ast/tokens.py b/includes/ast/tokens.vp similarity index 100% rename from includes/ast/tokens.py rename to includes/ast/tokens.vp diff --git a/includes/atom.py b/includes/atom.vp similarity index 100% rename from includes/atom.py rename to includes/atom.vp diff --git a/includes/base64.py b/includes/base64.vp similarity index 100% rename from includes/base64.py rename to includes/base64.vp diff --git a/includes/binascii.py b/includes/binascii.vp similarity index 100% rename from includes/binascii.py rename to includes/binascii.vp diff --git a/includes/builtins.py b/includes/builtins.vp similarity index 100% rename from includes/builtins.py rename to includes/builtins.vp diff --git a/includes/condition.py b/includes/condition.vp similarity index 100% rename from includes/condition.py rename to includes/condition.vp diff --git a/includes/ctraits.pyi b/includes/ctraits.vpi similarity index 100% rename from includes/ctraits.pyi rename to includes/ctraits.vpi diff --git a/includes/event.py b/includes/event.vp similarity index 100% rename from includes/event.py rename to includes/event.vp diff --git a/includes/hashlib/__init__.py b/includes/hashlib/__init__.vp similarity index 100% rename from includes/hashlib/__init__.py rename to includes/hashlib/__init__.vp diff --git a/includes/hashlib/__md5.py b/includes/hashlib/__md5.vp similarity index 100% rename from includes/hashlib/__md5.py rename to includes/hashlib/__md5.vp diff --git a/includes/hashlib/__sha1.py b/includes/hashlib/__sha1.vp similarity index 100% rename from includes/hashlib/__sha1.py rename to includes/hashlib/__sha1.vp diff --git a/includes/hashlib/__sha256.py b/includes/hashlib/__sha256.vp similarity index 100% rename from includes/hashlib/__sha256.py rename to includes/hashlib/__sha256.vp diff --git a/includes/hashlib/__sha512.py b/includes/hashlib/__sha512.vp similarity index 100% rename from includes/hashlib/__sha512.py rename to includes/hashlib/__sha512.vp diff --git a/includes/hashtable.py b/includes/hashtable.vp similarity index 100% rename from includes/hashtable.py rename to includes/hashtable.vp diff --git a/includes/hello.py b/includes/hello.vp similarity index 100% rename from includes/hello.py rename to includes/hello.vp diff --git a/includes/json/__init__.py b/includes/json/__init__.vp similarity index 100% rename from includes/json/__init__.py rename to includes/json/__init__.vp diff --git a/includes/json/__parser.py b/includes/json/__parser.vp similarity index 100% rename from includes/json/__parser.py rename to includes/json/__parser.vp diff --git a/includes/json/__writer.py b/includes/json/__writer.vp similarity index 100% rename from includes/json/__writer.py rename to includes/json/__writer.vp diff --git a/includes/linkedlist.py b/includes/linkedlist.vp similarity index 100% rename from includes/linkedlist.py rename to includes/linkedlist.vp diff --git a/includes/llvmlite/__builder.py b/includes/llvmlite/__builder.vp similarity index 100% rename from includes/llvmlite/__builder.py rename to includes/llvmlite/__builder.vp diff --git a/includes/llvmlite/__function.py b/includes/llvmlite/__function.vp similarity index 100% rename from includes/llvmlite/__function.py rename to includes/llvmlite/__function.vp diff --git a/includes/llvmlite/__init__.py b/includes/llvmlite/__init__.vp similarity index 100% rename from includes/llvmlite/__init__.py rename to includes/llvmlite/__init__.vp diff --git a/includes/llvmlite/__module.py b/includes/llvmlite/__module.vp similarity index 100% rename from includes/llvmlite/__module.py rename to includes/llvmlite/__module.vp diff --git a/includes/llvmlite/__types.py b/includes/llvmlite/__types.vp similarity index 100% rename from includes/llvmlite/__types.py rename to includes/llvmlite/__types.vp diff --git a/includes/llvmlite/__values.py b/includes/llvmlite/__values.vp similarity index 100% rename from includes/llvmlite/__values.py rename to includes/llvmlite/__values.vp diff --git a/includes/llvmlite/__verify.py b/includes/llvmlite/__verify.vp similarity index 100% rename from includes/llvmlite/__verify.py rename to includes/llvmlite/__verify.vp diff --git a/includes/lock.py b/includes/lock.vp similarity index 100% rename from includes/lock.py rename to includes/lock.vp diff --git a/includes/memhub.py b/includes/memhub.vp similarity index 100% rename from includes/memhub.py rename to includes/memhub.vp diff --git a/includes/numpy/__init__.py b/includes/numpy/__init__.vp similarity index 100% rename from includes/numpy/__init__.py rename to includes/numpy/__init__.vp diff --git a/includes/os/__init__.py b/includes/os/__init__.vp similarity index 100% rename from includes/os/__init__.py rename to includes/os/__init__.vp diff --git a/includes/os/_posix.py b/includes/os/_posix.vp similarity index 100% rename from includes/os/_posix.py rename to includes/os/_posix.vp diff --git a/includes/os/_win32.py b/includes/os/_win32.vp similarity index 100% rename from includes/os/_win32.py rename to includes/os/_win32.vp diff --git a/includes/os/path.py b/includes/os/path.vp similarity index 100% rename from includes/os/path.py rename to includes/os/path.vp diff --git a/includes/platmacro.py b/includes/platmacro.vp similarity index 100% rename from includes/platmacro.py rename to includes/platmacro.vp diff --git a/includes/posix.py b/includes/posix.vp similarity index 100% rename from includes/posix.py rename to includes/posix.vp diff --git a/includes/requests.py b/includes/requests.vp similarity index 100% rename from includes/requests.py rename to includes/requests.vp diff --git a/includes/rwlock.py b/includes/rwlock.vp similarity index 100% rename from includes/rwlock.py rename to includes/rwlock.vp diff --git a/includes/shutil.py b/includes/shutil.vp similarity index 100% rename from includes/shutil.py rename to includes/shutil.vp diff --git a/includes/socket.py b/includes/socket.vp similarity index 100% rename from includes/socket.py rename to includes/socket.vp diff --git a/includes/spinlock.py b/includes/spinlock.vp similarity index 100% rename from includes/spinlock.py rename to includes/spinlock.vp diff --git a/includes/stdarg.py b/includes/stdarg.vp similarity index 100% rename from includes/stdarg.py rename to includes/stdarg.vp diff --git a/includes/stdint.py b/includes/stdint.vp similarity index 100% rename from includes/stdint.py rename to includes/stdint.vp diff --git a/includes/stdio.py b/includes/stdio.vp similarity index 100% rename from includes/stdio.py rename to includes/stdio.vp diff --git a/includes/stdlib.py b/includes/stdlib.vp similarity index 100% rename from includes/stdlib.py rename to includes/stdlib.vp diff --git a/includes/string.py b/includes/string.vp similarity index 100% rename from includes/string.py rename to includes/string.vp diff --git a/includes/subprocess.py b/includes/subprocess.vp similarity index 100% rename from includes/subprocess.py rename to includes/subprocess.vp diff --git a/includes/sys.py b/includes/sys.vp similarity index 100% rename from includes/sys.py rename to includes/sys.vp diff --git a/includes/testcheck.py b/includes/testcheck.vp similarity index 100% rename from includes/testcheck.py rename to includes/testcheck.vp diff --git a/includes/this.py b/includes/this.vp similarity index 100% rename from includes/this.py rename to includes/this.vp diff --git a/includes/vector.py b/includes/vector.vp similarity index 100% rename from includes/vector.py rename to includes/vector.vp diff --git a/includes/viperio.py b/includes/viperio.vp similarity index 100% rename from includes/viperio.py rename to includes/viperio.vp diff --git a/includes/viperlib.py b/includes/viperlib.vp similarity index 100% rename from includes/viperlib.py rename to includes/viperlib.vp diff --git a/includes/vipermath.py b/includes/vipermath.vp similarity index 100% rename from includes/vipermath.py rename to includes/vipermath.vp diff --git a/includes/vipersimd.py b/includes/vipersimd.vp similarity index 100% rename from includes/vipersimd.py rename to includes/vipersimd.vp diff --git a/includes/viperstring.py b/includes/viperstring.vp similarity index 100% rename from includes/viperstring.py rename to includes/viperstring.vp diff --git a/includes/vqt6 copy/__init__.py b/includes/vqt6 copy/__init__.vp similarity index 100% rename from includes/vqt6 copy/__init__.py rename to includes/vqt6 copy/__init__.vp diff --git a/includes/vqt6 copy/_qtcore.py b/includes/vqt6 copy/_qtcore.vp similarity index 100% rename from includes/vqt6 copy/_qtcore.py rename to includes/vqt6 copy/_qtcore.vp diff --git a/includes/vqt6 copy/_qtgui.py b/includes/vqt6 copy/_qtgui.vp similarity index 100% rename from includes/vqt6 copy/_qtgui.py rename to includes/vqt6 copy/_qtgui.vp diff --git a/includes/vqt6 copy/_qtnetwork.py b/includes/vqt6 copy/_qtnetwork.vp similarity index 100% rename from includes/vqt6 copy/_qtnetwork.py rename to includes/vqt6 copy/_qtnetwork.vp diff --git a/includes/vqt6 copy/_qtwidgets.py b/includes/vqt6 copy/_qtwidgets.vp similarity index 100% rename from includes/vqt6 copy/_qtwidgets.py rename to includes/vqt6 copy/_qtwidgets.vp diff --git a/includes/vqt6 copy/_types.py b/includes/vqt6 copy/_types.vp similarity index 100% rename from includes/vqt6 copy/_types.py rename to includes/vqt6 copy/_types.vp diff --git a/includes/vqt6/__init__.py b/includes/vqt6/__init__.vp similarity index 100% rename from includes/vqt6/__init__.py rename to includes/vqt6/__init__.vp diff --git a/includes/vqt6/_qtcore.py b/includes/vqt6/_qtcore.vp similarity index 100% rename from includes/vqt6/_qtcore.py rename to includes/vqt6/_qtcore.vp diff --git a/includes/vqt6/_qtgui.py b/includes/vqt6/_qtgui.vp similarity index 100% rename from includes/vqt6/_qtgui.py rename to includes/vqt6/_qtgui.vp diff --git a/includes/vqt6/_qtnetwork.py b/includes/vqt6/_qtnetwork.vp similarity index 100% rename from includes/vqt6/_qtnetwork.py rename to includes/vqt6/_qtnetwork.vp diff --git a/includes/vqt6/_qtwidgets.py b/includes/vqt6/_qtwidgets.vp similarity index 100% rename from includes/vqt6/_qtwidgets.py rename to includes/vqt6/_qtwidgets.vp diff --git a/includes/vqt6/_types.py b/includes/vqt6/_types.vp similarity index 100% rename from includes/vqt6/_types.py rename to includes/vqt6/_types.vp diff --git a/includes/vrandom.py b/includes/vrandom.vp similarity index 100% rename from includes/vrandom.py rename to includes/vrandom.vp diff --git a/includes/vthreading.py b/includes/vthreading.vp similarity index 100% rename from includes/vthreading.py rename to includes/vthreading.vp diff --git a/includes/w32/fileio.py b/includes/w32/fileio.vp similarity index 100% rename from includes/w32/fileio.py rename to includes/w32/fileio.vp diff --git a/includes/w32/win32base.py b/includes/w32/win32base.vp similarity index 100% rename from includes/w32/win32base.py rename to includes/w32/win32base.vp diff --git a/includes/w32/win32console.py b/includes/w32/win32console.vp similarity index 100% rename from includes/w32/win32console.py rename to includes/w32/win32console.vp diff --git a/includes/w32/win32file.py b/includes/w32/win32file.vp similarity index 100% rename from includes/w32/win32file.py rename to includes/w32/win32file.vp diff --git a/includes/w32/win32memory.py b/includes/w32/win32memory.vp similarity index 100% rename from includes/w32/win32memory.py rename to includes/w32/win32memory.vp diff --git a/includes/w32/win32process.py b/includes/w32/win32process.vp similarity index 100% rename from includes/w32/win32process.py rename to includes/w32/win32process.vp diff --git a/includes/w32/win32sync.py b/includes/w32/win32sync.vp similarity index 100% rename from includes/w32/win32sync.py rename to includes/w32/win32sync.vp diff --git a/includes/w32/winsock2.py b/includes/w32/winsock2.vp similarity index 100% rename from includes/w32/winsock2.py rename to includes/w32/winsock2.vp diff --git a/includes/zlib/__init__.py b/includes/zlib/__init__.vp similarity index 100% rename from includes/zlib/__init__.py rename to includes/zlib/__init__.vp diff --git a/includes/zlib/pyzlib.py b/includes/zlib/pyzlib.vp similarity index 100% rename from includes/zlib/pyzlib.py rename to includes/zlib/pyzlib.vp diff --git a/includes/zlib/zchecksum.py b/includes/zlib/zchecksum.vp similarity index 100% rename from includes/zlib/zchecksum.py rename to includes/zlib/zchecksum.vp diff --git a/includes/zlib/zdef.py b/includes/zlib/zdef.vp similarity index 100% rename from includes/zlib/zdef.py rename to includes/zlib/zdef.vp diff --git a/includes/zlib/zdeflate.py b/includes/zlib/zdeflate.vp similarity index 100% rename from includes/zlib/zdeflate.py rename to includes/zlib/zdeflate.vp diff --git a/includes/zlib/zhuff.py b/includes/zlib/zhuff.vp similarity index 100% rename from includes/zlib/zhuff.py rename to includes/zlib/zhuff.vp diff --git a/includes/zlib/zinflate.py b/includes/zlib/zinflate.vp similarity index 100% rename from includes/zlib/zinflate.py rename to includes/zlib/zinflate.vp diff --git a/lib/Projectrans/Config.py b/lib/Projectrans/Config.py index 4829057..7761fe0 100644 --- a/lib/Projectrans/Config.py +++ b/lib/Projectrans/Config.py @@ -146,7 +146,7 @@ def main() -> None: parser.add_argument('--clean', action='store_true', help='清理 output 和 temp 目录') parser.add_argument('--run', action='store_true', help='编译成功后立即执行生成的可执行文件') parser.add_argument('--rebuild-includes', action='store_true', help='删除 includes.binary 预编译缓存并重新编译所有 includes') - parser.add_argument('--clear-cache', action='store_true', help='清除 .transpyc_cache 全局缓存(.pyi/.stub.ll/.doc.json)') + parser.add_argument('--clear-cache', action='store_true', help='清除 .transpyc_cache 全局缓存(.vpi/.stub.ll/.doc.json)') args: argparse.Namespace = parser.parse_args() diff --git a/lib/Projectrans/Phase1Generator.py b/lib/Projectrans/Phase1Generator.py index 26a2ba9..ee8ec4e 100644 --- a/lib/Projectrans/Phase1Generator.py +++ b/lib/Projectrans/Phase1Generator.py @@ -119,7 +119,7 @@ class Phase1Generator: for root, dirs, files in os.walk(includes_dir): 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'): + if fname.endswith('.vp') or fname.endswith('.py') or fname.endswith('.vpi') or fname.endswith('.pyi'): 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('/', '.') @@ -127,10 +127,10 @@ class Phase1Generator: info: tuple[str, str, str] = (src_path, rel_from_inc, includes_dir) include_file_map[module_name] = info top_pkg: str = module_name.split('.')[0] - # __init__.py 是包入口,应优先作为 top_pkg 的代表 + # __init__.vp/__init__.py 是包入口,应优先作为 top_pkg 的代表 # (参考 find_reachable_files_from_entries 的优先级逻辑), - # 否则若 os/path.py 先被遍历,'os' 会错误指向 path.py - # 而非 os/__init__.py,导致包入口 SHA1 未注册到 sha1_map + # 否则若 os/path.vp 先被遍历,'os' 会错误指向 path.vp + # 而非 os/__init__.vp,导致包入口 SHA1 未注册到 sha1_map if module_name == f"{top_pkg}.__init__": include_file_map[top_pkg] = info elif top_pkg not in include_file_map: @@ -208,12 +208,15 @@ class Phase1Generator: return needed_infos def run(self) -> None: - """扫描源目录,只处理入口文件可达的 .py 文件(导入遍历)""" + """扫描源目录,只处理入口文件可达的 .vp/.py 文件(导入遍历)""" py_files: list[str] if self.entry_files: py_files = list(self.entry_files) else: - main_py: str = os.path.join(self.src_root, 'main.py') + main_py: str = os.path.join(self.src_root, 'main.vp') + if not os.path.exists(main_py): + # 回退到 main.py(向后兼容) + main_py = os.path.join(self.src_root, 'main.py') if os.path.exists(main_py): py_files = [main_py] else: @@ -221,7 +224,7 @@ class Phase1Generator: for root, dirs, files in os.walk(self.src_root): dirs[:] = [d for d in dirs if d not in ('__pycache__',)] for file in files: - if file.endswith('.py'): + if file.endswith('.vp') or file.endswith('.py'): py_files.append(os.path.join(root, file)) if not py_files: @@ -286,7 +289,7 @@ class Phase1Generator: for root, dirs, files in os.walk(includes_dir): 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'): + if fname.endswith('.vp') or fname.endswith('.py') or fname.endswith('.vpi') or fname.endswith('.pyi'): 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)) @@ -315,14 +318,14 @@ class Phase1Generator: self.include_py_map[top_module] = sha1 self.include_py_map[module_name] = sha1 - sig_path: str = os.path.join(self.temp_dir, f"{sha1}.pyi") + sig_path: str = os.path.join(self.temp_dir, f"{sha1}.vpi") if os.path.isfile(sig_path): - _vlog().info(f" 缓存命中: {rel_from_inc} -> {sha1}.pyi") + _vlog().info(f" 缓存命中: {rel_from_inc} -> {sha1}.vpi") continue # 全局缓存检查(不被 --clean 清除) if _TryGlobalCache(sha1, 'pyi', sig_path): - _vlog().info(f" 缓存命中(全局): {rel_from_inc} -> {sha1}.pyi") + _vlog().info(f" 缓存命中(全局): {rel_from_inc} -> {sha1}.vpi") continue # 缓存未命中,需读取 content 生成 .pyi @@ -332,7 +335,7 @@ class Phase1Generator: with open(sig_path, 'w', encoding='utf-8', newline='\n') as f: f.write(sig_content) _SaveToGlobalCache(sha1, 'pyi', sig_path) - _vlog().info(f" 生成签名: {rel_from_inc} -> {sha1}.pyi") + _vlog().info(f" 生成签名: {rel_from_inc} -> {sha1}.vpi") except Exception as e: _vlog().error(f"处理 include 文件失败 {rel_from_inc}: {e}") @@ -341,7 +344,7 @@ class Phase1Generator: if not os.path.isdir(self.temp_dir): return typedef_map for fname in os.listdir(self.temp_dir): - if not fname.endswith('.pyi'): + if not (fname.endswith('.vpi') or fname.endswith('.pyi')): continue pyi_path: str = os.path.join(self.temp_dir, fname) try: @@ -474,7 +477,7 @@ class Phase1Generator: except Exception: pass - sig_path: str = os.path.join(self.temp_dir, f"{sha1}.pyi") + sig_path: str = os.path.join(self.temp_dir, f"{sha1}.vpi") if not os.path.isfile(sig_path): _TryGlobalCache(sha1, 'pyi', sig_path) with open(sig_path, 'r', encoding='utf-8') as f: @@ -530,9 +533,9 @@ class Phase1Generator: return self.sha1_map[sha1] = rel_path.replace(os.sep, '/').replace(chr(92), '/') - sig_path: str = os.path.join(self.temp_dir, f"{sha1}.pyi") + sig_path: str = os.path.join(self.temp_dir, f"{sha1}.vpi") if os.path.isfile(sig_path): - _vlog().info(f" -> {sha1}.pyi (缓存)") + _vlog().info(f" -> {sha1}.vpi (缓存)") # 缓存命中时补全缺失的 .doc.json doc_path: str = os.path.join(self.temp_dir, f"{sha1}.doc.json") if not os.path.isfile(doc_path): @@ -551,7 +554,7 @@ class Phase1Generator: # 全局缓存检查 if _TryGlobalCache(sha1, 'pyi', sig_path): - _vlog().info(f" -> {sha1}.pyi (全局缓存)") + _vlog().info(f" -> {sha1}.vpi (全局缓存)") doc_path: str = os.path.join(self.temp_dir, f"{sha1}.doc.json") if not os.path.isfile(doc_path): _TryGlobalCache(sha1, 'doc.json', doc_path) @@ -566,7 +569,7 @@ class Phase1Generator: with open(sig_path, 'w', encoding='utf-8', newline='\n') as f: f.write(sig_content) _SaveToGlobalCache(sha1, 'pyi', sig_path) - _vlog().info(f" -> {sha1}.pyi (签名)") + _vlog().info(f" -> {sha1}.vpi (签名)") # 提取 docstring 写入 {sha1}.doc.json,供 Phase2 跨模块 __doc__ 加载 docs: dict[str, str] = self._extract_docstrings(content) @@ -588,7 +591,7 @@ class Phase1Generator: _vlog().info(f" -> {sha1}.stub.ll (缓存)") return - sig_path: str = os.path.join(self.temp_dir, f"{sha1}.pyi") + sig_path: str = os.path.join(self.temp_dir, f"{sha1}.vpi") with open(sig_path, 'r', encoding='utf-8') as f: sig_content: str = f.read() @@ -613,9 +616,9 @@ class Phase1Generator: ctype_marker_names.add(attr_name) valid_sha1_keys: set[str] = set(self.sha1_map.keys()) for fname in os.listdir(self.temp_dir): - if not fname.endswith('.pyi'): + if not (fname.endswith('.vpi') or fname.endswith('.pyi')): continue - sha1_key: str = fname.replace('.pyi', '') + sha1_key: str = fname.replace('.vpi', '').replace('.pyi', '') if sha1_key not in valid_sha1_keys: continue pyi_path: str = os.path.join(self.temp_dir, fname) diff --git a/lib/Projectrans/Phase2Translator.py b/lib/Projectrans/Phase2Translator.py index 91d1bfa..be3f933 100644 --- a/lib/Projectrans/Phase2Translator.py +++ b/lib/Projectrans/Phase2Translator.py @@ -217,19 +217,19 @@ class Phase2Translator: fpath = os.path.join(self.temp_dir, fname) if fname.startswith('_'): continue - if fname.endswith('.pyi'): + if fname.endswith('.vpi') or fname.endswith('.pyi'): sha1 = fname[:-4] self.sig_files[sha1] = fpath elif fname.endswith('.stub.ll'): sha1 = fname[:-8] self.stub_files[sha1] = fpath - # 从全局缓存补充 temp_dir 中缺失的 .pyi / .stub.ll + # 从全局缓存补充 temp_dir 中缺失的 .vpi / .stub.ll if os.path.isdir(_GLOBAL_CACHE_DIR): for fname in os.listdir(_GLOBAL_CACHE_DIR): if fname.startswith('_'): continue - if fname.endswith('.pyi'): + if fname.endswith('.vpi') or fname.endswith('.pyi'): sha1 = fname[:-4] if sha1 not in self.sig_files: self.sig_files[sha1] = os.path.join(_GLOBAL_CACHE_DIR, fname) @@ -256,7 +256,7 @@ class Phase2Translator: def _build_struct_sha1_map(self) -> dict[str, str]: struct_sha1_map = {} valid_sha1_keys = set(self.sha1_map.keys()) - # 收集 temp_dir 和全局缓存中的 .pyi 文件 + # 收集 temp_dir 和全局缓存中的 .vpi/.pyi 文件 pyi_dirs: list[str] = [self.temp_dir] if os.path.isdir(_GLOBAL_CACHE_DIR): pyi_dirs.append(_GLOBAL_CACHE_DIR) @@ -264,9 +264,9 @@ class Phase2Translator: if not os.path.isdir(scan_dir): continue for fname in os.listdir(scan_dir): - if not fname.endswith('.pyi'): + if not (fname.endswith('.vpi') or fname.endswith('.pyi')): continue - sha1_key = fname.replace('.pyi', '') + sha1_key = fname.replace('.vpi', '').replace('.pyi', '') if sha1_key not in valid_sha1_keys: continue if sha1_key in struct_sha1_map: @@ -287,7 +287,10 @@ class Phase2Translator: if self.entry_files: py_files = list(self.entry_files) else: - main_py = os.path.join(self.src_root, 'main.py') + main_py = os.path.join(self.src_root, 'main.vp') + if not os.path.exists(main_py): + # 回退到 main.py(向后兼容) + main_py = os.path.join(self.src_root, 'main.py') if os.path.exists(main_py): py_files = [main_py] else: @@ -295,7 +298,7 @@ class Phase2Translator: for root, dirs, files in os.walk(self.src_root): dirs[:] = [d for d in dirs if d not in ('__pycache__',)] for file in files: - if file.endswith('.py'): + if file.endswith('.vp') or file.endswith('.py'): py_files.append(os.path.join(root, file)) if not py_files: @@ -525,7 +528,10 @@ class Phase2Translator: for inc_dir in self.include_dirs: if os.path.isdir(inc_dir): py_path = os.path.join(inc_dir, rel_path[len('includes/'):].replace(os.sep, '/')) - py_path = os.path.splitext(py_path)[0] + '.py' + py_path = os.path.splitext(py_path)[0] + '.vp' + if not os.path.isfile(py_path): + # 回退到 .py(向后兼容) + py_path = os.path.splitext(py_path)[0] + '.py' if os.path.isfile(py_path): with open(py_path, 'r', encoding='utf-8') as f: py_sha1 = compute_sha1(f.read()) @@ -982,12 +988,12 @@ class Phase2Translator: for includes_dir in self.include_dirs: if os.path.isdir(includes_dir): for pyi_file in os.listdir(includes_dir): - if pyi_file.endswith('.pyi'): + if pyi_file.endswith('.vpi') or pyi_file.endswith('.pyi'): pyi_path = os.path.join(includes_dir, pyi_file) 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('_') or py_file == '_list.py' or py_file == '_dict.py'): + if (py_file.endswith('.vp') or py_file.endswith('.py')) and (not py_file.startswith('_') or py_file == '_list.vp' or py_file == '_list.py' or py_file == '_dict.vp' 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: @@ -1635,7 +1641,7 @@ class Phase2Translator: for root, dirs, files in os.walk(includes_dir): dirs[:] = [d for d in dirs if not d.startswith('.') and d != '__pycache__'] for fname in files: - if not fname.endswith('.py'): + if not (fname.endswith('.vp') or fname.endswith('.py')): continue py_path: str = os.path.join(root, fname) code, tree = parse_python_file(py_path) @@ -1691,7 +1697,7 @@ class Phase2Translator: for root, dirs, files in os.walk(includes_dir): dirs[:] = [d for d in dirs if not d.startswith('.') and d != '__pycache__'] for fname in files: - if fname.endswith('.py'): + if fname.endswith('.vp') or fname.endswith('.py'): py_index.add(os.path.normcase(os.path.join(root, fname))) return py_index @@ -1714,7 +1720,7 @@ class Phase2Translator: for root, dirs, files in os.walk(module_dir): dirs[:] = [d for d in dirs if not d.startswith('.') and d != '__pycache__'] for fname in files: - if fname.endswith('.py'): + if fname.endswith('.vp') or fname.endswith('.py'): py_path = os.path.join(root, fname) if py_path not in self.extra_py_files: self.extra_py_files.append(py_path) @@ -1732,7 +1738,10 @@ class Phase2Translator: self.extra_compile_files.append(src_path) _vlog().info(f" [includes] 发现源文件: {os.path.relpath(src_path, includes_dir)}") - py_path = os.path.join(includes_dir, module_name + '.py') + py_path = os.path.join(includes_dir, module_name + '.vp') + if os.path.normcase(py_path) not in py_index: + # 回退到 .py(向后兼容) + py_path = os.path.join(includes_dir, module_name + '.py') if os.path.normcase(py_path) in py_index: self.extra_py_files.append(py_path) _vlog().info(f" [includes] 发现 Python 源文件: {os.path.relpath(py_path, includes_dir)}") @@ -1790,15 +1799,18 @@ class Phase2Translator: py_index 非空时用 set 查询替代 os.path.isfile(O(1) vs 24ms/次)。 """ - # 候选路径:子包路径(w32/win32base.py)、顶层模块(w32.py)、子包 __init__.py + # 候选路径:子包路径(w32/win32base.vp/.py)、顶层模块(w32.vp/.py)、子包 __init__.vp/__init__.py candidates: list[str] = [] - # 子包路径:w32.win32base → w32/win32base.py + # 子包路径:w32.win32base → w32/win32base.vp / .py + candidates.append(os.path.join(includes_dir, module_name.replace('.', os.sep) + '.vp')) candidates.append(os.path.join(includes_dir, module_name.replace('.', os.sep) + '.py')) - # 子包 __init__.py:w32.win32base → w32/win32base/__init__.py + # 子包 __init__.vp/__init__.py:w32.win32base → w32/win32base/__init__.vp / .py + candidates.append(os.path.join(includes_dir, module_name.replace('.', os.sep), '__init__.vp')) candidates.append(os.path.join(includes_dir, module_name.replace('.', os.sep), '__init__.py')) - # 顶层模块:取第一个组件 → w32.py + # 顶层模块:取第一个组件 → w32.vp / .py top_module = module_name.split('.')[0] if top_module != module_name: + candidates.append(os.path.join(includes_dir, top_module + '.vp')) candidates.append(os.path.join(includes_dir, top_module + '.py')) for py_path in candidates: @@ -2423,7 +2435,7 @@ class Phase2Translator: if not os.path.isdir(includes_dir): continue for filename in os.listdir(includes_dir): - if not filename.endswith('.py'): + if not (filename.endswith('.vp') or filename.endswith('.py')): continue src_path = os.path.join(includes_dir, filename) try: @@ -2533,7 +2545,7 @@ class Phase2Translator: pass # 1. 生成 .pyi 签名文件(如果还没有的话) - sig_path = os.path.join(self.temp_dir, f"{sha1}.pyi") + sig_path = os.path.join(self.temp_dir, f"{sha1}.vpi") if not os.path.isfile(sig_path): # 全局缓存检查(不被 --clean 清除) _TryGlobalCache(sha1, 'pyi', sig_path) @@ -2554,7 +2566,7 @@ class Phase2Translator: # 注册到 sig_files 和 _source_module_sig_files if os.path.isfile(sig_path): self.sig_files[sha1] = sig_path - self.sha1_map[sha1] = f"includes/{mod_full.replace('.', '/')}.py" + self.sha1_map[sha1] = f"includes/{mod_full.replace('.', '/')}.vp" if self._shared_source_module_sig_files is not None: self._shared_source_module_sig_files[mod_full] = sig_path self._shared_source_module_sig_files[module_name] = sig_path @@ -2611,10 +2623,13 @@ class Phase2Translator: for root, dirs, files in os.walk(module_dir): dirs[:] = [d for d in dirs if not d.startswith('.') and d != '__pycache__'] for fname in files: - if fname.endswith('.py'): + if fname.endswith('.vp') or fname.endswith('.py'): src_path = os.path.join(root, fname) self._collect_inline_symbols(src_path) - py_path = os.path.join(includes_dir, module_name + '.py') + py_path = os.path.join(includes_dir, module_name + '.vp') + if not os.path.isfile(py_path): + # 回退到 .py(向后兼容) + py_path = os.path.join(includes_dir, module_name + '.py') if os.path.isfile(py_path): self._collect_inline_symbols(py_path) for ef in self.extra_py_files: @@ -2677,12 +2692,12 @@ class Phase2Translator: for includes_dir in self.include_dirs: if os.path.isdir(includes_dir): for pyi_file in os.listdir(includes_dir): - if pyi_file.endswith('.pyi'): + if pyi_file.endswith('.vpi') or pyi_file.endswith('.pyi'): pyi_path = os.path.join(includes_dir, pyi_file) 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('_') or py_file == '_list.py' or py_file == '_dict.py'): + if (py_file.endswith('.vp') or py_file.endswith('.py')) and (not py_file.startswith('_') or py_file == '_list.vp' or py_file == '_list.py' or py_file == '_dict.vp' 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: @@ -2775,7 +2790,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('_') or py_file == '_list.py' or py_file == '_dict.py'): + if (py_file.endswith('.vp') or py_file.endswith('.py')) and (not py_file.startswith('_') or py_file == '_list.vp' or py_file == '_list.py' or py_file == '_dict.vp' or py_file == '_dict.py'): py_path = os.path.join(abs_includes, py_file) try: # 复用 parse_python_file 的 AST 缓存 diff --git a/lib/Projectrans/Utils.py b/lib/Projectrans/Utils.py index 187eaba..ff56c76 100644 --- a/lib/Projectrans/Utils.py +++ b/lib/Projectrans/Utils.py @@ -127,19 +127,19 @@ def clear_file_deps_cache() -> None: def find_reachable_files_from_entries(src_root: str, entry_files: list[str]) -> set[str]: - """从入口文件出发,找出所有可达的 .py 文件(通过导入关系)""" + """从入口文件出发,找出所有可达的 .vp/.py 文件(通过导入关系)""" 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'): + if file.endswith('.vp') or file.endswith('.py'): 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'): + if filepath.endswith('__init__.vp') or filepath.endswith('__init__.py'): all_files[module] = filepath 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'): + if parent_module not in all_files or not (all_files[parent_module].endswith('__init__.vp') or all_files[parent_module].endswith('__init__.py')): all_files[parent_module] = filepath elif module not in all_files: all_files[module] = filepath diff --git a/lib/Shell/TransPyC.py b/lib/Shell/TransPyC.py index 2aa92e7..324d3ee 100644 --- a/lib/Shell/TransPyC.py +++ b/lib/Shell/TransPyC.py @@ -89,7 +89,7 @@ class TransPyC: FileType: str | None = SymbolFile.FileType if not FileType and SymbolFile.FilePath: # 从文件路径推断类型 - if SymbolFile.FilePath.endswith('.py'): + if SymbolFile.FilePath.endswith('.vp') or SymbolFile.FilePath.endswith('.py'): FileType = 'py' elif SymbolFile.FilePath.endswith('.c') or SymbolFile.FilePath.endswith('.h'): FileType = 'c' @@ -298,7 +298,7 @@ class TransPyC: # 如果没有指定输出文件,使用默认名称 if not OutputFile: - OutputFile = InputFile.replace('.py', '.symbin').replace('.c', '.symbin') + OutputFile = InputFile.replace('.vp', '.symbin').replace('.py', '.symbin').replace('.c', '.symbin') # 执行预处理 self.Args['PreSym'] = { @@ -599,7 +599,7 @@ class TransPyC: encoding: str = self.Args.get('Encoding', 'utf-8') # 推断文件类型 - FileType: str | None = 'py' if InputFile.endswith('.py') else 'c' if InputFile.endswith('.c') else None + FileType: str | None = 'py' if (InputFile.endswith('.vp') or InputFile.endswith('.py')) else 'c' if InputFile.endswith('.c') else None # 创建 SymbolFile 对象,传入编码参数 SymbolFile: SymbolFile = SymbolFile(file=InputFile, type=FileType, encoding=encoding) @@ -629,11 +629,11 @@ class TransPyC: # 没有命令行参数,使用默认的测试文件名称 InputFile: str = DEFAULT_INPUT_FILE OutputFile: str = DEFAULT_OUTPUT_FILE - info('使用默认测试文件: test.py -> test.c') + info('使用默认测试文件: test.vp -> test.c') FileType: str = DetectFileType(InputFile) - if FileType == '.py': + if FileType in ('.vp', '.py'): self.PythonToC(InputFile, OutputFile) # 检查是否需要编译和运行 if 'CompileCommand' in self.Args or self.Args.get('Run', False): diff --git a/lib/StubGen/Config.py b/lib/StubGen/Config.py index 4e3b135..c1ce04b 100644 --- a/lib/StubGen/Config.py +++ b/lib/StubGen/Config.py @@ -11,7 +11,7 @@ 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"]) + IncludePatterns: List[str] = field(default_factory=lambda: ["*.h", "*.c", "*.vp", "*.py"]) ExcludePatterns: List[str] = field(default_factory=list) TypeMappings: Dict[str, str] = field(default_factory=dict) PreserveStructure: bool = True # 保持目录结构 @@ -26,7 +26,7 @@ class StubGenConfig: InputDir=data.get('InputDir'), OutputDir=data.get('OutputDir', './stubs'), InputFiles=data.get('InputFiles', []), - IncludePatterns=data.get('IncludePatterns', ['*.h', '*.c', '*.py']), + IncludePatterns=data.get('IncludePatterns', ['*.h', '*.c', '*.vp', '*.py']), ExcludePatterns=data.get('ExcludePatterns', []), TypeMappings=data.get('TypeMappings', {}), PreserveStructure=data.get('PreserveStructure', True), diff --git a/lib/StubGen/Converter.py b/lib/StubGen/Converter.py index d4ca485..743ea5d 100644 --- a/lib/StubGen/Converter.py +++ b/lib/StubGen/Converter.py @@ -58,7 +58,7 @@ class PythonToStubConverter: # 添加文件头 StubLines.append('"""') - StubLines.append(f'Auto-generated Python stub file from {ModuleName}.py') + StubLines.append(f'Auto-generated Python stub file from {ModuleName}.vp') StubLines.append(f'Module: {ModuleName}') StubLines.append('"""') StubLines.append('') diff --git a/lib/StubGen/Generator.py b/lib/StubGen/Generator.py index 526071f..867b711 100644 --- a/lib/StubGen/Generator.py +++ b/lib/StubGen/Generator.py @@ -98,9 +98,9 @@ class StubGen: def _GetOutputPath(self, RelPath: str) -> str: """获取输出文件路径""" - # 更改扩展名为 .pyi (Python stub file) + # 更改扩展名为 .vpi (Python stub file) BaseName: str = os.path.splitext(RelPath)[0] - OutputRelPath: str = BaseName + '.pyi' + OutputRelPath: str = BaseName + '.vpi' # 构建完整输出路径 if self.config.OutputDir: @@ -280,7 +280,7 @@ Examples: config: StubGenConfig = StubGenConfig.from_file(args.config) else: config = StubGenConfig() - config.IncludePatterns = args.include or ['*.h', '*.c', '*.py'] + config.IncludePatterns = args.include or ['*.h', '*.c', '*.vp', '*.py'] config.ExcludePatterns = args.exclude or [] config.GenerateGuards = not args.no_guards config.PreserveStructure = not args.no_structure diff --git a/lib/constants/config.py b/lib/constants/config.py index 250a029..6cf9a7d 100644 --- a/lib/constants/config.py +++ b/lib/constants/config.py @@ -1,7 +1,7 @@ # 常量定义 from __future__ import annotations -DEFAULT_INPUT_FILE: str = 'test.py' +DEFAULT_INPUT_FILE: str = 'test.vp' DEFAULT_OUTPUT_FILE: str = 'test.ll' SLICE_THRESHOLD: int = 50 diff --git a/lib/core/Handles/HandlesExprCall.py b/lib/core/Handles/HandlesExprCall.py index c583570..9d4e179 100644 --- a/lib/core/Handles/HandlesExprCall.py +++ b/lib/core/Handles/HandlesExprCall.py @@ -2124,9 +2124,12 @@ class ExprCallHandle(BaseHandle): def load_pyi(sha1: str) -> dict[str, ast.ClassDef] | None: if sha1 in pyi_cache: return pyi_cache[sha1] - pyi_path = os.path.join(project_root, 'temp', f'{sha1}.pyi') + pyi_path = os.path.join(project_root, 'temp', f'{sha1}.vpi') if not os.path.isfile(pyi_path): - return None + # 回退读取旧缓存 .pyi + pyi_path = os.path.join(project_root, 'temp', f'{sha1}.pyi') + if not os.path.isfile(pyi_path): + return None with open(pyi_path, 'r', encoding='utf-8') as f: pyi_code = f.read() tree = ast.parse(pyi_code) diff --git a/lib/core/Handles/HandlesImports.py b/lib/core/Handles/HandlesImports.py index 3c4461c..f295e7a 100644 --- a/lib/core/Handles/HandlesImports.py +++ b/lib/core/Handles/HandlesImports.py @@ -199,7 +199,7 @@ class ImportHandle(BaseHandle): for _ in range(Node.level - 1): parent_dir = os.path.dirname(parent_dir) if module: - SearchExtensions = ['.pyi', '.py'] + SearchExtensions = ['.vpi', '.vp', '.pyi', '.py'] sub_path_base = os.path.join(parent_dir, module) for ext in SearchExtensions: candidate = sub_path_base + ext @@ -215,7 +215,7 @@ class ImportHandle(BaseHandle): if target_sha1: temp_dir = getattr(Gen, '_temp_dir', None) if temp_dir: - sha1_pyi = os.path.join(temp_dir, f"{target_sha1}.pyi") + sha1_pyi = os.path.join(temp_dir, f"{target_sha1}.vpi") if os.path.isfile(sha1_pyi): self.Trans._ImportedModules.add(module) self._LoadModuleDeclarationsFromFile(sha1_pyi, Gen, module_name=module, register_module_name=current_module) @@ -224,7 +224,7 @@ class ImportHandle(BaseHandle): else: mod_dir = parent_dir - SearchExtensions = ['.pyi', '.py'] + SearchExtensions = ['.vpi', '.vp', '.pyi', '.py'] pkg_name = '' if not module: # When 'from . import name' is used, Load the package's __init__ @@ -251,7 +251,7 @@ class ImportHandle(BaseHandle): if target_sha1: temp_dir = getattr(Gen, '_temp_dir', None) if temp_dir: - sha1_pyi = os.path.join(temp_dir, f"{target_sha1}.pyi") + sha1_pyi = os.path.join(temp_dir, f"{target_sha1}.vpi") if os.path.isfile(sha1_pyi): self.Trans._ImportedModules.add(sub_ModulePath) self._LoadModuleDeclarationsFromFile(sha1_pyi, Gen, module_name=alias.name, register_module_name=current_module) @@ -274,8 +274,8 @@ class ImportHandle(BaseHandle): if not module_prefix: return basename: str = os.path.basename(pyi_path) - # 若传入 .py 文件,则从 _source_module_sig_files 查找对应的 {sha1}.pyi - if basename.endswith('.py'): + # 若传入 .vp/.py 文件,则从 _source_module_sig_files 查找对应的 {sha1}.vpi + if basename.endswith('.vp') or basename.endswith('.py'): source_sig_files = getattr(self.Trans, '_source_module_sig_files', None) if source_sig_files: sig_path = source_sig_files.get(module_prefix) @@ -286,9 +286,9 @@ class ImportHandle(BaseHandle): return else: return - if not basename.endswith('.pyi'): + if not (basename.endswith('.vpi') or basename.endswith('.pyi')): return - sha1: str = basename[:-len('.pyi')] + sha1: str = basename[:-4] # 去掉 .vpi 或 .pyi 后缀(均为 4 字符) shared_doc_meta = getattr(self.Trans, '_shared_doc_meta', None) if not shared_doc_meta: return @@ -390,7 +390,7 @@ class ImportHandle(BaseHandle): for _ in range(node.level - 1): parent_dir = os.path.dirname(parent_dir) if node.module: - SearchExtensions = ['.pyi', '.py'] + SearchExtensions = ['.vpi', '.vp', '.pyi', '.py'] sub_path_base = os.path.join(parent_dir, node.module) found_sub = False # 治本修复:用包目录名(如 'json')而非 register_module_name(当前编译模块名,如 '_dict')。 @@ -428,7 +428,7 @@ class ImportHandle(BaseHandle): if target_sha1: temp_dir = getattr(Gen, '_temp_dir', None) if temp_dir: - sha1_pyi = os.path.join(temp_dir, f"{target_sha1}.pyi") + sha1_pyi = os.path.join(temp_dir, f"{target_sha1}.vpi") if os.path.isfile(sha1_pyi): if not getattr(self.Trans, '_ImportedModules', None): self.Trans._ImportedModules = set() @@ -440,7 +440,7 @@ class ImportHandle(BaseHandle): self._LoadModuleDeclarationsFromFile(sha1_pyi, Gen, module_name=alias.name, register_module_name=register_module_name, actual_module_name=actual_module, reexport_package=reexport_package or module_name) else: mod_dir = parent_dir - SearchExtensions = ['.pyi', '.py'] + SearchExtensions = ['.vpi', '.vp', '.pyi', '.py'] # Load __init__.py to make package-level names available self._LoadPackageInitForRelativeImport(mod_dir, Gen, register_module_name) # 治本修复:用包目录名(如 'json')而非 register_module_name(当前编译模块名,如 '_dict')。 @@ -472,7 +472,7 @@ class ImportHandle(BaseHandle): if target_sha1: temp_dir = getattr(Gen, '_temp_dir', None) if temp_dir: - sha1_pyi = os.path.join(temp_dir, f"{target_sha1}.pyi") + sha1_pyi = os.path.join(temp_dir, f"{target_sha1}.vpi") if os.path.isfile(sha1_pyi): if not getattr(self.Trans, '_ImportedModules', None): self.Trans._ImportedModules = set() @@ -528,14 +528,14 @@ class ImportHandle(BaseHandle): if pkg_sha1: temp_dir = getattr(Gen, '_temp_dir', None) if temp_dir: - sha1_pyi = os.path.join(temp_dir, f"{pkg_sha1}.pyi") + sha1_pyi = os.path.join(temp_dir, f"{pkg_sha1}.vpi") if os.path.isfile(sha1_pyi): self._LoadModuleDeclarationsFromFile(sha1_pyi, Gen, module_name=pkg_name, register_module_name=register_module_name) init_Loaded = True # Fallback: try Loading __init__.py directly from the package directory if not init_Loaded: - for ext in ['.pyi', '.py']: + for ext in ['.vpi', '.vp', '.pyi', '.py']: init_path = os.path.join(mod_dir, '__init__' + ext) if os.path.isfile(init_path): self._LoadModuleDeclarationsFromFile(init_path, Gen, module_name=pkg_name, register_module_name=register_module_name) @@ -552,48 +552,59 @@ class ImportHandle(BaseHandle): self._emitted_module_decls.add(decl_key) 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' + ModulePathBase = module_name.replace('.', os.sep) + PackageInitPathBase = module_name.replace('.', os.sep) + os.sep + '__init__' ProjectRoot = os.path.dirname(os.path.abspath(getattr(self.Trans, 'CurrentFile', '') or '')) or os.getcwd() HandlesFile = os.path.abspath(inspect.getfile(self.__class__)) TransPyCRoot = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(HandlesFile)))) - + FullModulePath = None SearchDirs = [os.path.join(TransPyCRoot, 'includes'), os.path.join(TransPyCRoot, 'lib', 'includes')] + list(self.Trans.LibraryPaths) for LibPath in SearchDirs: SearchPath = os.path.join(ProjectRoot, LibPath) if not os.path.isabs(LibPath) else LibPath - CandidatePath = os.path.join(SearchPath, ModulePath) - if os.path.isfile(CandidatePath): - FullModulePath = CandidatePath + # 优先尝试 .vpi,回退 .pyi + for stub_ext in ('.vpi', '.pyi'): + CandidatePath = os.path.join(SearchPath, ModulePathBase + stub_ext) + if os.path.isfile(CandidatePath): + FullModulePath = CandidatePath + break + CandidatePath = os.path.join(SearchPath, PackageInitPathBase + stub_ext) + if os.path.isfile(CandidatePath): + FullModulePath = CandidatePath + break + if FullModulePath: break - CandidatePath = os.path.join(SearchPath, PackageInitPath) - if os.path.isfile(CandidatePath): - FullModulePath = CandidatePath - break - ModuleParts = ModulePath.split(os.sep) + ModuleParts = ModulePathBase.split(os.sep) if len(ModuleParts) > 1: LibPathBasename = os.path.basename(LibPath.rstrip('/\\')) if LibPathBasename == ModuleParts[0]: RemainingPath = os.sep.join(ModuleParts[1:]) - CandidatePath = os.path.join(SearchPath, RemainingPath) - if os.path.isfile(CandidatePath): - FullModulePath = CandidatePath + for stub_ext in ('.vpi', '.pyi'): + CandidatePath = os.path.join(SearchPath, RemainingPath + stub_ext) + if os.path.isfile(CandidatePath): + FullModulePath = CandidatePath + break + if FullModulePath: break if not FullModulePath: - ModulePathPy = module_name.replace('.', os.sep) + '.py' - PackageInitPathPy = module_name.replace('.', os.sep) + os.sep + '__init__.py' + ModulePathPyBase = module_name.replace('.', os.sep) + PackageInitPathPyBase = module_name.replace('.', os.sep) + os.sep + '__init__' SearchDirsForPy = [os.path.join(TransPyCRoot, 'includes'), os.path.join(TransPyCRoot, 'lib', 'includes')] + list(self.Trans.LibraryPaths) for LibPath in SearchDirsForPy: SearchPath = os.path.join(ProjectRoot, LibPath) if not os.path.isabs(LibPath) else LibPath - CandidatePath = os.path.join(SearchPath, ModulePathPy) - if os.path.isfile(CandidatePath): - FullModulePath = CandidatePath - break - CandidatePath = os.path.join(SearchPath, PackageInitPathPy) - if os.path.isfile(CandidatePath): - FullModulePath = CandidatePath + # 优先尝试 .vp,回退 .py + for src_ext in ('.vp', '.py'): + CandidatePath = os.path.join(SearchPath, ModulePathPyBase + src_ext) + if os.path.isfile(CandidatePath): + FullModulePath = CandidatePath + break + CandidatePath = os.path.join(SearchPath, PackageInitPathPyBase + src_ext) + if os.path.isfile(CandidatePath): + FullModulePath = CandidatePath + break + if FullModulePath: break if not FullModulePath or not os.path.isfile(FullModulePath): source_sig_files = getattr(self.Trans, '_source_module_sig_files', None) @@ -622,11 +633,11 @@ class ImportHandle(BaseHandle): for root, dirs, files in os.walk(SearchPath): if '__pycache__' in root: continue - if module_name + '.py' in files: - FullModulePath = os.path.join(root, module_name + '.py') - break - if module_name + '.pyi' in files: - FullModulePath = os.path.join(root, module_name + '.pyi') + for src_ext in ('.vp', '.py', '.vpi', '.pyi'): + if module_name + src_ext in files: + FullModulePath = os.path.join(root, module_name + src_ext) + break + if FullModulePath: break if FullModulePath: break @@ -687,7 +698,7 @@ class ImportHandle(BaseHandle): for _ in range(node.level - 1): parent_dir = os.path.dirname(parent_dir) if node.module: - SearchExtensions = ['.pyi', '.py'] + SearchExtensions = ['.vpi', '.vp', '.pyi', '.py'] sub_path_base = os.path.join(parent_dir, node.module) found_sub = False for ext in SearchExtensions: @@ -715,7 +726,7 @@ class ImportHandle(BaseHandle): if target_sha1: temp_dir = getattr(Gen, '_temp_dir', None) if temp_dir: - sha1_pyi = os.path.join(temp_dir, f"{target_sha1}.pyi") + sha1_pyi = os.path.join(temp_dir, f"{target_sha1}.vpi") if os.path.isfile(sha1_pyi): if not getattr(self.Trans, '_ImportedModules', None): self.Trans._ImportedModules = set() @@ -728,7 +739,7 @@ class ImportHandle(BaseHandle): has_functions_or_classes = True else: mod_dir = parent_dir - SearchExtensions = ['.pyi', '.py'] + SearchExtensions = ['.vpi', '.vp', '.pyi', '.py'] # Load __init__.py to make package-level names available self._LoadPackageInitForRelativeImport(mod_dir, Gen, register_module_name or module_name) for alias in node.names: @@ -755,7 +766,7 @@ class ImportHandle(BaseHandle): if target_sha1: temp_dir = getattr(Gen, '_temp_dir', None) if temp_dir: - sha1_pyi = os.path.join(temp_dir, f"{target_sha1}.pyi") + sha1_pyi = os.path.join(temp_dir, f"{target_sha1}.vpi") if os.path.isfile(sha1_pyi): if not getattr(self.Trans, '_ImportedModules', None): self.Trans._ImportedModules = set() @@ -2063,8 +2074,12 @@ class ImportHandle(BaseHandle): temp_dir = os.path.join(ProjectRoot, 'temp') if class_name in Gen.class_members and len(Gen.class_members[class_name]) > 0: return - pyi_basename = stub_filename.replace('.stub.ll', '.pyi') + pyi_basename = stub_filename.replace('.stub.ll', '.vpi') pyi_path = os.path.join(temp_dir, pyi_basename) + if not os.path.isfile(pyi_path): + # 回退读取旧缓存 .pyi + pyi_basename = stub_filename.replace('.stub.ll', '.pyi') + pyi_path = os.path.join(temp_dir, pyi_basename) if self._pyi_cache_dir != temp_dir: self._pyi_cache.clear() @@ -2286,7 +2301,7 @@ class ImportHandle(BaseHandle): if module_name: for key, val in source_sig_files.items(): if key == module_name or key.endswith('.' + module_name): - target_sha1 = os.path.basename(val).replace('.pyi', '') + target_sha1 = os.path.basename(val).replace('.vpi', '').replace('.pyi', '') break if not target_sha1: ModuleSha1Map = getattr(Gen, 'ModuleSha1Map', {}) diff --git a/lib/core/LLVMCG/FuncGen.py b/lib/core/LLVMCG/FuncGen.py index dc743c6..2ba6123 100644 --- a/lib/core/LLVMCG/FuncGen.py +++ b/lib/core/LLVMCG/FuncGen.py @@ -395,8 +395,8 @@ class FuncGenMixin: 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') + if pyi_file.endswith('.vpi') or pyi_file.endswith('.pyi'): + stub_name: str = pyi_file.replace('.vpi', '.stub.ll').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: diff --git a/lib/core/stub_generator.py b/lib/core/stub_generator.py index 5b60618..aa71085 100644 --- a/lib/core/stub_generator.py +++ b/lib/core/stub_generator.py @@ -2,7 +2,7 @@ """ C/H 文件到 Python 存根文件生成器 -将 C 头文件 (.h) 或 C 源文件 (.c) 转换为 Python 存根文件 (.pyi) +将 C 头文件 (.h) 或 C 源文件 (.c) 转换为 Python 存根文件 (.vpi) 生成的 Python 代码使用 TransPyC 语法,包含类型注解 """ from __future__ import annotations diff --git a/test.py b/test.vp similarity index 100% rename from test.py rename to test.vp diff --git a/thistest/App/main.py b/thistest/App/main.vp similarity index 100% rename from thistest/App/main.py rename to thistest/App/main.vp