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 =====