refactor(tpv): 新语法 R10 单语句块并一行(7722 处 if/for/while 单语句体)

This commit is contained in:
TermiNexus committed 2026-10-05 03:10:55 +08:00
1 parent f923dc4d8d
commit 4a685d478f
69 files changed
+7723 -15445

No files matched your search

+95 -190
View File
@@ -26,20 +26,17 @@ def _eval_binop_valid(node: ast.AST*) -> int:
k: int = node.kind()
if k == ast.ASTKind.Constant:
cn: ast.Constant* = ast.Constant*(node)
if cn.const_kind == ast.CONST_INT:
return 1
if cn.const_kind == ast.CONST_INT: return 1
return 0
if k == ast.ASTKind.UnaryOp:
uop: ast.UnaryOp* = ast.UnaryOp*(node)
if uop.operand is not None:
return _eval_binop_valid(uop.operand)
if uop.operand is not None: return _eval_binop_valid(uop.operand)
return 0
if k == ast.ASTKind.BinOp:
bop: ast.BinOp* = ast.BinOp*(node)
if bop.left is not None and bop.right is not None:
if _eval_binop_valid(bop.left) != 0:
if _eval_binop_valid(bop.right) != 0:
return 1
if _eval_binop_valid(bop.right) != 0: return 1
return 0
if k == ast.ASTKind.Name:
# Name 引用:检查是否是已注册的 CDefine 常量
@@ -47,35 +44,28 @@ def _eval_binop_valid(node: ast.AST*) -> int:
if nm.id is not None:
# 从本地 CDefine 表查找
val: int = _lookup_cdefine_for_pyi(nm.id)
if _pyi_cdefine_found() != 0:
return 1
if _pyi_cdefine_found() != 0: return 1
return 0
return 0
def _eval_binop_int(node: ast.AST*) -> int64:
"""递归计算 BinOp 节点的整数值(64 位,避免大整数 CDefine 截断)"""
if node is None:
return 0
if node is None: return 0
k: int = node.kind()
if k == ast.ASTKind.Constant:
cn: ast.Constant* = ast.Constant*(node)
if cn.const_kind == ast.CONST_INT:
return cn.int_val
if cn.const_kind == ast.CONST_INT: return cn.int_val
return 0
if k == ast.ASTKind.UnaryOp:
uop: ast.UnaryOp* = ast.UnaryOp*(node)
if uop.op == ast.OpKind.USub and uop.operand is not None:
return -_eval_binop_int(uop.operand)
if uop.op == ast.OpKind.UAdd and uop.operand is not None:
return _eval_binop_int(uop.operand)
if uop.op == ast.OpKind.Invert and uop.operand is not None:
return ~_eval_binop_int(uop.operand)
if uop.op == ast.OpKind.USub and uop.operand is not None: return -_eval_binop_int(uop.operand)
if uop.op == ast.OpKind.UAdd and uop.operand is not None: return _eval_binop_int(uop.operand)
if uop.op == ast.OpKind.Invert and uop.operand is not None: return ~_eval_binop_int(uop.operand)
return 0
if k == ast.ASTKind.BinOp:
bop: ast.BinOp* = ast.BinOp*(node)
if bop.left is None or bop.right is None:
return 0
if bop.left is None or bop.right is None: return 0
lv: int64 = _eval_binop_int(bop.left)
rv: int64 = _eval_binop_int(bop.right)
if bop.op == ast.OpKind.BitOr: return lv | rv
@@ -92,8 +82,7 @@ def _eval_binop_int(node: ast.AST*) -> int64:
return 0
if k == ast.ASTKind.Name:
nm: ast.Name* = ast.Name*(node)
if nm.id is not None:
return _lookup_cdefine_for_pyi(nm.id)
if nm.id is not None: return _lookup_cdefine_for_pyi(nm.id)
return 0
return 0
@@ -132,30 +121,23 @@ def _lookup_cdefine_for_pyi(name: str) -> int64:
def _eval_cdefine_value_cache(node: ast.AST*) -> int64:
"""求值 CDefine 值(Constant/UnaryOp/BinOp/Call/Name),供 vpi 预处理注册缓存"""
if node is None:
return 0
if node is None: return 0
k: int = node.kind()
if k == ast.ASTKind.Constant:
cn_c: ast.Constant* = ast.Constant*(node)
if cn_c.const_kind == ast.CONST_INT:
return cn_c.int_val
if cn_c.const_kind == ast.CONST_BOOL:
return cn_c.int_val
if cn_c.const_kind == ast.CONST_INT: return cn_c.int_val
if cn_c.const_kind == ast.CONST_BOOL: return cn_c.int_val
# STR/FLOAT/NONE 不参与整数 BinOp 引用(注册 0 无害)
return 0
if k == ast.ASTKind.UnaryOp:
return _eval_binop_int(node)
if k == ast.ASTKind.BinOp:
return _eval_binop_int(node)
if k == ast.ASTKind.UnaryOp: return _eval_binop_int(node)
if k == ast.ASTKind.BinOp: return _eval_binop_int(node)
if k == ast.ASTKind.Call:
cl_c: ast.Call* = ast.Call*(node)
if cl_c.args is not None and len(cl_c.args) > 0:
return _eval_cdefine_value_cache(cl_c.args.get(0))
if cl_c.args is not None and len(cl_c.args) > 0: return _eval_cdefine_value_cache(cl_c.args.get(0))
return 0
if k == ast.ASTKind.Name:
nm_c: ast.Name* = ast.Name*(node)
if nm_c.id is not None:
return _lookup_cdefine_for_pyi(nm_c.id)
if nm_c.id is not None: return _lookup_cdefine_for_pyi(nm_c.id)
return 0
return 0
@@ -174,16 +156,12 @@ def _pyi_cdefine_found() -> int:
def _PyiEmit(buf: bytes, buf_size: sizet, pos: sizet,
text: str) -> sizet:
"""追加 text 到 buf 的 pos 位置,返回新的 pos"""
if buf is None or text is None or pos >= buf_size:
return pos
if buf is None or text is None or pos >= buf_size: return pos
tlen: sizet = string.strlen(text)
if tlen == 0:
return pos
if tlen == 0: return pos
remain: sizet = buf_size - pos
if tlen >= remain:
tlen = remain - 1
if tlen > 0:
string.memcpy(buf + pos, text, tlen)
if tlen >= remain: tlen = remain - 1
if tlen > 0: string.memcpy(buf + pos, text, tlen)
return pos + tlen
@@ -248,16 +226,14 @@ def _PyiTypeStr(buf: bytes, buf_size: sizet, pos: sizet,
if depth > 64:
VLogger.error("vpi 类型注解递归过深(AST 环或嵌套超过 64 层)", "StubGen")
sys.exit(1)
if annot is None:
return _PyiEmit(buf, buf_size, pos, "int")
if annot is None: return _PyiEmit(buf, buf_size, pos, "int")
k: int = annot.kind()
# Name: 简单类型名 (如 int, str, MyClass)
if k == ast.ASTKind.Name:
nm: ast.Name* = ast.Name*(annot)
if nm.id is not None:
return _PyiEmit(buf, buf_size, pos, nm.id)
if nm.id is not None: return _PyiEmit(buf, buf_size, pos, nm.id)
return _PyiEmit(buf, buf_size, pos, "int")
# Attribute: 属性引用 (如 int, memhub.MemBuddy)
@@ -265,8 +241,7 @@ def _PyiTypeStr(buf: bytes, buf_size: sizet, pos: sizet,
at: ast.Attribute* = ast.Attribute*(annot)
pos = _PyiTypeStr(buf, buf_size, pos, at.value, depth + 1)
pos = _PyiEmit(buf, buf_size, pos, ".")
if at.attr is not None:
pos = _PyiEmit(buf, buf_size, pos, at.attr)
if at.attr is not None: pos = _PyiEmit(buf, buf_size, pos, at.attr)
return pos
# Subscript: 下标类型 (如 list[int], t.CArray[elem, count])
@@ -293,12 +268,9 @@ def _PyiTypeStr(buf: bytes, buf_size: sizet, pos: sizet,
# USub → "-";其余一元运算符两侧都不支持 → fail-fast(不静默写错符号)。
if k == ast.ASTKind.UnaryOp:
uop_t: ast.UnaryOp* = ast.UnaryOp*(annot)
if uop_t.op == ast.OpKind.Not:
pos = _PyiEmit(buf, buf_size, pos, "not ")
elif uop_t.op == ast.OpKind.Invert:
pos = _PyiEmit(buf, buf_size, pos, "~")
elif uop_t.op == ast.OpKind.USub:
pos = _PyiEmit(buf, buf_size, pos, "-")
if uop_t.op == ast.OpKind.Not: pos = _PyiEmit(buf, buf_size, pos, "not ")
elif uop_t.op == ast.OpKind.Invert: pos = _PyiEmit(buf, buf_size, pos, "~")
elif uop_t.op == ast.OpKind.USub: pos = _PyiEmit(buf, buf_size, pos, "-")
else:
GenApi.fatal_error(annot, "vpi 类型注解节点类型未知", "TypeError")
return pos # 不可达(fatal_error 已退出)
@@ -326,8 +298,7 @@ def _PyiTypeStr(buf: bytes, buf_size: sizet, pos: sizet,
else: pos = _PyiEmit(buf, buf_size, pos, " ? ")
# TPC 按 ops 的下标取 comparators[i];此处加长度守卫,
# 畸形 AST(ops/comparators 不等长)不越界。
if cmps_ct is not None and oi_ct < len(cmps_ct):
pos = _PyiTypeStr(buf, buf_size, pos, cmps_ct.get(oi_ct), depth + 1)
if cmps_ct is not None and oi_ct < len(cmps_ct): pos = _PyiTypeStr(buf, buf_size, pos, cmps_ct.get(oi_ct), depth + 1)
oi_ct += 1
return pos
@@ -341,10 +312,8 @@ def _PyiTypeStr(buf: bytes, buf_size: sizet, pos: sizet,
vi_bt: sizet = 0
while vi_bt < vn_bt:
if vi_bt > 0:
if bool_t.op == ast.OpKind.Or:
pos = _PyiEmit(buf, buf_size, pos, " or ")
else:
pos = _PyiEmit(buf, buf_size, pos, " and ")
if bool_t.op == ast.OpKind.Or: pos = _PyiEmit(buf, buf_size, pos, " or ")
else: pos = _PyiEmit(buf, buf_size, pos, " and ")
pos = _PyiTypeStr(buf, buf_size, pos, vals_bt.get(vi_bt), depth + 1)
vi_bt += 1
return pos
@@ -354,12 +323,10 @@ def _PyiTypeStr(buf: bytes, buf_size: sizet, pos: sizet,
cn: ast.Constant* = ast.Constant*(annot)
if cn.const_kind == ast.CONST_STR:
pos = _PyiEmit(buf, buf_size, pos, "'")
if cn.str_val is not None:
pos = _PyiEmit(buf, buf_size, pos, cn.str_val)
if cn.str_val is not None: pos = _PyiEmit(buf, buf_size, pos, cn.str_val)
pos = _PyiEmit(buf, buf_size, pos, "'")
return pos
if cn.const_kind == ast.CONST_NONE:
return _PyiEmit(buf, buf_size, pos, "None")
if cn.const_kind == ast.CONST_NONE: return _PyiEmit(buf, buf_size, pos, "None")
# 数字常量(t.CArray[uint32, 64] 的 count 等):输出数值本身,
# 而不是回退 int——否则 vpi 生成 "t.CArray[..., int]" 在加载
# stub 时触发 TypeError(count 必须是整数常量、None、CDefine 常量名
@@ -385,8 +352,7 @@ def _PyiTypeStr(buf: bytes, buf_size: sizet, pos: sizet,
ln: sizet = len(lst_elts)
li: sizet = 0
while li < ln:
if li > 0:
pos = _PyiEmit(buf, buf_size, pos, ", ")
if li > 0: pos = _PyiEmit(buf, buf_size, pos, ", ")
le: ast.AST* = lst_elts.get(li)
pos = _PyiTypeStr(buf, buf_size, pos, le, depth + 1)
li += 1
@@ -401,8 +367,7 @@ def _PyiTypeStr(buf: bytes, buf_size: sizet, pos: sizet,
tn: sizet = len(tup_elts)
ti: sizet = 0
while ti < tn:
if ti > 0:
pos = _PyiEmit(buf, buf_size, pos, ", ")
if ti > 0: pos = _PyiEmit(buf, buf_size, pos, ", ")
el: ast.AST* = tup_elts.get(ti)
pos = _PyiTypeStr(buf, buf_size, pos, el, depth + 1)
ti += 1
@@ -418,8 +383,7 @@ def _PyiTypeStr(buf: bytes, buf_size: sizet, pos: sizet,
can: sizet = len(cl_args)
cai: sizet = 0
while cai < can:
if cai > 0:
pos = _PyiEmit(buf, buf_size, pos, ", ")
if cai > 0: pos = _PyiEmit(buf, buf_size, pos, ", ")
ca: ast.AST* = cl_args.get(cai)
pos = _PyiTypeStr(buf, buf_size, pos, ca, depth + 1)
cai += 1
@@ -448,8 +412,7 @@ def _PyiDefaultStr(buf: bytes, buf_size: sizet, pos: sizet,
if depth > 64:
VLogger.error("vpi 默认值表达式递归过深(AST 环或嵌套超过 64 层)", "StubGen")
sys.exit(1)
if node is None:
return pos
if node is None: return pos
k: int = node.kind()
# Constant: 数字/字符串/bool/None 直接输出字面量
@@ -464,37 +427,28 @@ def _PyiDefaultStr(buf: bytes, buf_size: sizet, pos: sizet,
return pos
if cn.const_kind == ast.CONST_STR:
pos = _PyiEmit(buf, buf_size, pos, "\"")
if cn.str_val is not None:
pos = _PyiEmit(buf, buf_size, pos, cn.str_val)
if cn.str_val is not None: pos = _PyiEmit(buf, buf_size, pos, cn.str_val)
return _PyiEmit(buf, buf_size, pos, "\"")
if cn.const_kind == ast.CONST_BOOL:
if cn.int_val != 0:
return _PyiEmit(buf, buf_size, pos, "True")
if cn.int_val != 0: return _PyiEmit(buf, buf_size, pos, "True")
return _PyiEmit(buf, buf_size, pos, "False")
if cn.const_kind == ast.CONST_NONE:
return _PyiEmit(buf, buf_size, pos, "None")
if cn.const_kind == ast.CONST_NONE: return _PyiEmit(buf, buf_size, pos, "None")
return pos
# Name: CDefine 常量名(如 share: ULONG = SHARE_READ)
if k == ast.ASTKind.Name:
nm: ast.Name* = ast.Name*(node)
if nm.id is not None:
return _PyiEmit(buf, buf_size, pos, nm.id)
if nm.id is not None: return _PyiEmit(buf, buf_size, pos, nm.id)
return pos
# UnaryOp: 一元运算(如 -1, ~0)
if k == ast.ASTKind.UnaryOp:
uop: ast.UnaryOp* = ast.UnaryOp*(node)
if uop.op == ast.OpKind.USub:
pos = _PyiEmit(buf, buf_size, pos, "-")
elif uop.op == ast.OpKind.UAdd:
pos = _PyiEmit(buf, buf_size, pos, "+")
elif uop.op == ast.OpKind.Invert:
pos = _PyiEmit(buf, buf_size, pos, "~")
else:
return pos
if uop.operand is not None:
return _PyiDefaultStr(buf, buf_size, pos, uop.operand, depth + 1)
if uop.op == ast.OpKind.USub: pos = _PyiEmit(buf, buf_size, pos, "-")
elif uop.op == ast.OpKind.UAdd: pos = _PyiEmit(buf, buf_size, pos, "+")
elif uop.op == ast.OpKind.Invert: pos = _PyiEmit(buf, buf_size, pos, "~")
else: return pos
if uop.operand is not None: return _PyiDefaultStr(buf, buf_size, pos, uop.operand, depth + 1)
return pos
# 其它(BinOp 等复杂表达式):不输出,保持无默认值(fail-fast 由调用侧兜底)
@@ -511,25 +465,20 @@ def _PyiDefaultStr(buf: bytes, buf_size: sizet, pos: sizet,
def _PyiRejectCReturnDecorator(node: ast.AST*,
decorators: list[ast.AST*]*) -> int:
"""装饰器列表里出现 @c.CReturn 即 fatal_error(返回 0 = 无该装饰器)"""
if decorators is None:
return 0
if decorators is None: return 0
dn: sizet = len(decorators)
di: sizet = 0
while di < dn:
dnode: ast.AST* = decorators.get(di)
di += 1
if dnode is None:
continue
if dnode is None: continue
# 兼容 @c.CReturn(...)(Call(func=Attribute))与裸 @c.CReturn(Attribute)两形态
dattr: ast.Attribute* = None
if dnode.kind() == ast.ASTKind.Call:
dcall: ast.Call* = ast.Call*(dnode)
if dcall.func is not None and dcall.func.kind() == ast.ASTKind.Attribute:
dattr = ast.Attribute*(dcall.func)
elif dnode.kind() == ast.ASTKind.Attribute:
dattr = ast.Attribute*(dnode)
if dattr is None or dattr.attr is None:
continue
if dcall.func is not None and dcall.func.kind() == ast.ASTKind.Attribute: dattr = ast.Attribute*(dcall.func)
elif dnode.kind() == ast.ASTKind.Attribute: dattr = ast.Attribute*(dnode)
if dattr is None or dattr.attr is None: continue
if string.strcmp(dattr.attr, "CReturn") == 0:
GenApi.fatal_error(node, "vpi 中仍带 `@c.CReturn`(已移除):请用返回注解 `-> tuple[ty1, ty2, ...]` 重新生成该 .vpi(可加 --clean)", "TypeError")
return 1
@@ -561,8 +510,7 @@ def _PyiFunction(buf: bytes, buf_size: sizet, pos: sizet,
pos = _PyiIndent(buf, buf_size, pos, indent_level)
pos = _PyiEmit(buf, buf_size, pos, "def ")
if fn.name is not None:
pos = _PyiEmit(buf, buf_size, pos, fn.name)
if fn.name is not None: pos = _PyiEmit(buf, buf_size, pos, fn.name)
pos = _PyiEmit(buf, buf_size, pos, "(")
# 参数列表
@@ -580,16 +528,13 @@ def _PyiFunction(buf: bytes, buf_size: sizet, pos: sizet,
# arg_defaults 必须内联声明:联合接收者的 .get 会被误分派,预声明 + 重赋值会解析成 list[int].get 返回 i32 截断指针而崩溃。
arg_defaults: list[ast.AST*]* = args.defaults
dn: sizet = 0
if arg_defaults is not None:
dn = len(arg_defaults)
if arg_defaults is not None: dn = len(arg_defaults)
ai: sizet = 0
while ai < an:
if first == 0:
pos = _PyiEmit(buf, buf_size, pos, ", ")
if first == 0: pos = _PyiEmit(buf, buf_size, pos, ", ")
first = 0
ag: ast.Arg* = ast.Arg*(args_args.get(ai))
if ag.arg is not None:
pos = _PyiEmit(buf, buf_size, pos, ag.arg)
if ag.arg is not None: pos = _PyiEmit(buf, buf_size, pos, ag.arg)
if ag.annotation is not None:
pos = _PyiEmit(buf, buf_size, pos, ": ")
pos = _PyiTypeStr(buf, buf_size, pos, ag.annotation)
@@ -603,23 +548,19 @@ def _PyiFunction(buf: bytes, buf_size: sizet, pos: sizet,
# *args
if args.vararg is not None:
if first == 0:
pos = _PyiEmit(buf, buf_size, pos, ", ")
if first == 0: pos = _PyiEmit(buf, buf_size, pos, ", ")
first = 0
pos = _PyiEmit(buf, buf_size, pos, "*")
va: ast.Arg* = ast.Arg*(args.vararg)
if va.arg is not None:
pos = _PyiEmit(buf, buf_size, pos, va.arg)
if va.arg is not None: pos = _PyiEmit(buf, buf_size, pos, va.arg)
# **kwargs
if args.kwarg is not None:
if first == 0:
pos = _PyiEmit(buf, buf_size, pos, ", ")
if first == 0: pos = _PyiEmit(buf, buf_size, pos, ", ")
first = 0
pos = _PyiEmit(buf, buf_size, pos, "**")
kw: ast.Arg* = ast.Arg*(args.kwarg)
if kw.arg is not None:
pos = _PyiEmit(buf, buf_size, pos, kw.arg)
if kw.arg is not None: pos = _PyiEmit(buf, buf_size, pos, kw.arg)
pos = _PyiEmit(buf, buf_size, pos, ")")
@@ -662,8 +603,7 @@ def _PyiClass(buf: bytes, buf_size: sizet, pos: sizet,
pos = _PyiIndent(buf, buf_size, pos, indent_level)
pos = _PyiEmit(buf, buf_size, pos, "class ")
if cls.name is not None:
pos = _PyiEmit(buf, buf_size, pos, cls.name)
if cls.name is not None: pos = _PyiEmit(buf, buf_size, pos, cls.name)
# PEP 695 类型参数 (class Foo[T]:)
if cls.type_params is not None:
@@ -682,11 +622,9 @@ def _PyiClass(buf: bytes, buf_size: sizet, pos: sizet,
pos = _PyiEmit(buf, buf_size, pos, "[")
tpi: sizet = 0
while tpi < tpn:
if tpi > 0:
pos = _PyiEmit(buf, buf_size, pos, ", ")
if tpi > 0: pos = _PyiEmit(buf, buf_size, pos, ", ")
tpname: str = cls_type_params.get(tpi)
if tpname is not None:
pos = _PyiEmit(buf, buf_size, pos, tpname)
if tpname is not None: pos = _PyiEmit(buf, buf_size, pos, tpname)
tpi += 1
pos = _PyiEmit(buf, buf_size, pos, "]")
@@ -698,8 +636,7 @@ def _PyiClass(buf: bytes, buf_size: sizet, pos: sizet,
pos = _PyiEmit(buf, buf_size, pos, "(")
bi: sizet = 0
while bi < bn:
if bi > 0:
pos = _PyiEmit(buf, buf_size, pos, ", ")
if bi > 0: pos = _PyiEmit(buf, buf_size, pos, ", ")
base: ast.AST* = cls_bases.get(bi)
pos = _PyiTypeStr(buf, buf_size, pos, base)
bi += 1
@@ -741,8 +678,7 @@ def _PyiClass(buf: bytes, buf_size: sizet, pos: sizet,
ici += 1
continue
pos = _PyiIndent(buf, buf_size, pos, indent_level + 1)
if iat.attr is not None:
pos = _PyiEmit(buf, buf_size, pos, iat.attr)
if iat.attr is not None: pos = _PyiEmit(buf, buf_size, pos, iat.attr)
pos = _PyiEmit(buf, buf_size, pos, ": ")
pos = _PyiTypeStr(buf, buf_size, pos, iaa.annotation)
pos = _PyiEmit(buf, buf_size, pos, "\n")
@@ -757,8 +693,7 @@ def _PyiClass(buf: bytes, buf_size: sizet, pos: sizet,
if aa.target is not None and aa.target.kind() == ast.ASTKind.Name:
tn: ast.Name* = ast.Name*(aa.target)
pos = _PyiIndent(buf, buf_size, pos, indent_level + 1)
if tn.id is not None:
pos = _PyiEmit(buf, buf_size, pos, tn.id)
if tn.id is not None: pos = _PyiEmit(buf, buf_size, pos, tn.id)
pos = _PyiEmit(buf, buf_size, pos, ": ")
pos = _PyiTypeStr(buf, buf_size, pos, aa.annotation)
pos = _PyiEmit(buf, buf_size, pos, "\n")
@@ -789,8 +724,7 @@ def _GeneratePyiFromAst(mb: memhub.MemBuddy*, tree: ast.AST*,
rel_path: str, buf: bytes,
buf_size: sizet) -> sizet:
"""从 AST 生成 .vpi 存根文件内容到 buf"""
if tree is None or buf is None or buf_size == 0:
return 0
if tree is None or buf is None or buf_size == 0: return 0
# 错误归因:把"当前文件"指向正在生成 stub 的这份(rel_path 非 None 时)。
# 本函数内触发的 fatal_error(如 L227/L303/L430 的注解节点类型未知)应指向
@@ -801,8 +735,7 @@ def _GeneratePyiFromAst(mb: memhub.MemBuddy*, tree: ast.AST*,
# 中途新增的分支;入口设一次覆盖全部(含后续所有 fatal_error / push_trace)。
# rel_path 为 None 时不改写 CurrentFile(保持上一次设置值):调用侧确实拿不到
# 路径时,宁可沿用"上一次设置的文件"也不要把归因抹成 None。
if rel_path is not None:
GenApi.set_current_file_type(rel_path)
if rel_path is not None: GenApi.set_current_file_type(rel_path)
pos: sizet = 0
@@ -822,8 +755,7 @@ def _GeneratePyiFromAst(mb: memhub.MemBuddy*, tree: ast.AST*,
tgt_pc0: ast.Name* = ast.Name*(aa_pc0.target)
if tgt_pc0.id is not None and aa_pc0.annotation.kind() == ast.ASTKind.Attribute:
ann_pc0: ast.Attribute* = ast.Attribute*(aa_pc0.annotation)
if ann_pc0.attr is not None and string.strcmp(ann_pc0.attr, "CDefine") == 0:
_g_pyi_cdef_count += 1
if ann_pc0.attr is not None and string.strcmp(ann_pc0.attr, "CDefine") == 0: _g_pyi_cdef_count += 1
if _g_pyi_cdef_count > 0:
_g_pyi_cdef_names = (str*)(mb.alloc(sizet(_g_pyi_cdef_count) * 8))
_g_pyi_cdef_vals = (int64*)(mb.alloc(sizet(_g_pyi_cdef_count) * 8))
@@ -849,8 +781,7 @@ def _GeneratePyiFromAst(mb: memhub.MemBuddy*, tree: ast.AST*,
pos = _PyiEmit(buf, buf_size, pos, "\"\"\"Auto-generated Python stub file\"\"\"\n\n")
if tree.children is None:
if pos < buf_size:
buf[pos] = 0
if pos < buf_size: buf[pos] = 0
return pos
tree_children: list[ast.AST*]* = tree.children
@@ -869,20 +800,14 @@ def _GeneratePyiFromAst(mb: memhub.MemBuddy*, tree: ast.AST*,
for ai in range(an):
al: ast.Alias* = ast.Alias*(imp_names.get(ai))
if al is not None and al.name is not None:
if string.strcmp(al.name, "t") == 0:
has_import_t = 1
elif string.strcmp(al.name, "c") == 0:
has_import_c = 1
if string.strcmp(al.name, "t") == 0: has_import_t = 1
elif string.strcmp(al.name, "c") == 0: has_import_c = 1
# 补充缺失的 import t/c
if has_import_t == 0 and has_import_c == 0:
pos = _PyiEmit(buf, buf_size, pos, "import t, c\n\n")
elif has_import_t == 0:
pos = _PyiEmit(buf, buf_size, pos, "import t\n\n")
elif has_import_c == 0:
pos = _PyiEmit(buf, buf_size, pos, "import c\n\n")
else:
pos = _PyiEmit(buf, buf_size, pos, "\n")
if has_import_t == 0 and has_import_c == 0: pos = _PyiEmit(buf, buf_size, pos, "import t, c\n\n")
elif has_import_t == 0: pos = _PyiEmit(buf, buf_size, pos, "import t\n\n")
elif has_import_c == 0: pos = _PyiEmit(buf, buf_size, pos, "import c\n\n")
else: pos = _PyiEmit(buf, buf_size, pos, "\n")
# 第二遍扫描:生成声明
for i in range(n):
@@ -905,8 +830,7 @@ def _GeneratePyiFromAst(mb: memhub.MemBuddy*, tree: ast.AST*,
an2: sizet = len(imp2_names)
ai2: sizet = 0
while ai2 < an2:
if ai2 > 0:
pos = _PyiEmit(buf, buf_size, pos, ", ")
if ai2 > 0: pos = _PyiEmit(buf, buf_size, pos, ", ")
al2: ast.Alias* = ast.Alias*(imp2_names.get(ai2))
# fail-fast:别名节点或其名字为空 ⇒ 绝不静默写出 "import , "。
# vpi 里 import 行的名字是**包重导出注册的唯一输入**
@@ -942,8 +866,7 @@ def _GeneratePyiFromAst(mb: memhub.MemBuddy*, tree: ast.AST*,
while lvl > 0:
pos = _PyiEmit(buf, buf_size, pos, ".")
lvl -= 1
if ifr.module is not None:
pos = _PyiEmit(buf, buf_size, pos, ifr.module)
if ifr.module is not None: pos = _PyiEmit(buf, buf_size, pos, ifr.module)
pos = _PyiEmit(buf, buf_size, pos, " import ")
# fail-fast:同 Import 分支——`from X import *` 走的是 Alias("*"),
# 列表为空或名字为空都说明 AST 坏;静默写出 `from X import ` 会让
@@ -958,8 +881,7 @@ def _GeneratePyiFromAst(mb: memhub.MemBuddy*, tree: ast.AST*,
an3: sizet = len(ifr_names)
ai3: sizet = 0
while ai3 < an3:
if ai3 > 0:
pos = _PyiEmit(buf, buf_size, pos, ", ")
if ai3 > 0: pos = _PyiEmit(buf, buf_size, pos, ", ")
al3: ast.Alias* = ast.Alias*(ifr_names.get(ai3))
# fail-fast:同 Import 分支(两种成因分开报,一次定位)。
if al3 is None:
@@ -987,8 +909,7 @@ def _GeneratePyiFromAst(mb: memhub.MemBuddy*, tree: ast.AST*,
# 特化体按调用点单态化生成({模板SHA1}.f[args]),其签名由编译器
# 内存中的模板表 + 实参跨模块复现(见 ClassGenGeneric.
# _ensure_generic_func_declare),不落 vpi。
if fn.type_params is not None:
continue
if fn.type_params is not None: continue
pos = _PyiFunction(buf, buf_size, pos, fn, 0, "")
# 类定义
@@ -1014,8 +935,7 @@ def _GeneratePyiFromAst(mb: memhub.MemBuddy*, tree: ast.AST*,
if ctd_at.attr is not None and string.strcmp(ctd_at.attr, "CTypedef") == 0:
if ctd_at.value is not None and ctd_at.value.kind() == ast.ASTKind.Name:
ctd_mod: ast.Name* = ast.Name*(ctd_at.value)
if ctd_mod.id is not None and string.strcmp(ctd_mod.id, "t") == 0:
is_ctypedef_ann = 1
if ctd_mod.id is not None and string.strcmp(ctd_mod.id, "t") == 0: is_ctypedef_ann = 1
if is_ctypedef_ann != 0 and aa.value is not None:
pos = _PyiEmit(buf, buf_size, pos, " = ")
pos = _PyiTypeStr(buf, buf_size, pos, aa.value)
@@ -1032,10 +952,8 @@ def _GeneratePyiFromAst(mb: memhub.MemBuddy*, tree: ast.AST*,
viperlib.snprintf(fbuf_c, 64, " = %.17g", cv.float_val)
pos = _PyiEmit(buf, buf_size, pos, fbuf_c)
elif cv.const_kind == ast.CONST_BOOL:
if cv.int_val != 0:
pos = _PyiEmit(buf, buf_size, pos, " = True")
else:
pos = _PyiEmit(buf, buf_size, pos, " = False")
if cv.int_val != 0: pos = _PyiEmit(buf, buf_size, pos, " = True")
else: pos = _PyiEmit(buf, buf_size, pos, " = False")
elif cv.const_kind == ast.CONST_STR:
# 字符串 CDefine(pyzlib.ZLIB_VERSION = "1.3.2" 等)必须输出值,让 stub 自包含(读回端按目标名判定会回退源文件)
sbuf_c: bytes = mb.alloc(string.strlen(cv.str_val) + 6)
@@ -1043,8 +961,7 @@ def _GeneratePyiFromAst(mb: memhub.MemBuddy*, tree: ast.AST*,
viperlib.snprintf(sbuf_c, string.strlen(cv.str_val) + 6,
" = \"%s\"", cv.str_val)
pos = _PyiEmit(buf, buf_size, pos, sbuf_c)
elif cv.const_kind == ast.CONST_NONE:
pos = _PyiEmit(buf, buf_size, pos, " = None")
elif cv.const_kind == ast.CONST_NONE: pos = _PyiEmit(buf, buf_size, pos, " = None")
elif aa.value is not None and aa.value.kind() == ast.ASTKind.UnaryOp:
# 处理负值常量(如 INVALID_HANDLE_VALUE = -1)
# UnaryOp(USub, Constant(1)) → -1
@@ -1138,34 +1055,22 @@ def _GeneratePyiFromAst(mb: memhub.MemBuddy*, tree: ast.AST*,
inferred: int = 0
if avk == ast.ASTKind.Constant:
acv: ast.Constant* = ast.Constant*(aval)
if acv.const_kind == ast.CONST_INT:
inferred = 1
elif acv.const_kind == ast.CONST_FLOAT:
inferred = 2
elif acv.const_kind == ast.CONST_STR:
inferred = 3
elif acv.const_kind == ast.CONST_BOOL:
inferred = 4
elif acv.const_kind == ast.CONST_NONE:
inferred = 5
if acv.const_kind == ast.CONST_INT: inferred = 1
elif acv.const_kind == ast.CONST_FLOAT: inferred = 2
elif acv.const_kind == ast.CONST_STR: inferred = 3
elif acv.const_kind == ast.CONST_BOOL: inferred = 4
elif acv.const_kind == ast.CONST_NONE: inferred = 5
if inferred > 0 and agn.id is not None:
pos = _PyiEmit(buf, buf_size, pos, agn.id)
pos = _PyiEmit(buf, buf_size, pos, ": ")
if inferred == 1:
pos = _PyiEmit(buf, buf_size, pos, "int")
elif inferred == 2:
pos = _PyiEmit(buf, buf_size, pos, "double")
elif inferred == 3:
pos = _PyiEmit(buf, buf_size, pos, "str")
elif inferred == 4:
pos = _PyiEmit(buf, buf_size, pos, "bool")
elif inferred == 5:
pos = _PyiEmit(buf, buf_size, pos, "None")
if inferred == 1: pos = _PyiEmit(buf, buf_size, pos, "int")
elif inferred == 2: pos = _PyiEmit(buf, buf_size, pos, "double")
elif inferred == 3: pos = _PyiEmit(buf, buf_size, pos, "str")
elif inferred == 4: pos = _PyiEmit(buf, buf_size, pos, "bool")
elif inferred == 5: pos = _PyiEmit(buf, buf_size, pos, "None")
pos = _PyiEmit(buf, buf_size, pos, "\n")
# NUL 终止
if pos < buf_size:
buf[pos] = 0
else:
buf[buf_size - 1] = 0
if pos < buf_size: buf[pos] = 0
else: buf[buf_size - 1] = 0
return pos
File diff suppressed because it is too large. Load diff
+49 -98
View File
@@ -35,16 +35,13 @@ import lib.Stub.StubMerger as StubMerger
# ============================================================
def _IsAppModule(mod_name: str) -> int:
"""mod_name 是否为 App 源文件(store 命中且 incdir 为空)"""
if mod_name is None:
return 0
if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_mod is None:
return 0
if mod_name is None: return 0
if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_mod is None: return 0
for i in range(StubMerger._sha1_store_count):
midx: sizet = sizet(i) * 64
if string.strcmp(StubMerger._sha1_store_mod + midx, mod_name) == 0:
iidx: sizet = sizet(i) * StubMerger.MAX_INC_DIR_LEN
if StubMerger._sha1_store_incdir[iidx] == '\0':
return 1
if StubMerger._sha1_store_incdir[iidx] == '\0': return 1
return 0
return 0
# ============================================================
@@ -58,32 +55,25 @@ def _IsAppModule(mod_name: str) -> int:
# ============================================================
def _AppendDepsToWorklist(worklist: bytes, wl_len: sizet,
deps_str: str, processed: str) -> int:
if worklist is None or deps_str is None:
return -1
if worklist is None or deps_str is None: return -1
cur_len: sizet = wl_len
dl: sizet = string.strlen(deps_str)
dpos: sizet = 0
while dpos < dl:
dstart: sizet = dpos
while dpos < dl and deps_str[dpos] != ' ':
dpos += 1
while dpos < dl and deps_str[dpos] != ' ': dpos += 1
dlen: sizet = dpos - dstart
if dpos < dl:
dpos += 1
if dlen == 0:
continue
if dpos < dl: dpos += 1
if dlen == 0: continue
dmod: bytes = stdlib.malloc(dlen + 1)
if dmod is None:
continue
if dmod is None: continue
string.strncpy(dmod, deps_str + dstart, dlen)
dmod[dlen] = '\0'
in_wl: int = 0
if cur_len > 0:
if GenApi.is_module_imported(worklist, dmod) != 0:
in_wl = 1
if GenApi.is_module_imported(worklist, dmod) != 0: in_wl = 1
if in_wl == 0 and processed is not None:
if GenApi.is_module_imported(processed, dmod) != 0:
in_wl = 1
if GenApi.is_module_imported(processed, dmod) != 0: in_wl = 1
if in_wl == 0:
if cur_len + dlen + 2 < StubMerger.REACH_WORKLIST_BUF:
if cur_len > 0 and worklist[cur_len - 1] != ' ':
@@ -119,8 +109,7 @@ def _BuildReachableSha1Set(mb: memhub.MemBuddy*, source_dir: str,
app_deps: str = None,
includes_dirs: str = None) -> int:
"""构建可达 SHA1 集合(依赖图按需扫描,App 优先)"""
if source_dir is None or temp_dir is None or reachable_set is None:
return -1
if source_dir is None or temp_dir is None or reachable_set is None: return -1
if includes_dirs is None:
VLogger.error("includes_dirs 缺失,无法按需解析依赖图", "Reachable")
return -1
@@ -129,8 +118,7 @@ def _BuildReachableSha1Set(mb: memhub.MemBuddy*, source_dir: str,
# 工作列表(空格分隔的模块名)
worklist: bytes = stdlib.malloc(StubMerger.REACH_WORKLIST_BUF)
if worklist is None:
return -1
if worklist is None: return -1
worklist[0] = '\0'
wl_len: sizet = 0
@@ -142,8 +130,7 @@ def _BuildReachableSha1Set(mb: memhub.MemBuddy*, source_dir: str,
es_r: sizet = IncludesScanner.FileEntry.__sizeof__()
for e_i_r in range(scan_res_r.Count):
e_r: rawptr[IncludesScanner.FileEntry] = rawptr[IncludesScanner.FileEntry](uint64(scan_res_r.Entries) + uint64(e_i_r) * es_r)
if e_r is None or e_r.Path is None:
continue
if e_r is None or e_r.Path is None: continue
# 文件级 mark:parse 完立即回收 AST(App 全量 parse 驻留会 OOM)
app_mark: sizet = mb.mark()
sbuf: bytes = Utils.read_file_to_buf(e_r.Path, SRC_BUF_SIZE_R)
@@ -186,21 +173,16 @@ def _BuildReachableSha1Set(mb: memhub.MemBuddy*, source_dir: str,
im_pos_a: sizet = 0
while im_pos_a < im_len_a:
im_start_a: sizet = im_pos_a
while im_pos_a < im_len_a and tr._imported_modules[im_pos_a] != ' ':
im_pos_a += 1
while im_pos_a < im_len_a and tr._imported_modules[im_pos_a] != ' ': im_pos_a += 1
im_mod_len: sizet = im_pos_a - im_start_a
if im_pos_a < im_len_a:
im_pos_a += 1
if im_mod_len == 0:
continue
if im_pos_a < im_len_a: im_pos_a += 1
if im_mod_len == 0: continue
im_buf_a: bytes = stdlib.malloc(im_mod_len + 1)
if im_buf_a is None:
continue
if im_buf_a is None: continue
string.strncpy(im_buf_a, tr._imported_modules + im_start_a, im_mod_len)
im_buf_a[im_mod_len] = '\0'
in_wl_a: int = 0
if wl_len > 0 and GenApi.is_module_imported(worklist, im_buf_a) != 0:
in_wl_a = 1
if wl_len > 0 and GenApi.is_module_imported(worklist, im_buf_a) != 0: in_wl_a = 1
if in_wl_a == 0:
if wl_len + im_mod_len + 2 < StubMerger.REACH_WORKLIST_BUF:
if wl_len > 0:
@@ -213,10 +195,8 @@ def _BuildReachableSha1Set(mb: memhub.MemBuddy*, source_dir: str,
worklist[wl_len] = '\0'
stdlib.free(im_buf_a)
# 释放 Translator 资源
if tr._global_names is not None:
stdlib.free(tr._global_names)
if tr._nonlocal_names is not None:
stdlib.free(tr._nonlocal_names)
if tr._global_names is not None: stdlib.free(tr._global_names)
if tr._nonlocal_names is not None: stdlib.free(tr._nonlocal_names)
stdlib.free(sbuf)
mb.reset_to(app_mark)
else:
@@ -263,12 +243,9 @@ def _BuildReachableSha1Set(mb: memhub.MemBuddy*, source_dir: str,
tb_inc_slot[0] = 0
tb_found = IncludesScanner.ResolveModuleToPath(
includes_dirs, "traceback", tb_abs, tb_rel, tb_inc)
if tb_abs is not None:
stdlib.free(tb_abs)
if tb_rel is not None:
stdlib.free(tb_rel)
if tb_inc is not None:
stdlib.free(tb_inc)
if tb_abs is not None: stdlib.free(tb_abs)
if tb_rel is not None: stdlib.free(tb_rel)
if tb_inc is not None: stdlib.free(tb_inc)
if tb_found != 0:
stdlib.free(worklist)
VLogger.error(f"--traceback: 在 includes 目录中找不到 traceback.vp,无法编译并链接 Install()(请确认 project.vpj 的 includes 包含仓库 includes 目录;已扫描: {includes_dirs})", "Traceback")
@@ -299,19 +276,15 @@ def _BuildReachableSha1Set(mb: memhub.MemBuddy*, source_dir: str,
pos: sizet = wl_pos_slot[0]
# 提取一个模块名(到空格或末尾)
name_start: sizet = pos
while pos < wl_len and worklist[pos] != ' ':
pos += 1
while pos < wl_len and worklist[pos] != ' ': pos += 1
name_len: sizet = pos - name_start
if pos < wl_len:
pos += 1
if pos < wl_len: pos += 1
wl_pos_slot[0] = pos
if name_len == 0:
continue
if name_len == 0: continue
# 复制模块名
mod_buf: bytes = stdlib.malloc(name_len + 1)
if mod_buf is None:
continue
if mod_buf is None: continue
string.strncpy(mod_buf, worklist + name_start, name_len)
mod_buf[name_len] = '\0'
@@ -354,12 +327,9 @@ def _BuildReachableSha1Set(mb: memhub.MemBuddy*, source_dir: str,
out_rel: t.CPtr = stdlib.malloc(8)
out_inc: t.CPtr = stdlib.malloc(8)
if out_abs is None or out_rel is None or out_inc is None:
if out_abs is not None:
stdlib.free(out_abs)
if out_rel is not None:
stdlib.free(out_rel)
if out_inc is not None:
stdlib.free(out_inc)
if out_abs is not None: stdlib.free(out_abs)
if out_rel is not None: stdlib.free(out_rel)
if out_inc is not None: stdlib.free(out_inc)
stdlib.free(mod_buf)
continue
# 输出槽防御性初始化(成功路径必全写;未找到/未命中时仅 free 槽本身)
@@ -501,10 +471,8 @@ def _BuildReachableSha1Set(mb: memhub.MemBuddy*, source_dir: str,
stdlib.free(out_rel)
stdlib.free(out_inc)
stdlib.free(sbuf_r)
if tr_r2._global_names is not None:
stdlib.free(tr_r2._global_names)
if tr_r2._nonlocal_names is not None:
stdlib.free(tr_r2._nonlocal_names)
if tr_r2._global_names is not None: stdlib.free(tr_r2._global_names)
if tr_r2._nonlocal_names is not None: stdlib.free(tr_r2._nonlocal_names)
stdlib.free(mod_buf)
stdlib.free(worklist)
stdlib.free(processed)
@@ -525,8 +493,7 @@ def _BuildReachableSha1Set(mb: memhub.MemBuddy*, source_dir: str,
df_w: rawptr[fileio.File] = fileio.File(deps_path_w, fileio.MODE.W)
if not df_w.closed:
dl_w: sizet = string.strlen(deps_r2)
if dl_w > 0:
df_w.write(deps_r2, dl_w)
if dl_w > 0: df_w.write(deps_r2, dl_w)
df_w.close()
stdlib.free(deps_path_w)
# 追加依赖到 worklist(去重防溢出)
@@ -546,14 +513,11 @@ def _BuildReachableSha1Set(mb: memhub.MemBuddy*, source_dir: str,
mb.reset_to(scan_mark_r)
return -1
wl_len = sizet(ret_w)
else:
VLogger.debug(f"无依赖: {rel_path}", "Reachable")
else: VLogger.debug(f"无依赖: {rel_path}", "Reachable")
# 释放 Translator 的 C malloc 资源 + 回收本文件 AST
if tr_r2._global_names is not None:
stdlib.free(tr_r2._global_names)
if tr_r2._nonlocal_names is not None:
stdlib.free(tr_r2._nonlocal_names)
if tr_r2._global_names is not None: stdlib.free(tr_r2._global_names)
if tr_r2._nonlocal_names is not None: stdlib.free(tr_r2._nonlocal_names)
stdlib.free(sbuf_r)
mb.reset_to(scan_mark_r)
@@ -581,25 +545,21 @@ def _BuildReachableSha1Set(mb: memhub.MemBuddy*, source_dir: str,
def LoadFullIR(temp_dir: str, sha1: str,
out_buf: bytes, out_size: sizet) -> sizet:
"""读取 {sha1}.full.ll 到 out_buf;返回长度(0=失败)"""
if temp_dir is None or sha1 is None or out_buf is None or out_size == 0:
return 0
if temp_dir is None or sha1 is None or out_buf is None or out_size == 0: return 0
td_len: sizet = string.strlen(temp_dir)
p: str = StubMergerCollect._sliced_path(temp_dir, td_len, sha1, "full.ll")
if p is None:
return 0
if p is None: return 0
f: rawptr[fileio.File] = fileio.File(p, fileio.MODE.R)
stdlib.free(p)
out_buf[0] = '\0'
if f.closed:
return 0
if f.closed: return 0
if f.size() >= out_size:
f.close()
VLogger.error("full.ll 超过 IR 缓冲上限", "StubMerger")
return 0
rd: int64 = f.read_all(out_buf, out_size)
f.close()
if rd <= 0:
return 0
if rd <= 0: return 0
out_buf[rd] = '\0'
return sizet(rd)
@@ -620,10 +580,8 @@ def LoadDepVpiIntoModule(pool: memhub.MemBuddy*,
temp_dir: str,
trans: rawptr[HandlesTranslator.Translator]) -> int:
"""加载依赖模块的 .vpi 文件,将函数声明注入到当前模块"""
if pool is None or mod is None or temp_dir is None or trans is None:
return 0
if imported_modules is None:
return 0
if pool is None or mod is None or temp_dir is None or trans is None: return 0
if imported_modules is None: return 0
# 每个模块的 stub 注入前重置 typedef 递归注册的防环标记:
# CTypedef 表每文件隔离(translate 前 clear),visited 若跨模块残留会
@@ -642,22 +600,17 @@ def LoadDepVpiIntoModule(pool: memhub.MemBuddy*,
ci: sizet = 0
while ci < total_len:
# 跳过前导空格
while ci < total_len and imported_modules[ci] == ' ':
ci += 1
if ci >= total_len:
break
while ci < total_len and imported_modules[ci] == ' ': ci += 1
if ci >= total_len: break
# 提取模块名(到下一个空格或字符串末尾)
word_start: sizet = ci
while ci < total_len and imported_modules[ci] != ' ':
ci += 1
while ci < total_len and imported_modules[ci] != ' ': ci += 1
word_len: sizet = ci - word_start
if word_len == 0:
continue
if word_len == 0: continue
# 复制模块名到临时缓冲区并 null 终止
mod_nm_buf: str = stdlib.malloc(word_len + 1)
if mod_nm_buf is None:
continue
if mod_nm_buf is None: continue
string.strncpy(mod_nm_buf, imported_modules + word_start, word_len)
mod_nm_buf[word_len] = '\0'
@@ -667,8 +620,7 @@ def LoadDepVpiIntoModule(pool: memhub.MemBuddy*,
# 改名别名(import X as Y,如 HT→lib.core.Handles.HandlesTranslator):
# 精确/包名回退均失败时从 from_imports 查别名映射再查 SHA1,
# 否则该类模块的 vpi/stub 不注入 → 跨模块符号解析失败
if sha1_val is None and from_imports is not None:
sha1_val = StubMergerStore.LookupSha1ByAlias(from_imports, mod_nm_buf)
if sha1_val is None and from_imports is not None: sha1_val = StubMergerStore.LookupSha1ByAlias(from_imports, mod_nm_buf)
# 如果精确查找失败,尝试包名回退(如 "ast" → "ast.__init__")
# LookupSha1ByModName 内部已处理包名回退,此处无需重复
@@ -684,8 +636,7 @@ def LoadDepVpiIntoModule(pool: memhub.MemBuddy*,
# 调用 VpiReader 解析 .vpi 并注入 declare
# (错误上下文帧由调用方 HandlesTranslator 维护)
ret: int = VpiReader.ParseVpiIntoModule(pool, mod, vpi_path, trans)
if ret == 1:
success_count += 1
if ret == 1: success_count += 1
stdlib.free(vpi_path)
# sha1_val 指向内部存储,无需 free
+13 -26
View File
@@ -44,8 +44,7 @@ def _sliced_path(temp_dir: str, td_len: sizet, sha1: str, ext: str) -> str:
level>0 时自动调用 ensure_dir 创建子目录。
"""
if temp_dir is None or sha1 is None or ext is None:
return None
if temp_dir is None or sha1 is None or ext is None: return None
sha1_len: sizet = string.strlen(sha1)
ext_len: sizet = string.strlen(ext)
@@ -71,13 +70,11 @@ def _sliced_path(temp_dir: str, td_len: sizet, sha1: str, ext: str) -> str:
if sub_len > 0:
path_len = td_len + sub_len + sha1_len + ext_len + 4
path = stdlib.malloc(path_len)
if path is not None:
viperlib.snprintf(path, path_len, "%s/%s/%s.%s", temp_dir, subdir_buf, sha1, ext)
if path is not None: viperlib.snprintf(path, path_len, "%s/%s/%s.%s", temp_dir, subdir_buf, sha1, ext)
else:
path_len = td_len + sha1_len + ext_len + 3
path = stdlib.malloc(path_len)
if path is not None:
viperlib.snprintf(path, path_len, "%s/%s.%s", temp_dir, sha1, ext)
if path is not None: viperlib.snprintf(path, path_len, "%s/%s.%s", temp_dir, sha1, ext)
return path
@@ -96,14 +93,11 @@ def _load_includes_sha1_set(pool: memhub.MemBuddy*,
数据来源是 PopulateSha1MapStore 填充的全局存储器。
sha1_set 大小为 MAX_INCLUDES_SHA1 * 17(每个 SHA1 16字符+null)
返回找到的 includes SHA1 数量,-1 表示错误"""
if sha1_set is None:
return -1
if StubMerger._sha1_store_arr is None:
return -1
if sha1_set is None: return -1
if StubMerger._sha1_store_arr is None: return -1
count: int = 0
for i in range(StubMerger._sha1_store_count):
if count >= StubMerger.MAX_INCLUDES_SHA1:
break
if count >= StubMerger.MAX_INCLUDES_SHA1: break
idx: sizet = sizet(i) * 17
string.strcpy(sha1_set + sizet(count) * 17, StubMerger._sha1_store_arr + idx)
count += 1
@@ -113,11 +107,9 @@ def _load_includes_sha1_set(pool: memhub.MemBuddy*,
# ============================================================
def _is_in_sha1_set(sha1: str, sha1_set: str, set_count: int) -> int:
"""检查 sha1 是否在集合中"""
if sha1 is None or sha1_set is None:
return 0
if sha1 is None or sha1_set is None: return 0
for i in range(set_count):
if string.strcmp(sha1_set + i * 17, sha1) == 0:
return 1
if string.strcmp(sha1_set + i * 17, sha1) == 0: return 1
return 0
# ============================================================
# WriteIncludesSha1Map - 将 includes 扫描结果写入 _sha1_map.txt(仅人类可读的调试输出,程序内部不读取,
@@ -134,20 +126,17 @@ def WriteIncludesSha1Map(mb: memhub.MemBuddy*, temp_dir: str,
若 filter_set 不为 None 且 filter_count > 0,只写入 filter_set 中的条目。
"""
if temp_dir is None or scan_result is None:
return 1
if temp_dir is None or scan_result is None: return 1
# 构造路径 temp_dir/_sha1_map.txt
dir_len: sizet = string.strlen(temp_dir)
map_path: bytes = stdlib.malloc(dir_len + 32)
if map_path is None:
return 1
if map_path is None: return 1
viperlib.snprintf(map_path, dir_len + 32, "%s/_sha1_map.txt", temp_dir)
# 打开文件写入(CREATE_ALWAYS)
f: rawptr[fileio.File] = fileio.File(map_path, fileio.MODE.W)
if f.closed:
return 1
if f.closed: return 1
# 写入每个 include 条目: {sha1}:includes/{rel_path}\n
entry_size_w: sizet = IncludesScanner.FileEntry.__sizeof__()
@@ -160,12 +149,10 @@ def WriteIncludesSha1Map(mb: memhub.MemBuddy*, temp_dir: str,
for i in range(scan_result.Count):
ea_w: uint64 = uint64(scan_result.Entries) + i * entry_size_w
ent_w: rawptr[IncludesScanner.FileEntry] = (rawptr[IncludesScanner.FileEntry])(ea_w)
if ent_w is None or ent_w.Sha1 is None or ent_w.RelPath is None:
continue
if ent_w is None or ent_w.Sha1 is None or ent_w.RelPath is None: continue
# 若提供过滤集合,只写入集合中的条目
if filter_set is not None and filter_count > 0:
if _is_in_sha1_set(ent_w.Sha1, filter_set, filter_count) == 0:
continue
if _is_in_sha1_set(ent_w.Sha1, filter_set, filter_count) == 0: continue
viperlib.snprintf(line_buf, 512, "%s:includes/%s\n", ent_w.Sha1, ent_w.RelPath)
line_len_w: sizet = string.strlen(line_buf)
f.write(line_buf, line_len_w)
+26 -52
View File
@@ -76,8 +76,7 @@ def WriteModuleMeta(mod: mlirlite.LLVMModule*, temp_dir: str,
VLogger.error("meta 写出:行缓冲分配失败", "Meta")
break
mark: str = "DECL"
if mlirlite.function_is_declared(cur) == 0:
mark = "DEF"
if mlirlite.function_is_declared(cur) == 0: mark = "DEF"
viperlib.snprintf(line, nlen + 16, "FUNC %s %s\n", nm, mark)
mf.write(line, string.strlen(line))
stdlib.free(line)
@@ -98,10 +97,8 @@ def WriteModuleMeta(mod: mlirlite.LLVMModule*, temp_dir: str,
VLogger.error("meta 写出:行缓冲分配失败", "Meta")
break
fc: int = mlirlite.get_struct_fcount(nt.Ty)
if fc < 0:
viperlib.snprintf(lb, tl + 48, "STRUCT %s OPAQUE\n", tn)
else:
viperlib.snprintf(lb, tl + 48, "STRUCT %s FIELDS %d PACKED %d\n", tn, fc, nt.IsPacked)
if fc < 0: viperlib.snprintf(lb, tl + 48, "STRUCT %s OPAQUE\n", tn)
else: viperlib.snprintf(lb, tl + 48, "STRUCT %s FIELDS %d PACKED %d\n", tn, fc, nt.IsPacked)
mf.write(lb, string.strlen(lb))
stdlib.free(lb)
nt = nt.Next
@@ -123,11 +120,9 @@ def WriteModuleMeta(mod: mlirlite.LLVMModule*, temp_dir: str,
string.strncpy(base, gn, base_len)
base[base_len] = '\0'
ar: int = mlirlite.get_struct_fcount(gv.Ty)
if ar < 0:
ar = 0
if ar < 0: ar = 0
lb2: bytes = stdlib.malloc(base_len + 40)
if lb2 is None:
VLogger.error("meta 写出:行缓冲分配失败", "Meta")
if lb2 is None: VLogger.error("meta 写出:行缓冲分配失败", "Meta")
else:
viperlib.snprintf(lb2, base_len + 40, "VTABLE %s SLOTS %d\n", base, ar)
mf.write(lb2, string.strlen(lb2))
@@ -146,41 +141,32 @@ def WriteModuleMeta(mod: mlirlite.LLVMModule*, temp_dir: str,
# ============================================================
def _MetaHasDef(temp_dir: str, td_len: sizet, sha1: str) -> int:
"""读 {sha1}.meta:含 "FUNC ... DEF" 行返回 1,无则 0,文件不可读 -1"""
if temp_dir is None or sha1 is None:
return -1
if temp_dir is None or sha1 is None: return -1
mpath: str = StubMergerCollect._sliced_path(temp_dir, td_len, sha1, "meta")
if mpath is None:
return -1
if mpath is None: return -1
mf: fileio.File = fileio.File(mpath, fileio.MODE.R)
stdlib.free(mpath)
if mf.closed:
return -1
if mf.closed: return -1
mbuf: bytes = stdlib.malloc(StubMerger.STUB_READ_BUF_SIZE)
mbr: int64 = 0
if mbuf is not None:
mbr = mf.read_all(mbuf, StubMerger.STUB_READ_BUF_SIZE)
if mbuf is not None: mbr = mf.read_all(mbuf, StubMerger.STUB_READ_BUF_SIZE)
mf.close()
if mbuf is None:
return -1
if mbuf is None: return -1
if mbr <= 0:
# 空 meta:无 DEF,纯声明
stdlib.free(mbuf)
return 0
if mbr < StubMerger.STUB_READ_BUF_SIZE:
mbuf[mbr] = '\0'
if mbr < StubMerger.STUB_READ_BUF_SIZE: mbuf[mbr] = '\0'
# 逐行扫描:行尾 " DEF" 即为实现文件
mpos: sizet = 0
while mpos < mbr:
mls: sizet = mpos
while mpos < mbr:
if mbuf[mpos] == '\n':
break
if mbuf[mpos] == '\n': break
mpos += 1
mll: sizet = mpos - mls
if mpos < mbr:
mpos += 1
if mll > 0 and mbuf[mls + mll - 1] == '\r':
mll -= 1
if mpos < mbr: mpos += 1
if mll > 0 and mbuf[mls + mll - 1] == '\r': mll -= 1
if mll >= 10 and string.strncmp(mbuf + mls, "FUNC ", 5) == 0:
if mbuf[mls + mll - 4] == ' ' and string.strncmp(mbuf + mls + mll - 3, "DEF", 3) == 0:
stdlib.free(mbuf)
@@ -199,10 +185,8 @@ def _MetaHasDef(temp_dir: str, td_len: sizet, sha1: str) -> int:
def IsDeclOnlyModule(temp_dir: str, td_len: sizet, sha1: str) -> int:
"""判断模块是否为纯声明文件(meta 无 FUNC ... DEF 行)"""
h: int = _MetaHasDef(temp_dir, td_len, sha1)
if h < 0:
return -1
if h == 1:
return 0
if h < 0: return -1
if h == 1: return 0
return 1
# ============================================================
# _is_submodule_of_imported - 检查模块名是否是已导入包的子模块
@@ -212,15 +196,12 @@ def IsDeclOnlyModule(temp_dir: str, td_len: sizet, sha1: str) -> int:
# ============================================================
def _is_submodule_of_imported(deps_buf: str, mod_name: str) -> int:
"""检查 mod_name 是否是 deps_buf 中已导入包的子模块"""
if deps_buf is None or mod_name is None:
return 0
if deps_buf is None or mod_name is None: return 0
# 查找第一个 '.',提取顶层包名
dot_pos: str = string.strchr(mod_name, 46) # '.' = 46
if dot_pos is None:
return 0
if dot_pos is None: return 0
pkg_len: sizet = sizet(uint64(dot_pos) - uint64(mod_name))
if pkg_len == 0 or pkg_len >= 256:
return 0
if pkg_len == 0 or pkg_len >= 256: return 0
# 构造顶层包名(截断到 '.' 之前)
# 直接在 mod_name 上临时截断检查,避免分配
saved_ch: char = mod_name[pkg_len]
@@ -243,14 +224,11 @@ def _BuildIncludesSha1Map(temp_dir: str, td_len: sizet,
temp_dir/td_len 参数保留以兼容现有调用者,但不再使用。
数据来源是 PopulateSha1MapStore 填充的全局存储器。
"""
if sha1_list is None or mod_list is None:
return 0
if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_mod is None:
return 0
if sha1_list is None or mod_list is None: return 0
if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_mod is None: return 0
count: int = 0
for i in range(StubMerger._sha1_store_count):
if count >= StubMerger.MAX_INCLUDES:
break
if count >= StubMerger.MAX_INCLUDES: break
idx: sizet = sizet(i) * 17
idx2: sizet = sizet(i) * 64
string.strcpy(sha1_list + sizet(count) * 17, StubMerger._sha1_store_arr + idx)
@@ -270,10 +248,8 @@ def _FindSha1ByModName(sha1_arr: str, mod_arr: str,
精确匹配失败时,尝试 "{mod_name}.__init__" 回退,
支持 import ast(包)→ ast.__init__ 的 SHA1 查找。
"""
if sha1_arr is None or mod_arr is None or mod_name is None:
return None
if count <= 0:
return None
if sha1_arr is None or mod_arr is None or mod_name is None: return None
if count <= 0: return None
# 第一遍:精确匹配
for i in range(count):
idx: sizet = sizet(i) * 64
@@ -303,12 +279,10 @@ def _FindSha1ByModName(sha1_arr: str, mod_arr: str,
# ============================================================
def _AddSha1ToSet(set_buf: str, count: int, sha1: str) -> int:
"""将 SHA1 加入集合,返回新 count"""
if set_buf is None or sha1 is None:
return count
if set_buf is None or sha1 is None: return count
for i in range(count):
idx: sizet = sizet(i) * 17
if string.strcmp(set_buf + idx, sha1) == 0:
return count
if string.strcmp(set_buf + idx, sha1) == 0: return count
if count < StubMerger.MAX_INCLUDES_SHA1:
idx: sizet = sizet(count) * 17
string.strcpy(set_buf + idx, sha1)
+78 -156
View File
@@ -57,13 +57,11 @@ class ImportCtx:
# ============================================================
def AppendImportedModule(pool: memhub.MemBuddy*, cur: str, name: str) -> str:
"""追加模块名到空格分隔列表(pool 分配),返回新列表"""
if name is None:
return cur
if name is None: return cur
if cur is None:
nlen: sizet = string.strlen(name)
buf: str = pool.alloc(nlen + 1)
if buf is not None:
string.strcpy(buf, name)
if buf is not None: string.strcpy(buf, name)
return buf
old_len: sizet = string.strlen(cur)
name_len: sizet = string.strlen(name)
@@ -85,8 +83,7 @@ def AppendImportedModule(pool: memhub.MemBuddy*, cur: str, name: str) -> str:
def AppendFromImport(pool: memhub.MemBuddy*, cur: str,
local: str, mod: str, orig: str) -> str:
"""追加 from-import 映射(pool 分配),返回新列表"""
if local is None or mod is None:
return cur
if local is None or mod is None: return cur
llen: sizet = string.strlen(local)
mlen: sizet = string.strlen(mod)
use_orig: int = 0
@@ -96,19 +93,16 @@ def AppendFromImport(pool: memhub.MemBuddy*, cur: str,
olen = string.strlen(orig)
# local ':' mod [':' orig] '\0'
need: sizet = llen + 1 + mlen + 1
if use_orig != 0:
need += 1 + olen
if use_orig != 0: need += 1 + olen
entry: str = pool.alloc(need)
if entry is None:
return cur
if entry is None: return cur
string.strcpy(entry, local)
entry[llen] = ':'
string.strcpy(entry + llen + 1, mod)
if use_orig != 0:
entry[llen + 1 + mlen] = ':'
string.strcpy(entry + llen + 1 + mlen + 1, orig)
if cur is None:
return entry
if cur is None: return entry
old_len: sizet = string.strlen(cur)
entry_len: sizet = string.strlen(entry)
buf: str = pool.alloc(old_len + 1 + entry_len + 1)
@@ -126,8 +120,7 @@ def AllocImportCtx(pool: memhub.MemBuddy*,
imported_modules: str, from_imports: str) -> ImportCtx*:
"""构造导入上下文容器(pool 分配);两串可为 None"""
ctx: ImportCtx* = pool.alloc(ImportCtx.__sizeof__())
if ctx is None:
return None
if ctx is None: return None
ctx.ImportedModules = imported_modules
ctx.FromImports = from_imports
return ctx
@@ -144,8 +137,7 @@ def AllocImportCtx(pool: memhub.MemBuddy*,
def NotePlainImport(pool: memhub.MemBuddy*, ctx: ImportCtx*,
name: str, asname: str) -> int:
"""记账单条 import(就地更新 ctx),返回 0"""
if ctx is None or name is None:
return 1
if ctx is None or name is None: return 1
ctx.ImportedModules = AppendImportedModule(pool, ctx.ImportedModules, name)
if asname is not None:
ctx.ImportedModules = AppendImportedModule(pool, ctx.ImportedModules, asname)
@@ -178,23 +170,17 @@ def PopulateSha1MapStore(scan_result: rawptr[IncludesScanner.ScanResult]) -> int
模块名通过 _PathToModuleName(includes/rel_path) 计算。
内存用 stdlib.malloc 分配(全局存储器,不随 mbuddy 释放)。
"""
if scan_result is None:
return -1
if scan_result is None: return -1
# 释放旧存储器
if StubMerger._sha1_store_arr is not None:
stdlib.free(StubMerger._sha1_store_arr)
if StubMerger._sha1_store_mod is not None:
stdlib.free(StubMerger._sha1_store_mod)
if StubMerger._sha1_store_rel is not None:
stdlib.free(StubMerger._sha1_store_rel)
if StubMerger._sha1_store_incdir is not None:
stdlib.free(StubMerger._sha1_store_incdir)
if StubMerger._sha1_store_arr is not None: stdlib.free(StubMerger._sha1_store_arr)
if StubMerger._sha1_store_mod is not None: stdlib.free(StubMerger._sha1_store_mod)
if StubMerger._sha1_store_rel is not None: stdlib.free(StubMerger._sha1_store_rel)
if StubMerger._sha1_store_incdir is not None: stdlib.free(StubMerger._sha1_store_incdir)
StubMerger._sha1_store_arr = stdlib.malloc(StubMerger.MAX_INCLUDES * 17)
StubMerger._sha1_store_mod = stdlib.malloc(StubMerger.MAX_INCLUDES * 64)
StubMerger._sha1_store_rel = stdlib.malloc(StubMerger.MAX_INCLUDES * StubMerger.MAX_REL_PATH_LEN)
StubMerger._sha1_store_incdir = stdlib.malloc(StubMerger.MAX_INCLUDES * StubMerger.MAX_INC_DIR_LEN)
if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_mod is None or StubMerger._sha1_store_rel is None or StubMerger._sha1_store_incdir is None:
return -1
if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_mod is None or StubMerger._sha1_store_rel is None or StubMerger._sha1_store_incdir is None: return -1
string.memset(StubMerger._sha1_store_arr, 0, StubMerger.MAX_INCLUDES * 17)
string.memset(StubMerger._sha1_store_mod, 0, StubMerger.MAX_INCLUDES * 64)
string.memset(StubMerger._sha1_store_rel, 0, StubMerger.MAX_INCLUDES * StubMerger.MAX_REL_PATH_LEN)
@@ -203,8 +189,7 @@ def PopulateSha1MapStore(scan_result: rawptr[IncludesScanner.ScanResult]) -> int
p_bad: int = 0
entry_size_p: sizet = IncludesScanner.FileEntry.__sizeof__()
for i in range(scan_result.Count):
if StubMerger._sha1_store_count >= StubMerger.MAX_INCLUDES:
VLogger.error("includes SHA1 存储超上限,终止", "StubMerger")
if StubMerger._sha1_store_count >= StubMerger.MAX_INCLUDES: VLogger.error("includes SHA1 存储超上限,终止", "StubMerger")
ea: uint64 = uint64(scan_result.Entries) + i * entry_size_p
ent: rawptr[IncludesScanner.FileEntry] = rawptr[IncludesScanner.FileEntry](ea)
if ent is None or ent.Sha1 is None or ent.RelPath is None:
@@ -224,16 +209,14 @@ def PopulateSha1MapStore(scan_result: rawptr[IncludesScanner.ScanResult]) -> int
string.strcpy(StubMerger._sha1_store_arr + idx, ent.Sha1)
idx2: sizet = sizet(StubMerger._sha1_store_count) * 64
mn_len: sizet = string.strlen(mod_name)
if mn_len < 64:
string.strcpy(StubMerger._sha1_store_mod + idx2, mod_name)
if mn_len < 64: string.strcpy(StubMerger._sha1_store_mod + idx2, mod_name)
else:
string.strncpy(StubMerger._sha1_store_mod + idx2, mod_name, 63)
StubMerger._sha1_store_mod[idx2 + 63] = '\0'
stdlib.free(mod_name)
# 保存 rel_path(供 Phase2 3.5 编译缺失 includes 使用)
idx3: sizet = sizet(StubMerger._sha1_store_count) * StubMerger.MAX_REL_PATH_LEN
if rp_len < StubMerger.MAX_REL_PATH_LEN:
string.strcpy(StubMerger._sha1_store_rel + idx3, ent.RelPath)
if rp_len < StubMerger.MAX_REL_PATH_LEN: string.strcpy(StubMerger._sha1_store_rel + idx3, ent.RelPath)
else:
string.strncpy(StubMerger._sha1_store_rel + idx3, ent.RelPath, StubMerger.MAX_REL_PATH_LEN - 1)
StubMerger._sha1_store_rel[idx3 + StubMerger.MAX_REL_PATH_LEN - 1] = '\0'
@@ -241,14 +224,12 @@ def PopulateSha1MapStore(scan_result: rawptr[IncludesScanner.ScanResult]) -> int
idx_inc: sizet = sizet(StubMerger._sha1_store_count) * StubMerger.MAX_INC_DIR_LEN
if ent.IncDir is not None:
icd_len: sizet = string.strlen(ent.IncDir)
if icd_len < StubMerger.MAX_INC_DIR_LEN:
string.strcpy(StubMerger._sha1_store_incdir + idx_inc, ent.IncDir)
if icd_len < StubMerger.MAX_INC_DIR_LEN: string.strcpy(StubMerger._sha1_store_incdir + idx_inc, ent.IncDir)
else:
string.strncpy(StubMerger._sha1_store_incdir + idx_inc, ent.IncDir, StubMerger.MAX_INC_DIR_LEN - 1)
StubMerger._sha1_store_incdir[idx_inc + StubMerger.MAX_INC_DIR_LEN - 1] = '\0'
StubMerger._sha1_store_count += 1
if p_bad > 0:
VLogger.error(f"includes SHA1 存储有 {p_bad} 个条目失败", "StubMerger")
if p_bad > 0: VLogger.error(f"includes SHA1 存储有 {p_bad} 个条目失败", "StubMerger")
return StubMerger._sha1_store_count
# ============================================================
# AppendToSha1MapStore - 追加 App 模块条目到全局 SHA1 映射存储器(Phase1 先用 PopulateSha1MapStore 填 includes,
@@ -260,32 +241,27 @@ def PopulateSha1MapStore(scan_result: rawptr[IncludesScanner.ScanResult]) -> int
# ============================================================
def AppendToSha1MapStore(sha1: str, rel_path: str) -> int:
"""追加条目到全局 SHA1 映射存储器(Phase2 用)"""
if sha1 is None or rel_path is None:
return 1
if sha1 is None or rel_path is None: return 1
# 存储器未初始化:自动初始化(Phase2 可能先于 Phase1 调用)
if StubMerger._sha1_store_arr is None:
StubMerger._sha1_store_arr = stdlib.malloc(StubMerger.MAX_INCLUDES * 17)
StubMerger._sha1_store_mod = stdlib.malloc(StubMerger.MAX_INCLUDES * 64)
StubMerger._sha1_store_rel = stdlib.malloc(StubMerger.MAX_INCLUDES * StubMerger.MAX_REL_PATH_LEN)
StubMerger._sha1_store_incdir = stdlib.malloc(StubMerger.MAX_INCLUDES * StubMerger.MAX_INC_DIR_LEN)
if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_mod is None or StubMerger._sha1_store_rel is None or StubMerger._sha1_store_incdir is None:
return 1
if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_mod is None or StubMerger._sha1_store_rel is None or StubMerger._sha1_store_incdir is None: return 1
string.memset(StubMerger._sha1_store_arr, 0, StubMerger.MAX_INCLUDES * 17)
string.memset(StubMerger._sha1_store_mod, 0, StubMerger.MAX_INCLUDES * 64)
string.memset(StubMerger._sha1_store_rel, 0, StubMerger.MAX_INCLUDES * StubMerger.MAX_REL_PATH_LEN)
string.memset(StubMerger._sha1_store_incdir, 0, StubMerger.MAX_INCLUDES * StubMerger.MAX_INC_DIR_LEN)
StubMerger._sha1_store_count = 0
if StubMerger._sha1_store_count >= StubMerger.MAX_INCLUDES:
return 1
if StubMerger._sha1_store_count >= StubMerger.MAX_INCLUDES: return 1
# 模块名:rel_path "lib/core/StubMerger.vp" → "lib.core.StubMerger"
full_path_buf: bytes = stdlib.malloc(string.strlen(rel_path) + 10)
if full_path_buf is None:
return 1
if full_path_buf is None: return 1
viperlib.snprintf(full_path_buf, string.strlen(rel_path) + 10, "includes/%s", rel_path)
mod_name: str = Utils.PathToModuleName(full_path_buf, 1)
stdlib.free(full_path_buf)
if mod_name is None:
return 1
if mod_name is None: return 1
# 去重:SHA1 与模块名都相同才跳过——同一 SHA1 可能先以全路径模块名注册(App 源文件在 includes 目录下),
# App 追加的短模块名必须保留,否则 import 该模块的精确查找失败、后缀匹配会劫持到其它同名模块。
for i in range(StubMerger._sha1_store_count):
@@ -301,8 +277,7 @@ def AppendToSha1MapStore(sha1: str, rel_path: str) -> int:
# 写入模块名
idx_m: sizet = sizet(StubMerger._sha1_store_count) * 64
mn_len: sizet = string.strlen(mod_name)
if mn_len < 64:
string.strcpy(StubMerger._sha1_store_mod + idx_m, mod_name)
if mn_len < 64: string.strcpy(StubMerger._sha1_store_mod + idx_m, mod_name)
else:
string.strncpy(StubMerger._sha1_store_mod + idx_m, mod_name, 63)
StubMerger._sha1_store_mod[idx_m + 63] = '\0'
@@ -310,8 +285,7 @@ def AppendToSha1MapStore(sha1: str, rel_path: str) -> int:
# 写入相对路径
idx_r: sizet = sizet(StubMerger._sha1_store_count) * StubMerger.MAX_REL_PATH_LEN
rp_len: sizet = string.strlen(rel_path)
if rp_len < StubMerger.MAX_REL_PATH_LEN:
string.strcpy(StubMerger._sha1_store_rel + idx_r, rel_path)
if rp_len < StubMerger.MAX_REL_PATH_LEN: string.strcpy(StubMerger._sha1_store_rel + idx_r, rel_path)
else:
string.strncpy(StubMerger._sha1_store_rel + idx_r, rel_path, StubMerger.MAX_REL_PATH_LEN - 1)
StubMerger._sha1_store_rel[idx_r + StubMerger.MAX_REL_PATH_LEN - 1] = '\0'
@@ -330,46 +304,40 @@ def AppendToSha1MapStore(sha1: str, rel_path: str) -> int:
# ============================================================
def AddIncludeToSha1MapStore(sha1: str, rel_path: str, inc_dir: str, mod_name: str) -> int:
"""单条登记 includes 条目到全局 SHA1 映射存储器(依赖图按需扫描用)"""
if sha1 is None or rel_path is None or mod_name is None:
return 1
if sha1 is None or rel_path is None or mod_name is None: return 1
# 存储器未初始化:自动初始化
if StubMerger._sha1_store_arr is None:
StubMerger._sha1_store_arr = stdlib.malloc(StubMerger.MAX_INCLUDES * 17)
StubMerger._sha1_store_mod = stdlib.malloc(StubMerger.MAX_INCLUDES * 64)
StubMerger._sha1_store_rel = stdlib.malloc(StubMerger.MAX_INCLUDES * StubMerger.MAX_REL_PATH_LEN)
StubMerger._sha1_store_incdir = stdlib.malloc(StubMerger.MAX_INCLUDES * StubMerger.MAX_INC_DIR_LEN)
if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_mod is None or StubMerger._sha1_store_rel is None or StubMerger._sha1_store_incdir is None:
return 1
if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_mod is None or StubMerger._sha1_store_rel is None or StubMerger._sha1_store_incdir is None: return 1
string.memset(StubMerger._sha1_store_arr, 0, StubMerger.MAX_INCLUDES * 17)
string.memset(StubMerger._sha1_store_mod, 0, StubMerger.MAX_INCLUDES * 64)
string.memset(StubMerger._sha1_store_rel, 0, StubMerger.MAX_INCLUDES * StubMerger.MAX_REL_PATH_LEN)
string.memset(StubMerger._sha1_store_incdir, 0, StubMerger.MAX_INCLUDES * StubMerger.MAX_INC_DIR_LEN)
StubMerger._sha1_store_count = 0
if StubMerger._sha1_store_count >= StubMerger.MAX_INCLUDES:
return 1
if StubMerger._sha1_store_count >= StubMerger.MAX_INCLUDES: return 1
# 去重:SHA1 与模块名都相同才跳过(对齐 AppendToSha1MapStore)
for i in range(StubMerger._sha1_store_count):
sidx_d: sizet = sizet(i) * 17
if string.strcmp(StubMerger._sha1_store_arr + sidx_d, sha1) == 0:
midx_d: sizet = sizet(i) * 64
if string.strcmp(StubMerger._sha1_store_mod + midx_d, mod_name) == 0:
return 0
if string.strcmp(StubMerger._sha1_store_mod + midx_d, mod_name) == 0: return 0
# 写 SHA1
idx_a: sizet = sizet(StubMerger._sha1_store_count) * 17
string.strcpy(StubMerger._sha1_store_arr + idx_a, sha1)
# 写模块名
idx_m: sizet = sizet(StubMerger._sha1_store_count) * 64
mn_len: sizet = string.strlen(mod_name)
if mn_len < 64:
string.strcpy(StubMerger._sha1_store_mod + idx_m, mod_name)
if mn_len < 64: string.strcpy(StubMerger._sha1_store_mod + idx_m, mod_name)
else:
string.strncpy(StubMerger._sha1_store_mod + idx_m, mod_name, 63)
StubMerger._sha1_store_mod[idx_m + 63] = '\0'
# 写相对路径
idx_r: sizet = sizet(StubMerger._sha1_store_count) * StubMerger.MAX_REL_PATH_LEN
rp_len: sizet = string.strlen(rel_path)
if rp_len < StubMerger.MAX_REL_PATH_LEN:
string.strcpy(StubMerger._sha1_store_rel + idx_r, rel_path)
if rp_len < StubMerger.MAX_REL_PATH_LEN: string.strcpy(StubMerger._sha1_store_rel + idx_r, rel_path)
else:
string.strncpy(StubMerger._sha1_store_rel + idx_r, rel_path, StubMerger.MAX_REL_PATH_LEN - 1)
StubMerger._sha1_store_rel[idx_r + StubMerger.MAX_REL_PATH_LEN - 1] = '\0'
@@ -377,13 +345,11 @@ def AddIncludeToSha1MapStore(sha1: str, rel_path: str, inc_dir: str, mod_name: s
idx_inc: sizet = sizet(StubMerger._sha1_store_count) * StubMerger.MAX_INC_DIR_LEN
if inc_dir is not None:
icd_len: sizet = string.strlen(inc_dir)
if icd_len < StubMerger.MAX_INC_DIR_LEN:
string.strcpy(StubMerger._sha1_store_incdir + idx_inc, inc_dir)
if icd_len < StubMerger.MAX_INC_DIR_LEN: string.strcpy(StubMerger._sha1_store_incdir + idx_inc, inc_dir)
else:
string.strncpy(StubMerger._sha1_store_incdir + idx_inc, inc_dir, StubMerger.MAX_INC_DIR_LEN - 1)
StubMerger._sha1_store_incdir[idx_inc + StubMerger.MAX_INC_DIR_LEN - 1] = '\0'
else:
StubMerger._sha1_store_incdir[idx_inc] = '\0'
else: StubMerger._sha1_store_incdir[idx_inc] = '\0'
StubMerger._sha1_store_count += 1
return 0
# ============================================================
@@ -446,26 +412,21 @@ def RegisterGenericOwner(cls_name: str, mod_sha1: str) -> int:
同名异 sha1(跨模块同名泛型类)保留首个,与泛型模板表按类名去重的口径一致。
"""
global _generic_owner_names, _generic_owner_sha1s, _generic_owner_count
if cls_name is None or mod_sha1 is None:
return 0
if cls_name[0] == '\0' or mod_sha1[0] == '\0':
return 0
if cls_name is None or mod_sha1 is None: return 0
if cls_name[0] == '\0' or mod_sha1[0] == '\0': return 0
if _generic_owner_names is None:
_generic_owner_names = stdlib.malloc(GENERIC_OWNER_MAX * 64)
_generic_owner_sha1s = stdlib.malloc(GENERIC_OWNER_MAX * 17)
if _generic_owner_names is None or _generic_owner_sha1s is None:
return 0
if _generic_owner_names is None or _generic_owner_sha1s is None: return 0
string.memset(_generic_owner_names, 0, GENERIC_OWNER_MAX * 64)
string.memset(_generic_owner_sha1s, 0, GENERIC_OWNER_MAX * 17)
_generic_owner_count = 0
i_go: int
for i_go in range(_generic_owner_count):
if string.strcmp(_generic_owner_names + sizet(i_go) * 64, cls_name) == 0:
if string.strcmp(_generic_owner_sha1s + sizet(i_go) * 17, mod_sha1) == 0:
return 1
if string.strcmp(_generic_owner_sha1s + sizet(i_go) * 17, mod_sha1) == 0: return 1
return 0
if _generic_owner_count >= GENERIC_OWNER_MAX:
return 0
if _generic_owner_count >= GENERIC_OWNER_MAX: return 0
string.strncpy(_generic_owner_names + sizet(_generic_owner_count) * 64, cls_name, 63)
string.strncpy(_generic_owner_sha1s + sizet(_generic_owner_count) * 17, mod_sha1, 16)
_generic_owner_count += 1
@@ -474,12 +435,10 @@ def RegisterGenericOwner(cls_name: str, mod_sha1: str) -> int:
def LookupGenericOwnerSha1(cls_name: str) -> str:
"""按泛型类名取定义模块 SHA1(返回内部指针,无需释放;未登记 None)"""
if cls_name is None or _generic_owner_names is None:
return None
if cls_name is None or _generic_owner_names is None: return None
i_lg: int
for i_lg in range(_generic_owner_count):
if string.strcmp(_generic_owner_names + sizet(i_lg) * 64, cls_name) == 0:
return _generic_owner_sha1s + sizet(i_lg) * 17
if string.strcmp(_generic_owner_names + sizet(i_lg) * 64, cls_name) == 0: return _generic_owner_sha1s + sizet(i_lg) * 17
return None
# ============================================================
# LookupSha1ByModNameSuffix - 后缀匹配查找模块 SHA1(用于 from .X import Y:impf.module 是 ".X",而映射表键是 "pkg.X")
@@ -489,22 +448,17 @@ def LookupGenericOwnerSha1(cls_name: str) -> str:
# ============================================================
def LookupSha1ByModNameSuffix(mod_suffix: str) -> str:
"""后缀匹配查找模块 SHA1"""
if mod_suffix is None:
return None
if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_mod is None:
return None
if StubMerger._sha1_store_count <= 0:
return None
if mod_suffix is None: return None
if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_mod is None: return None
if StubMerger._sha1_store_count <= 0: return None
suffix_len_sf: sizet = string.strlen(mod_suffix)
if suffix_len_sf == 0:
return None
if suffix_len_sf == 0: return None
i_sf: int
for i_sf in range(StubMerger._sha1_store_count):
idx_sf: sizet = sizet(i_sf) * 64
mod_name_sf: str = StubMerger._sha1_store_mod + idx_sf
mod_len_sf: sizet = string.strlen(mod_name_sf)
if mod_len_sf == 0:
continue
if mod_len_sf == 0: continue
# 精确匹配
if mod_len_sf == suffix_len_sf:
if string.strcmp(mod_name_sf, mod_suffix) == 0:
@@ -534,23 +488,18 @@ def LookupSha1ByModNameSuffix(mod_suffix: str) -> str:
# ============================================================
def LookupSha1ByAlias(from_imports: str, alias: str) -> str:
"""从 from_imports 别名映射解析模块 SHA1(改名别名 import X as Y 场景)"""
if from_imports is None or alias is None:
return None
if from_imports is None or alias is None: return None
alias_len: sizet = string.strlen(alias)
if alias_len == 0:
return None
if alias_len == 0: return None
total_len: sizet = string.strlen(from_imports)
ci: sizet = 0
while ci < total_len:
# 跳过前导空格
while ci < total_len and from_imports[ci] == ' ':
ci += 1
if ci >= total_len:
break
while ci < total_len and from_imports[ci] == ' ': ci += 1
if ci >= total_len: break
# 条目起点 ci,找 ':'(local_name 结束)
colon: sizet = ci
while colon < total_len and from_imports[colon] != ':' and from_imports[colon] != ' ':
colon += 1
while colon < total_len and from_imports[colon] != ':' and from_imports[colon] != ' ': colon += 1
local_len: sizet = colon - ci
if colon < total_len and from_imports[colon] == ':' and local_len == alias_len:
# 比较 local_name == alias
@@ -565,8 +514,7 @@ def LookupSha1ByAlias(from_imports: str, alias: str) -> str:
# 提取 module(colon+1 到下一个 ':' 或空格)
m_start: sizet = colon + 1
m_end: sizet = m_start
while m_end < total_len and from_imports[m_end] != ':' and from_imports[m_end] != ' ':
m_end += 1
while m_end < total_len and from_imports[m_end] != ':' and from_imports[m_end] != ' ': m_end += 1
if m_end > m_start:
mbuf: str = stdlib.malloc(m_end - m_start + 1)
if mbuf is not None:
@@ -577,8 +525,7 @@ def LookupSha1ByAlias(from_imports: str, alias: str) -> str:
return res
return None
# 跳到下一条目
while ci < total_len and from_imports[ci] != ' ':
ci += 1
while ci < total_len and from_imports[ci] != ' ': ci += 1
return None
# ============================================================
# LookupModNameByAlias - 从 from_imports 别名映射解析模块真名
@@ -589,23 +536,18 @@ def LookupSha1ByAlias(from_imports: str, alias: str) -> str:
# ============================================================
def LookupModNameByAlias(from_imports: str, alias: str) -> str:
"""从 from_imports 别名映射解析模块真名(import X as Y → Y:X)"""
if from_imports is None or alias is None:
return None
if from_imports is None or alias is None: return None
alias_len: sizet = string.strlen(alias)
if alias_len == 0:
return None
if alias_len == 0: return None
total_len: sizet = string.strlen(from_imports)
ci: sizet = 0
while ci < total_len:
# 跳过前导空格
while ci < total_len and from_imports[ci] == ' ':
ci += 1
if ci >= total_len:
break
while ci < total_len and from_imports[ci] == ' ': ci += 1
if ci >= total_len: break
# 条目起点 ci,找 ':'(local_name 结束)
colon: sizet = ci
while colon < total_len and from_imports[colon] != ':' and from_imports[colon] != ' ':
colon += 1
while colon < total_len and from_imports[colon] != ':' and from_imports[colon] != ' ': colon += 1
local_len: sizet = colon - ci
if colon < total_len and from_imports[colon] == ':' and local_len == alias_len:
# 比较 local_name == alias
@@ -620,8 +562,7 @@ def LookupModNameByAlias(from_imports: str, alias: str) -> str:
# 提取 module(colon+1 到下一个 ':' 或空格)
m_start: sizet = colon + 1
m_end: sizet = m_start
while m_end < total_len and from_imports[m_end] != ':' and from_imports[m_end] != ' ':
m_end += 1
while m_end < total_len and from_imports[m_end] != ':' and from_imports[m_end] != ' ': m_end += 1
if m_end > m_start:
mbuf: str = stdlib.malloc(m_end - m_start + 1)
if mbuf is not None:
@@ -630,8 +571,7 @@ def LookupModNameByAlias(from_imports: str, alias: str) -> str:
return mbuf
return None
# 跳到下一条目
while ci < total_len and from_imports[ci] != ' ':
ci += 1
while ci < total_len and from_imports[ci] != ' ': ci += 1
return None
# ============================================================
# PopulateIncludesDeps - 将 includes 文件的依赖存入内存
@@ -642,24 +582,20 @@ def LookupModNameByAlias(from_imports: str, alias: str) -> str:
# ============================================================
def PopulateIncludesDeps(sha1: str, deps_str: str) -> int:
"""将 includes 文件的依赖存入内存"""
if sha1 is None:
return 1
if sha1 is None: return 1
# 延迟初始化
if StubMerger._includes_deps_sha1 is None:
StubMerger._includes_deps_sha1 = stdlib.malloc(StubMerger.MAX_INCLUDES * 17)
StubMerger._includes_deps_str = stdlib.malloc(StubMerger.MAX_INCLUDES * StubMerger.MAX_DEPS_STR_LEN)
if StubMerger._includes_deps_sha1 is None or StubMerger._includes_deps_str is None:
return 1
if StubMerger._includes_deps_sha1 is None or StubMerger._includes_deps_str is None: return 1
string.memset(StubMerger._includes_deps_sha1, 0, StubMerger.MAX_INCLUDES * 17)
string.memset(StubMerger._includes_deps_str, 0, StubMerger.MAX_INCLUDES * StubMerger.MAX_DEPS_STR_LEN)
StubMerger._includes_deps_count = 0
if StubMerger._includes_deps_count >= StubMerger.MAX_INCLUDES:
return 1
if StubMerger._includes_deps_count >= StubMerger.MAX_INCLUDES: return 1
# 去重:若 SHA1 已存在则跳过
for i in range(StubMerger._includes_deps_count):
sidx: sizet = sizet(i) * 17
if string.strcmp(StubMerger._includes_deps_sha1 + sidx, sha1) == 0:
return 0
if string.strcmp(StubMerger._includes_deps_sha1 + sidx, sha1) == 0: return 0
# 写入 SHA1
idx: sizet = sizet(StubMerger._includes_deps_count) * 17
string.strcpy(StubMerger._includes_deps_sha1 + idx, sha1)
@@ -667,12 +603,9 @@ def PopulateIncludesDeps(sha1: str, deps_str: str) -> int:
idx2: sizet = sizet(StubMerger._includes_deps_count) * StubMerger.MAX_DEPS_STR_LEN
if deps_str is not None:
dl: sizet = string.strlen(deps_str)
if dl < StubMerger.MAX_DEPS_STR_LEN:
string.strcpy(StubMerger._includes_deps_str + idx2, deps_str)
else:
string.strncpy(StubMerger._includes_deps_str + idx2, deps_str, StubMerger.MAX_DEPS_STR_LEN - 1)
else:
StubMerger._includes_deps_str[idx2] = '\0'
if dl < StubMerger.MAX_DEPS_STR_LEN: string.strcpy(StubMerger._includes_deps_str + idx2, deps_str)
else: string.strncpy(StubMerger._includes_deps_str + idx2, deps_str, StubMerger.MAX_DEPS_STR_LEN - 1)
else: StubMerger._includes_deps_str[idx2] = '\0'
StubMerger._includes_deps_count = StubMerger._includes_deps_count + 1
return 0
# ============================================================
@@ -686,10 +619,8 @@ def PopulateIncludesDeps(sha1: str, deps_str: str) -> int:
# ============================================================
def LookupIncludesDeps(sha1: str) -> str:
"""从内存查找 includes 文件的依赖"""
if sha1 is None or StubMerger._includes_deps_sha1 is None:
return None
if StubMerger._includes_deps_count <= 0:
return None
if sha1 is None or StubMerger._includes_deps_sha1 is None: return None
if StubMerger._includes_deps_count <= 0: return None
for i in range(StubMerger._includes_deps_count):
sidx: sizet = sizet(i) * 17
if string.strcmp(StubMerger._includes_deps_sha1 + sidx, sha1) == 0:
@@ -721,19 +652,14 @@ def GetSha1StoreArr(out_sha1_arr: rawptr[t.CPtr], out_mod_arr: rawptr[t.CPtr], o
out_sha1_arr/out_mod_arr/out_rel_arr 是调用者提供的 t.CPtr 槽的地址(t.CPtr*),
函数把存储器数组指针写入这些槽。返回条目数,-1 失败
"""
if out_sha1_arr is None or out_mod_arr is None or out_rel_arr is None:
return -1
if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_mod is None or StubMerger._sha1_store_rel is None:
return -1
if out_sha1_arr is None or out_mod_arr is None or out_rel_arr is None: return -1
if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_mod is None or StubMerger._sha1_store_rel is None: return -1
sp: rawptr[t.CPtr] = out_sha1_arr
if sp is not None:
sp[0] = StubMerger._sha1_store_arr
if sp is not None: sp[0] = StubMerger._sha1_store_arr
mp: rawptr[t.CPtr] = out_mod_arr
if mp is not None:
mp[0] = StubMerger._sha1_store_mod
if mp is not None: mp[0] = StubMerger._sha1_store_mod
rp: rawptr[t.CPtr] = out_rel_arr
if rp is not None:
rp[0] = StubMerger._sha1_store_rel
if rp is not None: rp[0] = StubMerger._sha1_store_rel
return StubMerger._sha1_store_count
# ============================================================
@@ -745,10 +671,8 @@ def GetSha1StoreArr(out_sha1_arr: rawptr[t.CPtr], out_mod_arr: rawptr[t.CPtr], o
# ============================================================
def LookupSha1RelPath(sha1: str) -> str:
"""通过 SHA1 查找相对路径,返回只读指针,None=未找到"""
if sha1 is None:
return None
if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_rel is None:
return None
if sha1 is None: return None
if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_rel is None: return None
for i in range(StubMerger._sha1_store_count):
sidx: sizet = sizet(i) * 17
if string.strcmp(StubMerger._sha1_store_arr + sidx, sha1) == 0:
@@ -776,10 +700,8 @@ def LookupSha1RelPath(sha1: str) -> str:
# ============================================================
def LookupModNameBySha1(sha1: str) -> str:
"""通过 SHA1 查找模块名,返回只读指针,None=未找到"""
if sha1 is None or sha1[0] == '\0':
return None
if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_mod is None:
return None
if sha1 is None or sha1[0] == '\0': return None
if StubMerger._sha1_store_arr is None or StubMerger._sha1_store_mod is None: return None
for i in range(StubMerger._sha1_store_count):
sidx_mb: sizet = sizet(i) * 17
if string.strcmp(StubMerger._sha1_store_arr + sidx_mb, sha1) == 0:
+15 -30
View File
@@ -46,18 +46,14 @@ def BuildTopoSortedIndices(store_count: int, store_sha1_arr: bytes,
reachable_count: int,
sorted_idx: sizet*) -> int:
"""对可达 includes 逆拓扑排序(被依赖者先),store 索引写入 sorted_idx"""
if store_count <= 0 or store_sha1_arr is None or store_mod_arr is None or sorted_idx is None:
return 0
if store_count <= 0 or store_sha1_arr is None or store_mod_arr is None or sorted_idx is None: return 0
indegree: sizet* = (sizet*)(stdlib.malloc(8 * (store_count + 1)))
queue: sizet* = (sizet*)(stdlib.malloc(8 * (store_count + 1)))
rel_idx: sizet* = (sizet*)(stdlib.malloc(8 * (store_count + 1)))
if indegree is None or queue is None or rel_idx is None:
if indegree is not None:
stdlib.free(indegree)
if queue is not None:
stdlib.free(queue)
if rel_idx is not None:
stdlib.free(rel_idx)
if indegree is not None: stdlib.free(indegree)
if queue is not None: stdlib.free(queue)
if rel_idx is not None: stdlib.free(rel_idx)
return 0
# 清零 indegree/queue/rel_idx(malloc 返回未初始化内存,Kahn 依赖入度初值 0)
zi: int = 0
@@ -82,22 +78,17 @@ def BuildTopoSortedIndices(store_count: int, store_sha1_arr: bytes,
for i_r in range(rel_count):
si: int = rel_idx[i_r]
deps_si: str = StubMergerStore.LookupIncludesDeps(store_sha1_arr + sizet(si) * 17)
if deps_si is None:
continue
if deps_si is None: continue
dl_si: sizet = string.strlen(deps_si)
dpos: sizet = 0
while dpos < dl_si:
dstart: sizet = dpos
while dpos < dl_si and deps_si[dpos] != ' ':
dpos += 1
while dpos < dl_si and deps_si[dpos] != ' ': dpos += 1
dlen: sizet = dpos - dstart
if dpos < dl_si:
dpos += 1
if dlen == 0:
continue
if dpos < dl_si: dpos += 1
if dlen == 0: continue
dname_buf: bytes = stdlib.malloc(dlen + 1)
if dname_buf is None:
continue
if dname_buf is None: continue
string.strncpy(dname_buf, deps_si + dstart, dlen)
dname_buf[dlen] = '\0'
dsha1: str = StubMergerIR._FindSha1ByModName(store_sha1_arr, store_mod_arr, store_count, dname_buf)
@@ -127,25 +118,19 @@ def BuildTopoSortedIndices(store_count: int, store_sha1_arr: bytes,
mod_m_len: sizet = string.strlen(mod_m)
for i_r in range(rel_count):
si3: int = rel_idx[i_r]
if indegree[si3] == 0:
continue
if indegree[si3] == 0: continue
deps_si3: str = StubMergerStore.LookupIncludesDeps(store_sha1_arr + sizet(si3) * 17)
if deps_si3 is None:
continue
if deps_si3 is None: continue
dl_si3: sizet = string.strlen(deps_si3)
dpos3: sizet = 0
found_dep: int = 0
while dpos3 < dl_si3 and found_dep == 0:
dstart3: sizet = dpos3
while dpos3 < dl_si3 and deps_si3[dpos3] != ' ':
dpos3 += 1
while dpos3 < dl_si3 and deps_si3[dpos3] != ' ': dpos3 += 1
dlen3: sizet = dpos3 - dstart3
if dpos3 < dl_si3:
dpos3 += 1
if dlen3 == 0:
continue
if dlen3 == mod_m_len and string.strncmp(deps_si3 + dstart3, mod_m, mod_m_len) == 0:
found_dep = 1
if dpos3 < dl_si3: dpos3 += 1
if dlen3 == 0: continue
if dlen3 == mod_m_len and string.strncmp(deps_si3 + dstart3, mod_m, mod_m_len) == 0: found_dep = 1
if found_dep == 1:
# 中间 int 变量递减:绕过联合类型指针算术编译 bug
indg3: int = indegree[si3]