diff --git a/Notify.py b/Notify.py new file mode 100644 index 0000000..de1f2e4 --- /dev/null +++ b/Notify.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- +"""非阻塞式 Windows Toast 通知工具。 + +用法: + python Notify.py "标题(任务事项内容)" ["正文(可选)"] + +替代旧的阻塞式 `msg *` 弹窗,通知右下角弹出后自动消失,无需手动点击。 +""" + +import subprocess +import sys + + +def SendToast(Title: str, Body: str = ""): + """发送一条非阻塞式 Windows Toast 通知(Balloon Tip)。 + + 参数: + Title: 通知标题,即"本次完成的任务事项内容",用于识别是谁完成了什么任务。 + Body: 通知正文,可省略。 + """ + # 转义 PowerShell 单引号,防止任务内容中的特殊字符破坏脚本 + # BalloonTipText 不能为空,Body 省略时用默认正文 + TitleEsc = Title.replace("'", "''") + BodyEsc = (Body if Body else "任务完成").replace("'", "''") + PsScript = ( + "Add-Type -AssemblyName System.Windows.Forms; " + "Add-Type -AssemblyName System.Drawing; " + "$n = New-Object System.Windows.Forms.NotifyIcon; " + "$n.Icon = [System.Drawing.SystemIcons]::Information; " + "$n.BalloonTipIcon = 'Info'; " + "$n.BalloonTipTitle = '{0}'; " + "$n.BalloonTipText = '{1}'; " + "$n.Visible = $true; " + "$n.ShowBalloonTip(5000); " + "Start-Sleep -Milliseconds 6000; " + "$n.Dispose()" + ).format(TitleEsc, BodyEsc) + try: + subprocess.run( + ["powershell", "-NoProfile", "-WindowStyle", "Hidden", "-Command", PsScript], + check=True, + timeout=15, + ) + except Exception as Ex: + sys.stderr.write("Notify failed: %s\n" % Ex) + sys.exit(1) + + +if __name__ == "__main__": + if len(sys.argv) < 2: + sys.stderr.write("Usage: python Notify.py [Body]\n") + sys.exit(2) + SendToast(sys.argv[1], sys.argv[2] if len(sys.argv) > 2 else "") diff --git a/TODO b/TODO index 42ed134..f038a5c 100644 --- a/TODO +++ b/TODO @@ -1,5 +1,5 @@ 更复杂的 泛型 -函数装饰器 +复杂原始(仿Python)函数装饰器 # main 收集(和 导入模块的自动执行) 元类型 # @p.set @@ -7,24 +7,26 @@ 崩溃/返回作用域 回调 # 假鸭子 # f-string 自动 snprintf -__doc__ -自动索引 -testcheck默认中文 +# __doc__(后续需完善) +# 自动索引 +# testcheck默认中文 vdebug 工具和 vsdt 工具 多态 ops 允许单个函数拥有装饰器(可修改,走函数指针) 协程关键字支持 with 出入多态 -哈希表 +# 哈希表 内联快速迭代器 出栈调用函数 -构造函数隐式参数 +# 构造函数隐式参数 小数组直接栈上创建+ i in [xxx] -字符串索引 +# 字符串索引 -单 @t.Object +单函数 @t.CVTable import 自动执行代码 限制全局 import 符号到局部(其他文件import而本文件没import,但是仍然生效不报错) +生成器表达式 +await 表达式(平台无关协程支持) # 统一 mpool 和 mbuddy 接口 MCViper after 自举 @@ -35,4 +37,5 @@ init_set 构造 不在乎编译器时间的大小优化(无关符号剔除) 给 linkedlist 库改成 node 库,或者拆分 linkedlist 库 -TPV 的 typedef 名是硬编码的,后期尝试修正 \ No newline at end of file +TPV 的 typedef 名是硬编码的,后期尝试修正 +TPV 再次支持泛型能力检查和字节序 \ No newline at end of file diff --git a/TransPyV/temp/_phase1_manifest.json b/TransPyV/temp/_phase1_manifest.json index 9460ed5..b74797d 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.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": "edfb76eb5b11cb51", "mtime": 1785470008.8908188, "size": 36399}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\StubGen\\VpiReader.vp": {"sha1": "60b1f1f83634820e", "mtime": 1785470742.1546993, "size": 12673}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\__init__.vp": {"sha1": "c2a4277744568003", "mtime": 1785424554.7031634, "size": 820}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\BuildPipeline.vp": {"sha1": "0029b86ca4ba3c8a", "mtime": 1785469972.0876107, "size": 25400}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesAnnAssign.vp": {"sha1": "b7705a803012e701", "mtime": 1785478290.7112954, "size": 25035}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesAssign.vp": {"sha1": "0fd87ff8da897c9b", "mtime": 1785478447.198817, "size": 25107}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesAugAssign.vp": {"sha1": "0d60272ffec7421e", "mtime": 1785478333.5054357, "size": 14418}, "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": "8a88001814aa6e7b", "mtime": 1785485408.946777, "size": 10469}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesClassDef.vp": {"sha1": "07093bc887a35256", "mtime": 1785478535.6808052, "size": 145619}, "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": "ebe9603dbffb6a35", "mtime": 1785478439.6070976, "size": 155333}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesExprCall.vp": {"sha1": "b70057095779b5be", "mtime": 1785482646.5378678, "size": 281321}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesExprOps.vp": {"sha1": "ede39cea216a347e", "mtime": 1785478524.0725746, "size": 13507}, "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": "f33eba0679c883b5", "mtime": 1785482062.1941507, "size": 48438}, "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": "c34e22cc668c6a6e", "mtime": 1785424554.7057025, "size": 25292}, "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": "3e7835a9deb60427", "mtime": 1785485362.3779018, "size": 7459}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesReturn.vp": {"sha1": "9224f6a9c894a6cf", "mtime": 1785478537.512802, "size": 6346}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesStruct.vp": {"sha1": "f09b2f4a0f9d053e", "mtime": 1785426809.706652, "size": 47907}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesTranslator.vp": {"sha1": "decd2fdd82387662", "mtime": 1785481813.1345608, "size": 23666}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesType.vp": {"sha1": "735fcd4c340edd2d", "mtime": 1785470195.0236213, "size": 79666}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesVar.vp": {"sha1": "ea374464a0b93230", "mtime": 1785474869.3558953, "size": 16575}, "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": "55be14b41dd7ca15", "mtime": 1785424554.7031634, "size": 13067}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Phase1.vp": {"sha1": "8a526c65749808c5", "mtime": 1785470618.1566038, "size": 51263}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Phase2.vp": {"sha1": "f34071b7cf6c8158", "mtime": 1785469983.5727682, "size": 49494}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\StubMerger.vp": {"sha1": "0f9622f83dd1f680", "mtime": 1785470514.574895, "size": 99549}, "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": "f30a3b2d5f6bf092", "mtime": 1785424554.7082667, "size": 27278}, "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": "2b77d783c41d21d1", "mtime": 1785424554.7031634, "size": 9719}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\json\\__init__.vp": {"sha1": "6ddf430432a0e373", "mtime": 1785424554.7204792, "size": 7707}, "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": "33d64eeb99369a85", "mtime": 1785480244.1533804, "size": 17045}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\llvmlite\\__builder.vp": {"sha1": "e4eb57e8026bccc7", "mtime": 1785480214.1090708, "size": 52230}, "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": "295b7ed2c244f309", "mtime": 1785486521.0491738, "size": 20633}, "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": "ffaf70367668b227", "mtime": 1785424554.7179716, "size": 11048}, "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": "3ed8c578036234a7", "mtime": 1785439636.6696486, "size": 57646}, "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 +{"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": "edfb76eb5b11cb51", "mtime": 1785470008.8908188, "size": 36399}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\StubGen\\VpiReader.vp": {"sha1": "3395dd5ebf7032b7", "mtime": 1785688467.8441546, "size": 21045}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\__init__.vp": {"sha1": "c2a4277744568003", "mtime": 1785424554.7031634, "size": 820}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\BuildPipeline.vp": {"sha1": "0029b86ca4ba3c8a", "mtime": 1785469972.0876107, "size": 25400}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesAnnAssign.vp": {"sha1": "b7705a803012e701", "mtime": 1785478290.7112954, "size": 25035}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesAssign.vp": {"sha1": "4614c82057c20ce0", "mtime": 1785612002.0288458, "size": 26204}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesAugAssign.vp": {"sha1": "0d60272ffec7421e", "mtime": 1785478333.5054357, "size": 14418}, "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": "144543e5c3a8e884", "mtime": 1785500799.3788817, "size": 10543}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesClassDef.vp": {"sha1": "22b233500a91b82a", "mtime": 1785688461.7589297, "size": 147577}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesEnum.vp": {"sha1": "d8379d695f0ce7ea", "mtime": 1785598131.284988, "size": 8533}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesExpr.vp": {"sha1": "ebe9603dbffb6a35", "mtime": 1785478439.6070976, "size": 155333}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesExprCall.vp": {"sha1": "1d86dddccc01909b", "mtime": 1785688462.1500714, "size": 296707}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesExprOps.vp": {"sha1": "ede39cea216a347e", "mtime": 1785478524.0725746, "size": 13507}, "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": "f33eba0679c883b5", "mtime": 1785580039.9426627, "size": 49481}, "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": "c34e22cc668c6a6e", "mtime": 1785424554.7057025, "size": 25292}, "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\\HandlesMatch.vp": {"sha1": "4eb645a9b00ea530", "mtime": 1785688462.3238158, "size": 39328}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesNonlocal.vp": {"sha1": "3e7835a9deb60427", "mtime": 1785485362.3779018, "size": 7459}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesReturn.vp": {"sha1": "9224f6a9c894a6cf", "mtime": 1785478537.512802, "size": 6346}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesStruct.vp": {"sha1": "d539c830f47d8334", "mtime": 1785688462.3561263, "size": 48050}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesTranslator.vp": {"sha1": "d064df0bb07fe1ff", "mtime": 1785688462.4070482, "size": 24182}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesType.vp": {"sha1": "6a25d9b413498b72", "mtime": 1785608629.9467041, "size": 80761}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Handles\\HandlesVar.vp": {"sha1": "ea374464a0b93230", "mtime": 1785474869.3558953, "size": 16575}, "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": "55be14b41dd7ca15", "mtime": 1785424554.7031634, "size": 13067}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Phase1.vp": {"sha1": "8a526c65749808c5", "mtime": 1785470618.1566038, "size": 51263}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\Phase2.vp": {"sha1": "f34071b7cf6c8158", "mtime": 1785469983.5727682, "size": 49494}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\TransPyV\\App\\lib\\core\\StubMerger.vp": {"sha1": "0bae3da2213d51e9", "mtime": 1785600884.7381954, "size": 104586}, "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": "a6c58174a4b03877", "mtime": 1785612916.0578, "size": 28757}, "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": "2b77d783c41d21d1", "mtime": 1785424554.7031634, "size": 9719}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\json\\__init__.vp": {"sha1": "6ddf430432a0e373", "mtime": 1785424554.7204792, "size": 7707}, "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": "33d64eeb99369a85", "mtime": 1785480244.1533804, "size": 17045}, "D:\\Users\\TermiNexus\\Desktop\\TransPyC\\includes\\llvmlite\\__builder.vp": {"sha1": "a7748ef067f79205", "mtime": 1785688461.307784, "size": 52267}, "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": "295b7ed2c244f309", "mtime": 1785486521.0491738, "size": 20633}, "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": "c2d8b39bbdb8380a", "mtime": 1785684738.5654402, "size": 22256}, "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": 1785563642.3805652, "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": "ffaf70367668b227", "mtime": 1785671630.828129, "size": 11048}, "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": "f6ab8989f3545e83", "mtime": 1785568198.234555, "size": 59045}, "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 972d4dc..f44dcbc 100644 --- a/TransPyV/temp/_sha1_map.txt +++ b/TransPyV/temp/_sha1_map.txt @@ -1,79 +1,80 @@ 0029b86ca4ba3c8a:lib/core/BuildPipeline.vp 067c78e9f121dce3:includes/w32\win32process.vp 06f53cc594b4ac6c:includes/w32\win32sync.vp -07093bc887a35256:lib/core/Handles/HandlesClassDef.vp +0bae3da2213d51e9:lib/core/StubMerger.vp 0c67644125bea0fd:includes/sys.vp 0d60272ffec7421e:lib/core/Handles/HandlesAugAssign.vp 0df65b8ed15664b0:includes/hashlib\__sha1.vp -0f9622f83dd1f680:lib/core/StubMerger.vp -0fd87ff8da897c9b:lib/core/Handles/HandlesAssign.vp +144543e5c3a8e884:lib/core/Handles/HandlesBody.vp 19f8024d10c828e8:includes/hashlib\__md5.vp +1d86dddccc01909b:lib/core/Handles/HandlesExprCall.vp 20cd49775c100a38:includes/json\__writer.vp +22b233500a91b82a:lib/core/Handles/HandlesClassDef.vp 22bc0df83b3f0e62:includes/ast\base.vp 240a9a4157959a9f:includes/json\__parser.vp 285b6aa29a34754d:includes/stdio.vp 28de517e3820658a:includes/posix.vp 295b7ed2c244f309:includes/llvmlite\__types.vp 2b77d783c41d21d1:includes/hashtable.vp +3395dd5ebf7032b7:lib/StubGen/VpiReader.vp 33d64eeb99369a85:includes/llvmlite\__init__.vp 3aa6057398be5673:includes/stdlib.vp 3e7835a9deb60427:lib/core/Handles/HandlesNonlocal.vp -3ed8c578036234a7:includes/viperlib.vp 4337fb260448bbe2:includes/ast\astaux.vp 456fb516ba3c5002:lib/core/Handles/HandlesFor.vp +4614c82057c20ce0:lib/core/Handles/HandlesAssign.vp 4650533467115342:lib/Projectrans/Utils.vp 4a7b57e6bd18f65e:lib/core/Handles/HandlesMain.vp 4dd6b3f1427d1cc5:includes/ast\match.vp +4eb645a9b00ea530:lib/core/Handles/HandlesMatch.vp 55be14b41dd7ca15:lib/core/IncludesScanner.vp -60b1f1f83634820e:lib/StubGen/VpiReader.vp 63a3d17e96a083ac:lib/core/Handles/HandlesBase.vp 657e182b27c2a022:includes/ast\stmts.vp 692919c5a194ac8d:includes/llvmlite\__module.vp +6a25d9b413498b72:lib/core/Handles/HandlesType.vp 6b3bc463fd044545:includes/llvmlite\__verify.vp 6ddf430432a0e373:includes/json\__init__.vp 6ff26590374ae6fc:includes/hashlib\__sha512.vp 71e0a3ffcb3ebfad:includes/stdarg.vp 72dbbb563aa943b0:includes/w32\fileio.vp -735fcd4c340edd2d:lib/core/Handles/HandlesType.vp 7cadfe07e983fd90:includes/_list.vp 874bac141c97bae9:includes/llvmlite\__function.vp 8a526c65749808c5:lib/core/Phase1.vp -8a88001814aa6e7b:lib/core/Handles/HandlesBody.vp 8dc65d4c71e2936a:lib/core/Handles/HandlesWhile.vp 9224f6a9c894a6cf:lib/core/Handles/HandlesReturn.vp 96837bcc64032444:includes/hashlib\__init__.vp a335eb99f2e34479:includes/subprocess.vp a5e9a83e9db303ad:includes/linkedlist.vp +a6c58174a4b03877:main.vp +a7748ef067f79205:includes/llvmlite\__builder.vp aa246c6e6aa30484:includes/atom.vp b370d93b74bf55cc:includes/argparse.vp b543bc1dfb592119:includes/ast\exprs.vp b547ac4f380bddb6:includes/ast\tokens.vp b57252077e6b596b:includes/platmacro.vp -b70057095779b5be:lib/core/Handles/HandlesExprCall.vp b7705a803012e701:lib/core/Handles/HandlesAnnAssign.vp bbdf3bbd4c3bc28c:includes/w32\win32console.vp bdf5730851fb95f2:lib/core/VLogger.vp c0042adc0b7ec5df:lib/Projectrans/Config.vp c2a4277744568003:lib/__init__.vp +c2d8b39bbdb8380a:includes/memhub.vp c34e22cc668c6a6e:lib/core/Handles/HandlesImports.vp c9d54a4158f7f5a8:includes/hashlib\__sha256.vp c9f4be41ca1cc2b4:includes/viperio.vp -ca40915f11b8b6ad:includes/memhub.vp -decd2fdd82387662:lib/core/Handles/HandlesTranslator.vp +d064df0bb07fe1ff:lib/core/Handles/HandlesTranslator.vp +d539c830f47d8334:lib/core/Handles/HandlesStruct.vp +d8379d695f0ce7ea:lib/core/Handles/HandlesEnum.vp e217def267d3d4a8:includes/ast\lexer.vp -e4eb57e8026bccc7:includes/llvmlite\__builder.vp ea374464a0b93230:lib/core/Handles/HandlesVar.vp ebe9603dbffb6a35:lib/core/Handles/HandlesExpr.vp ede39cea216a347e:lib/core/Handles/HandlesExprOps.vp edfb76eb5b11cb51:lib/StubGen/Converter.vp -f05b14a2ad5767a7:lib/core/Handles/HandlesEnum.vp -f09b2f4a0f9d053e:lib/core/Handles/HandlesStruct.vp -f30a3b2d5f6bf092:main.vp f33eba0679c883b5:lib/core/Handles/HandlesFunctions.vp f34071b7cf6c8158:lib/core/Phase2.vp f3444ec56937284f:includes/ast\__init__.vp f4cdbca2f8802c12:lib/core/Handles/HandlesIf.vp f5522571bcce7bcb:includes/stdint.vp +f6ab8989f3545e83:includes/viperlib.vp f6b51804a0ba8ff0:includes/w32\win32file.vp f9e36e2cd6fa659f:includes/llvmlite\__values.vp fc980acec33d69a7:includes/w32\win32base.vp diff --git a/TransPyV/temp/_shared_sym.json b/TransPyV/temp/_shared_sym.json index b25d260..8c81d8f 100644 Binary files a/TransPyV/temp/_shared_sym.json and b/TransPyV/temp/_shared_sym.json differ diff --git a/_RemoveDebug.py b/_RemoveDebug.py new file mode 100644 index 0000000..7b6fdab --- /dev/null +++ b/_RemoveDebug.py @@ -0,0 +1,84 @@ +# -*- coding: utf-8 -*- +import pathlib + +# 1. VpiReader.vp +p = pathlib.Path(r'd:\Users\TermiNexus\Desktop\TransPyC\TransPyV\App\lib\StubGen\VpiReader.vp') +c = p.read_text(encoding='utf-8') +lines = c.split('\n') +new_lines = [] +skip = False +for i, line in enumerate(lines): + if 'DEBUG: sha1_buf length mismatch' in line: + skip = True + # also skip preceding lines + while new_lines and ('_buflen' in new_lines[-1] or 'sha1_buf' in new_lines[-1] or len(new_lines[-1].strip()) == 0 or new_lines[-1].strip().startswith('#')): + new_lines.pop() + continue + if skip: + if 'sys.exit(1)' in line: + skip = False + continue + if 'stdio.' in line or '_buflen' in line: + continue + if line.strip() == '' or line.strip().startswith('if _buflen'): + continue + skip = False + new_lines.append(line) +p.write_text('\n'.join(new_lines), encoding='utf-8') +print('VpiReader.vp done') + +# 2. HandlesFunctions.vp +p2 = pathlib.Path(r'd:\Users\TermiNexus\Desktop\TransPyC\TransPyV\App\lib\core\Handles\HandlesFunctions.vp') +c2 = p2.read_text(encoding='utf-8') +lines2 = c2.split('\n') +new_lines2 = [] +skip2 = False +for line in lines2: + if 'DEBUG: double-dot in _mangle_name' in line: + skip2 = True + while new_lines2 and ('_mi' in new_lines2[-1] or 'mangled[_mi' in new_lines2[-1] or 'stdio.' in new_lines2[-1] or 'sys.exit' in new_lines2[-1] or new_lines2[-1].strip().startswith('#')): + new_lines2.pop() + continue + if skip2: + if 'sys.exit(1)' in line: + skip2 = False + continue + if 'stdio.' in line or '_mi' in line or 'mangled[_mi' in line or line.strip().startswith('if mangled'): + continue + if line.strip() == '' or line.strip() == 'return mangled': + if line.strip() == 'return mangled': + new_lines2.append(line) + skip2 = False + continue + skip2 = False + new_lines2.append(line) +p2.write_text('\n'.join(new_lines2), encoding='utf-8') +print('HandlesFunctions.vp done') + +# 3. HandlesExprCall.vp +p3 = pathlib.Path(r'd:\Users\TermiNexus\Desktop\TransPyC\TransPyV\App\lib\core\Handles\HandlesExprCall.vp') +c3 = p3.read_text(encoding='utf-8') +lines3 = c3.split('\n') +new_lines3 = [] +skip3 = False +for line in lines3: + if 'DEBUG: double-dot in call_name' in line: + skip3 = True + while new_lines3 and ('_cni' in new_lines3[-1] or 'call_name[_cni' in new_lines3[-1] or 'stdio.' in new_lines3[-1] or 'sys.exit' in new_lines3[-1] or new_lines3[-1].strip().startswith('#')): + new_lines3.pop() + continue + if skip3: + if 'sys.exit(1)' in line: + skip3 = False + continue + if 'stdio.' in line or '_cni' in line or 'call_name[_cni' in line or line.strip().startswith('if call_name'): + continue + if line.strip() == '' or line.strip().startswith('#'): + if line.strip().startswith('#'): + new_lines3.append(line) + skip3 = False + continue + skip3 = False + new_lines3.append(line) +p3.write_text('\n'.join(new_lines3), encoding='utf-8') +print('HandlesExprCall.vp done') diff --git a/_console.py b/_console.py index a2eeabe..c6b2531 100644 --- a/_console.py +++ b/_console.py @@ -7,6 +7,8 @@ import os import queue import time + + class ConsoleApp: def __init__(self, root, args): self.root = root diff --git a/includes/llvmlite/__builder.vp b/includes/llvmlite/__builder.vp index 0db52b0..fd8afa5 100644 --- a/includes/llvmlite/__builder.vp +++ b/includes/llvmlite/__builder.vp @@ -7,7 +7,7 @@ import stdio from linkedlist import GSListNode, GSList from .__types import LLVMType, TypePrint from .__values import Value, new_value, SSAValue -from .__function import Function, BasicBlock, block_append_text, block_set_terminated, block_get_terminated, function_move_block_to_end, _ll_name_needs_quote +from .__function import Function, BasicBlock, block_append_text, block_set_terminated, block_get_terminated, function_move_block_to_end, _ll_name_needs_quote, block_insert_text_before_terminator # ============================================================ # IRBuilder: 游标式 IR 指令发射器 diff --git a/includes/memhub.vp b/includes/memhub.vp index fba3a8d..c5ed23b 100644 --- a/includes/memhub.vp +++ b/includes/memhub.vp @@ -4,6 +4,7 @@ import string import atom import viperio import stdio +import sys # ============================================================ # memhub - Unified memory management library @@ -430,11 +431,15 @@ class MemBuddy(MemManager): c.DerefAs(block, t.CVoid(t.CUInt64T((order << 1) | 1), t.CPtr)) result = t.CVoid(t.CUInt64T(block) + MEMBUDDY_HEADER_SIZE, t.CPtr) if result is None: - # Allocation failure: print memory usage statistics + # Allocation failure: print memory usage statistics and exit with OOM fb: t.CSizeT = self.free_bytes() ub: t.CSizeT = self.usable_size - fb - stdio.printf("[MEM-FAIL] alloc(%zu) failed: total=%zu used=%zu free=%zu free_blocks=%zu\n", - size, self.usable_size, ub, fb, self.free_count()) + stdio.printf("\n[OOM] 内存不足 (Out of Memory)\n") + stdio.printf("[OOM] 尝试分配: %zu 字节,失败\n", size) + stdio.printf("[OOM] 内存池: total=%zu used=%zu free=%zu free_blocks=%zu\n", + self.usable_size, ub, fb, self.free_count()) + stdio.printf("[OOM] 说明: 内存池已耗尽。可能原因: (1) 池大小不足,需增大 POOL_SIZE; (2) 存在内存泄漏。\n") + sys.exit(1) self._unlock() return result diff --git a/includes/viperlib.vp b/includes/viperlib.vp index f765701..f1d9c69 100644 --- a/includes/viperlib.vp +++ b/includes/viperlib.vp @@ -1,1376 +1,1377 @@ -import t, c -import viperio -from stdarg import arg, va_arg - -TEMP_BUF_SIZE: t.CDefine = 68 - -def get_digit_count(num: t.CUnsignedInt, base: t.CInt) -> t.CStatic | t.CInt: - count: t.CInt = 0 - if num == 0: return 1 - while num > 0: - count += 1 - num //= base - return count - -def sprintf(buf: t.CChar | t.CPtr, rule: str, *args) -> t.CVoid | t.CExport: - if buf is None or rule is None: return - vsnprintf(buf, 0x7FFFFFFF, rule, args) - -def vsprintf(buf: t.CChar | t.CPtr, rule: str, *args) -> t.CInt: - if buf is None or rule is None: return 0 - return vsnprintf(buf, 0x7FFFFFFF, rule, args) - -def snprintf(buf: t.CChar | t.CPtr, size: t.CSizeT, fmt: str, *args) -> t.CInt | t.CExport: - if fmt is None: return 0 - if buf is None or size == 0: - return vsnprintf(None, 0, fmt, args) - return vsnprintf(buf, size, fmt, args) - -# Check floating-point special values (IEEE 754) -# Return: 0=normal, 1=+inf, 2=-inf, 3=nan -def _check_special_float(fv: t.CDouble) -> t.CInt: - fbits: t.CUInt64T = 0 - c.Load(c.Addr(fbits), c.Addr(fv)) - if ((fbits >> 52) & 0x7FF) != 0x7FF: - return 0 - is_neg: t.CInt = 1 if (fbits >> 63) != 0 else 0 - if (fbits & 0x000FFFFFFFFFFFFF) == 0: - if is_neg: - return 2 - return 1 - return 3 - -def vsnprintf(buf: t.CChar | t.CPtr, size: t.CSizeT, fmt: str, ap: t.CChar | t.CPtr) -> t.CInt | t.CExport: - if fmt is None: return 0 - # 长度探测模式:buf is None 时只计算格式化后长度,不实际写入 - # _step=0 使 ptr 不前进,反复写入同一个 dummy 字节(无害),write_count 正确累加 - count_mode: t.CInt = 0 - _step: t.CInt = 1 - _dummy: t.CChar = '\0' - if buf is None or size == 0: - count_mode = 1 - _step = 0 - buf = c.Addr(_dummy) - size = 0x7FFFFFFF - ptr: t.CChar | t.CPtr = buf - write_count: t.CInt = 0 - temp: t.CArray[t.CChar, 68] - temp[0] = '\t' - while c.Deref(fmt) != 0 and write_count < size - 1: - if c.Deref(fmt) != 37: - ptr[0] = c.Deref(fmt) - write_count += 1 - ptr += _step - fmt += 1 - else: - fmt += 1 - if c.Deref(fmt) == 0: break - width: t.CInt = 0 - pad_zero: t.CInt = 0 - left_align: t.CInt = 0 - show_sign: t.CInt = 0 - space_sign: t.CInt = 0 - alt_form: t.CInt = 0 - precision: t.CInt = -1 - is_long: t.CInt = 0 - is_long_long: t.CInt = 0 - is_size: t.CInt = 0 - is_short: t.CInt = 0 - is_char: t.CInt = 0 - while True: - if c.Deref(fmt) == 45: - left_align = 1 - fmt += 1 - elif c.Deref(fmt) == 48: - pad_zero = 1 - fmt += 1 - elif c.Deref(fmt) == 43: - show_sign = 1 - fmt += 1 - elif c.Deref(fmt) == 32: - space_sign = 1 - fmt += 1 - elif c.Deref(fmt) == 35: - alt_form = 1 - fmt += 1 - else: break - if show_sign: space_sign = 0 - while c.Deref(fmt) >= 48 and c.Deref(fmt) <= 57: - width = width * 10 + (c.Deref(fmt) - 48) - fmt += 1 - if c.Deref(fmt) == 46: - fmt += 1 - precision = 0 - while c.Deref(fmt) >= 48 and c.Deref(fmt) <= 57: - precision = precision * 10 + (c.Deref(fmt) - 48) - fmt += 1 - if left_align: pad_zero = 0 - if c.Deref(fmt) == 108: - is_long = 1 - fmt += 1 - if c.Deref(fmt) == 108: - is_long_long = 1 - is_long = 0 - fmt += 1 - elif c.Deref(fmt) == 104: - is_short = 1 - fmt += 1 - if c.Deref(fmt) == 104: - is_char = 1 - is_short = 0 - fmt += 1 - elif c.Deref(fmt) == 122: - is_size = 1 - fmt += 1 - elif c.Deref(fmt) == 106: - is_long_long = 1 - fmt += 1 - elif c.Deref(fmt) == 116: - is_long = 1 - fmt += 1 - if c.Deref(fmt) == 99: - if write_count < size - 1: - ptr_i: t.CInt = va_arg(ap) - ptr[0] = t.CChar(ptr_i) - write_count += 1 - ptr += _step - else: - ptr_i: t.CInt = va_arg(ap) - elif c.Deref(fmt) == 115: - s: str = va_arg(ap, t.CPtr) - if s is None: s = "(None)" - slen: t.CInt = 0 - sc: str = s - while c.Deref(sc) != 0: - slen += 1 - sc += 1 - if not left_align and width > slen: - pad_count: t.CInt = width - slen - while pad_count > 0 and write_count < size - 1: - ptr[0] = 32 - write_count += 1 - ptr += _step - pad_count -= 1 - while c.Deref(s) != 0 and write_count < size - 1: - ptr[0] = c.Deref(s) - write_count += 1 - ptr += _step - s += 1 - if left_align and width > slen: - pad_count = width - slen - while pad_count > 0 and write_count < size - 1: - ptr[0] = 32 - write_count += 1 - ptr += _step - pad_count -= 1 - elif c.Deref(fmt) == 100 or c.Deref(fmt) == 105: - if is_long_long or is_size or is_long: - num_l: t.CInt64T = va_arg(ap, t.CInt64T) - else: - num_l: t.CInt64T = t.CInt64T(va_arg(ap, t.CInt)) - if is_char: - num_l = t.CInt64T(t.CChar(num_l)) - elif is_short: - num_l = t.CInt64T(t.CShort(num_l)) - sign: t.CInt = 0 - if num_l < 0: - sign = 1 - if num_l == (-9223372036854775807 - 1): - u_num: t.CUInt64T = t.CUInt64T(0x8000000000000000) - else: - u_num: t.CUInt64T = t.CUInt64T(-num_l) - else: - u_num: t.CUInt64T = t.CUInt64T(num_l) - if show_sign: sign = 2 - elif space_sign: sign = 3 - i: t.CInt = 0 - while True: - if i >= TEMP_BUF_SIZE - 1: break - temp[i] = t.CChar(u_num % 10 + 48) - i += 1 - u_num //= 10 - if u_num <= 0: break - if sign == 1 and i < TEMP_BUF_SIZE - 1: - temp[i] = 45 - i += 1 - elif sign == 2 and i < TEMP_BUF_SIZE - 1: - temp[i] = 43 - i += 1 - elif sign == 3 and i < TEMP_BUF_SIZE - 1: - temp[i] = 32 - i += 1 - if not left_align and not pad_zero and width > i: - pad_count = width - i - while pad_count > 0 and write_count < size - 1: - ptr[0] = 32 - write_count += 1 - ptr += _step - pad_count -= 1 - if pad_zero and width > i: - pad_count = width - i - while pad_count > 0 and write_count < size - 1: - ptr[0] = 48 - write_count += 1 - ptr += _step - pad_count -= 1 - while i > 0 and write_count < size - 1: - i -= 1 - ptr[0] = temp[i] - write_count += 1 - ptr += _step - if left_align and width > i: - pad_count = width - i - while pad_count > 0 and write_count < size - 1: - ptr[0] = 32 - write_count += 1 - ptr += _step - pad_count -= 1 - elif c.Deref(fmt) == 117: - if is_long or is_long_long or is_size: - u_num_l: t.CUInt64T = va_arg(ap, t.CUInt64T) - else: - u_num_l: t.CUInt64T = t.CUInt64T(t.CUnsignedInt(va_arg(ap))) - i = 0 - while True: - if i >= TEMP_BUF_SIZE - 1: break - temp[i] = t.CChar(u_num_l % 10 + 48) - i += 1 - u_num_l //= 10 - if u_num_l <= 0: break - if not left_align and not pad_zero and width > i: - pad_count = width - i - while pad_count > 0 and write_count < size - 1: - ptr[0] = 32 - write_count += 1 - ptr += _step - pad_count -= 1 - if pad_zero and width > i: - pad_count = width - i - while pad_count > 0 and write_count < size - 1: - ptr[0] = 48 - write_count += 1 - ptr += _step - pad_count -= 1 - while i > 0 and write_count < size - 1: - i -= 1 - ptr[0] = temp[i] - write_count += 1 - ptr += _step - if left_align and width > i: - pad_count = width - i - while pad_count > 0 and write_count < size - 1: - ptr[0] = 32 - write_count += 1 - ptr += _step - pad_count -= 1 - elif c.Deref(fmt) == 120: - if is_long or is_long_long or is_size: - u_num_l: t.CUInt64T = va_arg(ap, t.CUInt64T) - else: - u_num_l: t.CUInt64T = t.CUInt64T(t.CUnsignedInt(va_arg(ap))) - is_nonzero: t.CInt = 0 - if u_num_l != 0: - is_nonzero = 1 - i = 0 - while True: - if i >= TEMP_BUF_SIZE - 1: break - digit: t.CInt = t.CInt(u_num_l % 16) - if digit < 10: - temp[i] = t.CChar(digit + 48) - else: - temp[i] = t.CChar(digit - 10 + 97) - u_num_l //= 16 - i += 1 - if u_num_l <= 0: break - digit_count: t.CInt = i - prefix_len: t.CInt = 0 - if alt_form and is_nonzero: - prefix_len = 2 - effective_len: t.CInt = digit_count + prefix_len - if not left_align and not pad_zero and width > effective_len: - pad_count = width - effective_len - while pad_count > 0 and write_count < size - 1: - ptr[0] = 32 - write_count += 1 - ptr += _step - pad_count -= 1 - if prefix_len > 0: - if write_count < size - 1: - ptr[0] = 48 - write_count += 1 - ptr += _step - if write_count < size - 1: - ptr[0] = 120 - write_count += 1 - ptr += _step - if pad_zero and width > effective_len: - pad_count = width - effective_len - while pad_count > 0 and write_count < size - 1: - ptr[0] = 48 - write_count += 1 - ptr += _step - pad_count -= 1 - while i > 0 and write_count < size - 1: - i -= 1 - ptr[0] = temp[i] - write_count += 1 - ptr += _step - if left_align and width > effective_len: - pad_count = width - effective_len - while pad_count > 0 and write_count < size - 1: - ptr[0] = 32 - write_count += 1 - ptr += _step - pad_count -= 1 - elif c.Deref(fmt) == 88: - if is_long or is_long_long or is_size: - u_num_l: t.CUInt64T = va_arg(ap) - else: - u_num_l: t.CUInt64T = t.CUInt64T(t.CUnsignedInt(va_arg(ap))) - is_nonzero = 0 - if u_num_l != 0: - is_nonzero = 1 - i = 0 - while True: - if i >= TEMP_BUF_SIZE - 1: break - digit = t.CInt(u_num_l % 16) - if digit < 10: - temp[i] = t.CChar(digit + 48) - else: - temp[i] = t.CChar(digit - 10 + 65) - u_num_l //= 16 - i += 1 - if u_num_l <= 0: break - digit_count = i - prefix_len = 0 - if alt_form and is_nonzero: - prefix_len = 2 - effective_len = digit_count + prefix_len - if not left_align and not pad_zero and width > effective_len: - pad_count = width - effective_len - while pad_count > 0 and write_count < size - 1: - ptr[0] = 32 - write_count += 1 - ptr += _step - pad_count -= 1 - if prefix_len > 0: - if write_count < size - 1: - ptr[0] = 48 - write_count += 1 - ptr += _step - if write_count < size - 1: - ptr[0] = 88 - write_count += 1 - ptr += _step - if pad_zero and width > effective_len: - pad_count = width - effective_len - while pad_count > 0 and write_count < size - 1: - ptr[0] = 48 - write_count += 1 - ptr += _step - pad_count -= 1 - while i > 0 and write_count < size - 1: - i -= 1 - ptr[0] = temp[i] - write_count += 1 - ptr += _step - if left_align and width > effective_len: - pad_count = width - effective_len - while pad_count > 0 and write_count < size - 1: - ptr[0] = 32 - write_count += 1 - ptr += _step - pad_count -= 1 - elif c.Deref(fmt) == 111: - if is_long or is_long_long or is_size: - u_num_l: t.CUInt64T = va_arg(ap, t.CUInt64T) - else: - u_num_l: t.CUInt64T = t.CUInt64T(t.CUnsignedInt(va_arg(ap))) - if is_char: - u_num_l = t.CUInt64T(t.CChar(u_num_l)) - elif is_short: - u_num_l = t.CUInt64T(t.CShort(u_num_l)) - i = 0 - if u_num_l == 0 and not alt_form: - temp[0] = 48 - i = 1 - else: - while True: - if i >= TEMP_BUF_SIZE - 1: break - temp[i] = t.CChar(u_num_l % 8 + 48) - i += 1 - u_num_l //= 8 - if u_num_l <= 0: break - if alt_form and i < TEMP_BUF_SIZE - 1: - temp[i] = 48 - i += 1 - if not left_align and not pad_zero and width > i: - pad_count = width - i - while pad_count > 0 and write_count < size - 1: - ptr[0] = 32 - write_count += 1 - ptr += _step - pad_count -= 1 - if pad_zero and width > i: - pad_count = width - i - while pad_count > 0 and write_count < size - 1: - ptr[0] = 48 - write_count += 1 - ptr += _step - pad_count -= 1 - while i > 0 and write_count < size - 1: - i -= 1 - ptr[0] = temp[i] - write_count += 1 - ptr += _step - if left_align and width > i: - pad_count = width - i - while pad_count > 0 and write_count < size - 1: - ptr[0] = 32 - write_count += 1 - ptr += _step - pad_count -= 1 - elif c.Deref(fmt) == 98: - if is_long or is_long_long or is_size: - u_num_l: t.CUInt64T = va_arg(ap, t.CUInt64T) - else: - u_num_l: t.CUInt64T = t.CUInt64T(t.CUnsignedInt(va_arg(ap))) - if is_char: - u_num_l = t.CUInt64T(t.CChar(u_num_l)) - elif is_short: - u_num_l = t.CUInt64T(t.CShort(u_num_l)) - i = 0 - if u_num_l == 0: - temp[0] = 48 - i = 1 - else: - while True: - if i >= TEMP_BUF_SIZE - 1: break - temp[i] = t.CChar(u_num_l % 2 + 48) - i += 1 - u_num_l //= 2 - if u_num_l <= 0: break - if alt_form and i < TEMP_BUF_SIZE - 1: - temp[i] = 98 - i += 1 - if not left_align and not pad_zero and width > i: - pad_count = width - i - while pad_count > 0 and write_count < size - 1: - ptr[0] = 32 - write_count += 1 - ptr += _step - pad_count -= 1 - if pad_zero and width > i: - pad_count = width - i - while pad_count > 0 and write_count < size - 1: - ptr[0] = 48 - write_count += 1 - ptr += _step - pad_count -= 1 - while i > 0 and write_count < size - 1: - i -= 1 - ptr[0] = temp[i] - write_count += 1 - ptr += _step - if left_align and width > i: - pad_count = width - i - while pad_count > 0 and write_count < size - 1: - ptr[0] = 32 - write_count += 1 - ptr += _step - pad_count -= 1 - elif c.Deref(fmt) == 112: - ptr_val: t.CUInt64T = t.CUInt64T(va_arg(ap, t.CPtr)) - if ptr_val == 0: - temp[0] = 40 - temp[1] = 110 - temp[2] = 105 - temp[3] = 108 - temp[4] = 41 - i = 5 - else: - u_num_l = ptr_val - i = 0 - while True: - if i >= TEMP_BUF_SIZE - 1: break - digit = t.CInt(u_num_l % 16) - if digit < 10: - temp[i] = t.CChar(digit + 48) - else: - temp[i] = t.CChar(digit - 10 + 97) - u_num_l //= 16 - i += 1 - if u_num_l <= 0: break - if i < TEMP_BUF_SIZE - 1: - temp[i] = 120 - i += 1 - if i < TEMP_BUF_SIZE - 1: - temp[i] = 48 - i += 1 - if not left_align and not pad_zero and width > i: - pad_count = width - i - while pad_count > 0 and write_count < size - 1: - ptr[0] = 32 - write_count += 1 - ptr += _step - pad_count -= 1 - if pad_zero and width > i: - pad_count = width - i - while pad_count > 0 and write_count < size - 1: - ptr[0] = 48 - write_count += 1 - ptr += _step - pad_count -= 1 - while i > 0 and write_count < size - 1: - i -= 1 - ptr[0] = temp[i] - write_count += 1 - ptr += _step - if left_align and width > i: - pad_count = width - i - while pad_count > 0 and write_count < size - 1: - ptr[0] = 32 - write_count += 1 - ptr += _step - pad_count -= 1 - elif c.Deref(fmt) == 102 or c.Deref(fmt) == 70: - f_upper: t.CInt = 1 if c.Deref(fmt) == 70 else 0 - if precision < 0: precision = 6 - fv: t.CDouble = va_arg(ap, t.CDouble) - f_sp: t.CInt = _check_special_float(fv) - if f_sp != 0: - f_sgn_len: t.CInt = 0 - if f_sp == 2: - f_sgn_len = 1 - elif f_sp == 1 and show_sign: - f_sgn_len = 1 - elif f_sp == 1 and space_sign: - f_sgn_len = 1 - f_total_len: t.CInt = f_sgn_len + 3 - if not left_align and width > f_total_len: - f_pad: t.CInt = width - f_total_len - while f_pad > 0 and write_count < size - 1: - ptr[0] = 32 - write_count += 1 - ptr += _step - f_pad -= 1 - if f_sp == 2: - if write_count < size - 1: - ptr[0] = 45 - write_count += 1 - ptr += _step - elif f_sp == 1 and show_sign: - if write_count < size - 1: - ptr[0] = 43 - write_count += 1 - ptr += _step - elif f_sp == 1 and space_sign: - if write_count < size - 1: - ptr[0] = 32 - write_count += 1 - ptr += _step - fi_c: t.CInt = 0 - while fi_c < 3 and write_count < size - 1: - fc: t.CInt = 0 - if f_sp == 3: - # nan - if fi_c == 0: - fc = 110 - elif fi_c == 1: - fc = 97 - else: - fc = 110 - else: - # inf (f_sp==1 +inf 或 f_sp==2 -inf) - if fi_c == 0: - fc = 105 - elif fi_c == 1: - fc = 110 - else: - fc = 102 - if f_upper and fc >= 97 and fc <= 122: - fc -= 32 - ptr[0] = t.CChar(fc) - write_count += 1 - ptr += _step - fi_c += 1 - if left_align and width > f_total_len: - f_pad = width - f_total_len - while f_pad > 0 and write_count < size - 1: - ptr[0] = 32 - write_count += 1 - ptr += _step - f_pad -= 1 - fmt += 1 - continue - if fv < 0.0: - if write_count < size - 1: - ptr[0] = 45 - write_count += 1 - ptr += _step - fv = 0.0 - fv - elif show_sign: - if write_count < size - 1: - ptr[0] = 43 - write_count += 1 - ptr += _step - elif space_sign: - if write_count < size - 1: - ptr[0] = 32 - write_count += 1 - ptr += _step - di: t.CInt = 0 - work: t.CDouble = fv - if work < 1.0: - temp[0] = 48 - di = 1 - else: - scale: t.CDouble = 1.0 - while work >= scale * 10.0: - scale *= 10.0 - while scale >= 1.0 and di < TEMP_BUF_SIZE - 1: - d: t.CInt = t.CInt(work / scale) - if d > 9: d = 9 - temp[di] = t.CChar(d + 48) - di += 1 - work = work - t.CDouble(d) * scale - scale /= 10.0 - frac_val: t.CDouble = work - p: t.CInt = 0 - while p < precision: - frac_val *= 10.0 - p += 1 - frac_part: t.CUInt64T = t.CUInt64T(frac_val + 0.5) - f_total: t.CInt = di + (precision + 1 if precision > 0 else 0) - if not left_align and not pad_zero and width > f_total: - pad_count = width - f_total - while pad_count > 0 and write_count < size - 1: - ptr[0] = 32 - write_count += 1 - ptr += _step - pad_count -= 1 - if pad_zero and width > f_total: - pad_count = width - f_total - while pad_count > 0 and write_count < size - 1: - ptr[0] = 48 - write_count += 1 - ptr += _step - pad_count -= 1 - while di > 0 and write_count < size - 1: - di -= 1 - ptr[0] = temp[di] - write_count += 1 - ptr += _step - if precision > 0: - if write_count < size - 1: - ptr[0] = 46 - write_count += 1 - ptr += _step - fi: t.CInt = 0 - while fi < precision and fi < TEMP_BUF_SIZE - 1: - temp[fi] = t.CChar(frac_part % 10 + 48) - fi += 1 - frac_part //= 10 - while fi < precision: - temp[fi] = 48 - fi += 1 - while fi > 0 and write_count < size - 1: - fi -= 1 - ptr[0] = temp[fi] - write_count += 1 - ptr += _step - elif alt_form: - if write_count < size - 1: - ptr[0] = 46 - write_count += 1 - ptr += _step - if left_align and width > f_total: - pad_count = width - f_total - while pad_count > 0 and write_count < size - 1: - ptr[0] = 32 - write_count += 1 - ptr += _step - pad_count -= 1 - elif c.Deref(fmt) == 101 or c.Deref(fmt) == 69: - if precision < 0: precision = 6 - fv: t.CDouble = va_arg(ap, t.CDouble) - e_upper: t.CInt = 1 if c.Deref(fmt) == 69 else 0 - e_sp: t.CInt = _check_special_float(fv) - if e_sp != 0: - e_sgn_len: t.CInt = 0 - if e_sp == 2: - e_sgn_len = 1 - elif e_sp == 1 and show_sign: - e_sgn_len = 1 - elif e_sp == 1 and space_sign: - e_sgn_len = 1 - e_total_len: t.CInt = e_sgn_len + 3 - if not left_align and width > e_total_len: - e_pad: t.CInt = width - e_total_len - while e_pad > 0 and write_count < size - 1: - ptr[0] = 32 - write_count += 1 - ptr += _step - e_pad -= 1 - if e_sp == 2: - if write_count < size - 1: - ptr[0] = 45 - write_count += 1 - ptr += _step - elif e_sp == 1 and show_sign: - if write_count < size - 1: - ptr[0] = 43 - write_count += 1 - ptr += _step - elif e_sp == 1 and space_sign: - if write_count < size - 1: - ptr[0] = 32 - write_count += 1 - ptr += _step - ei_c: t.CInt = 0 - while ei_c < 3 and write_count < size - 1: - ec: t.CInt = 0 - if e_sp == 3: - # nan - if ei_c == 0: - ec = 110 - elif ei_c == 1: - ec = 97 - else: - ec = 110 - else: - # inf (e_sp==1 +inf 或 e_sp==2 -inf) - if ei_c == 0: - ec = 105 - elif ei_c == 1: - ec = 110 - else: - ec = 102 - if e_upper and ec >= 97 and ec <= 122: - ec -= 32 - ptr[0] = t.CChar(ec) - write_count += 1 - ptr += _step - ei_c += 1 - if left_align and width > e_total_len: - e_pad = width - e_total_len - while e_pad > 0 and write_count < size - 1: - ptr[0] = 32 - write_count += 1 - ptr += _step - e_pad -= 1 - fmt += 1 - continue - if fv < 0.0: - if write_count < size - 1: - ptr[0] = 45 - write_count += 1 - ptr += _step - fv = 0.0 - fv - elif show_sign: - if write_count < size - 1: - ptr[0] = 43 - write_count += 1 - ptr += _step - elif space_sign: - if write_count < size - 1: - ptr[0] = 32 - write_count += 1 - ptr += _step - exp10: t.CInt = 0 - if fv != 0.0: - while fv >= 10.0: - fv /= 10.0 - exp10 += 1 - while fv < 1.0: - fv *= 10.0 - exp10 -= 1 - int_digit: t.CInt = t.CInt(fv) - if int_digit > 9: int_digit = 9 - if int_digit < 0: int_digit = 0 - frac_v: t.CDouble = fv - t.CDouble(int_digit) - p: t.CInt = 0 - while p < precision: - frac_v *= 10.0 - p += 1 - frac_p: t.CUInt64T = t.CUInt64T(frac_v + 0.5) - carry: t.CUInt64T = 1 - p = 0 - while p < precision: - carry *= 10 - p += 1 - if frac_p >= carry and carry > 0: - frac_p = 0 - int_digit += 1 - if int_digit > 9: - int_digit = 1 - exp10 += 1 - e_total: t.CInt = 1 + (precision + 1 if precision > 0 else 0) + 4 - if not left_align and not pad_zero and width > e_total: - pad_count = width - e_total - while pad_count > 0 and write_count < size - 1: - ptr[0] = 32 - write_count += 1 - ptr += _step - pad_count -= 1 - if pad_zero and width > e_total: - pad_count = width - e_total - while pad_count > 0 and write_count < size - 1: - ptr[0] = 48 - write_count += 1 - ptr += _step - pad_count -= 1 - if write_count < size - 1: - ptr[0] = t.CChar(int_digit + 48) - write_count += 1 - ptr += _step - if precision > 0: - if write_count < size - 1: - ptr[0] = 46 - write_count += 1 - ptr += _step - fi: t.CInt = 0 - while fi < precision and fi < TEMP_BUF_SIZE - 1: - temp[fi] = t.CChar(frac_p % 10 + 48) - fi += 1 - frac_p //= 10 - while fi < precision: - temp[fi] = 48 - fi += 1 - while fi > 0 and write_count < size - 1: - fi -= 1 - ptr[0] = temp[fi] - write_count += 1 - ptr += _step - elif alt_form: - if write_count < size - 1: - ptr[0] = 46 - write_count += 1 - ptr += _step - if write_count < size - 1: - ptr[0] = 101 if e_upper == 0 else 69 - write_count += 1 - ptr += _step - if write_count < size - 1: - ptr[0] = 45 if exp10 < 0 else 43 - write_count += 1 - ptr += _step - exp_abs: t.CUInt64T = t.CUInt64T(exp10) if exp10 >= 0 else t.CUInt64T(0 - exp10) - ei: t.CInt = 0 - if exp_abs == 0: - temp[0] = 48 - temp[1] = 48 - ei = 2 - else: - while exp_abs > 0 and ei < TEMP_BUF_SIZE - 1: - temp[ei] = t.CChar(exp_abs % 10 + 48) - ei += 1 - exp_abs //= 10 - while ei < 2: - temp[ei] = 48 - ei += 1 - while ei > 0 and write_count < size - 1: - ei -= 1 - ptr[0] = temp[ei] - write_count += 1 - ptr += _step - if left_align and width > e_total: - pad_count = width - e_total - while pad_count > 0 and write_count < size - 1: - ptr[0] = 32 - write_count += 1 - ptr += _step - pad_count -= 1 - elif c.Deref(fmt) == 103 or c.Deref(fmt) == 71: - if precision < 0: precision = 6 - if precision == 0: precision = 1 - fv: t.CDouble = va_arg(ap, t.CDouble) - g_upper: t.CInt = 1 if c.Deref(fmt) == 71 else 0 - g_sp: t.CInt = _check_special_float(fv) - if g_sp != 0: - g_sgn_len: t.CInt = 0 - if g_sp == 2: - g_sgn_len = 1 - elif g_sp == 1 and show_sign: - g_sgn_len = 1 - elif g_sp == 1 and space_sign: - g_sgn_len = 1 - g_total_len: t.CInt = g_sgn_len + 3 - if not left_align and width > g_total_len: - g_pad: t.CInt = width - g_total_len - while g_pad > 0 and write_count < size - 1: - ptr[0] = 32 - write_count += 1 - ptr += _step - g_pad -= 1 - if g_sp == 2: - if write_count < size - 1: - ptr[0] = 45 - write_count += 1 - ptr += _step - elif g_sp == 1 and show_sign: - if write_count < size - 1: - ptr[0] = 43 - write_count += 1 - ptr += _step - elif g_sp == 1 and space_sign: - if write_count < size - 1: - ptr[0] = 32 - write_count += 1 - ptr += _step - gi_c: t.CInt = 0 - while gi_c < 3 and write_count < size - 1: - gc: t.CInt = 0 - if g_sp == 3: - # nan - if gi_c == 0: - gc = 110 - elif gi_c == 1: - gc = 97 - else: - gc = 110 - else: - # inf (g_sp==1 +inf 或 g_sp==2 -inf) - if gi_c == 0: - gc = 105 - elif gi_c == 1: - gc = 110 - else: - gc = 102 - if g_upper and gc >= 97 and gc <= 122: - gc -= 32 - ptr[0] = t.CChar(gc) - write_count += 1 - ptr += _step - gi_c += 1 - if left_align and width > g_total_len: - g_pad = width - g_total_len - while g_pad > 0 and write_count < size - 1: - ptr[0] = 32 - write_count += 1 - ptr += _step - g_pad -= 1 - fmt += 1 - continue - if fv < 0.0: - if write_count < size - 1: - ptr[0] = 45 - write_count += 1 - ptr += _step - fv = 0.0 - fv - elif show_sign: - if write_count < size - 1: - ptr[0] = 43 - write_count += 1 - ptr += _step - elif space_sign: - if write_count < size - 1: - ptr[0] = 32 - write_count += 1 - ptr += _step - fv_orig: t.CDouble = fv - exp10: t.CInt = 0 - if fv != 0.0: - while fv >= 10.0: - fv /= 10.0 - exp10 += 1 - while fv < 1.0: - fv *= 10.0 - exp10 -= 1 - g_use_e: t.CInt = 0 - if exp10 < -4 or exp10 >= precision: - g_use_e = 1 - g_len: t.CInt = 0 - if g_use_e: - int_digit: t.CInt = t.CInt(fv) - if int_digit > 9: int_digit = 9 - if int_digit < 0: int_digit = 0 - frac_v: t.CDouble = fv - t.CDouble(int_digit) - prec_e: t.CInt = precision - 1 - p: t.CInt = 0 - while p < prec_e: - frac_v *= 10.0 - p += 1 - frac_p: t.CUInt64T = t.CUInt64T(frac_v + 0.5) - carry: t.CUInt64T = 1 - p = 0 - while p < prec_e: - carry *= 10 - p += 1 - if frac_p >= carry and carry > 0: - frac_p = 0 - int_digit += 1 - if int_digit > 9: - int_digit = 1 - exp10 += 1 - temp[0] = t.CChar(int_digit + 48) - g_len = 1 - if prec_e > 0: - temp[1] = 46 - g_len = 2 - fi: t.CInt = 0 - while fi < prec_e and g_len < TEMP_BUF_SIZE - 1: - temp[g_len] = t.CChar(frac_p % 10 + 48) - g_len += 1 - frac_p //= 10 - lo: t.CInt = 2 - hi: t.CInt = g_len - 1 - while lo < hi: - tc: t.CChar = temp[lo] - temp[lo] = temp[hi] - temp[hi] = tc - lo += 1 - hi -= 1 - else: - prec_f: t.CInt = precision - 1 - exp10 - if prec_f < 0: prec_f = 0 - work: t.CDouble = fv_orig - if work < 1.0: - temp[0] = 48 - g_len = 1 - else: - scale: t.CDouble = 1.0 - while work >= scale * 10.0: - scale *= 10.0 - while scale >= 1.0 and g_len < TEMP_BUF_SIZE - 1: - d: t.CInt = t.CInt(work / scale) - if d > 9: d = 9 - temp[g_len] = t.CChar(d + 48) - g_len += 1 - work = work - t.CDouble(d) * scale - scale /= 10.0 - if prec_f > 0 and g_len < TEMP_BUF_SIZE - 1: - temp[g_len] = 46 - g_len += 1 - frac_val: t.CDouble = work - p = 0 - while p < prec_f: - frac_val *= 10.0 - p += 1 - frac_part: t.CUInt64T = t.CUInt64T(frac_val + 0.5) - fi = 0 - while fi < prec_f and g_len < TEMP_BUF_SIZE - 1: - temp[g_len] = t.CChar(frac_part % 10 + 48) - g_len += 1 - frac_part //= 10 - lo = g_len - prec_f - hi = g_len - 1 - while lo < hi: - tc = temp[lo] - temp[lo] = temp[hi] - temp[hi] = tc - lo += 1 - hi -= 1 - if not alt_form and g_len > 0: - while g_len > 0: - if temp[g_len - 1] == 48: - g_len -= 1 - else: - break - if g_len > 0 and temp[g_len - 1] == 46: - g_len -= 1 - g_total: t.CInt = g_len - if g_use_e: g_total = g_len + 4 - if not left_align and not pad_zero and width > g_total: - pad_count = width - g_total - while pad_count > 0 and write_count < size - 1: - ptr[0] = 32 - write_count += 1 - ptr += _step - pad_count -= 1 - if pad_zero and width > g_total: - pad_count = width - g_total - while pad_count > 0 and write_count < size - 1: - ptr[0] = 48 - write_count += 1 - ptr += _step - pad_count -= 1 - gi: t.CInt = 0 - while gi < g_len and write_count < size - 1: - ptr[0] = temp[gi] - write_count += 1 - ptr += _step - gi += 1 - if g_use_e: - if write_count < size - 1: - ptr[0] = 101 if g_upper == 0 else 69 - write_count += 1 - ptr += _step - if write_count < size - 1: - ptr[0] = 45 if exp10 < 0 else 43 - write_count += 1 - ptr += _step - exp_abs: t.CUInt64T = t.CUInt64T(exp10) if exp10 >= 0 else t.CUInt64T(0 - exp10) - ei: t.CInt = 0 - if exp_abs == 0: - temp[0] = 48 - temp[1] = 48 - ei = 2 - else: - while exp_abs > 0 and ei < TEMP_BUF_SIZE - 1: - temp[ei] = t.CChar(exp_abs % 10 + 48) - ei += 1 - exp_abs //= 10 - while ei < 2: - temp[ei] = 48 - ei += 1 - while ei > 0 and write_count < size - 1: - ei -= 1 - ptr[0] = temp[ei] - write_count += 1 - ptr += _step - if left_align and width > g_total: - pad_count = width - g_total - while pad_count > 0 and write_count < size - 1: - ptr[0] = 32 - write_count += 1 - ptr += _step - pad_count -= 1 - elif c.Deref(fmt) == 97 or c.Deref(fmt) == 65: - a_upper: t.CInt = 1 if c.Deref(fmt) == 65 else 0 - fv: t.CDouble = va_arg(ap, t.CDouble) - a_sp: t.CInt = _check_special_float(fv) - if a_sp != 0: - a_sgn_len: t.CInt = 0 - if a_sp == 2: - a_sgn_len = 1 - elif a_sp == 1 and show_sign: - a_sgn_len = 1 - elif a_sp == 1 and space_sign: - a_sgn_len = 1 - a_total_len: t.CInt = a_sgn_len + 3 - if not left_align and width > a_total_len: - a_pad: t.CInt = width - a_total_len - while a_pad > 0 and write_count < size - 1: - ptr[0] = 32 - write_count += 1 - ptr += _step - a_pad -= 1 - if a_sp == 2: - if write_count < size - 1: - ptr[0] = 45 - write_count += 1 - ptr += _step - elif a_sp == 1 and show_sign: - if write_count < size - 1: - ptr[0] = 43 - write_count += 1 - ptr += _step - elif a_sp == 1 and space_sign: - if write_count < size - 1: - ptr[0] = 32 - write_count += 1 - ptr += _step - ai_c: t.CInt = 0 - while ai_c < 3 and write_count < size - 1: - ac: t.CInt = 0 - if a_sp == 3: - # nan - if ai_c == 0: - ac = 110 - elif ai_c == 1: - ac = 97 - else: - ac = 110 - else: - # inf (a_sp==1 +inf 或 a_sp==2 -inf) - if ai_c == 0: - ac = 105 - elif ai_c == 1: - ac = 110 - else: - ac = 102 - if a_upper and ac >= 97 and ac <= 122: - ac -= 32 - ptr[0] = t.CChar(ac) - write_count += 1 - ptr += _step - ai_c += 1 - if left_align and width > a_total_len: - a_pad = width - a_total_len - while a_pad > 0 and write_count < size - 1: - ptr[0] = 32 - write_count += 1 - ptr += _step - a_pad -= 1 - fmt += 1 - continue - fbits: t.CUInt64T = 0 - c.Load(c.Addr(fbits), c.Addr(fv)) - a_neg: t.CInt = 1 if (fbits >> 63) != 0 else 0 - a_exp: t.CInt = t.CInt((fbits >> 52) & 0x7FF) - a_frac: t.CUInt64T = fbits & 0x000FFFFFFFFFFFFF - a_leading: t.CInt = 0 - a_binexp: t.CInt = 0 - if a_exp == 0: - a_leading = 0 - if a_frac == 0: - a_binexp = 0 - else: - a_binexp = -1022 - else: - a_leading = 1 - a_binexp = a_exp - 1023 - a_prec: t.CInt = precision - if a_prec < 0: - a_prec = 13 - if a_prec > 50: - a_prec = 50 - a_hi: t.CInt = 0 - while a_hi < 13 and a_hi < a_prec: - a_digit: t.CInt = t.CInt((a_frac >> (48 - 4 * a_hi)) & 0xF) - if a_digit < 10: - temp[a_hi] = t.CChar(a_digit + 48) - else: - if a_upper: - temp[a_hi] = t.CChar(a_digit - 10 + 65) - else: - temp[a_hi] = t.CChar(a_digit - 10 + 97) - a_hi += 1 - while a_hi < a_prec: - temp[a_hi] = 48 - a_hi += 1 - a_hd_count: t.CInt = a_prec - if precision < 0: - while a_hd_count > 0 and temp[a_hd_count - 1] == 48: - a_hd_count -= 1 - a_has_dot: t.CInt = 0 - if a_hd_count > 0: - a_has_dot = 1 - elif alt_form: - a_has_dot = 1 - a_eb: t.CInt = a_binexp - a_esign: t.CInt = 0 - if a_binexp < 0: - a_esign = 1 - a_eb = -a_binexp - a_ei: t.CInt = 0 - if a_eb == 0: - temp[60] = 48 - a_ei = 1 - else: - while a_eb > 0 and a_ei < 7: - temp[60 + a_ei] = t.CChar(a_eb % 10 + 48) - a_ei += 1 - a_eb //= 10 - a_ecount: t.CInt = a_ei - a_sign_len: t.CInt = 0 - if a_neg: - a_sign_len = 1 - elif show_sign: - a_sign_len = 1 - elif space_sign: - a_sign_len = 1 - a_content_len: t.CInt = a_sign_len + 2 + 1 + a_has_dot + a_hd_count + 1 + 1 + a_ecount - if not left_align and not pad_zero and width > a_content_len: - a_pad = width - a_content_len - while a_pad > 0 and write_count < size - 1: - ptr[0] = 32 - write_count += 1 - ptr += _step - a_pad -= 1 - if a_neg: - if write_count < size - 1: - ptr[0] = 45 - write_count += 1 - ptr += _step - elif show_sign: - if write_count < size - 1: - ptr[0] = 43 - write_count += 1 - ptr += _step - elif space_sign: - if write_count < size - 1: - ptr[0] = 32 - write_count += 1 - ptr += _step - if pad_zero and width > a_content_len: - a_pad = width - a_content_len - while a_pad > 0 and write_count < size - 1: - ptr[0] = 48 - write_count += 1 - ptr += _step - a_pad -= 1 - if write_count < size - 1: - ptr[0] = 48 - write_count += 1 - ptr += _step - if write_count < size - 1: - if a_upper: - ptr[0] = 88 - else: - ptr[0] = 120 - write_count += 1 - ptr += _step - if write_count < size - 1: - ptr[0] = t.CChar(a_leading + 48) - write_count += 1 - ptr += _step - if a_has_dot: - if write_count < size - 1: - ptr[0] = 46 - write_count += 1 - ptr += _step - a_hj: t.CInt = 0 - while a_hj < a_hd_count and write_count < size - 1: - ptr[0] = temp[a_hj] - write_count += 1 - ptr += _step - a_hj += 1 - if write_count < size - 1: - if a_upper: - ptr[0] = 80 - else: - ptr[0] = 112 - write_count += 1 - ptr += _step - if write_count < size - 1: - if a_esign: - ptr[0] = 45 - else: - ptr[0] = 43 - write_count += 1 - ptr += _step - a_ek: t.CInt = a_ecount - while a_ek > 0 and write_count < size - 1: - a_ek -= 1 - ptr[0] = temp[60 + a_ek] - write_count += 1 - ptr += _step - if left_align and width > a_content_len: - a_pad = width - a_content_len - while a_pad > 0 and write_count < size - 1: - ptr[0] = 32 - write_count += 1 - ptr += _step - a_pad -= 1 - elif c.Deref(fmt) == 110: - if is_long_long or is_long: - np: t.CInt64T | t.CPtr = va_arg(ap, t.CInt64T | t.CPtr) - if np != None: - np[0] = t.CInt64T(write_count) - elif is_short: - sp: t.CShort | t.CPtr = va_arg(ap, t.CShort | t.CPtr) - if sp != None: - sp[0] = t.CShort(write_count) - elif is_char: - cp: t.CChar | t.CPtr = va_arg(ap, t.CChar | t.CPtr) - if cp != None: - cp[0] = t.CChar(write_count) - else: - ip: t.CInt | t.CPtr = va_arg(ap, t.CInt | t.CPtr) - if ip != None: - ip[0] = write_count - elif c.Deref(fmt) == 37: - if write_count < size - 1: - ptr[0] = 37 - write_count += 1 - ptr += _step - else: - if write_count < size - 1: - ptr[0] = c.Deref(fmt) - write_count += 1 - ptr += _step - fmt += 1 - ptr[0] = 0 - return write_count +import t, c +import viperio +from stdarg import arg, va_arg + +TEMP_BUF_SIZE: t.CDefine = 68 + +def get_digit_count(num: t.CUnsignedInt, base: t.CInt) -> t.CStatic | t.CInt: + count: t.CInt = 0 + if num == 0: return 1 + while num > 0: + count += 1 + num //= base + return count + +def sprintf(buf: t.CChar | t.CPtr, rule: str, *args) -> t.CVoid | t.CExport: + if buf is None or rule is None: return + vsnprintf(buf, 0x7FFFFFFF, rule, args) + +def vsprintf(buf: t.CChar | t.CPtr, rule: str, *args) -> t.CInt: + if buf is None or rule is None: return 0 + return vsnprintf(buf, 0x7FFFFFFF, rule, args) + +def snprintf(buf: t.CChar | t.CPtr, size: t.CSizeT, fmt: str, *args) -> t.CInt | t.CExport: + if fmt is None: return 0 + if buf is None or size == 0: + return vsnprintf(None, 0, fmt, args) + ret: t.CInt = vsnprintf(buf, size, fmt, args) + return ret + +# Check floating-point special values (IEEE 754) +# Return: 0=normal, 1=+inf, 2=-inf, 3=nan +def _check_special_float(fv: t.CDouble) -> t.CInt: + fbits: t.CUInt64T = 0 + c.Load(c.Addr(fbits), c.Addr(fv)) + if ((fbits >> 52) & 0x7FF) != 0x7FF: + return 0 + is_neg: t.CInt = 1 if (fbits >> 63) != 0 else 0 + if (fbits & 0x000FFFFFFFFFFFFF) == 0: + if is_neg: + return 2 + return 1 + return 3 + +def vsnprintf(buf: t.CChar | t.CPtr, size: t.CSizeT, fmt: str, ap: t.CChar | t.CPtr) -> t.CInt | t.CExport: + if fmt is None: return 0 + # 长度探测模式:buf is None 时只计算格式化后长度,不实际写入 + # _step=0 使 ptr 不前进,反复写入同一个 dummy 字节(无害),write_count 正确累加 + count_mode: t.CInt = 0 + _step: t.CInt = 1 + _dummy: t.CChar = '\0' + if buf is None or size == 0: + count_mode = 1 + _step = 0 + buf = c.Addr(_dummy) + size = 0x7FFFFFFF + ptr: t.CChar | t.CPtr = buf + write_count: t.CInt = 0 + temp: t.CArray[t.CChar, 68] + temp[0] = '\t' + while c.Deref(fmt) != 0 and write_count < size - 1: + if c.Deref(fmt) != 37: + ptr[0] = c.Deref(fmt) + write_count += 1 + ptr += _step + fmt += 1 + else: + fmt += 1 + if c.Deref(fmt) == 0: break + width: t.CInt = 0 + pad_zero: t.CInt = 0 + left_align: t.CInt = 0 + show_sign: t.CInt = 0 + space_sign: t.CInt = 0 + alt_form: t.CInt = 0 + precision: t.CInt = -1 + is_long: t.CInt = 0 + is_long_long: t.CInt = 0 + is_size: t.CInt = 0 + is_short: t.CInt = 0 + is_char: t.CInt = 0 + while True: + if c.Deref(fmt) == 45: + left_align = 1 + fmt += 1 + elif c.Deref(fmt) == 48: + pad_zero = 1 + fmt += 1 + elif c.Deref(fmt) == 43: + show_sign = 1 + fmt += 1 + elif c.Deref(fmt) == 32: + space_sign = 1 + fmt += 1 + elif c.Deref(fmt) == 35: + alt_form = 1 + fmt += 1 + else: break + if show_sign: space_sign = 0 + while c.Deref(fmt) >= 48 and c.Deref(fmt) <= 57: + width = width * 10 + (c.Deref(fmt) - 48) + fmt += 1 + if c.Deref(fmt) == 46: + fmt += 1 + precision = 0 + while c.Deref(fmt) >= 48 and c.Deref(fmt) <= 57: + precision = precision * 10 + (c.Deref(fmt) - 48) + fmt += 1 + if left_align: pad_zero = 0 + if c.Deref(fmt) == 108: + is_long = 1 + fmt += 1 + if c.Deref(fmt) == 108: + is_long_long = 1 + is_long = 0 + fmt += 1 + elif c.Deref(fmt) == 104: + is_short = 1 + fmt += 1 + if c.Deref(fmt) == 104: + is_char = 1 + is_short = 0 + fmt += 1 + elif c.Deref(fmt) == 122: + is_size = 1 + fmt += 1 + elif c.Deref(fmt) == 106: + is_long_long = 1 + fmt += 1 + elif c.Deref(fmt) == 116: + is_long = 1 + fmt += 1 + if c.Deref(fmt) == 99: + if write_count < size - 1: + ptr_i: t.CInt = va_arg(ap) + ptr[0] = t.CChar(ptr_i) + write_count += 1 + ptr += _step + else: + ptr_i: t.CInt = va_arg(ap) + elif c.Deref(fmt) == 115: + s: str = va_arg(ap, t.CPtr) + if s is None: s = "(None)" + slen: t.CInt = 0 + sc: str = s + while c.Deref(sc) != 0: + slen += 1 + sc += 1 + if not left_align and width > slen: + pad_count: t.CInt = width - slen + while pad_count > 0 and write_count < size - 1: + ptr[0] = 32 + write_count += 1 + ptr += _step + pad_count -= 1 + while c.Deref(s) != 0 and write_count < size - 1: + ptr[0] = c.Deref(s) + write_count += 1 + ptr += _step + s += 1 + if left_align and width > slen: + pad_count = width - slen + while pad_count > 0 and write_count < size - 1: + ptr[0] = 32 + write_count += 1 + ptr += _step + pad_count -= 1 + elif c.Deref(fmt) == 100 or c.Deref(fmt) == 105: + if is_long_long or is_size or is_long: + num_l: t.CInt64T = va_arg(ap, t.CInt64T) + else: + num_l: t.CInt64T = t.CInt64T(va_arg(ap, t.CInt)) + if is_char: + num_l = t.CInt64T(t.CChar(num_l)) + elif is_short: + num_l = t.CInt64T(t.CShort(num_l)) + sign: t.CInt = 0 + if num_l < 0: + sign = 1 + if num_l == (-9223372036854775807 - 1): + u_num: t.CUInt64T = t.CUInt64T(0x8000000000000000) + else: + u_num: t.CUInt64T = t.CUInt64T(-num_l) + else: + u_num: t.CUInt64T = t.CUInt64T(num_l) + if show_sign: sign = 2 + elif space_sign: sign = 3 + i: t.CInt = 0 + while True: + if i >= TEMP_BUF_SIZE - 1: break + temp[i] = t.CChar(u_num % 10 + 48) + i += 1 + u_num //= 10 + if u_num <= 0: break + if sign == 1 and i < TEMP_BUF_SIZE - 1: + temp[i] = 45 + i += 1 + elif sign == 2 and i < TEMP_BUF_SIZE - 1: + temp[i] = 43 + i += 1 + elif sign == 3 and i < TEMP_BUF_SIZE - 1: + temp[i] = 32 + i += 1 + if not left_align and not pad_zero and width > i: + pad_count = width - i + while pad_count > 0 and write_count < size - 1: + ptr[0] = 32 + write_count += 1 + ptr += _step + pad_count -= 1 + if pad_zero and width > i: + pad_count = width - i + while pad_count > 0 and write_count < size - 1: + ptr[0] = 48 + write_count += 1 + ptr += _step + pad_count -= 1 + while i > 0 and write_count < size - 1: + i -= 1 + ptr[0] = temp[i] + write_count += 1 + ptr += _step + if left_align and width > i: + pad_count = width - i + while pad_count > 0 and write_count < size - 1: + ptr[0] = 32 + write_count += 1 + ptr += _step + pad_count -= 1 + elif c.Deref(fmt) == 117: + if is_long or is_long_long or is_size: + u_num_l: t.CUInt64T = va_arg(ap, t.CUInt64T) + else: + u_num_l: t.CUInt64T = t.CUInt64T(t.CUnsignedInt(va_arg(ap))) + i = 0 + while True: + if i >= TEMP_BUF_SIZE - 1: break + temp[i] = t.CChar(u_num_l % 10 + 48) + i += 1 + u_num_l //= 10 + if u_num_l <= 0: break + if not left_align and not pad_zero and width > i: + pad_count = width - i + while pad_count > 0 and write_count < size - 1: + ptr[0] = 32 + write_count += 1 + ptr += _step + pad_count -= 1 + if pad_zero and width > i: + pad_count = width - i + while pad_count > 0 and write_count < size - 1: + ptr[0] = 48 + write_count += 1 + ptr += _step + pad_count -= 1 + while i > 0 and write_count < size - 1: + i -= 1 + ptr[0] = temp[i] + write_count += 1 + ptr += _step + if left_align and width > i: + pad_count = width - i + while pad_count > 0 and write_count < size - 1: + ptr[0] = 32 + write_count += 1 + ptr += _step + pad_count -= 1 + elif c.Deref(fmt) == 120: + if is_long or is_long_long or is_size: + u_num_l: t.CUInt64T = va_arg(ap, t.CUInt64T) + else: + u_num_l: t.CUInt64T = t.CUInt64T(t.CUnsignedInt(va_arg(ap))) + is_nonzero: t.CInt = 0 + if u_num_l != 0: + is_nonzero = 1 + i = 0 + while True: + if i >= TEMP_BUF_SIZE - 1: break + digit: t.CInt = t.CInt(u_num_l % 16) + if digit < 10: + temp[i] = t.CChar(digit + 48) + else: + temp[i] = t.CChar(digit - 10 + 97) + u_num_l //= 16 + i += 1 + if u_num_l <= 0: break + digit_count: t.CInt = i + prefix_len: t.CInt = 0 + if alt_form and is_nonzero: + prefix_len = 2 + effective_len: t.CInt = digit_count + prefix_len + if not left_align and not pad_zero and width > effective_len: + pad_count = width - effective_len + while pad_count > 0 and write_count < size - 1: + ptr[0] = 32 + write_count += 1 + ptr += _step + pad_count -= 1 + if prefix_len > 0: + if write_count < size - 1: + ptr[0] = 48 + write_count += 1 + ptr += _step + if write_count < size - 1: + ptr[0] = 120 + write_count += 1 + ptr += _step + if pad_zero and width > effective_len: + pad_count = width - effective_len + while pad_count > 0 and write_count < size - 1: + ptr[0] = 48 + write_count += 1 + ptr += _step + pad_count -= 1 + while i > 0 and write_count < size - 1: + i -= 1 + ptr[0] = temp[i] + write_count += 1 + ptr += _step + if left_align and width > effective_len: + pad_count = width - effective_len + while pad_count > 0 and write_count < size - 1: + ptr[0] = 32 + write_count += 1 + ptr += _step + pad_count -= 1 + elif c.Deref(fmt) == 88: + if is_long or is_long_long or is_size: + u_num_l: t.CUInt64T = va_arg(ap) + else: + u_num_l: t.CUInt64T = t.CUInt64T(t.CUnsignedInt(va_arg(ap))) + is_nonzero = 0 + if u_num_l != 0: + is_nonzero = 1 + i = 0 + while True: + if i >= TEMP_BUF_SIZE - 1: break + digit = t.CInt(u_num_l % 16) + if digit < 10: + temp[i] = t.CChar(digit + 48) + else: + temp[i] = t.CChar(digit - 10 + 65) + u_num_l //= 16 + i += 1 + if u_num_l <= 0: break + digit_count = i + prefix_len = 0 + if alt_form and is_nonzero: + prefix_len = 2 + effective_len = digit_count + prefix_len + if not left_align and not pad_zero and width > effective_len: + pad_count = width - effective_len + while pad_count > 0 and write_count < size - 1: + ptr[0] = 32 + write_count += 1 + ptr += _step + pad_count -= 1 + if prefix_len > 0: + if write_count < size - 1: + ptr[0] = 48 + write_count += 1 + ptr += _step + if write_count < size - 1: + ptr[0] = 88 + write_count += 1 + ptr += _step + if pad_zero and width > effective_len: + pad_count = width - effective_len + while pad_count > 0 and write_count < size - 1: + ptr[0] = 48 + write_count += 1 + ptr += _step + pad_count -= 1 + while i > 0 and write_count < size - 1: + i -= 1 + ptr[0] = temp[i] + write_count += 1 + ptr += _step + if left_align and width > effective_len: + pad_count = width - effective_len + while pad_count > 0 and write_count < size - 1: + ptr[0] = 32 + write_count += 1 + ptr += _step + pad_count -= 1 + elif c.Deref(fmt) == 111: + if is_long or is_long_long or is_size: + u_num_l: t.CUInt64T = va_arg(ap, t.CUInt64T) + else: + u_num_l: t.CUInt64T = t.CUInt64T(t.CUnsignedInt(va_arg(ap))) + if is_char: + u_num_l = t.CUInt64T(t.CChar(u_num_l)) + elif is_short: + u_num_l = t.CUInt64T(t.CShort(u_num_l)) + i = 0 + if u_num_l == 0 and not alt_form: + temp[0] = 48 + i = 1 + else: + while True: + if i >= TEMP_BUF_SIZE - 1: break + temp[i] = t.CChar(u_num_l % 8 + 48) + i += 1 + u_num_l //= 8 + if u_num_l <= 0: break + if alt_form and i < TEMP_BUF_SIZE - 1: + temp[i] = 48 + i += 1 + if not left_align and not pad_zero and width > i: + pad_count = width - i + while pad_count > 0 and write_count < size - 1: + ptr[0] = 32 + write_count += 1 + ptr += _step + pad_count -= 1 + if pad_zero and width > i: + pad_count = width - i + while pad_count > 0 and write_count < size - 1: + ptr[0] = 48 + write_count += 1 + ptr += _step + pad_count -= 1 + while i > 0 and write_count < size - 1: + i -= 1 + ptr[0] = temp[i] + write_count += 1 + ptr += _step + if left_align and width > i: + pad_count = width - i + while pad_count > 0 and write_count < size - 1: + ptr[0] = 32 + write_count += 1 + ptr += _step + pad_count -= 1 + elif c.Deref(fmt) == 98: + if is_long or is_long_long or is_size: + u_num_l: t.CUInt64T = va_arg(ap, t.CUInt64T) + else: + u_num_l: t.CUInt64T = t.CUInt64T(t.CUnsignedInt(va_arg(ap))) + if is_char: + u_num_l = t.CUInt64T(t.CChar(u_num_l)) + elif is_short: + u_num_l = t.CUInt64T(t.CShort(u_num_l)) + i = 0 + if u_num_l == 0: + temp[0] = 48 + i = 1 + else: + while True: + if i >= TEMP_BUF_SIZE - 1: break + temp[i] = t.CChar(u_num_l % 2 + 48) + i += 1 + u_num_l //= 2 + if u_num_l <= 0: break + if alt_form and i < TEMP_BUF_SIZE - 1: + temp[i] = 98 + i += 1 + if not left_align and not pad_zero and width > i: + pad_count = width - i + while pad_count > 0 and write_count < size - 1: + ptr[0] = 32 + write_count += 1 + ptr += _step + pad_count -= 1 + if pad_zero and width > i: + pad_count = width - i + while pad_count > 0 and write_count < size - 1: + ptr[0] = 48 + write_count += 1 + ptr += _step + pad_count -= 1 + while i > 0 and write_count < size - 1: + i -= 1 + ptr[0] = temp[i] + write_count += 1 + ptr += _step + if left_align and width > i: + pad_count = width - i + while pad_count > 0 and write_count < size - 1: + ptr[0] = 32 + write_count += 1 + ptr += _step + pad_count -= 1 + elif c.Deref(fmt) == 112: + ptr_val: t.CUInt64T = t.CUInt64T(va_arg(ap, t.CPtr)) + if ptr_val == 0: + temp[0] = 40 + temp[1] = 110 + temp[2] = 105 + temp[3] = 108 + temp[4] = 41 + i = 5 + else: + u_num_l = ptr_val + i = 0 + while True: + if i >= TEMP_BUF_SIZE - 1: break + digit = t.CInt(u_num_l % 16) + if digit < 10: + temp[i] = t.CChar(digit + 48) + else: + temp[i] = t.CChar(digit - 10 + 97) + u_num_l //= 16 + i += 1 + if u_num_l <= 0: break + if i < TEMP_BUF_SIZE - 1: + temp[i] = 120 + i += 1 + if i < TEMP_BUF_SIZE - 1: + temp[i] = 48 + i += 1 + if not left_align and not pad_zero and width > i: + pad_count = width - i + while pad_count > 0 and write_count < size - 1: + ptr[0] = 32 + write_count += 1 + ptr += _step + pad_count -= 1 + if pad_zero and width > i: + pad_count = width - i + while pad_count > 0 and write_count < size - 1: + ptr[0] = 48 + write_count += 1 + ptr += _step + pad_count -= 1 + while i > 0 and write_count < size - 1: + i -= 1 + ptr[0] = temp[i] + write_count += 1 + ptr += _step + if left_align and width > i: + pad_count = width - i + while pad_count > 0 and write_count < size - 1: + ptr[0] = 32 + write_count += 1 + ptr += _step + pad_count -= 1 + elif c.Deref(fmt) == 102 or c.Deref(fmt) == 70: + f_upper: t.CInt = 1 if c.Deref(fmt) == 70 else 0 + if precision < 0: precision = 6 + fv: t.CDouble = va_arg(ap, t.CDouble) + f_sp: t.CInt = _check_special_float(fv) + if f_sp != 0: + f_sgn_len: t.CInt = 0 + if f_sp == 2: + f_sgn_len = 1 + elif f_sp == 1 and show_sign: + f_sgn_len = 1 + elif f_sp == 1 and space_sign: + f_sgn_len = 1 + f_total_len: t.CInt = f_sgn_len + 3 + if not left_align and width > f_total_len: + f_pad: t.CInt = width - f_total_len + while f_pad > 0 and write_count < size - 1: + ptr[0] = 32 + write_count += 1 + ptr += _step + f_pad -= 1 + if f_sp == 2: + if write_count < size - 1: + ptr[0] = 45 + write_count += 1 + ptr += _step + elif f_sp == 1 and show_sign: + if write_count < size - 1: + ptr[0] = 43 + write_count += 1 + ptr += _step + elif f_sp == 1 and space_sign: + if write_count < size - 1: + ptr[0] = 32 + write_count += 1 + ptr += _step + fi_c: t.CInt = 0 + while fi_c < 3 and write_count < size - 1: + fc: t.CInt = 0 + if f_sp == 3: + # nan + if fi_c == 0: + fc = 110 + elif fi_c == 1: + fc = 97 + else: + fc = 110 + else: + # inf (f_sp==1 +inf 或 f_sp==2 -inf) + if fi_c == 0: + fc = 105 + elif fi_c == 1: + fc = 110 + else: + fc = 102 + if f_upper and fc >= 97 and fc <= 122: + fc -= 32 + ptr[0] = t.CChar(fc) + write_count += 1 + ptr += _step + fi_c += 1 + if left_align and width > f_total_len: + f_pad = width - f_total_len + while f_pad > 0 and write_count < size - 1: + ptr[0] = 32 + write_count += 1 + ptr += _step + f_pad -= 1 + fmt += 1 + continue + if fv < 0.0: + if write_count < size - 1: + ptr[0] = 45 + write_count += 1 + ptr += _step + fv = 0.0 - fv + elif show_sign: + if write_count < size - 1: + ptr[0] = 43 + write_count += 1 + ptr += _step + elif space_sign: + if write_count < size - 1: + ptr[0] = 32 + write_count += 1 + ptr += _step + di: t.CInt = 0 + work: t.CDouble = fv + if work < 1.0: + temp[0] = 48 + di = 1 + else: + scale: t.CDouble = 1.0 + while work >= scale * 10.0: + scale *= 10.0 + while scale >= 1.0 and di < TEMP_BUF_SIZE - 1: + d: t.CInt = t.CInt(work / scale) + if d > 9: d = 9 + temp[di] = t.CChar(d + 48) + di += 1 + work = work - t.CDouble(d) * scale + scale /= 10.0 + frac_val: t.CDouble = work + p: t.CInt = 0 + while p < precision: + frac_val *= 10.0 + p += 1 + frac_part: t.CUInt64T = t.CUInt64T(frac_val + 0.5) + f_total: t.CInt = di + (precision + 1 if precision > 0 else 0) + if not left_align and not pad_zero and width > f_total: + pad_count = width - f_total + while pad_count > 0 and write_count < size - 1: + ptr[0] = 32 + write_count += 1 + ptr += _step + pad_count -= 1 + if pad_zero and width > f_total: + pad_count = width - f_total + while pad_count > 0 and write_count < size - 1: + ptr[0] = 48 + write_count += 1 + ptr += _step + pad_count -= 1 + while di > 0 and write_count < size - 1: + di -= 1 + ptr[0] = temp[di] + write_count += 1 + ptr += _step + if precision > 0: + if write_count < size - 1: + ptr[0] = 46 + write_count += 1 + ptr += _step + fi: t.CInt = 0 + while fi < precision and fi < TEMP_BUF_SIZE - 1: + temp[fi] = t.CChar(frac_part % 10 + 48) + fi += 1 + frac_part //= 10 + while fi < precision: + temp[fi] = 48 + fi += 1 + while fi > 0 and write_count < size - 1: + fi -= 1 + ptr[0] = temp[fi] + write_count += 1 + ptr += _step + elif alt_form: + if write_count < size - 1: + ptr[0] = 46 + write_count += 1 + ptr += _step + if left_align and width > f_total: + pad_count = width - f_total + while pad_count > 0 and write_count < size - 1: + ptr[0] = 32 + write_count += 1 + ptr += _step + pad_count -= 1 + elif c.Deref(fmt) == 101 or c.Deref(fmt) == 69: + if precision < 0: precision = 6 + fv: t.CDouble = va_arg(ap, t.CDouble) + e_upper: t.CInt = 1 if c.Deref(fmt) == 69 else 0 + e_sp: t.CInt = _check_special_float(fv) + if e_sp != 0: + e_sgn_len: t.CInt = 0 + if e_sp == 2: + e_sgn_len = 1 + elif e_sp == 1 and show_sign: + e_sgn_len = 1 + elif e_sp == 1 and space_sign: + e_sgn_len = 1 + e_total_len: t.CInt = e_sgn_len + 3 + if not left_align and width > e_total_len: + e_pad: t.CInt = width - e_total_len + while e_pad > 0 and write_count < size - 1: + ptr[0] = 32 + write_count += 1 + ptr += _step + e_pad -= 1 + if e_sp == 2: + if write_count < size - 1: + ptr[0] = 45 + write_count += 1 + ptr += _step + elif e_sp == 1 and show_sign: + if write_count < size - 1: + ptr[0] = 43 + write_count += 1 + ptr += _step + elif e_sp == 1 and space_sign: + if write_count < size - 1: + ptr[0] = 32 + write_count += 1 + ptr += _step + ei_c: t.CInt = 0 + while ei_c < 3 and write_count < size - 1: + ec: t.CInt = 0 + if e_sp == 3: + # nan + if ei_c == 0: + ec = 110 + elif ei_c == 1: + ec = 97 + else: + ec = 110 + else: + # inf (e_sp==1 +inf 或 e_sp==2 -inf) + if ei_c == 0: + ec = 105 + elif ei_c == 1: + ec = 110 + else: + ec = 102 + if e_upper and ec >= 97 and ec <= 122: + ec -= 32 + ptr[0] = t.CChar(ec) + write_count += 1 + ptr += _step + ei_c += 1 + if left_align and width > e_total_len: + e_pad = width - e_total_len + while e_pad > 0 and write_count < size - 1: + ptr[0] = 32 + write_count += 1 + ptr += _step + e_pad -= 1 + fmt += 1 + continue + if fv < 0.0: + if write_count < size - 1: + ptr[0] = 45 + write_count += 1 + ptr += _step + fv = 0.0 - fv + elif show_sign: + if write_count < size - 1: + ptr[0] = 43 + write_count += 1 + ptr += _step + elif space_sign: + if write_count < size - 1: + ptr[0] = 32 + write_count += 1 + ptr += _step + exp10: t.CInt = 0 + if fv != 0.0: + while fv >= 10.0: + fv /= 10.0 + exp10 += 1 + while fv < 1.0: + fv *= 10.0 + exp10 -= 1 + int_digit: t.CInt = t.CInt(fv) + if int_digit > 9: int_digit = 9 + if int_digit < 0: int_digit = 0 + frac_v: t.CDouble = fv - t.CDouble(int_digit) + p: t.CInt = 0 + while p < precision: + frac_v *= 10.0 + p += 1 + frac_p: t.CUInt64T = t.CUInt64T(frac_v + 0.5) + carry: t.CUInt64T = 1 + p = 0 + while p < precision: + carry *= 10 + p += 1 + if frac_p >= carry and carry > 0: + frac_p = 0 + int_digit += 1 + if int_digit > 9: + int_digit = 1 + exp10 += 1 + e_total: t.CInt = 1 + (precision + 1 if precision > 0 else 0) + 4 + if not left_align and not pad_zero and width > e_total: + pad_count = width - e_total + while pad_count > 0 and write_count < size - 1: + ptr[0] = 32 + write_count += 1 + ptr += _step + pad_count -= 1 + if pad_zero and width > e_total: + pad_count = width - e_total + while pad_count > 0 and write_count < size - 1: + ptr[0] = 48 + write_count += 1 + ptr += _step + pad_count -= 1 + if write_count < size - 1: + ptr[0] = t.CChar(int_digit + 48) + write_count += 1 + ptr += _step + if precision > 0: + if write_count < size - 1: + ptr[0] = 46 + write_count += 1 + ptr += _step + fi: t.CInt = 0 + while fi < precision and fi < TEMP_BUF_SIZE - 1: + temp[fi] = t.CChar(frac_p % 10 + 48) + fi += 1 + frac_p //= 10 + while fi < precision: + temp[fi] = 48 + fi += 1 + while fi > 0 and write_count < size - 1: + fi -= 1 + ptr[0] = temp[fi] + write_count += 1 + ptr += _step + elif alt_form: + if write_count < size - 1: + ptr[0] = 46 + write_count += 1 + ptr += _step + if write_count < size - 1: + ptr[0] = 101 if e_upper == 0 else 69 + write_count += 1 + ptr += _step + if write_count < size - 1: + ptr[0] = 45 if exp10 < 0 else 43 + write_count += 1 + ptr += _step + exp_abs: t.CUInt64T = t.CUInt64T(exp10) if exp10 >= 0 else t.CUInt64T(0 - exp10) + ei: t.CInt = 0 + if exp_abs == 0: + temp[0] = 48 + temp[1] = 48 + ei = 2 + else: + while exp_abs > 0 and ei < TEMP_BUF_SIZE - 1: + temp[ei] = t.CChar(exp_abs % 10 + 48) + ei += 1 + exp_abs //= 10 + while ei < 2: + temp[ei] = 48 + ei += 1 + while ei > 0 and write_count < size - 1: + ei -= 1 + ptr[0] = temp[ei] + write_count += 1 + ptr += _step + if left_align and width > e_total: + pad_count = width - e_total + while pad_count > 0 and write_count < size - 1: + ptr[0] = 32 + write_count += 1 + ptr += _step + pad_count -= 1 + elif c.Deref(fmt) == 103 or c.Deref(fmt) == 71: + if precision < 0: precision = 6 + if precision == 0: precision = 1 + fv: t.CDouble = va_arg(ap, t.CDouble) + g_upper: t.CInt = 1 if c.Deref(fmt) == 71 else 0 + g_sp: t.CInt = _check_special_float(fv) + if g_sp != 0: + g_sgn_len: t.CInt = 0 + if g_sp == 2: + g_sgn_len = 1 + elif g_sp == 1 and show_sign: + g_sgn_len = 1 + elif g_sp == 1 and space_sign: + g_sgn_len = 1 + g_total_len: t.CInt = g_sgn_len + 3 + if not left_align and width > g_total_len: + g_pad: t.CInt = width - g_total_len + while g_pad > 0 and write_count < size - 1: + ptr[0] = 32 + write_count += 1 + ptr += _step + g_pad -= 1 + if g_sp == 2: + if write_count < size - 1: + ptr[0] = 45 + write_count += 1 + ptr += _step + elif g_sp == 1 and show_sign: + if write_count < size - 1: + ptr[0] = 43 + write_count += 1 + ptr += _step + elif g_sp == 1 and space_sign: + if write_count < size - 1: + ptr[0] = 32 + write_count += 1 + ptr += _step + gi_c: t.CInt = 0 + while gi_c < 3 and write_count < size - 1: + gc: t.CInt = 0 + if g_sp == 3: + # nan + if gi_c == 0: + gc = 110 + elif gi_c == 1: + gc = 97 + else: + gc = 110 + else: + # inf (g_sp==1 +inf 或 g_sp==2 -inf) + if gi_c == 0: + gc = 105 + elif gi_c == 1: + gc = 110 + else: + gc = 102 + if g_upper and gc >= 97 and gc <= 122: + gc -= 32 + ptr[0] = t.CChar(gc) + write_count += 1 + ptr += _step + gi_c += 1 + if left_align and width > g_total_len: + g_pad = width - g_total_len + while g_pad > 0 and write_count < size - 1: + ptr[0] = 32 + write_count += 1 + ptr += _step + g_pad -= 1 + fmt += 1 + continue + if fv < 0.0: + if write_count < size - 1: + ptr[0] = 45 + write_count += 1 + ptr += _step + fv = 0.0 - fv + elif show_sign: + if write_count < size - 1: + ptr[0] = 43 + write_count += 1 + ptr += _step + elif space_sign: + if write_count < size - 1: + ptr[0] = 32 + write_count += 1 + ptr += _step + fv_orig: t.CDouble = fv + exp10: t.CInt = 0 + if fv != 0.0: + while fv >= 10.0: + fv /= 10.0 + exp10 += 1 + while fv < 1.0: + fv *= 10.0 + exp10 -= 1 + g_use_e: t.CInt = 0 + if exp10 < -4 or exp10 >= precision: + g_use_e = 1 + g_len: t.CInt = 0 + if g_use_e: + int_digit: t.CInt = t.CInt(fv) + if int_digit > 9: int_digit = 9 + if int_digit < 0: int_digit = 0 + frac_v: t.CDouble = fv - t.CDouble(int_digit) + prec_e: t.CInt = precision - 1 + p: t.CInt = 0 + while p < prec_e: + frac_v *= 10.0 + p += 1 + frac_p: t.CUInt64T = t.CUInt64T(frac_v + 0.5) + carry: t.CUInt64T = 1 + p = 0 + while p < prec_e: + carry *= 10 + p += 1 + if frac_p >= carry and carry > 0: + frac_p = 0 + int_digit += 1 + if int_digit > 9: + int_digit = 1 + exp10 += 1 + temp[0] = t.CChar(int_digit + 48) + g_len = 1 + if prec_e > 0: + temp[1] = 46 + g_len = 2 + fi: t.CInt = 0 + while fi < prec_e and g_len < TEMP_BUF_SIZE - 1: + temp[g_len] = t.CChar(frac_p % 10 + 48) + g_len += 1 + frac_p //= 10 + lo: t.CInt = 2 + hi: t.CInt = g_len - 1 + while lo < hi: + tc: t.CChar = temp[lo] + temp[lo] = temp[hi] + temp[hi] = tc + lo += 1 + hi -= 1 + else: + prec_f: t.CInt = precision - 1 - exp10 + if prec_f < 0: prec_f = 0 + work: t.CDouble = fv_orig + if work < 1.0: + temp[0] = 48 + g_len = 1 + else: + scale: t.CDouble = 1.0 + while work >= scale * 10.0: + scale *= 10.0 + while scale >= 1.0 and g_len < TEMP_BUF_SIZE - 1: + d: t.CInt = t.CInt(work / scale) + if d > 9: d = 9 + temp[g_len] = t.CChar(d + 48) + g_len += 1 + work = work - t.CDouble(d) * scale + scale /= 10.0 + if prec_f > 0 and g_len < TEMP_BUF_SIZE - 1: + temp[g_len] = 46 + g_len += 1 + frac_val: t.CDouble = work + p = 0 + while p < prec_f: + frac_val *= 10.0 + p += 1 + frac_part: t.CUInt64T = t.CUInt64T(frac_val + 0.5) + fi = 0 + while fi < prec_f and g_len < TEMP_BUF_SIZE - 1: + temp[g_len] = t.CChar(frac_part % 10 + 48) + g_len += 1 + frac_part //= 10 + lo = g_len - prec_f + hi = g_len - 1 + while lo < hi: + tc = temp[lo] + temp[lo] = temp[hi] + temp[hi] = tc + lo += 1 + hi -= 1 + if not alt_form and g_len > 0: + while g_len > 0: + if temp[g_len - 1] == 48: + g_len -= 1 + else: + break + if g_len > 0 and temp[g_len - 1] == 46: + g_len -= 1 + g_total: t.CInt = g_len + if g_use_e: g_total = g_len + 4 + if not left_align and not pad_zero and width > g_total: + pad_count = width - g_total + while pad_count > 0 and write_count < size - 1: + ptr[0] = 32 + write_count += 1 + ptr += _step + pad_count -= 1 + if pad_zero and width > g_total: + pad_count = width - g_total + while pad_count > 0 and write_count < size - 1: + ptr[0] = 48 + write_count += 1 + ptr += _step + pad_count -= 1 + gi: t.CInt = 0 + while gi < g_len and write_count < size - 1: + ptr[0] = temp[gi] + write_count += 1 + ptr += _step + gi += 1 + if g_use_e: + if write_count < size - 1: + ptr[0] = 101 if g_upper == 0 else 69 + write_count += 1 + ptr += _step + if write_count < size - 1: + ptr[0] = 45 if exp10 < 0 else 43 + write_count += 1 + ptr += _step + exp_abs: t.CUInt64T = t.CUInt64T(exp10) if exp10 >= 0 else t.CUInt64T(0 - exp10) + ei: t.CInt = 0 + if exp_abs == 0: + temp[0] = 48 + temp[1] = 48 + ei = 2 + else: + while exp_abs > 0 and ei < TEMP_BUF_SIZE - 1: + temp[ei] = t.CChar(exp_abs % 10 + 48) + ei += 1 + exp_abs //= 10 + while ei < 2: + temp[ei] = 48 + ei += 1 + while ei > 0 and write_count < size - 1: + ei -= 1 + ptr[0] = temp[ei] + write_count += 1 + ptr += _step + if left_align and width > g_total: + pad_count = width - g_total + while pad_count > 0 and write_count < size - 1: + ptr[0] = 32 + write_count += 1 + ptr += _step + pad_count -= 1 + elif c.Deref(fmt) == 97 or c.Deref(fmt) == 65: + a_upper: t.CInt = 1 if c.Deref(fmt) == 65 else 0 + fv: t.CDouble = va_arg(ap, t.CDouble) + a_sp: t.CInt = _check_special_float(fv) + if a_sp != 0: + a_sgn_len: t.CInt = 0 + if a_sp == 2: + a_sgn_len = 1 + elif a_sp == 1 and show_sign: + a_sgn_len = 1 + elif a_sp == 1 and space_sign: + a_sgn_len = 1 + a_total_len: t.CInt = a_sgn_len + 3 + if not left_align and width > a_total_len: + a_pad: t.CInt = width - a_total_len + while a_pad > 0 and write_count < size - 1: + ptr[0] = 32 + write_count += 1 + ptr += _step + a_pad -= 1 + if a_sp == 2: + if write_count < size - 1: + ptr[0] = 45 + write_count += 1 + ptr += _step + elif a_sp == 1 and show_sign: + if write_count < size - 1: + ptr[0] = 43 + write_count += 1 + ptr += _step + elif a_sp == 1 and space_sign: + if write_count < size - 1: + ptr[0] = 32 + write_count += 1 + ptr += _step + ai_c: t.CInt = 0 + while ai_c < 3 and write_count < size - 1: + ac: t.CInt = 0 + if a_sp == 3: + # nan + if ai_c == 0: + ac = 110 + elif ai_c == 1: + ac = 97 + else: + ac = 110 + else: + # inf (a_sp==1 +inf 或 a_sp==2 -inf) + if ai_c == 0: + ac = 105 + elif ai_c == 1: + ac = 110 + else: + ac = 102 + if a_upper and ac >= 97 and ac <= 122: + ac -= 32 + ptr[0] = t.CChar(ac) + write_count += 1 + ptr += _step + ai_c += 1 + if left_align and width > a_total_len: + a_pad = width - a_total_len + while a_pad > 0 and write_count < size - 1: + ptr[0] = 32 + write_count += 1 + ptr += _step + a_pad -= 1 + fmt += 1 + continue + fbits: t.CUInt64T = 0 + c.Load(c.Addr(fbits), c.Addr(fv)) + a_neg: t.CInt = 1 if (fbits >> 63) != 0 else 0 + a_exp: t.CInt = t.CInt((fbits >> 52) & 0x7FF) + a_frac: t.CUInt64T = fbits & 0x000FFFFFFFFFFFFF + a_leading: t.CInt = 0 + a_binexp: t.CInt = 0 + if a_exp == 0: + a_leading = 0 + if a_frac == 0: + a_binexp = 0 + else: + a_binexp = -1022 + else: + a_leading = 1 + a_binexp = a_exp - 1023 + a_prec: t.CInt = precision + if a_prec < 0: + a_prec = 13 + if a_prec > 50: + a_prec = 50 + a_hi: t.CInt = 0 + while a_hi < 13 and a_hi < a_prec: + a_digit: t.CInt = t.CInt((a_frac >> (48 - 4 * a_hi)) & 0xF) + if a_digit < 10: + temp[a_hi] = t.CChar(a_digit + 48) + else: + if a_upper: + temp[a_hi] = t.CChar(a_digit - 10 + 65) + else: + temp[a_hi] = t.CChar(a_digit - 10 + 97) + a_hi += 1 + while a_hi < a_prec: + temp[a_hi] = 48 + a_hi += 1 + a_hd_count: t.CInt = a_prec + if precision < 0: + while a_hd_count > 0 and temp[a_hd_count - 1] == 48: + a_hd_count -= 1 + a_has_dot: t.CInt = 0 + if a_hd_count > 0: + a_has_dot = 1 + elif alt_form: + a_has_dot = 1 + a_eb: t.CInt = a_binexp + a_esign: t.CInt = 0 + if a_binexp < 0: + a_esign = 1 + a_eb = -a_binexp + a_ei: t.CInt = 0 + if a_eb == 0: + temp[60] = 48 + a_ei = 1 + else: + while a_eb > 0 and a_ei < 7: + temp[60 + a_ei] = t.CChar(a_eb % 10 + 48) + a_ei += 1 + a_eb //= 10 + a_ecount: t.CInt = a_ei + a_sign_len: t.CInt = 0 + if a_neg: + a_sign_len = 1 + elif show_sign: + a_sign_len = 1 + elif space_sign: + a_sign_len = 1 + a_content_len: t.CInt = a_sign_len + 2 + 1 + a_has_dot + a_hd_count + 1 + 1 + a_ecount + if not left_align and not pad_zero and width > a_content_len: + a_pad = width - a_content_len + while a_pad > 0 and write_count < size - 1: + ptr[0] = 32 + write_count += 1 + ptr += _step + a_pad -= 1 + if a_neg: + if write_count < size - 1: + ptr[0] = 45 + write_count += 1 + ptr += _step + elif show_sign: + if write_count < size - 1: + ptr[0] = 43 + write_count += 1 + ptr += _step + elif space_sign: + if write_count < size - 1: + ptr[0] = 32 + write_count += 1 + ptr += _step + if pad_zero and width > a_content_len: + a_pad = width - a_content_len + while a_pad > 0 and write_count < size - 1: + ptr[0] = 48 + write_count += 1 + ptr += _step + a_pad -= 1 + if write_count < size - 1: + ptr[0] = 48 + write_count += 1 + ptr += _step + if write_count < size - 1: + if a_upper: + ptr[0] = 88 + else: + ptr[0] = 120 + write_count += 1 + ptr += _step + if write_count < size - 1: + ptr[0] = t.CChar(a_leading + 48) + write_count += 1 + ptr += _step + if a_has_dot: + if write_count < size - 1: + ptr[0] = 46 + write_count += 1 + ptr += _step + a_hj: t.CInt = 0 + while a_hj < a_hd_count and write_count < size - 1: + ptr[0] = temp[a_hj] + write_count += 1 + ptr += _step + a_hj += 1 + if write_count < size - 1: + if a_upper: + ptr[0] = 80 + else: + ptr[0] = 112 + write_count += 1 + ptr += _step + if write_count < size - 1: + if a_esign: + ptr[0] = 45 + else: + ptr[0] = 43 + write_count += 1 + ptr += _step + a_ek: t.CInt = a_ecount + while a_ek > 0 and write_count < size - 1: + a_ek -= 1 + ptr[0] = temp[60 + a_ek] + write_count += 1 + ptr += _step + if left_align and width > a_content_len: + a_pad = width - a_content_len + while a_pad > 0 and write_count < size - 1: + ptr[0] = 32 + write_count += 1 + ptr += _step + a_pad -= 1 + elif c.Deref(fmt) == 110: + if is_long_long or is_long: + np: t.CInt64T | t.CPtr = va_arg(ap, t.CInt64T | t.CPtr) + if np != None: + np[0] = t.CInt64T(write_count) + elif is_short: + sp: t.CShort | t.CPtr = va_arg(ap, t.CShort | t.CPtr) + if sp != None: + sp[0] = t.CShort(write_count) + elif is_char: + cp: t.CChar | t.CPtr = va_arg(ap, t.CChar | t.CPtr) + if cp != None: + cp[0] = t.CChar(write_count) + else: + ip: t.CInt | t.CPtr = va_arg(ap, t.CInt | t.CPtr) + if ip != None: + ip[0] = write_count + elif c.Deref(fmt) == 37: + if write_count < size - 1: + ptr[0] = 37 + write_count += 1 + ptr += _step + else: + if write_count < size - 1: + ptr[0] = c.Deref(fmt) + write_count += 1 + ptr += _step + fmt += 1 + ptr[0] = 0 + return write_count diff --git a/lib/core/ConstEvaluator.py b/lib/core/ConstEvaluator.py index 4a6fd3e..47da8b2 100644 --- a/lib/core/ConstEvaluator.py +++ b/lib/core/ConstEvaluator.py @@ -483,10 +483,30 @@ class EvalContext: self.translator: Any = translator def lookup_name(self, name: str) -> Optional[Any]: - """查找 Name 节点的值:define_constants → SymbolTable → 平台宏""" + """查找 Name 节点的值:define_constants → SymbolTable → 平台宏 + + 治本修复:不再把 module.globals 的 initializer 当常量返回。 + CDefine 不创建 LLVM global(不在 module.globals),仅可变全局变量在 + module.globals 中;把可变全局的 initializer 当编译期常量会让 + range(_sha1_store_count) 等读取处求值成初始值 0 而不生成 load。 + CDefine 通过下方 _define_constants 查询返回常量,双点 bug 不复发。 + """ # 1. Gen._define_constants if self.Gen and name in self.Gen._define_constants: val: Any = self.Gen._define_constants[name] + # 治本修复:本模块全局变量初始化值优先,避免跨模块同名 CDefine 通过 + # 共享 _define_constants 覆盖本模块常量 + # (VpiReader.SHA1_LEN=16 被 Phase1.SHA1_LEN=17 覆盖导致双点符号 bug) + _gvar: Any = None + try: + if hasattr(self.Gen, 'module') and name in self.Gen.module.globals: + _gvar = self.Gen.module.globals[name] + except Exception: + _gvar = None + if _gvar is not None and getattr(_gvar, 'initializer', None) is not None: + _init: Any = _gvar.initializer + if hasattr(_init, 'constant') and isinstance(_init.constant, (int, float)): + val = _init.constant if isinstance(val, (int, float)): return ConstEvaluator._intify(val) diff --git a/lib/core/Handles/HandlesAssign.py b/lib/core/Handles/HandlesAssign.py index b30f086..67c6195 100644 --- a/lib/core/Handles/HandlesAssign.py +++ b/lib/core/Handles/HandlesAssign.py @@ -286,18 +286,23 @@ class AssignHandle(BaseHandle): Gen.var_type_info[VarName] = {'type': 't_type_runtime', 'source': call_func_name} return if VarName in Gen.global_vars: - if VarName in Gen.module.globals: - GVar: ir.GlobalVariable = Gen.module.globals[VarName] - Gen._store(Value, GVar) - Gen.variables[VarName] = GVar - if isinstance(Value.type, ir.PointerType) and isinstance(Value.type.pointee, (ir.LiteralStructType, ir.IdentifiedStructType)): - found: tuple[str, ir.Type] | None = Gen.find_struct_by_pointee(Value.type.pointee) - if found: - CN: str = found[0] - ST: ir.Type = found[1] - Gen.var_struct_class[VarName] = CN - elif VarName in Gen.variables and Gen.variables[VarName] is not None: - Gen._store(Value, Gen.variables[VarName]) + # 治本修复:global 声明的变量若未被模块级 AnnAssign 创建为 LLVM 全局 + # (注解无初始值的全局变量),此处自动创建零初始化全局变量 + GVar: ir.GlobalVariable + if VarName not in Gen.module.globals: + _gv_type: ir.Type = Value.type if isinstance(Value.type, (ir.IntType, ir.PointerType)) else ir.IntType(64) + GVar = ir.GlobalVariable(Gen.module, _gv_type, name=VarName) + GVar.initializer = ir.Constant(_gv_type, None) if isinstance(_gv_type, ir.PointerType) else ir.Constant(_gv_type, 0) + else: + GVar = Gen.module.globals[VarName] + Gen._store(Value, GVar) + Gen.variables[VarName] = GVar + if isinstance(Value.type, ir.PointerType) and isinstance(Value.type.pointee, (ir.LiteralStructType, ir.IdentifiedStructType)): + found: tuple[str, ir.Type] | None = Gen.find_struct_by_pointee(Value.type.pointee) + if found: + CN: str = found[0] + ST: ir.Type = found[1] + Gen.var_struct_class[VarName] = CN return if VarName in Gen._reg_values: OldVal: ir.Value = Gen._reg_values[VarName] diff --git a/lib/core/Handles/HandlesAugAssign.py b/lib/core/Handles/HandlesAugAssign.py index ea78caf..6b6adcd 100644 --- a/lib/core/Handles/HandlesAugAssign.py +++ b/lib/core/Handles/HandlesAugAssign.py @@ -87,8 +87,16 @@ class AugAssignHandle(BaseHandle): if isinstance(Node.target, ast.Name): VarName: str = Node.target.id Op: str = self.Trans.ExprHandler.GetOpSymbol(Node.op) - if VarName in Gen.global_vars and VarName in Gen.module.globals: - GVar: ir.GlobalVariable = Gen.module.globals[VarName] + if VarName in Gen.global_vars: + # 治本修复:global 声明的变量若未被模块级 AnnAssign 创建为 LLVM 全局 + # (注解无初始值的全局变量),此处自动创建零初始化全局变量 + GVar: ir.GlobalVariable + if VarName not in Gen.module.globals: + _gv_type: ir.Type = Value.type if isinstance(Value.type, ir.IntType) else ir.IntType(64) + GVar = ir.GlobalVariable(Gen.module, _gv_type, name=VarName) + GVar.initializer = ir.Constant(_gv_type, 0) + else: + GVar = Gen.module.globals[VarName] Gen.variables[VarName] = GVar OldVal: ir.Value = Gen._load(GVar, name=VarName) NewVal: ir.Value = Gen.emit_binary_op(Op, OldVal, Value, is_unsigned=is_unsigned) @@ -96,22 +104,14 @@ class AugAssignHandle(BaseHandle): return if VarName in Gen._reg_values: OldVal: ir.Value = Gen._reg_values[VarName] - saved_block: ir.Block = Gen.builder.block - entry_block: ir.Block = Gen.func.entry_basic_block - Gen.builder.position_at_start(entry_block) - var: ir.AllocaInstr = Gen.builder.alloca(OldVal.type, name=VarName) + var: ir.AllocaInstr = Gen._allocaEntry(OldVal.type, name=VarName) Gen._store(OldVal, var) - Gen.builder.position_at_end(saved_block) Gen.variables[VarName] = var del Gen._reg_values[VarName] if VarName in Gen._direct_values: OldVal: ir.Value = Gen._direct_values.pop(VarName) - saved_block: ir.Block = Gen.builder.block - entry_block: ir.Block = Gen.func.entry_basic_block - Gen.builder.position_at_start(entry_block) - var: ir.AllocaInstr = Gen.builder.alloca(OldVal.type, name=VarName) + var: ir.AllocaInstr = Gen._allocaEntry(OldVal.type, name=VarName) Gen._store(OldVal, var) - Gen.builder.position_at_end(saved_block) Gen.variables[VarName] = var if Gen.builder.block.is_terminated: return diff --git a/lib/core/Handles/HandlesBase.py b/lib/core/Handles/HandlesBase.py index 35225bb..ae55c22 100644 --- a/lib/core/Handles/HandlesBase.py +++ b/lib/core/Handles/HandlesBase.py @@ -657,6 +657,16 @@ class BaseHandle: ArrayCount = sym_info.value if ArrayCount == 1 and count_node.id in Gen._define_constants: def_val: Any = Gen._define_constants[count_node.id] + # 治本修复:本模块全局变量初始化值优先,避免跨模块同名 CDefine 覆盖 + try: + if hasattr(Gen, 'module') and count_node.id in Gen.module.globals: + _gv: Any = Gen.module.globals[count_node.id] + if getattr(_gv, 'initializer', None) is not None: + _iv: Any = _gv.initializer + if hasattr(_iv, 'constant') and isinstance(_iv.constant, int): + def_val = _iv.constant + except Exception: + pass if isinstance(def_val, int): ArrayCount = def_val return ArrayCount diff --git a/lib/core/Handles/HandlesExpr.py b/lib/core/Handles/HandlesExpr.py index 7522f4c..6e3ea35 100644 --- a/lib/core/Handles/HandlesExpr.py +++ b/lib/core/Handles/HandlesExpr.py @@ -1,493 +1,505 @@ -from __future__ import annotations -from typing import TYPE_CHECKING, Any -if TYPE_CHECKING: - from lib.core.translator import Translator - from lib.core.LlvmCodeGenerator import LlvmCodeGenerator -import ast -import re -import llvmlite.ir as ir -from lib.core.Handles.HandlesBase import BaseHandle -from lib.constants.config import mode as _config_mode -from lib.includes.t import CTypeRegistry as _CR - - -class ExprHandle(BaseHandle): - - # list 元素类型 → (字节大小, LLVM 元素类型) 映射表 - # 用于 _HandleListLlvm 中 alloc_size / byte_offset / elem_ptr 类型统一查表, - # 消除原代码三处重复的 if-elif 链。 - _ELEM_TYPE_INFO: dict[str, tuple[int, ir.Type]] = { - 'i8': (1, ir.IntType(8)), - 'i16': (2, ir.IntType(16)), - 'i32': (4, ir.IntType(32)), - 'float': (4, ir.FloatType()), - 'double': (8, ir.DoubleType()), - } - - def __init__(self, translator: "Translator") -> None: - super().__init__(translator) - - def GetOpSymbol(self, Op: ast.cmpop | ast.operator | ast.unaryoperator) -> str | None: - return self.Trans.ExprUtils.GetOpSymbol(Op) - - def GetUnaryOpSymbol(self, Op: ast.unaryoperator) -> str | None: - return self.Trans.ExprUtils.GetUnaryOpSymbol(Op) - - def GetComparatorSymbol(self, Op: ast.cmpop) -> str | None: - return self.Trans.ExprUtils.GetComparatorSymbol(Op) - - def _get_var_class(self, node: ast.AST, Gen: LlvmCodeGenerator) -> str | None: - return self.Trans.ExprUtils._get_var_class(node, Gen) - - def _try_operator_overLoad(self, ClassName: str, op_name: str, obj_val: ir.Value, Gen: LlvmCodeGenerator, other_val: ir.Value | None = None) -> ir.Value | None: - return self.Trans.ExprUtils._try_operator_overLoad(ClassName, op_name, obj_val, Gen, other_val) - - def _get_llvm_member_offset(self, field_name: str, ClassName: str, Gen: LlvmCodeGenerator) -> int | None: - return self.Trans.ExprAttrHandle._get_llvm_member_offset(field_name, ClassName, Gen) - - def HandleExprLlvm(self, Node: ast.AST, VarType: ir.Type | str | None = None) -> ir.Value | None: - Gen: LlvmCodeGenerator = self.Trans.LlvmGen - if not Gen or not Gen.builder: - return None - if isinstance(Node, ast.Constant): - return self._HandleConstantLlvm(Node, VarType) - elif isinstance(Node, ast.Name): - return self._HandleNameLlvm(Node, VarType) - elif isinstance(Node, ast.BinOp): - return self.Trans.ExprOpsHandle._HandleBinOpLlvm(Node, VarType) - elif isinstance(Node, ast.BoolOp): - return self.Trans.ExprOpsHandle._HandleBoolOpLlvm(Node) - elif isinstance(Node, ast.UnaryOp): - return self.Trans.ExprOpsHandle._HandleUnaryOpLlvm(Node) - elif isinstance(Node, ast.Call): - return self.Trans.ExprCallHandle._HandleCallLlvm(Node) - elif isinstance(Node, ast.Compare): - return self.Trans.ExprOpsHandle._HandleCompareLlvm(Node) - elif isinstance(Node, ast.Attribute): - return self.Trans.ExprAttrHandle._HandleAttributeLlvm(Node) - elif isinstance(Node, ast.Subscript): - return self.Trans.ExprAttrHandle._HandleSubscriptLlvm(Node) - elif isinstance(Node, ast.IfExp): - return self.Trans.ExprLambdaHandle._HandleIfExpLlvm(Node) - elif isinstance(Node, ast.NamedExpr): - return self.Trans.ExprLambdaHandle._HandleNamedExprLlvm(Node) - elif isinstance(Node, ast.JoinedStr): - return self.Trans.ExprFormatHandle._HandleJoinedStrLlvm(Node) - elif isinstance(Node, ast.Lambda): - return self.Trans.ExprLambdaHandle._HandleLambdaLlvm(Node) - elif isinstance(Node, ast.List): - return self._HandleListLlvm(Node, VarType) - return ir.Constant(ir.IntType(32), 0) - - def _HandleListLlvm(self, Node: ast.List, VarType: ir.Type | str | None = None) -> ir.Value | None: - Gen: LlvmCodeGenerator = self.Trans.LlvmGen - elements: list[ast.expr] = Node.elts - if not elements: - return ir.Constant(ir.IntType(8).as_pointer(), None) - - array_len: int = len(elements) - elem_type: str = 'i8' - - if VarType and isinstance(VarType, str) and 'list[' in VarType: - match: re.Match | None = re.search(r'list\[([^,\]]+)(?:,\s*(\d+))?\]', VarType) - if match: - type_str: str = match.group(1).strip() - if match.group(2): - array_len = int(match.group(2)) - if 'CChar' in type_str or 'char' in type_str.lower(): - elem_type = 'i8' - elif 'CFloat' in type_str or type_str.lower() == 'float': - elem_type = 'float' - elif 'CDouble' in type_str or type_str.lower() == 'double': - elem_type = 'double' - elif 'CInt' in type_str or ('int' in type_str.lower() and 'unsigned' not in type_str.lower()): - elem_type = 'i32' - elif 'CUnsignedInt' in type_str or 'unsigned' in type_str.lower(): - elem_type = 'i32' - elif 'CUnsignedChar' in type_str or 'unsigned char' in type_str.lower(): - elem_type = 'i8' - elif 'CShort' in type_str or 'short' in type_str.lower(): - elem_type = 'i16' - elif 'CUnsignedShort' in type_str: - elem_type = 'i16' - elif elements and all(isinstance(e, (ast.Constant,)) and isinstance(getattr(e, 'value', None), float) for e in elements): - elem_type = 'float' - - alloc_size: int = array_len - elem_info: tuple[int, ir.Type] = self._ELEM_TYPE_INFO.get(elem_type, (1, ir.IntType(8))) - elem_size: int = elem_info[0] - elem_llvm_type: ir.Type = elem_info[1] - alloc_size *= elem_size - - malloc_fn: Any = None - malloc_arg_type: ir.IntType = ir.IntType(64) - for fn in Gen.module.global_values: - if fn.name == 'malloc': - malloc_fn = fn - func_ftype: Any = getattr(fn, 'ftype', None) - if func_ftype and getattr(func_ftype, 'args', None): - if func_ftype.args: - malloc_arg_type = fn.ftype.args[0] - break - - if not malloc_fn: - try: - malloc_fn_type: ir.FunctionType = ir.FunctionType(ir.PointerType(ir.IntType(8)), [ir.IntType(64)]) - malloc_fn = ir.Function(Gen.module, malloc_fn_type, name='malloc') - Gen.functions['malloc'] = malloc_fn - except Exception: # 回退:malloc 函数创建失败时返回 null - return ir.Constant(ir.IntType(8).as_pointer(), None) - - alloc_ptr: Any = Gen.builder.call(malloc_fn, [ir.Constant(malloc_arg_type, alloc_size)]) - cast_ptr: Any = Gen.builder.bitcast(alloc_ptr, ir.PointerType(ir.IntType(8))) - - for i, elem in enumerate(elements): - if i >= array_len: - break - - elem_val: Any = self.HandleExprLlvm(elem, VarType=elem_type) - if elem_val is None: - continue - - byte_offset: int = i - if elem_type == 'i32': - byte_offset = i * 4 - elif elem_type == 'i16': - byte_offset = i * 2 - elif elem_type == 'float': - byte_offset = i * 4 - elif elem_type == 'double': - byte_offset = i * 8 - - ptr_as_int: Any = Gen.builder.ptrtoint(cast_ptr, ir.IntType(64)) - new_ptr_val: Any = Gen.builder.add(ptr_as_int, ir.Constant(ir.IntType(64), byte_offset)) - if elem_type == 'i32': - elem_ptr: Any = Gen.builder.inttoptr(new_ptr_val, ir.PointerType(ir.IntType(32))) - elif elem_type == 'i16': - elem_ptr = Gen.builder.inttoptr(new_ptr_val, ir.PointerType(ir.IntType(16))) - elif elem_type == 'float': - elem_ptr = Gen.builder.inttoptr(new_ptr_val, ir.PointerType(ir.FloatType())) - elif elem_type == 'double': - elem_ptr = Gen.builder.inttoptr(new_ptr_val, ir.PointerType(ir.DoubleType())) - else: - elem_ptr = Gen.builder.inttoptr(new_ptr_val, ir.PointerType(ir.IntType(8))) - - if elem_type == 'i8': - if isinstance(elem_val.type, ir.IntType) and elem_val.type.width > 8: - elem_val = Gen.builder.trunc(elem_val, ir.IntType(8), name=f"trunc_elem_{i}") - elif isinstance(elem_val.type, ir.PointerType): - elem_val = Gen.builder.ptrtoint(elem_val, ir.IntType(64), name=f"ptrtoint_elem_{i}") - elem_val = Gen.builder.trunc(elem_val, ir.IntType(8), name=f"trunc_elem_{i}") - elif elem_type == 'i32': - if isinstance(elem_val.type, ir.IntType): - if elem_val.type.width < 32: - elem_val = Gen.builder.zext(elem_val, ir.IntType(32), name=f"zext_elem_{i}") - elif elem_val.type.width > 32: - elem_val = Gen.builder.trunc(elem_val, ir.IntType(32), name=f"trunc_elem_{i}") - elif isinstance(elem_val.type, ir.PointerType): - elem_val = Gen.builder.ptrtoint(elem_val, ir.IntType(32), name=f"ptrtoint_elem_{i}") - elif elem_type == 'i16': - if isinstance(elem_val.type, ir.IntType): - if elem_val.type.width < 16: - elem_val = Gen.builder.zext(elem_val, ir.IntType(16), name=f"zext_elem_{i}") - elif elem_val.type.width > 16: - elem_val = Gen.builder.trunc(elem_val, ir.IntType(16), name=f"trunc_elem_{i}") - elif elem_type == 'float': - if isinstance(elem_val.type, ir.DoubleType): - elem_val = Gen.builder.fptrunc(elem_val, ir.FloatType(), name=f"fptrunc_elem_{i}") - elif isinstance(elem_val.type, ir.IntType): - elem_val = Gen.builder.sitofp(elem_val, ir.FloatType(), name=f"sitofp_elem_{i}") - elif elem_type == 'double': - if isinstance(elem_val.type, ir.FloatType): - elem_val = Gen.builder.fpext(elem_val, ir.DoubleType(), name=f"fpext_elem_{i}") - elif isinstance(elem_val.type, ir.IntType): - elem_val = Gen.builder.sitofp(elem_val, ir.DoubleType(), name=f"sitofp_elem_{i}") - - Gen.builder.store(elem_val, elem_ptr) - - if elem_type in ('float', 'double'): - return Gen.builder.bitcast(alloc_ptr, ir.PointerType(elem_llvm_type), name=f"list_{elem_type}_ptr") - return cast_ptr - - def _HandleConstantLlvm(self, Node: ast.Constant, VarType: ir.Type | str | None = None) -> ir.Value: - Gen: LlvmCodeGenerator = self.Trans.LlvmGen - Value: Any = Node.value - if Value is None: - if VarType is not None and isinstance(VarType, ir.PointerType): - return ir.Constant(VarType, None) - return ir.Constant(ir.IntType(8).as_pointer(), None) - elif isinstance(Value, bool): - return ir.Constant(ir.IntType(32), 1 if Value else 0) - elif isinstance(Value, int): - if VarType is not None: - if isinstance(VarType, ir.IntType): - return ir.Constant(VarType, Value & ((1 << VarType.width) - 1)) - if isinstance(VarType, ir.PointerType): - return ir.Constant(ir.IntType(64), Value) - if isinstance(VarType, (ir.FloatType, ir.DoubleType)): - return ir.Constant(VarType, float(Value)) - if isinstance(VarType, str) and '*' in VarType: - return ir.Constant(ir.IntType(64), Value) - if isinstance(VarType, str): - resolved: Any = _CR.ResolveName(VarType) or _CR.LLVMToCType(VarType) - if resolved: - ctype_cls: type = resolved[0] if isinstance(resolved, tuple) else resolved - inst: Any = ctype_cls() - size: int = getattr(inst, 'Size', 32) - is_unsigned: bool = getattr(inst, 'IsSigned', True) is False - mask: int = (1 << size) - 1 - return ir.Constant(ir.IntType(size), Value & mask) - llvm_match: re.Match | None = re.match(r'^i(\d+)$', VarType) - if llvm_match: - width: int = int(llvm_match.group(1)) - return ir.Constant(ir.IntType(width), Value & ((1 << width) - 1)) - if Value < 0 or Value > 0xFFFFFFFF: - return ir.Constant(ir.IntType(64), Value) - return ir.Constant(ir.IntType(32), Value & 0xFFFFFFFF) - elif isinstance(Value, float): - if VarType and isinstance(VarType, ir.FloatType): - return ir.Constant(VarType, Value) - elif VarType and isinstance(VarType, ir.DoubleType): - return ir.Constant(VarType, Value) - return ir.Constant(ir.DoubleType(), Value) - elif isinstance(Value, str): - is_wide: bool = getattr(Node, 'kind', None) == 'u' - # 引号类型推断:单引号单字符 → i8,双引号/多字符/三重 → i8*,空 → 0(None) - quote_char: str | None = None - is_triple: bool = False - if not is_wide: - col_offset: int = getattr(Node, 'col_offset', 0) - node_lineno: int = getattr(Node, 'lineno', 0) - # AST 的 lineno 可能不准确(常量节点可能指向下一行), - # 因此在 lineno 和 lineno-1 两行中查找引号 - for try_lineno in (node_lineno, node_lineno - 1): - source_line: str | None = Gen._get_source_line(try_lineno) - if source_line and col_offset < len(source_line): - ch: str = source_line[col_offset] - if ch in ("'", '"'): - quote_char = ch - if col_offset + 2 < len(source_line) and source_line[col_offset:col_offset + 3] in ("'''", '"""'): - is_triple = True - break - # 空字符串 → 创建指向 \0 的全局变量 (而非 null, 避免 strcmp 解引用空指针崩溃) - # 走与非空字符串相同的路径, 由下方 else 分支处理 - # 单引号单字符(非三重)→ i8 - is_char_literal: bool = (not is_triple) and (quote_char == "'") and (len(Value) == 1) and not is_wide - if is_char_literal: - if VarType is not None and isinstance(VarType, ir.PointerType): - pass # 类型不匹配:目标是 ptr 但值是 char,走 string 路径 - elif isinstance(VarType, ir.IntType): - return ir.Constant(VarType, ord(Value[0])) - elif isinstance(VarType, str): - resolved = _CR.ResolveName(VarType) or _CR.LLVMToCType(VarType) - if resolved: - ctype_cls = resolved[0] if isinstance(resolved, tuple) else resolved - inst = ctype_cls() - size = getattr(inst, 'Size', 32) - return ir.Constant(ir.IntType(size), ord(Value[0])) - llvm_match = re.match(r'^i(\d+)$', VarType) - if llvm_match: - return ir.Constant(ir.IntType(int(llvm_match.group(1))), ord(Value[0])) - elif VarType is not None: - return ir.Constant(ir.IntType(8), ord(Value[0])) - else: - # 无类型提示:单引号单字符默认为 i8 - return ir.Constant(ir.IntType(8), ord(Value[0])) - if is_wide: - str_value: str = Value + '\x00' - wide_chars: list[int] = [ord(c) for c in str_value] - target_count: int = len(wide_chars) - str_type: ir.ArrayType = ir.ArrayType(ir.IntType(16), target_count) - gv_name: str = f"str_const_{Gen.string_const_counter}" - gv: ir.GlobalVariable = ir.GlobalVariable(Gen.module, str_type, name=gv_name) - gv.initializer = ir.Constant(str_type, wide_chars) - gv.linkage = 'internal' - Gen.string_const_counter += 1 - ptr: Any = Gen.builder.gep(gv, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), 0)], name=f"{gv_name}_cast") - return ptr - else: - str_value = Value + '\x00' - str_bytes: bytes = str_value.encode('utf-8') - target_count = len(str_bytes) - if isinstance(VarType, ir.ArrayType) and isinstance(VarType.element, ir.IntType) and VarType.element.width == 8: - target_count = VarType.count - if len(str_bytes) < target_count: - str_bytes = str_bytes + b'\x00' * (target_count - len(str_bytes)) - else: - str_bytes = str_bytes[:target_count] - str_type = ir.ArrayType(ir.IntType(8), target_count) - gv_name = f"str_const_{Gen.string_const_counter}" - gv = ir.GlobalVariable(Gen.module, str_type, name=gv_name) - gv.initializer = ir.Constant(str_type, bytearray(str_bytes)) - gv.linkage = 'internal' - Gen.string_const_counter += 1 - ptr = Gen.builder.gep(gv, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), 0)], name=f"{gv_name}_cast") - return ptr - return ir.Constant(ir.IntType(32), 0) - - def _HandleNameLlvm(self, Node: ast.Name, VarType: ir.Type | str | None = None) -> ir.Value: - Gen: LlvmCodeGenerator = self.Trans.LlvmGen - VarName: str = Node.id - # [CD] 诊断:仅对关键常量输出(FOREGROUND_*, BACKGROUND_*, STD_*, *HANDLE*) - import sys as _sys - _is_cd_key: bool = isinstance(VarName, str) and (VarName.startswith('FOREGROUND_') or VarName.startswith('BACKGROUND_') or 'STD_' in VarName or 'HANDLE' in VarName) - define_constants: dict[str, Any] = getattr(Gen, '_define_constants', {}) - if VarName in define_constants: - val: Any = define_constants[VarName] - if _is_cd_key: - print(f"[CD] lookup: '{VarName}' found in _define_constants val={val}", file=_sys.stderr, flush=True) - if isinstance(val, int): - # Use VarType hint if available to avoid unnecessary type mismatch - if VarType is not None and isinstance(VarType, ir.IntType): - return ir.Constant(VarType, val & ((1 << VarType.width) - 1)) - if VarName in Gen.var_signedness and Gen.var_signedness[VarName]: - if val < -(1 << 31) or val > 0xFFFFFFFF: - return ir.Constant(ir.IntType(64), val & 0xFFFFFFFFFFFFFFFF) - return ir.Constant(ir.IntType(32), val & 0xFFFFFFFF) - if val < -(1 << 31) or val > 0xFFFFFFFF: - return ir.Constant(ir.IntType(64), val) - return ir.Constant(ir.IntType(32), val & 0xFFFFFFFF) - elif isinstance(val, float): - return ir.Constant(ir.DoubleType(), val) - elif isinstance(val, str): - return Gen._create_string_global(val) - # 如果 _define_constants 中没有,尝试从符号表查找 - if VarName not in define_constants: - try: - sym_info: Any = self.Trans.SymbolTable.lookup(VarName) - if sym_info and sym_info.IsDefine and sym_info.DefineValue is not None: - val = sym_info.DefineValue - if _is_cd_key: - print(f"[CD] lookup: '{VarName}' found in SymbolTable val={val}", file=_sys.stderr, flush=True) - if isinstance(val, int): - # Use VarType hint if available - if VarType is not None and isinstance(VarType, ir.IntType): - return ir.Constant(VarType, val & ((1 << VarType.width) - 1)) - if val < -(1 << 31) or val > 0xFFFFFFFF: - return ir.Constant(ir.IntType(64), val) - return ir.Constant(ir.IntType(32), val & 0xFFFFFFFF) - elif isinstance(val, float): - return ir.Constant(ir.DoubleType(), val) - elif isinstance(val, str): - return Gen._create_string_global(val) - elif _is_cd_key: - print(f"[CD] lookup: '{VarName}' NOT in SymbolTable", file=_sys.stderr, flush=True) - except Exception as _e: - if _config_mode == "strict": - self.Trans.LogWarning(f"异常被忽略: {_e}") - # 治本修复:如果符号表也没有,回退查询 _all_define_constants - # _all_define_constants 由 Phase2Translator 从所有 .pyi 文件预提取, - # 包含跨模块导入的 CDefine 常量(如 FOREGROUND_GREEN、STD_OUTPUT_HANDLE) - if VarName not in define_constants: - all_dc: dict[str, Any] = getattr(Gen, '_all_define_constants', None) or getattr(self.Trans, '_all_define_constants', None) or {} - if VarName in all_dc: - val: Any = all_dc[VarName] - if _is_cd_key: - print(f"[CD] lookup: '{VarName}' found in _all_define_constants val={val}", file=_sys.stderr, flush=True) - if isinstance(val, int): - if VarType is not None and isinstance(VarType, ir.IntType): - return ir.Constant(VarType, val & ((1 << VarType.width) - 1)) - if val < -(1 << 31) or val > 0xFFFFFFFF: - return ir.Constant(ir.IntType(64), val & 0xFFFFFFFFFFFFFFFF) - return ir.Constant(ir.IntType(32), val & 0xFFFFFFFF) - elif isinstance(val, float): - return ir.Constant(ir.DoubleType(), val) - elif isinstance(val, str): - return Gen._create_string_global(val) - elif _is_cd_key: - print(f"[CD] lookup: '{VarName}' NOT found in ANY CDefine table", file=_sys.stderr, flush=True) - # 优先检查 variables(alloca),因为变量可能已被 += 等操作迁移到 variables - if VarName in Gen.variables and Gen.variables[VarName] is not None: - VarPtr: Any = Gen.variables[VarName] - if isinstance(VarPtr, ir.GlobalVariable) and isinstance(VarPtr.type, ir.PointerType) and isinstance(VarPtr.type.pointee, (ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)): - if VarName in Gen.global_struct_class: - Gen.var_struct_class[VarName] = Gen.global_struct_class[VarName] - return VarPtr - if isinstance(VarPtr.type, ir.PointerType) and isinstance(VarPtr.type.pointee, (ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)): - if VarName in Gen.global_struct_class: - Gen.var_struct_class[VarName] = Gen.global_struct_class[VarName] - return VarPtr - # 防御性恢复:对于 double-pointer(如 ndarray**,pointee 是 PointerType) - # 或其他非结构体类型,若 global_struct_class 已记录该变量的类名, - # 也恢复 var_struct_class。这确保方法调用能查找到正确的特化类 - # (如 ndarray[double]),而非 fallback 到 opaque 基础类型。 - if VarName in Gen.global_struct_class and VarName not in Gen.var_struct_class: - Gen.var_struct_class[VarName] = Gen.global_struct_class[VarName] - loaded: ir.Value = Gen._load(VarPtr, name=VarName) - # 大端局部变量:读取时 bswap 还原 - loaded = Gen._apply_bswap_if_big(loaded, getattr(Gen, 'local_var_byteorders', {}).get(VarName, ""), f"bswap_load_{VarName}") - return loaded - if VarName in Gen._reg_values: - return Gen._reg_values[VarName] - if VarName in Gen._direct_values: - return Gen._direct_values[VarName] - if VarName in Gen.global_vars and VarName in Gen.module.globals: - GVar: Any = Gen.module.globals[VarName] - Gen.variables[VarName] = GVar - if isinstance(GVar, ir.Function): - return GVar - if isinstance(GVar.type, ir.PointerType) and isinstance(GVar.type.pointee, (ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)): - return GVar - return Gen._load(GVar, name=VarName) - if VarName in Gen.module.globals: - GVar = Gen.module.globals[VarName] - Gen.variables[VarName] = GVar - if isinstance(GVar, ir.Function): - return GVar - if VarName in Gen.global_struct_class: - Gen.var_struct_class[VarName] = Gen.global_struct_class[VarName] - if isinstance(GVar.type, ir.PointerType) and isinstance(GVar.type.pointee, (ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)): - return GVar - return Gen._load(GVar, name=VarName) - if VarName == 'self': - # 治本修复:方法名为 _get_var_ptr(小写),原 GetVarPtr 不存在会抛 AttributeError。 - # 当 self 未注册到 variables 时(如 opaque struct 参数走了 else 分支), - # 通过 _get_var_ptr 兜底返回 None,由调用方处理。 - SelfPtr: ir.Value | None = Gen._get_var_ptr('self') - if SelfPtr is not None: - return SelfPtr - # 最终兜底:若 _get_var_ptr 返回 None(self 既不在 _reg_values 也不在 variables), - # 直接返回函数参数本身(LLVM Argument)。这避免了 AttributeError 导致的异常路径。 - for arg in getattr(Gen.func, 'args', []): - if getattr(arg, 'name', None) == 'self': - return arg - return ir.Constant(ir.IntType(32), 0) - if Gen._has_function(VarName): - func: Any = Gen._get_function(VarName) - if func: - return Gen.builder.bitcast(func, ir.IntType(8).as_pointer(), name=f"funcptr_{VarName}") - if VarName in Gen.class_methods: - return ir.Constant(ir.IntType(8).as_pointer(), None) - if VarName == 'True' or VarName == 'False': - return ir.Constant(ir.IntType(32), 1 if VarName == 'True' else 0) - SymInfo: Any = self.Trans.SymbolTable.lookup(VarName) - if SymInfo: - if SymInfo.IsEnumMember and isinstance(SymInfo.value, int): - return ir.Constant(ir.IntType(32), SymInfo.value) - if SymInfo.IsFunction or SymInfo.IsFuncPtr: - MangledName: str = Gen._mangle_func_name(VarName) - if MangledName in Gen.module.globals: - g: Any = Gen.module.globals[MangledName] - if isinstance(g, ir.Function): - Gen.functions[VarName] = g - return Gen.builder.bitcast(g, ir.IntType(8).as_pointer(), name=f"funcptr_{VarName}") - for sha1 in Gen.ModuleSha1Map.values(): - prefixed: str = f"{sha1}.{VarName}" - if prefixed in Gen.module.globals: - g = Gen.module.globals[prefixed] - if isinstance(g, ir.Function): - Gen.functions[VarName] = g - return Gen.builder.bitcast(g, ir.IntType(8).as_pointer(), name=f"funcptr_{VarName}") - t_c_imported: dict[str, tuple[str, str]] = getattr(self.Trans, '_t_c_imported_names', {}) - if VarName in t_c_imported: - src_module: str - src_name: str - src_module, src_name = t_c_imported[VarName] - virtual_attr: ast.Attribute = ast.Attribute( - value=ast.Name(id=src_module, ctx=ast.Load()), - attr=src_name, - ctx=ast.Load() - ) - ast.copy_location(virtual_attr, Node) - return self.Trans.ExprAttrHandle._HandleAttributeLlvm(virtual_attr) +from __future__ import annotations +from typing import TYPE_CHECKING, Any +if TYPE_CHECKING: + from lib.core.translator import Translator + from lib.core.LlvmCodeGenerator import LlvmCodeGenerator +import ast +import re +import llvmlite.ir as ir +from lib.core.Handles.HandlesBase import BaseHandle +from lib.constants.config import mode as _config_mode +from lib.includes.t import CTypeRegistry as _CR + + +class ExprHandle(BaseHandle): + + # list 元素类型 → (字节大小, LLVM 元素类型) 映射表 + # 用于 _HandleListLlvm 中 alloc_size / byte_offset / elem_ptr 类型统一查表, + # 消除原代码三处重复的 if-elif 链。 + _ELEM_TYPE_INFO: dict[str, tuple[int, ir.Type]] = { + 'i8': (1, ir.IntType(8)), + 'i16': (2, ir.IntType(16)), + 'i32': (4, ir.IntType(32)), + 'float': (4, ir.FloatType()), + 'double': (8, ir.DoubleType()), + } + + def __init__(self, translator: "Translator") -> None: + super().__init__(translator) + + def GetOpSymbol(self, Op: ast.cmpop | ast.operator | ast.unaryoperator) -> str | None: + return self.Trans.ExprUtils.GetOpSymbol(Op) + + def GetUnaryOpSymbol(self, Op: ast.unaryoperator) -> str | None: + return self.Trans.ExprUtils.GetUnaryOpSymbol(Op) + + def GetComparatorSymbol(self, Op: ast.cmpop) -> str | None: + return self.Trans.ExprUtils.GetComparatorSymbol(Op) + + def _get_var_class(self, node: ast.AST, Gen: LlvmCodeGenerator) -> str | None: + return self.Trans.ExprUtils._get_var_class(node, Gen) + + def _try_operator_overLoad(self, ClassName: str, op_name: str, obj_val: ir.Value, Gen: LlvmCodeGenerator, other_val: ir.Value | None = None) -> ir.Value | None: + return self.Trans.ExprUtils._try_operator_overLoad(ClassName, op_name, obj_val, Gen, other_val) + + def _get_llvm_member_offset(self, field_name: str, ClassName: str, Gen: LlvmCodeGenerator) -> int | None: + return self.Trans.ExprAttrHandle._get_llvm_member_offset(field_name, ClassName, Gen) + + def HandleExprLlvm(self, Node: ast.AST, VarType: ir.Type | str | None = None) -> ir.Value | None: + Gen: LlvmCodeGenerator = self.Trans.LlvmGen + if not Gen or not Gen.builder: + return None + if isinstance(Node, ast.Constant): + return self._HandleConstantLlvm(Node, VarType) + elif isinstance(Node, ast.Name): + return self._HandleNameLlvm(Node, VarType) + elif isinstance(Node, ast.BinOp): + return self.Trans.ExprOpsHandle._HandleBinOpLlvm(Node, VarType) + elif isinstance(Node, ast.BoolOp): + return self.Trans.ExprOpsHandle._HandleBoolOpLlvm(Node) + elif isinstance(Node, ast.UnaryOp): + return self.Trans.ExprOpsHandle._HandleUnaryOpLlvm(Node) + elif isinstance(Node, ast.Call): + return self.Trans.ExprCallHandle._HandleCallLlvm(Node) + elif isinstance(Node, ast.Compare): + return self.Trans.ExprOpsHandle._HandleCompareLlvm(Node) + elif isinstance(Node, ast.Attribute): + return self.Trans.ExprAttrHandle._HandleAttributeLlvm(Node) + elif isinstance(Node, ast.Subscript): + return self.Trans.ExprAttrHandle._HandleSubscriptLlvm(Node) + elif isinstance(Node, ast.IfExp): + return self.Trans.ExprLambdaHandle._HandleIfExpLlvm(Node) + elif isinstance(Node, ast.NamedExpr): + return self.Trans.ExprLambdaHandle._HandleNamedExprLlvm(Node) + elif isinstance(Node, ast.JoinedStr): + return self.Trans.ExprFormatHandle._HandleJoinedStrLlvm(Node) + elif isinstance(Node, ast.Lambda): + return self.Trans.ExprLambdaHandle._HandleLambdaLlvm(Node) + elif isinstance(Node, ast.List): + return self._HandleListLlvm(Node, VarType) + return ir.Constant(ir.IntType(32), 0) + + def _HandleListLlvm(self, Node: ast.List, VarType: ir.Type | str | None = None) -> ir.Value | None: + Gen: LlvmCodeGenerator = self.Trans.LlvmGen + elements: list[ast.expr] = Node.elts + if not elements: + return ir.Constant(ir.IntType(8).as_pointer(), None) + + array_len: int = len(elements) + elem_type: str = 'i8' + + if VarType and isinstance(VarType, str) and 'list[' in VarType: + match: re.Match | None = re.search(r'list\[([^,\]]+)(?:,\s*(\d+))?\]', VarType) + if match: + type_str: str = match.group(1).strip() + if match.group(2): + array_len = int(match.group(2)) + if 'CChar' in type_str or 'char' in type_str.lower(): + elem_type = 'i8' + elif 'CFloat' in type_str or type_str.lower() == 'float': + elem_type = 'float' + elif 'CDouble' in type_str or type_str.lower() == 'double': + elem_type = 'double' + elif 'CInt' in type_str or ('int' in type_str.lower() and 'unsigned' not in type_str.lower()): + elem_type = 'i32' + elif 'CUnsignedInt' in type_str or 'unsigned' in type_str.lower(): + elem_type = 'i32' + elif 'CUnsignedChar' in type_str or 'unsigned char' in type_str.lower(): + elem_type = 'i8' + elif 'CShort' in type_str or 'short' in type_str.lower(): + elem_type = 'i16' + elif 'CUnsignedShort' in type_str: + elem_type = 'i16' + elif elements and all(isinstance(e, (ast.Constant,)) and isinstance(getattr(e, 'value', None), float) for e in elements): + elem_type = 'float' + + alloc_size: int = array_len + elem_info: tuple[int, ir.Type] = self._ELEM_TYPE_INFO.get(elem_type, (1, ir.IntType(8))) + elem_size: int = elem_info[0] + elem_llvm_type: ir.Type = elem_info[1] + alloc_size *= elem_size + + malloc_fn: Any = None + malloc_arg_type: ir.IntType = ir.IntType(64) + for fn in Gen.module.global_values: + if fn.name == 'malloc': + malloc_fn = fn + func_ftype: Any = getattr(fn, 'ftype', None) + if func_ftype and getattr(func_ftype, 'args', None): + if func_ftype.args: + malloc_arg_type = fn.ftype.args[0] + break + + if not malloc_fn: + try: + malloc_fn_type: ir.FunctionType = ir.FunctionType(ir.PointerType(ir.IntType(8)), [ir.IntType(64)]) + malloc_fn = ir.Function(Gen.module, malloc_fn_type, name='malloc') + Gen.functions['malloc'] = malloc_fn + except Exception: # 回退:malloc 函数创建失败时返回 null + return ir.Constant(ir.IntType(8).as_pointer(), None) + + alloc_ptr: Any = Gen.builder.call(malloc_fn, [ir.Constant(malloc_arg_type, alloc_size)]) + cast_ptr: Any = Gen.builder.bitcast(alloc_ptr, ir.PointerType(ir.IntType(8))) + + for i, elem in enumerate(elements): + if i >= array_len: + break + + elem_val: Any = self.HandleExprLlvm(elem, VarType=elem_type) + if elem_val is None: + continue + + byte_offset: int = i + if elem_type == 'i32': + byte_offset = i * 4 + elif elem_type == 'i16': + byte_offset = i * 2 + elif elem_type == 'float': + byte_offset = i * 4 + elif elem_type == 'double': + byte_offset = i * 8 + + ptr_as_int: Any = Gen.builder.ptrtoint(cast_ptr, ir.IntType(64)) + new_ptr_val: Any = Gen.builder.add(ptr_as_int, ir.Constant(ir.IntType(64), byte_offset)) + if elem_type == 'i32': + elem_ptr: Any = Gen.builder.inttoptr(new_ptr_val, ir.PointerType(ir.IntType(32))) + elif elem_type == 'i16': + elem_ptr = Gen.builder.inttoptr(new_ptr_val, ir.PointerType(ir.IntType(16))) + elif elem_type == 'float': + elem_ptr = Gen.builder.inttoptr(new_ptr_val, ir.PointerType(ir.FloatType())) + elif elem_type == 'double': + elem_ptr = Gen.builder.inttoptr(new_ptr_val, ir.PointerType(ir.DoubleType())) + else: + elem_ptr = Gen.builder.inttoptr(new_ptr_val, ir.PointerType(ir.IntType(8))) + + if elem_type == 'i8': + if isinstance(elem_val.type, ir.IntType) and elem_val.type.width > 8: + elem_val = Gen.builder.trunc(elem_val, ir.IntType(8), name=f"trunc_elem_{i}") + elif isinstance(elem_val.type, ir.PointerType): + elem_val = Gen.builder.ptrtoint(elem_val, ir.IntType(64), name=f"ptrtoint_elem_{i}") + elem_val = Gen.builder.trunc(elem_val, ir.IntType(8), name=f"trunc_elem_{i}") + elif elem_type == 'i32': + if isinstance(elem_val.type, ir.IntType): + if elem_val.type.width < 32: + elem_val = Gen.builder.zext(elem_val, ir.IntType(32), name=f"zext_elem_{i}") + elif elem_val.type.width > 32: + elem_val = Gen.builder.trunc(elem_val, ir.IntType(32), name=f"trunc_elem_{i}") + elif isinstance(elem_val.type, ir.PointerType): + elem_val = Gen.builder.ptrtoint(elem_val, ir.IntType(32), name=f"ptrtoint_elem_{i}") + elif elem_type == 'i16': + if isinstance(elem_val.type, ir.IntType): + if elem_val.type.width < 16: + elem_val = Gen.builder.zext(elem_val, ir.IntType(16), name=f"zext_elem_{i}") + elif elem_val.type.width > 16: + elem_val = Gen.builder.trunc(elem_val, ir.IntType(16), name=f"trunc_elem_{i}") + elif elem_type == 'float': + if isinstance(elem_val.type, ir.DoubleType): + elem_val = Gen.builder.fptrunc(elem_val, ir.FloatType(), name=f"fptrunc_elem_{i}") + elif isinstance(elem_val.type, ir.IntType): + elem_val = Gen.builder.sitofp(elem_val, ir.FloatType(), name=f"sitofp_elem_{i}") + elif elem_type == 'double': + if isinstance(elem_val.type, ir.FloatType): + elem_val = Gen.builder.fpext(elem_val, ir.DoubleType(), name=f"fpext_elem_{i}") + elif isinstance(elem_val.type, ir.IntType): + elem_val = Gen.builder.sitofp(elem_val, ir.DoubleType(), name=f"sitofp_elem_{i}") + + Gen.builder.store(elem_val, elem_ptr) + + if elem_type in ('float', 'double'): + return Gen.builder.bitcast(alloc_ptr, ir.PointerType(elem_llvm_type), name=f"list_{elem_type}_ptr") + return cast_ptr + + def _HandleConstantLlvm(self, Node: ast.Constant, VarType: ir.Type | str | None = None) -> ir.Value: + Gen: LlvmCodeGenerator = self.Trans.LlvmGen + Value: Any = Node.value + if Value is None: + if VarType is not None and isinstance(VarType, ir.PointerType): + return ir.Constant(VarType, None) + return ir.Constant(ir.IntType(8).as_pointer(), None) + elif isinstance(Value, bool): + return ir.Constant(ir.IntType(32), 1 if Value else 0) + elif isinstance(Value, int): + if VarType is not None: + if isinstance(VarType, ir.IntType): + return ir.Constant(VarType, Value & ((1 << VarType.width) - 1)) + if isinstance(VarType, ir.PointerType): + return ir.Constant(ir.IntType(64), Value) + if isinstance(VarType, (ir.FloatType, ir.DoubleType)): + return ir.Constant(VarType, float(Value)) + if isinstance(VarType, str) and '*' in VarType: + return ir.Constant(ir.IntType(64), Value) + if isinstance(VarType, str): + resolved: Any = _CR.ResolveName(VarType) or _CR.LLVMToCType(VarType) + if resolved: + ctype_cls: type = resolved[0] if isinstance(resolved, tuple) else resolved + inst: Any = ctype_cls() + size: int = getattr(inst, 'Size', 32) + is_unsigned: bool = getattr(inst, 'IsSigned', True) is False + mask: int = (1 << size) - 1 + return ir.Constant(ir.IntType(size), Value & mask) + llvm_match: re.Match | None = re.match(r'^i(\d+)$', VarType) + if llvm_match: + width: int = int(llvm_match.group(1)) + return ir.Constant(ir.IntType(width), Value & ((1 << width) - 1)) + if Value < 0 or Value > 0xFFFFFFFF: + return ir.Constant(ir.IntType(64), Value) + return ir.Constant(ir.IntType(32), Value & 0xFFFFFFFF) + elif isinstance(Value, float): + if VarType and isinstance(VarType, ir.FloatType): + return ir.Constant(VarType, Value) + elif VarType and isinstance(VarType, ir.DoubleType): + return ir.Constant(VarType, Value) + return ir.Constant(ir.DoubleType(), Value) + elif isinstance(Value, str): + is_wide: bool = getattr(Node, 'kind', None) == 'u' + # 引号类型推断:单引号单字符 → i8,双引号/多字符/三重 → i8*,空 → 0(None) + quote_char: str | None = None + is_triple: bool = False + if not is_wide: + col_offset: int = getattr(Node, 'col_offset', 0) + node_lineno: int = getattr(Node, 'lineno', 0) + # AST 的 lineno 可能不准确(常量节点可能指向下一行), + # 因此在 lineno 和 lineno-1 两行中查找引号 + for try_lineno in (node_lineno, node_lineno - 1): + source_line: str | None = Gen._get_source_line(try_lineno) + if source_line and col_offset < len(source_line): + ch: str = source_line[col_offset] + if ch in ("'", '"'): + quote_char = ch + if col_offset + 2 < len(source_line) and source_line[col_offset:col_offset + 3] in ("'''", '"""'): + is_triple = True + break + # 空字符串 → 创建指向 \0 的全局变量 (而非 null, 避免 strcmp 解引用空指针崩溃) + # 走与非空字符串相同的路径, 由下方 else 分支处理 + # 单引号单字符(非三重)→ i8 + is_char_literal: bool = (not is_triple) and (quote_char == "'") and (len(Value) == 1) and not is_wide + if is_char_literal: + if VarType is not None and isinstance(VarType, ir.PointerType): + pass # 类型不匹配:目标是 ptr 但值是 char,走 string 路径 + elif isinstance(VarType, ir.IntType): + return ir.Constant(VarType, ord(Value[0])) + elif isinstance(VarType, str): + resolved = _CR.ResolveName(VarType) or _CR.LLVMToCType(VarType) + if resolved: + ctype_cls = resolved[0] if isinstance(resolved, tuple) else resolved + inst = ctype_cls() + size = getattr(inst, 'Size', 32) + return ir.Constant(ir.IntType(size), ord(Value[0])) + llvm_match = re.match(r'^i(\d+)$', VarType) + if llvm_match: + return ir.Constant(ir.IntType(int(llvm_match.group(1))), ord(Value[0])) + elif VarType is not None: + return ir.Constant(ir.IntType(8), ord(Value[0])) + else: + # 无类型提示:单引号单字符默认为 i8 + return ir.Constant(ir.IntType(8), ord(Value[0])) + if is_wide: + str_value: str = Value + '\x00' + wide_chars: list[int] = [ord(c) for c in str_value] + target_count: int = len(wide_chars) + str_type: ir.ArrayType = ir.ArrayType(ir.IntType(16), target_count) + gv_name: str = f"str_const_{Gen.string_const_counter}" + gv: ir.GlobalVariable = ir.GlobalVariable(Gen.module, str_type, name=gv_name) + gv.initializer = ir.Constant(str_type, wide_chars) + gv.linkage = 'internal' + Gen.string_const_counter += 1 + ptr: Any = Gen.builder.gep(gv, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), 0)], name=f"{gv_name}_cast") + return ptr + else: + str_value = Value + '\x00' + str_bytes: bytes = str_value.encode('utf-8') + target_count = len(str_bytes) + if isinstance(VarType, ir.ArrayType) and isinstance(VarType.element, ir.IntType) and VarType.element.width == 8: + target_count = VarType.count + if len(str_bytes) < target_count: + str_bytes = str_bytes + b'\x00' * (target_count - len(str_bytes)) + else: + str_bytes = str_bytes[:target_count] + str_type = ir.ArrayType(ir.IntType(8), target_count) + gv_name = f"str_const_{Gen.string_const_counter}" + gv = ir.GlobalVariable(Gen.module, str_type, name=gv_name) + gv.initializer = ir.Constant(str_type, bytearray(str_bytes)) + gv.linkage = 'internal' + Gen.string_const_counter += 1 + ptr = Gen.builder.gep(gv, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), 0)], name=f"{gv_name}_cast") + return ptr + return ir.Constant(ir.IntType(32), 0) + + def _HandleNameLlvm(self, Node: ast.Name, VarType: ir.Type | str | None = None) -> ir.Value: + Gen: LlvmCodeGenerator = self.Trans.LlvmGen + VarName: str = Node.id + # [CD] 诊断:仅对关键常量输出(FOREGROUND_*, BACKGROUND_*, STD_*, *HANDLE*) + import sys as _sys + _is_cd_key: bool = isinstance(VarName, str) and (VarName.startswith('FOREGROUND_') or VarName.startswith('BACKGROUND_') or 'STD_' in VarName or 'HANDLE' in VarName) + # 治本修复:不把 module.globals 的 initializer 注入 _define_constants。 + # 原因:CDefine(t.CDefine 注解)在 AnnAssign/Assign 处理时已注册到 + # _define_constants 且不创建 LLVM global(不在 module.globals); + # module.globals 里全是可变全局变量(如 _sha1_store_count,有 += 写入), + # 若把其 initializer 当常量传播,会导致 range(_sha1_store_count) 被求值成 + # range(0)、printf 印 0 等问题(读取处不生成 load)。 + # CDefine 的本模块优先靠下方 _define_constants 查询保证,双点 bug 不复发。 + define_constants: dict[str, Any] = getattr(Gen, '_define_constants', {}) + # 治本防护:module.globals 里的都是可变全局变量(CDefine 不创建 LLVM global, + # 仅注册到 _define_constants)。可变全局有 += 等写入,不能当常量传播, + # 跳过 _define_constants 查询,直接走下方 variables/global_vars/module.globals 的 load。 + if VarName in define_constants and not (hasattr(Gen, 'module') and VarName in Gen.module.globals): + val: Any = define_constants[VarName] + # 治本修复:本模块全局变量初始化值优先,避免跨模块同名 CDefine 通过 + # 共享 _define_constants 覆盖本模块常量 + # (VpiReader.SHA1_LEN=16 被 Phase1.SHA1_LEN=17 覆盖导致双点符号 bug) + _gvar: Any = None + try: + if hasattr(Gen, 'module') and VarName in Gen.module.globals: + _gvar = Gen.module.globals[VarName] + except Exception: + _gvar = None + if _gvar is not None and getattr(_gvar, 'initializer', None) is not None: + _init: Any = _gvar.initializer + if isinstance(_init, ir.Constant) and isinstance(_init.constant, (int, float, str)): + val = _init.constant + if _is_cd_key: + print(f"[CD] lookup: '{VarName}' found in _define_constants val={val}", file=_sys.stderr, flush=True) + if isinstance(val, int): + # Use VarType hint if available to avoid unnecessary type mismatch + if VarType is not None and isinstance(VarType, ir.IntType): + return ir.Constant(VarType, val & ((1 << VarType.width) - 1)) + if VarName in Gen.var_signedness and Gen.var_signedness[VarName]: + if val < -(1 << 31) or val > 0xFFFFFFFF: + return ir.Constant(ir.IntType(64), val & 0xFFFFFFFFFFFFFFFF) + return ir.Constant(ir.IntType(32), val & 0xFFFFFFFF) + if val < -(1 << 31) or val > 0xFFFFFFFF: + return ir.Constant(ir.IntType(64), val) + return ir.Constant(ir.IntType(32), val & 0xFFFFFFFF) + elif isinstance(val, float): + return ir.Constant(ir.DoubleType(), val) + elif isinstance(val, str): + return Gen._create_string_global(val) + # 治本修复(方案C):CDefine 不通过共享 SymbolTable 跨模块裸名共享。 + # 此处不再消费 SymbolTable 中的 IsDefine 符号,避免其他模块 CDefine + # 覆盖本模块同名全局变量(VpiReader.SHA1_LEN=16 被 Phase1.SHA1_LEN=17 覆盖)。 + # 本模块 CDefine 已在步骤1(_define_constants)解析; + # 跨模块 CDefine 通过 _RegisterFromImportAliases 显式导入注册到 _define_constants。 + if VarName not in define_constants: + try: + sym_info: Any = self.Trans.SymbolTable.lookup(VarName) + if _is_cd_key and sym_info and sym_info.IsDefine: + print(f"[CD] lookup: '{VarName}' skipped in SymbolTable (CDefine not cross-module)", file=_sys.stderr, flush=True) + except Exception as _e: + if _config_mode == "strict": + self.Trans.LogWarning(f"异常被忽略: {_e}") + # 治本修复:如果符号表也没有,回退查询 _all_define_constants + # _all_define_constants 由 Phase2Translator 从所有 .pyi 文件预提取, + # 包含跨模块导入的 CDefine 常量(如 FOREGROUND_GREEN、STD_OUTPUT_HANDLE) + if VarName not in define_constants and VarName not in Gen.variables and not (hasattr(Gen, 'module') and VarName in Gen.module.globals): + all_dc: dict[str, Any] = getattr(Gen, '_all_define_constants', None) or getattr(self.Trans, '_all_define_constants', None) or {} + if VarName in all_dc: + val: Any = all_dc[VarName] + if _is_cd_key: + print(f"[CD] lookup: '{VarName}' found in _all_define_constants val={val}", file=_sys.stderr, flush=True) + if isinstance(val, int): + if VarType is not None and isinstance(VarType, ir.IntType): + return ir.Constant(VarType, val & ((1 << VarType.width) - 1)) + if val < -(1 << 31) or val > 0xFFFFFFFF: + return ir.Constant(ir.IntType(64), val & 0xFFFFFFFFFFFFFFFF) + return ir.Constant(ir.IntType(32), val & 0xFFFFFFFF) + elif isinstance(val, float): + return ir.Constant(ir.DoubleType(), val) + elif isinstance(val, str): + return Gen._create_string_global(val) + elif _is_cd_key: + print(f"[CD] lookup: '{VarName}' NOT found in ANY CDefine table", file=_sys.stderr, flush=True) + # 优先检查 variables(alloca),因为变量可能已被 += 等操作迁移到 variables + if VarName in Gen.variables and Gen.variables[VarName] is not None: + VarPtr: Any = Gen.variables[VarName] + if isinstance(VarPtr, ir.GlobalVariable) and isinstance(VarPtr.type, ir.PointerType) and isinstance(VarPtr.type.pointee, (ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)): + if VarName in Gen.global_struct_class: + Gen.var_struct_class[VarName] = Gen.global_struct_class[VarName] + return VarPtr + if isinstance(VarPtr.type, ir.PointerType) and isinstance(VarPtr.type.pointee, (ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)): + if VarName in Gen.global_struct_class: + Gen.var_struct_class[VarName] = Gen.global_struct_class[VarName] + return VarPtr + # 防御性恢复:对于 double-pointer(如 ndarray**,pointee 是 PointerType) + # 或其他非结构体类型,若 global_struct_class 已记录该变量的类名, + # 也恢复 var_struct_class。这确保方法调用能查找到正确的特化类 + # (如 ndarray[double]),而非 fallback 到 opaque 基础类型。 + if VarName in Gen.global_struct_class and VarName not in Gen.var_struct_class: + Gen.var_struct_class[VarName] = Gen.global_struct_class[VarName] + loaded: ir.Value = Gen._load(VarPtr, name=VarName) + # 大端局部变量:读取时 bswap 还原 + loaded = Gen._apply_bswap_if_big(loaded, getattr(Gen, 'local_var_byteorders', {}).get(VarName, ""), f"bswap_load_{VarName}") + return loaded + if VarName in Gen._reg_values: + return Gen._reg_values[VarName] + if VarName in Gen._direct_values: + return Gen._direct_values[VarName] + if VarName in Gen.global_vars and VarName in Gen.module.globals: + GVar: Any = Gen.module.globals[VarName] + Gen.variables[VarName] = GVar + if isinstance(GVar, ir.Function): + return GVar + if isinstance(GVar.type, ir.PointerType) and isinstance(GVar.type.pointee, (ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)): + return GVar + return Gen._load(GVar, name=VarName) + if VarName in Gen.module.globals: + GVar = Gen.module.globals[VarName] + Gen.variables[VarName] = GVar + if isinstance(GVar, ir.Function): + return GVar + if VarName in Gen.global_struct_class: + Gen.var_struct_class[VarName] = Gen.global_struct_class[VarName] + if isinstance(GVar.type, ir.PointerType) and isinstance(GVar.type.pointee, (ir.IdentifiedStructType, ir.LiteralStructType, ir.ArrayType)): + return GVar + return Gen._load(GVar, name=VarName) + if VarName == 'self': + # 治本修复:方法名为 _get_var_ptr(小写),原 GetVarPtr 不存在会抛 AttributeError。 + # 当 self 未注册到 variables 时(如 opaque struct 参数走了 else 分支), + # 通过 _get_var_ptr 兜底返回 None,由调用方处理。 + SelfPtr: ir.Value | None = Gen._get_var_ptr('self') + if SelfPtr is not None: + return SelfPtr + # 最终兜底:若 _get_var_ptr 返回 None(self 既不在 _reg_values 也不在 variables), + # 直接返回函数参数本身(LLVM Argument)。这避免了 AttributeError 导致的异常路径。 + for arg in getattr(Gen.func, 'args', []): + if getattr(arg, 'name', None) == 'self': + return arg + return ir.Constant(ir.IntType(32), 0) + if Gen._has_function(VarName): + func: Any = Gen._get_function(VarName) + if func: + return Gen.builder.bitcast(func, ir.IntType(8).as_pointer(), name=f"funcptr_{VarName}") + if VarName in Gen.class_methods: + return ir.Constant(ir.IntType(8).as_pointer(), None) + if VarName == 'True' or VarName == 'False': + return ir.Constant(ir.IntType(32), 1 if VarName == 'True' else 0) + SymInfo: Any = self.Trans.SymbolTable.lookup(VarName) + if SymInfo: + if SymInfo.IsEnumMember and isinstance(SymInfo.value, int): + return ir.Constant(ir.IntType(32), SymInfo.value) + if SymInfo.IsFunction or SymInfo.IsFuncPtr: + MangledName: str = Gen._mangle_func_name(VarName) + if MangledName in Gen.module.globals: + g: Any = Gen.module.globals[MangledName] + if isinstance(g, ir.Function): + Gen.functions[VarName] = g + return Gen.builder.bitcast(g, ir.IntType(8).as_pointer(), name=f"funcptr_{VarName}") + for sha1 in Gen.ModuleSha1Map.values(): + prefixed: str = f"{sha1}.{VarName}" + if prefixed in Gen.module.globals: + g = Gen.module.globals[prefixed] + if isinstance(g, ir.Function): + Gen.functions[VarName] = g + return Gen.builder.bitcast(g, ir.IntType(8).as_pointer(), name=f"funcptr_{VarName}") + t_c_imported: dict[str, tuple[str, str]] = getattr(self.Trans, '_t_c_imported_names', {}) + if VarName in t_c_imported: + src_module: str + src_name: str + src_module, src_name = t_c_imported[VarName] + virtual_attr: ast.Attribute = ast.Attribute( + value=ast.Name(id=src_module, ctx=ast.Load()), + attr=src_name, + ctx=ast.Load() + ) + ast.copy_location(virtual_attr, Node) + return self.Trans.ExprAttrHandle._HandleAttributeLlvm(virtual_attr) return ir.Constant(ir.IntType(32), 0) \ No newline at end of file diff --git a/lib/core/Handles/HandlesExprAsm.py b/lib/core/Handles/HandlesExprAsm.py index cacb44d..03d19e9 100644 --- a/lib/core/Handles/HandlesExprAsm.py +++ b/lib/core/Handles/HandlesExprAsm.py @@ -281,6 +281,11 @@ class ExprAsmHandle(BaseHandle): def _mangle_asm_calls(self, template: str) -> str: Gen: LlvmCodeGenerator = self.Trans.LlvmGen sha1: str = getattr(Gen, 'module_sha1', '') + # DDEBUG: 检测 module_sha1 是否带尾随点(双点 bug 根因拦截) + if sha1 and sha1.endswith('.'): + import sys as _dbg_sys + print(f"[DDEBUG_ASM] module_sha1 带尾随点: sha1='{sha1}' len={len(sha1)} template='{template[:80]}'", file=_dbg_sys.stderr) + _dbg_sys.exit(1) if not sha1: return template @@ -290,13 +295,18 @@ class ExprAsmHandle(BaseHandle): if func_name.lower() in self._X86_REGISTERS: return m.group(0) mangled: str = Gen._mangle_func_name(func_name) + # DDEBUG: 检测 mangled 是否含双点(双点 bug 根因拦截) + if '..' in mangled: + import sys as _dbg_sys + print(f"[DDEBUG_ASM] mangled 含双点: func='{func_name}' mangled='{mangled}' sha1='{sha1}'", file=_dbg_sys.stderr) + _dbg_sys.exit(1) if '.' in mangled: return f'{prefix}\\22{mangled}\\22' return f"{prefix}{mangled}" return re.sub(r'(call\s+)(\w+)', replace_call, template) - def _HandleAsmWithOpLlvm(self, asm_template_arg: ast.AST, op_arg: ast.AST | None = None, input_arg: ast.AST | None = None, output_arg: ast.AST | None = None, asm_format: str = 'Intel') -> ir.Value: + def _HandleAsmWithOpLlvm(self, asm_template_arg: ast.AST, op_arg: ast.AST | None = None, input_arg: ast.AST | None = None, output_arg: ast.AST | None = None, asm_format: str = 'Intel') -> ir.Value: Gen: LlvmCodeGenerator = self.Trans.LlvmGen input_ops: list[Any] = [] diff --git a/lib/core/Handles/HandlesExprCall.py b/lib/core/Handles/HandlesExprCall.py index e02fbc3..79dd27b 100644 --- a/lib/core/Handles/HandlesExprCall.py +++ b/lib/core/Handles/HandlesExprCall.py @@ -1873,6 +1873,15 @@ class ExprCallHandle(BaseHandle): def _HandleClosureCallLlvm(self, Node: ast.Call, FuncName: str) -> ir.Value: Gen = self.Trans.LlvmGen func = Gen.functions.get(FuncName) + # DDEBUG: 检测 func.name 含双点(说明 ir.Function 已被错误注册为双点名字) + if func is not None and '..' in getattr(func, 'name', ''): + import sys + sys.stderr.write(f"[DDEBUG] _HandleClosureCallLlvm DOUBLE-DOT func.name='{func.name}' FuncName='{FuncName}'\n") + sys.stderr.write(f"[DDEBUG] Gen.functions keys for '{FuncName}': {[k for k in list(Gen.functions.keys()) if '6ddf' in k or k == FuncName][:20]}\n") + import traceback + traceback.print_stack(file=sys.stderr, limit=10) + sys.stderr.flush() + sys.exit(1) if not func: if FuncName in self.Trans.FunctionDefCache: FuncDef = self.Trans.FunctionDefCache[FuncName] diff --git a/lib/core/Handles/HandlesIf.py b/lib/core/Handles/HandlesIf.py index 2fd361a..f3f577e 100644 --- a/lib/core/Handles/HandlesIf.py +++ b/lib/core/Handles/HandlesIf.py @@ -82,6 +82,16 @@ class IfHandle(BaseHandle): Gen: "Translator.LlvmGen" = self.Trans.LlvmGen if hasattr(Gen, '_define_constants') and name in Gen._define_constants: val: int | float | None = Gen._define_constants[name] + # 治本修复:本模块全局变量初始化值优先,避免跨模块同名 CDefine 覆盖 + try: + if hasattr(Gen, 'module') and name in Gen.module.globals: + _gv: Any = Gen.module.globals[name] + if getattr(_gv, 'initializer', None) is not None: + _iv: Any = _gv.initializer + if hasattr(_iv, 'constant') and isinstance(_iv.constant, (int, float)): + val = _iv.constant + except Exception: + pass if isinstance(val, (int, float)): return val info: "SymbolTable.SymbolInfo" = self.Trans.SymbolTable.lookup(name) diff --git a/lib/core/Handles/HandlesImports.py b/lib/core/Handles/HandlesImports.py index f295e7a..6679833 100644 --- a/lib/core/Handles/HandlesImports.py +++ b/lib/core/Handles/HandlesImports.py @@ -907,17 +907,21 @@ class ImportHandle(BaseHandle): return if IsCDefine: - # CDefine 宏不生成 LLVM 全局变量,只注册到 SymbolTable - # 引用时会直接替换为立即数 + # CDefine 宏不生成 LLVM 全局变量 + # 治本修复(方案C):裸名只注册到本模块 _define_constants, + # 不再注册到跨模块共享的 SymbolTable,避免同名 CDefine 污染其他模块的全局变量 + # (如 Phase1.SHA1_LEN=17 覆盖 VpiReader.SHA1_LEN=16 导致双点链接错误)。 + # 跨模块导入通过 _RegisterFromImportAliases 查带前缀全名后注册到本模块 _define_constants。 DefineValue = None if Node.value: DefineValue = self._ExtractConstValue(Node.value) - # 注册不带前缀的键名(例如 Z_NO_COMPRESSION) - # 但要先检查:如果符号已经存在且是 typedef,不覆盖它 - existing = self.Trans.SymbolTable.lookup(VarName) - if not (existing and existing.IsTypedef and existing.OriginalType): - self._RegisterCDefineSymbol(VarName, DefineValue, Node.lineno, ModulePath or 'unknown') - # 如果提供了模块名,也注册带模块前缀的键名 + # 仅本模块 CDefine 注册到 _define_constants(供 _HandleNameLlvm 步骤1 查找) + if module_name is None and DefineValue is not None: + define_constants = vars(Gen).setdefault('_define_constants', {}) + if VarName not in define_constants: + define_constants[VarName] = DefineValue + # 如果提供了模块名,注册带模块前缀的全名到 SymbolTable + # (供 _RegisterFromImportAliases 的 from X import Y 显式导入查找) if module_name: FullName = f"{module_name}.{VarName}" existing_full = self.Trans.SymbolTable.lookup(FullName) diff --git a/lib/core/Handles/HandlesWhile.py b/lib/core/Handles/HandlesWhile.py index b7b4eb4..4c00686 100644 --- a/lib/core/Handles/HandlesWhile.py +++ b/lib/core/Handles/HandlesWhile.py @@ -1,54 +1,53 @@ -from __future__ import annotations -from typing import TYPE_CHECKING -if TYPE_CHECKING: - from lib.core.translator import Translator -from lib.core.Handles.HandlesBase import BaseHandle -import llvmlite.ir as ir - - -class WhileHandle(BaseHandle): - def _HandleWhileLlvm(self, Node: ast.While) -> None: - Gen: "Translator.LlvmGen" = self.Trans.LlvmGen - if Gen._direct_values: - for var_name in list(Gen._direct_values.keys()): - OldVal: ir.Value = Gen._direct_values.pop(var_name) - if var_name not in Gen.variables or Gen.variables.get(var_name) is None: - saved_block: ir.Block = Gen.builder.block - entry_block: ir.Block = Gen.func.entry_basic_block - Gen.builder.position_at_start(entry_block) - var: ir.AllocaInstr = Gen.builder.alloca(OldVal.type, name=var_name) - Gen._store(OldVal, var) - Gen.builder.position_at_end(saved_block) - Gen.variables[var_name] = var - CondBB: ir.Block = Gen.func.append_basic_block(name="while.cond") - BodyBB: ir.Block = Gen.func.append_basic_block(name="while.body") - ElseBB: ir.Block | None = Gen.func.append_basic_block(name="while.else") if Node.orelse else None - AfterBB: ir.Block = Gen.func.append_basic_block(name="while.end") - Gen.loop_break_targets.append(AfterBB) - Gen.loop_continue_targets.append(CondBB) - Gen.builder.branch(CondBB) - Gen.builder.position_at_start(CondBB) - Cond: ir.Value | None = self.HandleExprLlvm(Node.test) - if Cond: - if not isinstance(Cond.type, ir.IntType) or Cond.type.width != 1: - if isinstance(Cond.type, (ir.FloatType, ir.DoubleType)): - Cond = Gen.builder.fcmp_ordered('!=', Cond, ir.Constant(Cond.type, 0.0), name="whilecond") - else: - Cond = Gen.builder.icmp_signed('!=', Cond, Gen._ZeroConst(Cond.type), name="whilecond") - if not Gen.builder.block.is_terminated: - Gen.builder.cbranch(Cond, BodyBB, ElseBB if ElseBB else AfterBB) - else: - if not Gen.builder.block.is_terminated: - Gen.builder.branch(ElseBB if ElseBB else AfterBB) - Gen.builder.position_at_start(BodyBB) - self.HandleBodyLlvm(Node.body) - if not Gen.builder.block.is_terminated: - Gen.builder.branch(CondBB) - Gen.loop_break_targets.pop() - Gen.loop_continue_targets.pop() - if ElseBB: - Gen.builder.position_at_start(ElseBB) - self.HandleBodyLlvm(Node.orelse) - if not Gen.builder.block.is_terminated: - Gen.builder.branch(AfterBB) +from __future__ import annotations +from typing import TYPE_CHECKING +if TYPE_CHECKING: + from lib.core.translator import Translator +from lib.core.Handles.HandlesBase import BaseHandle +import llvmlite.ir as ir + + +class WhileHandle(BaseHandle): + def _HandleWhileLlvm(self, Node: ast.While) -> None: + Gen: "Translator.LlvmGen" = self.Trans.LlvmGen + if Gen._direct_values: + for var_name in list(Gen._direct_values.keys()): + OldVal: ir.Value = Gen._direct_values.pop(var_name) + if var_name not in Gen.variables or Gen.variables.get(var_name) is None: + # 用 _allocaEntry 在入口块开头插入 alloca,然后在当前 builder + # 位置生成 store。避免 position_at_start 导致 store 插入到 + # 入口块开头(可能在 va_list_ptr 等 bitcast 定义之前,违反支配性)。 + var: ir.AllocaInstr = Gen._allocaEntry(OldVal.type, name=var_name) + Gen._store(OldVal, var) + Gen.variables[var_name] = var + CondBB: ir.Block = Gen.func.append_basic_block(name="while.cond") + BodyBB: ir.Block = Gen.func.append_basic_block(name="while.body") + ElseBB: ir.Block | None = Gen.func.append_basic_block(name="while.else") if Node.orelse else None + AfterBB: ir.Block = Gen.func.append_basic_block(name="while.end") + Gen.loop_break_targets.append(AfterBB) + Gen.loop_continue_targets.append(CondBB) + Gen.builder.branch(CondBB) + Gen.builder.position_at_start(CondBB) + Cond: ir.Value | None = self.HandleExprLlvm(Node.test) + if Cond: + if not isinstance(Cond.type, ir.IntType) or Cond.type.width != 1: + if isinstance(Cond.type, (ir.FloatType, ir.DoubleType)): + Cond = Gen.builder.fcmp_ordered('!=', Cond, ir.Constant(Cond.type, 0.0), name="whilecond") + else: + Cond = Gen.builder.icmp_signed('!=', Cond, Gen._ZeroConst(Cond.type), name="whilecond") + if not Gen.builder.block.is_terminated: + Gen.builder.cbranch(Cond, BodyBB, ElseBB if ElseBB else AfterBB) + else: + if not Gen.builder.block.is_terminated: + Gen.builder.branch(ElseBB if ElseBB else AfterBB) + Gen.builder.position_at_start(BodyBB) + self.HandleBodyLlvm(Node.body) + if not Gen.builder.block.is_terminated: + Gen.builder.branch(CondBB) + Gen.loop_break_targets.pop() + Gen.loop_continue_targets.pop() + if ElseBB: + Gen.builder.position_at_start(ElseBB) + self.HandleBodyLlvm(Node.orelse) + if not Gen.builder.block.is_terminated: + Gen.builder.branch(AfterBB) Gen.builder.position_at_start(AfterBB) \ No newline at end of file diff --git a/lib/core/LLVMCG/BaseGen.py b/lib/core/LLVMCG/BaseGen.py index 37759b5..f409a91 100644 --- a/lib/core/LLVMCG/BaseGen.py +++ b/lib/core/LLVMCG/BaseGen.py @@ -595,6 +595,14 @@ class BaseGenMixin: return self._find_function(name) is not None def _get_or_declare_function(self, mangled_name: str, func_type: ir.FunctionType) -> ir.Function: + # DDEBUG: 检测 mangled_name 含双点(不应到达这里) + if '..' in mangled_name: + import sys + sys.stderr.write(f"[DDEBUG] _get_or_declare_function DOUBLE-DOT mangled_name='{mangled_name}'\n") + import traceback + traceback.print_stack(file=sys.stderr, limit=10) + sys.stderr.flush() + sys.exit(1) g = self.module.globals.get(mangled_name) if g and isinstance(g, ir.Function): return g @@ -605,6 +613,14 @@ class BaseGenMixin: return func def _mangle_func_name(self, name: str, module_name: str | None = None) -> str: + # DDEBUG: 检测即将产生双点的情况,立即打印并终止 + if name.startswith('.') or (module_name and module_name.endswith('.') and len(module_name) > 0): + import sys + sys.stderr.write(f"[DDEBUG] _mangle_func_name LEADING-DOT name='{name}' module_name='{module_name}'\n") + import traceback + traceback.print_stack(file=sys.stderr, limit=8) + sys.stderr.flush() + sys.exit(1) if name in self._export_funcs and not module_name: return name if name in self._export_extern_funcs: @@ -659,8 +675,18 @@ class BaseGenMixin: if self._skip_mangle(name): return name if self.module_sha1: - return f"{self.module_sha1}.{name}" - return name + result = f"{self.module_sha1}.{name}" + else: + result = name + # DDEBUG: 检测返回结果中是否含双点 + if '..' in result: + import sys + sys.stderr.write(f"[DDEBUG] _mangle_func_name RESULT-DOUBLE-DOT name='{name}' module_name='{module_name}' result='{result}'\n") + import traceback + traceback.print_stack(file=sys.stderr, limit=10) + sys.stderr.flush() + sys.exit(1) + return result def _get_source_line(self, lineno: int) -> str | None: if 0 < lineno <= len(self._current_source_lines): diff --git a/run_err.txt b/run_err.txt new file mode 100644 index 0000000..e69de29 diff --git a/run_out.txt b/run_out.txt new file mode 100644 index 0000000..77651ec --- /dev/null +++ b/run_out.txt @@ -0,0 +1,478 @@ +===== TransPyV Test Suite ===== + +asm: nop ok +asm: nop2 ok +asm: multi-clobber ok +asm: input ok val=42 +asm: output result=123 +asm: in+out result2=11 (expect 11) +=== attr_test: c.Attribute 装饰器测试 === + +--- Test 1: c.Attribute(always_inline) --- +AlwaysInlineFunc(21)=42 (expect 42) +AlwaysInlineFunc OK +--- Test 2: c.Attribute(noinline) --- +NoInlineFunc(5)=105 (expect 105) +NoInlineFunc OK +--- Test 3: c.Attribute(noreturn) --- +NoReturnFunc declared with noreturn attr +NoReturnFunc OK (not called to avoid UB) +--- Test 4: normal function (no attr) --- +NormalFunc(7)=21 (expect 21) +NormalFunc OK +--- Test 5: c.Attribute(always_inline, pure) --- +MultiAttrFunc(10)=11 (expect 11) +MultiAttrFunc OK +--- Test 6: c.Attribute(packed) --- +PackedAttrFunc(10)=9 (expect 9) +PackedAttrFunc OK +--- Test 7: c.Attribute(llvm.nounwind) --- +NoUnwindFunc(10)=11 (expect 11) +NoUnwindFunc OK +--- Test 8: c.Attribute(llvm.noredzone) --- +NoRedZoneFunc(10)=12 (expect 12) +NoRedZoneFunc OK +--- Test 9: c.Attribute(llvm.willreturn) --- +WillReturnFunc(10)=13 (expect 13) +WillReturnFunc OK +--- Test 10: c.Attribute(llvm.mustprogress) --- +MustProgressFunc(10)=14 (expect 14) +MustProgressFunc OK +--- Test 11: c.Attribute(const) --- +ConstFunc(99)=42 (expect 42) +ConstFunc OK +--- Test 12: c.Attribute(always_inline, nounwind, noredzone) --- +TripleAttrFunc(10)=15 (expect 15) +TripleAttrFunc OK + +=== attr_test 完成 === +local +=: 15 +local -=: 12 +local *=: 24 +local /=: 6 +local %=: 6 +global +=: 1 +global +=: 11 +global -=: 8 +bit &=: 15 +bit |=: 63 +bit ^=: 192 +bit <<=: 16 +bit >>=: 4 +global: 9 +global: 10 +global: 11 +closure: 1 +closure: 1 +closure: 1 +=== deco_test: t/c 装饰器测试 === + +--- Test 1: t.CDefine --- +MAX_VALUE=256 (expect 256) +PI_APPROX=314 (expect 314) +MAX_VALUE OK +PI_APPROX OK +--- Test 2: t.CExport --- +ExportedAdd(3,4)=7 (expect 7) +ExportedAdd OK +--- Test 3: t.CInline --- +InlineSquare(5)=25 (expect 25) +InlineSquare OK +--- Test 4: normal function --- +NormalSub(10,3)=7 (expect 7) +NormalSub OK +--- Test 5: t.CExport | t.CInline --- +ExportedInlineCube(3)=27 (expect 27) +ExportedInlineCube OK +--- Test 6: t.CExport return ptr --- +ExportedFindChar found, char=108 (expect 108) +ExportedFindChar OK +--- Test 7: t.CExtern | t.CExport --- +ExternalDecl declared (not called) +ExternalDecl OK +--- Test 8: t.State --- +StateDecl declared (not called) +StateDecl OK +--- Test 9: t.State (void) --- +StateVoidDecl declared (not called) +StateVoidDecl OK +--- Test 10: t.CArray[elem, CDefine] --- +ARR_SIZE=8 (expect 8) +arr sum=280 (expect 280) +arr[0]=0 (expect 0) +arr[7]=70 (expect 70) +CArray CDefine count OK + +=== deco_test 完成 === +deref: 104 +ptr: len(hello)=5 +=== eq_test: ==、!=、is、None 比较测试 === + +--- Test 1: int == / != --- +int == int (same) OK +int != int (diff) OK +not (int == diff) OK +--- Test 2: int < > <= >= --- +int < OK +int > OK +int <= OK +int >= OK +--- Test 3: ptr is None / is not None --- +strchr found, is not None OK +strchr not found, is None OK +--- Test 4: assign None and compare --- +None assign, is None OK +None assign, is not None OK +--- Test 5: ptr == None / != None --- +strstr found, != None OK +strstr not found, == None OK +--- Test 6: bool and/or --- +1 and 0 = false OK +1 or 0 = true OK +not 0 = true OK + +=== eq_test 完成 === +float: f=3.140000 +double: d=3.141593 +float: f=2.500000 +union: u.f=3.140000 +union: u.i=42 (after f overwritten) +union: float overwrites int verified +arith: 1.50 + 2.50 = 4.00 +arith: 1.50 - 2.50 = -1.00 +arith: 1.50 * 2.50 = 3.75 +arith: 1.50 / 2.50 = 0.60 +arith: 10.0000 + 3.0000 = 13.0000 +arith: 10.0000 - 3.0000 = 7.0000 +arith: 10.0000 * 3.0000 = 30.0000 +arith: 10.0000 / 3.0000 = 3.3333 +arith: 10.0 % 3.0 = 1.0000 +arith: 3 + 1.50 = 4.50 +while: total=10 i=5 +break: k=0 +break: k=1 +break: k=2 +continue: m=0 +continue: m=1 +continue: m=3 +continue: m=4 +for: j=0 +for: j=1 +for: j=2 +for: j=3 +for: j=4 +add(3,4)=7 +mul(5,6)=30 +square(7)=49 +factorial(5)=120 +add(b=4,a=3)=7 +sub(b=3,a=10)=7 +Hello, World! +Hello, World! +greet mixed: returned=2 +Hi, TransPyC! +greet kwargs: returned=1 +=== llvmir_test: c.LLVMIR 内联 LLVM IR 测试 === + +--- Test 1: LLVMIR add --- +add(10, 20)=30 (expect 30) +LLVMIR add OK +--- Test 2: LLVMIR sub --- +sub(50, 20)=30 (expect 30) +LLVMIR sub OK +--- Test 3: LLVMIR mul --- +mul(6, 7)=42 (expect 42) +LLVMIR mul OK +--- Test 4: LLVMIR sdiv --- +sdiv(100, 4)=25 (expect 25) +LLVMIR sdiv OK +--- Test 5: LLVMIR and --- +and(255, 15)=15 (expect 15) +LLVMIR and OK +--- Test 6: LLVMIR or --- +or(240, 15)=255 (expect 255) +LLVMIR or OK +--- Test 7: LLVMIR xor --- +xor(255, 15)=240 (expect 240) +LLVMIR xor OK +--- Test 8: LLVMIR shl --- +shl(1, 4)=16 (expect 16) +LLVMIR shl OK +--- Test 9: LLVMIR LOut --- +LOut add(10, 20)=30 (expect 30) +LLVMIR LOut OK +--- Test 10: LLVMIR icmp eq --- +icmp eq(5, 5)=-1 (expect nonzero) +LLVMIR icmp eq OK +--- Test 11: LLVMIR icmp ne --- +icmp ne(5, 3)=-1 (expect nonzero) +LLVMIR icmp ne OK +--- Test 12: LLVMIR icmp slt --- +icmp slt(3, 5)=-1 (expect nonzero) +LLVMIR icmp slt OK +--- Test 13: LLVMIR srem --- +srem(17, 5)=2 (expect 2) +LLVMIR srem OK +--- Test 14: LLVMIR lshr --- +lshr(256, 2)=64 (expect 64) +LLVMIR lshr OK +--- Test 15: LLVMIR nested in expression --- +(LLVMIR add(10,20)) + 10 = 40 (expect 40) +LLVMIR nested OK + +=== llvmir_test 完成 === +oop: === Test 1: Basic Methods === +oop: p.x=10 p.y=20 +oop: after move p.x=100 p.y=200 +oop: === Test 2: Defaults + Methods === +oop: initial count=0 step=1 +oop: after 3 increments: 1 2 3 +oop: after reset+increment: 1 +oop: === Test 3: __init__ === +oop: rect 3x4 area=12 +oop: === All OOP Tests Passed === +ptr: len(hello)=5 +ptr: after DerefAs x=88 +ptr: sum(A,B,C)=198 +if: x is truthy +if: 1==1 is truthy +while: total=10 i=5 +for: j=0 +for: j=1 +for: j=2 +for: j=3 +for: j=4 +break: k=0 +break: k=1 +break: k=2 +continue: m=0 +continue: m=1 +continue: m=3 +continue: m=4 +bool: x>5 and x<100 is true +bool: x>100 or x>5 is true +ptr: len(hello)=5 +ptr: after DerefAs v=88 +ptr: sum(A,B,C)=198 +ptr: c.Load v2=42 (expected 42) +ptr: c.Load overwrite v3=200 (expected 200) +ptr: c.Load src unchanged v5=999 v6=999 (expected 999, 999) +hello +strlen(Hello)=5 +=== string_test: string.py 库函数测试 === + +--- Test 1: strlen --- +strlen(Hello)=5 (expect 5) +strlen()=0 (expect 0) +strlen(Hello, World!)=13 (expect 13) +--- Test 2: strcmp --- +strcmp(abc,abc)=0 (expect 0) +strcmp(abc,abd)=-1 (expect <0) +strcmp(abd,abc)=1 (expect >0) +--- Test 3: strncmp --- +strncmp(abcdef,abcXYZ,3)=0 (expect 0) +strncmp(abcdef,abcXYZ,4)=12 (expect <0) +--- Test 4: atoi --- +atoi(123)=123 (expect 123) +atoi(-456)=-456 (expect -456) +atoi( 789)=789 (expect 789) +--- Test 5: strchr --- +strchr(Hello,'l') found, char=108 (expect 108) +strchr(Hello,'z') not found OK +--- Test 6: strstr --- +strstr(Hello,World) found OK +strstr(Hello,xyz) not found OK + +=== string_test 完成 === +struct: p.x=10 p.y=20 +struct: modified p.x=100 p.y=200 +struct: sum=300 +struct: volume=60 +array: total=1500 +array: arr[2]=999 +ptr: len(hello)=5 +ptr: sum(A,B,C)=198 +ctor: z.x=0 z.y=0 +ctor: p3.x=7 p3.y=8 +ctor: bx.w=10 bx.h=20 bx.d=30 +kw: p4.x=10 p4.y=20 +kw: p5.x=5 p5.y=15 +kw: bx2.w=10 bx2.h=20 bx2.d=30 +def: sz.w=100 sz.h=200 +def: sz2.w=5 sz2.h=6 +def: sz3.w=888 sz3.h=999 +def: sz4.w=7 sz4.h=200 +enum: Idle=0 Run=1 Stop=2 +enum: Red=10 Green=11 Blue=20 Yellow=21 +enum: Small=0 Big=1 Medium=2 +enum: sum(Idle,Run,Stop)=3 +enum: Idle==0 true +enum: Red==10 true +enum: Run!=Stop true +union: u.i=42 +union: u.l=20015998343868 +union: shared memory verified +type: CInt=100 CInt32T=200 CUInt32T=300 +type: CLong=1000 CLongLong=2000 CInt64T=3000 CSizeT=4000 +bit: 240&15=0 +bit: 240|15=255 +bit: 240^15=255 +bit: 240<<2=960 +bit: 240>>2=60 +bit: 17%5=2 +vtable: === Test Start === +vtable: a.GetName()=42 (expected 42) +vtable: a.Speak()=0 (expected 0) +vtable: s.SetSides(4)=0 (expected 0) +vtable: s.GetSides()=4 (expected 4) +vtable: === All Tests Passed === +inherit: === Test 1: Base Class === +inherit: a.GetName()=42 (expected 42) +inherit: a.Speak()=0 (expected 0) +inherit: === Test 2: Dog (override Speak) === +inherit: d.GetName()=100 (expected 100) +inherit: d.Speak()=1 (expected 1) +inherit: d.GetBreed()=7 (expected 7) +inherit: === Test 3: Cat (inherit Speak) === +inherit: ct.GetName()=200 (expected 200) +inherit: ct.Speak()=0 (expected 0) +inherit: ct.GetColor()=3 (expected 3) +inherit: === All Tests Passed === +funcvt: === Test Start === +funcvt: A.VirtualMethod()=15 (expected 15) +funcvt: A.NormalMethod()=25 (expected 25) +funcvt: B.KeptMethod()=37 (expected 37) +funcvt: B.ExcludedMethod()=47 (expected 47) +funcvt: C.VirtualMethod()=59 (expected 59) +funcvt: C.NormalMethod()=69 (expected 69) +funcvt: === All Tests Passed === +vdispatch: === Test Start === +vdispatch: === Test 1: Direct Dispatch === +vdispatch: a.Speak()=0 (expected 0) +vdispatch: d.Speak()=1 (expected 1) +vdispatch: === Test 2: Virtual Dispatch === +vdispatch: a.Speak()=1 (expected 1 after vtable copy) +vdispatch: === Test 3: GetName After VTable Copy === +vdispatch: a.GetName()=42 (expected 42) +vdispatch: === All Tests Passed === +new: === Test Start === +new: === Test 1: __new__ returns self === +new: WithNew.__new__ called +new: WithNew.__init__ called +new: w.GetValue()=42 (expected 42) +new: === Test 2: __new__ no extra args === +new: WithNewNoArgs.__new__ called +new: n.GetValue()=99 (expected 99) +new: === Test 3: __new__ + vtable === +new: WithNewVTable.__new__ called +new: vt.GetValue()=10 (expected 10) +new: vt.Speak()=11 (expected 11) +new: === All Tests Passed === +nsisol: === Test Start === +nsisol: === Test 1: from-import bare constructor === +nsisol: w.GetId()=42 (expected 42) +nsisol: w.Render()=100 (expected 100) +nsisol: g.Render()=200 (expected 200) +nsisol: g.GetExtra()=9 (expected 9) +nsisol: === Test 2: module-qualified constructor === +nsisol: ps.Sum()=30 (expected 30) +nsisol: ps2.Sum()=11 (expected 11) +nsisol: === Test 3: type annotation with imported class === +nsisol: annot_w.GetId()=99 (expected 99) +nsisol: === Test 4: cross-module inheritance vtable === +nsisol: base.Render()=100 (expected 100) +nsisol: derived.Render()=200 (expected 200) +nsisol: derived.GetId()=2 (expected 2) +nsisol: === All Tests Passed === +=== testcheck_test === + +--- Arithmetic --- +PASS: 3+4=7 +PASS: 10-3=7 +PASS: 6*7=42 +--- String --- +PASS: strlen(hello)=5 +PASS: strcmp(abc,abc)=0 +--- Module Import --- +testcheck module imported and called successfully +PASS: import testcheck works + +--- Summary --- +PASS: 6, FAIL: 0 +=== Operator Overload Tests === + +--- Counter __add__ --- +PASS: cnt(10)+5=15 +--- Counter __sub__/__mul__/__div__/__mod__ --- +PASS: cnt-3=7 +PASS: cnt*3=30 +PASS: cnt/3=3 +PASS: cnt%3=1 +--- Counter compare overloads --- +PASS: cnt==10:1 +PASS: cnt!=10:0 +PASS: cnt<20:1 +PASS: cnt<=10:1 +PASS: cnt>5:1 +PASS: cnt>=10:1 +--- BitBox bitwise overloads --- +PASS: bb&0x0F=15 +PASS: bb|0x100=511 +PASS: bb^0x55=170 +PASS: bb<<4=4080 +PASS: bb>>4=15 +--- Native int binop --- +PASS: 7+8=15 +PASS: 10-3=7 +PASS: 4*5=20 +--- Native int compare --- +PASS: 3<5 +PASS: 10==10 +--- Vec2 struct overloads --- +PASS: a+b x=4 +PASS: a+b y=6 +PASS: a-b x=2 +PASS: a-b y=2 +--- Vec2 compare overloads --- +PASS: (5,5)==(5,5):1 +PASS: (5,5)!=(5,5):0 + +--- Summary --- +PASS: 27, FAIL: 0 +circ: === Test Start === +circ: === Test 1: A.MakeB() === +circ: a.GetValue()=10 (expected 10) +circ: b.GetValue()=10 (expected 10) +circ: === Test 2: B.MakeA() === +circ: a2.GetValue()=10 (expected 10) +circ: === Test 3: value chain A(20)->B->A === +circ: final=20 (expected 20) +circ: === All Tests Passed === +=== nested_match_test: 嵌套 match REnum 检测测试 === + +[DBG] _init_mbuddy: start +[DBG] _init_mbuddy: malloc arena=0 +[DBG] _init_mbuddy: malloc mb=0 +[DBG] _init_mbuddy: before_init +[DBG] _init_mbuddy: init +[DBG] _init_mbuddy: store +[DBG] _init_mbuddy: done +--- Test 1: 单层 match LLVMType --- +[DBG] Int32 done: 0 +Int(-693633024) OK +bits==-693633024 FAIL +--- Test 2: 嵌套 match(case 块内 match 另一值)--- +outer Int(-688782832), inner Int(0) OK +values FAIL +--- Test 3: 嵌套 match pointee --- +--- Test 4: 3 层嵌套 match --- +--- Test 5: if 块内嵌套 match --- +Float(-688782320) + Double(0) OK +float values FAIL +--- Test 6: 嵌套 match 不同变体(default 分支)--- +outer Int(-688782192), inner Float(0) OK +mismatch values FAIL + +=== nested_match_test: SOME FAIL === + +===== Test Suite Complete ===== diff --git a/run_output.txt b/run_output.txt new file mode 100644 index 0000000..b898f7f --- /dev/null +++ b/run_output.txt @@ -0,0 +1 @@ +===== Test Suite Complete =====