diff --git a/App/lib/core/Handles/HandlesIf.vp b/App/lib/core/Handles/HandlesIf.vp index 597a85d..cd02215 100644 --- a/App/lib/core/Handles/HandlesIf.vp +++ b/App/lib/core/Handles/HandlesIf.vp @@ -10,6 +10,365 @@ import lib.core.Handles.HandlesBase as HandlesBase import lib.core.Handles.HandlesTranslator as HT import lib.core.Handles.HandlesExpr as HandlesExpr import lib.core.Handles.HandlesBody as HandlesBody +import lib.core.Handles.HandlesType as HandlesType +import lib.core.Handles.HandlesImports as HandlesImports +import lib.Projectrans.Config as Config + + +# ============================================================ +# 编译期宏条件: if c.CIf(...) / c.CIfdef(...) / c.CIfndef(...) +# +# 对齐 TPC HandlesIf.py:编译期求值命中分支并剪枝(不发射运行时 IR)。 +# c.CIf(expr) → 常量表达式求值(CDefine/平台宏/算术/比较/逻辑) +# c.CIfdef(NAME) → NAME 已定义?(本地 CDefine / 跨模块 CDefine / 平台宏) +# c.CIfndef(NAME) → NAME 未定义? ← 未定义名特判:返回"未定义"而非报错 +# +# 求值失败(如运行时变量 val == 1)→ 回退运行时翻译 +# (c.CIf 由 HandlesExprCall.translate_call 特判翻译成运行时真值, +# c.CIfdef/c.CIfndef 运行时恒真,对齐 TPC HandlesExprCall.py L2434-2446)。 +# ============================================================ + +_g_cif_eval_ok: int = 0 + + +def _is_cif_attr(attr: str) -> int: + """检查方法名是否为 CIf 系(CIf/CIfdef/CIfndef)""" + if attr is None: + return 0 + if string.strcmp(attr, "CIf") == 0: return 1 + if string.strcmp(attr, "CIfdef") == 0: return 1 + if string.strcmp(attr, "CIfndef") == 0: return 1 + return 0 + + +def _is_cif_call(node: ast.AST | t.CPtr) -> int: + """检查 test 是否为 c.CIf(...)/c.CIfdef(...)/c.CIfndef(...)(或裸 CIf 系)调用""" + if node is None or node.kind() != ast.ASTKind.Call: + return 0 + cl: ast.Call | t.CPtr = (ast.Call | t.CPtr)(node) + if cl.func is None: + return 0 + fk: int = cl.func.kind() + if fk == ast.ASTKind.Attribute: + at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(cl.func) + if at.attr is None: + return 0 + if at.value is not None and at.value.kind() == ast.ASTKind.Name: + vn: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value) + if vn.id is not None and string.strcmp(vn.id, "c") == 0: + return _is_cif_attr(at.attr) + return 0 + if fk == ast.ASTKind.Name: + nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(cl.func) + if nm.id is not None and _is_cif_attr(nm.id) != 0: + return 1 + return 0 + + +def _get_platform_macro_value(name: str) -> int: + """平台内置宏值(从目标三元组推导,对齐 TPC HandlesIf._get_platform_macros)。 + + 命中置 _g_cif_eval_ok=1;未命中置 0 返回 0。 + """ + global _g_cif_eval_ok + _g_cif_eval_ok = 0 + if name is None: + return 0 + triple: str = Config.TargetTriple + if triple is None: + triple = "x86_64-pc-windows-gnu" + is_win: int = 0 + is_linux: int = 0 + is_x64: int = 0 + if string.strstr(triple, "windows") is not None \ + or string.strstr(triple, "win32") is not None \ + or string.strstr(triple, "mingw") is not None \ + or string.strstr(triple, "msvc") is not None: + is_win = 1 + if string.strstr(triple, "linux") is not None: + is_linux = 1 + if string.strstr(triple, "x86_64") is not None: + is_x64 = 1 + # 简化:本编译目标为 x86_64 Windows(_WIN64/WIN64 恒与 is_win 一致) + if string.strcmp(name, "_WIN32") == 0: _g_cif_eval_ok = is_win; return 1 if is_win else 0 + if string.strcmp(name, "WIN32") == 0: _g_cif_eval_ok = is_win; return 1 if is_win else 0 + if string.strcmp(name, "_WIN64") == 0: _g_cif_eval_ok = is_win; return 1 if is_win else 0 + if string.strcmp(name, "WIN64") == 0: _g_cif_eval_ok = is_win; return 1 if is_win else 0 + if string.strcmp(name, "__linux__") == 0: _g_cif_eval_ok = is_linux; return 1 if is_linux else 0 + if string.strcmp(name, "__x86_64__") == 0: _g_cif_eval_ok = is_x64; return 1 if is_x64 else 0 + if string.strcmp(name, "__x86_64") == 0: _g_cif_eval_ok = is_x64; return 1 if is_x64 else 0 + if string.strcmp(name, "_M_X64") == 0: _g_cif_eval_ok = is_x64; return 1 if is_x64 else 0 + if string.strcmp(name, "SIZEOF_VOID_P") == 0: _g_cif_eval_ok = 1; return 8 if is_x64 else 4 + if string.strcmp(name, "__SIZEOF_POINTER__") == 0: _g_cif_eval_ok = 1; return 8 if is_x64 else 4 + if string.strcmp(name, "NDEBUG") == 0: _g_cif_eval_ok = 1; return 0 + return 0 + + +def _cif_name_value(pool: memhub.MemBuddy | t.CPtr, + trans: HT.Translator | t.CPtr, + name: str) -> int: + """查宏名值: 本地 CDefine → 跨模块 CDefine → 平台宏。 + + 命中置 _g_cif_eval_ok=1(值 0 也算命中,如 DISABLED=0);未命中置 0。 + """ + global _g_cif_eval_ok + _g_cif_eval_ok = 0 + if name is None or trans is None: + return 0 + v: int = HandlesType.lookup_cdefine_constant(name) + if HandlesType.is_cdefine_found() != 0: + _g_cif_eval_ok = 1 + return v + v2: int = HandlesExpr._lookup_cross_module_cdefine( + pool, name, trans._from_imports, trans._imported_modules) + if HandlesType.is_cdefine_found() != 0: + _g_cif_eval_ok = 1 + return v2 + pv: int = _get_platform_macro_value(name) + if _g_cif_eval_ok != 0: + return pv + return 0 + + +def _cif_attr_value(pool: memhub.MemBuddy | t.CPtr, + trans: HT.Translator | t.CPtr, + at: ast.Attribute | t.CPtr) -> int: + """Attribute 宏值: platmacro.IS_WINDOWS → 本地 CDefine(attr) → 跨模块 CDefine。 + + 命中置 _g_cif_eval_ok=1;未命中置 0。 + """ + global _g_cif_eval_ok + _g_cif_eval_ok = 0 + if at is None or at.attr is None or at.value is None or trans is None: + return 0 + if at.value.kind() != ast.ASTKind.Name: + return 0 + vn: ast.Name | t.CPtr = (ast.Name | t.CPtr)(at.value) + if vn.id is None: + return 0 + v: int = HandlesType.lookup_cdefine_constant(at.attr) + if HandlesType.is_cdefine_found() != 0: + _g_cif_eval_ok = 1 + return v + # 跨模块: 确定真实模块名(解析 from_imports 别名) + real_mod: str = vn.id + if trans._from_imports is not None: + resolved: str = HandlesImports.lookup_from_import( + trans._from_imports, vn.id, 0) + if resolved is not None: + rm_len: t.CSizeT = 0 + while resolved[rm_len] != ' ' and resolved[rm_len] != '\0' and resolved[rm_len] != ':': + rm_len += 1 + rm_buf: str = pool.alloc(rm_len + 1) + if rm_buf is not None: + for rm_i in range(rm_len): + rm_buf[rm_i] = resolved[rm_i] + rm_buf[rm_len] = '\0' + real_mod = rm_buf + fi_len: t.CSizeT = string.strlen(at.attr) + string.strlen(real_mod) + 2 + fi: str = pool.alloc(fi_len) + if fi is None: + return 0 + viperlib.snprintf(fi, fi_len, "%s:%s", at.attr, real_mod) + v2: int = HandlesExpr._lookup_cross_module_cdefine(pool, at.attr, fi) + if HandlesType.is_cdefine_found() != 0: + _g_cif_eval_ok = 1 + return v2 + return 0 + + +def _cif_eval_node(pool: memhub.MemBuddy | t.CPtr, + trans: HT.Translator | t.CPtr, + node: ast.AST | t.CPtr) -> int: + """递归常量求值 CIf 表达式。 + + 支持: Constant(int) / Name(CDefine/跨模块/平台宏) / Attribute(跨模块 CDefine) + / BinOp(+ - * // % & | ^ << >>) / Compare(== != < > <= >=) + / BoolOp(and/or) / UnaryOp(not - + ~)。 + 成功置 _g_cif_eval_ok=1;失败(含运行时变量)置 0 返回 0。 + """ + global _g_cif_eval_ok + if node is None: + _g_cif_eval_ok = 0 + return 0 + k: int = node.kind() + if k == ast.ASTKind.Constant: + cn: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(node) + if cn.const_kind == ast.CONST_INT: + _g_cif_eval_ok = 1 + return cn.int_val + _g_cif_eval_ok = 0 + return 0 + if k == ast.ASTKind.Name: + nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(node) + if nm.id is None: + _g_cif_eval_ok = 0 + return 0 + return _cif_name_value(pool, trans, nm.id) + if k == ast.ASTKind.Attribute: + at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(node) + return _cif_attr_value(pool, trans, at) + if k == ast.ASTKind.UnaryOp: + uop: ast.UnaryOp | t.CPtr = (ast.UnaryOp | t.CPtr)(node) + if uop.operand is None: + _g_cif_eval_ok = 0 + return 0 + ov: int = _cif_eval_node(pool, trans, uop.operand) + if _g_cif_eval_ok == 0: + return 0 + if uop.op == ast.OpKind.Not: return 1 if ov == 0 else 0 + if uop.op == ast.OpKind.USub: return -ov + if uop.op == ast.OpKind.UAdd: return ov + if uop.op == ast.OpKind.Invert: return ~ov + _g_cif_eval_ok = 0 + return 0 + if k == ast.ASTKind.BoolOp: + bo: ast.BoolOp | t.CPtr = (ast.BoolOp | t.CPtr)(node) + vals: list[ast.AST | t.CPtr] | t.CPtr = bo.values + if vals is None: + _g_cif_eval_ok = 0 + return 0 + bn: t.CSizeT = vals.__len__() + if bo.op == ast.OpKind.And: + for bi in range(bn): + rv: int = _cif_eval_node(pool, trans, vals.get(bi)) + if _g_cif_eval_ok == 0: + return 0 + if rv == 0: + return 0 + return 1 + if bo.op == ast.OpKind.Or: + for bi in range(bn): + rv: int = _cif_eval_node(pool, trans, vals.get(bi)) + if _g_cif_eval_ok == 0: + return 0 + if rv != 0: + return 1 + return 0 + _g_cif_eval_ok = 0 + return 0 + if k == ast.ASTKind.Compare: + cmp: ast.Compare | t.CPtr = (ast.Compare | t.CPtr)(node) + lv: int = _cif_eval_node(pool, trans, cmp.left) + if _g_cif_eval_ok == 0: + return 0 + ops_list: list[t.CInt] | t.CPtr = (list[t.CInt] | t.CPtr)(cmp.ops) + comps: list[ast.AST | t.CPtr] | t.CPtr = cmp.comparators + if ops_list is None or comps is None: + _g_cif_eval_ok = 0 + return 0 + cc: t.CSizeT = comps.__len__() + ci: t.CSizeT + for ci in range(cc): + rv: int = _cif_eval_node(pool, trans, comps.get(ci)) + if _g_cif_eval_ok == 0: + return 0 + op_id: int = ops_list.get(ci) + ok_cmp: int = 0 + if op_id == ast.OpKind.Eq: ok_cmp = 1 if lv == rv else 0 + elif op_id == ast.OpKind.Ne: ok_cmp = 1 if lv != rv else 0 + elif op_id == ast.OpKind.Lt: ok_cmp = 1 if lv < rv else 0 + elif op_id == ast.OpKind.Le: ok_cmp = 1 if lv <= rv else 0 + elif op_id == ast.OpKind.Gt: ok_cmp = 1 if lv > rv else 0 + elif op_id == ast.OpKind.Ge: ok_cmp = 1 if lv >= rv else 0 + else: + _g_cif_eval_ok = 0 + return 0 + if ok_cmp == 0: + return 0 + lv = rv + return 1 + if k == ast.ASTKind.BinOp: + bop: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(node) + lv: int = _cif_eval_node(pool, trans, bop.left) + if _g_cif_eval_ok == 0: + return 0 + rv: int = _cif_eval_node(pool, trans, bop.right) + if _g_cif_eval_ok == 0: + return 0 + if bop.op == ast.OpKind.Add: return lv + rv + if bop.op == ast.OpKind.Sub: return lv - rv + if bop.op == ast.OpKind.Mult: return lv * rv + if bop.op == ast.OpKind.FloorDiv: + if rv == 0: + _g_cif_eval_ok = 0 + return 0 + return lv // rv + if bop.op == ast.OpKind.Mod: + if rv == 0: + _g_cif_eval_ok = 0 + return 0 + return lv % rv + if bop.op == ast.OpKind.BitAnd: return lv & rv + if bop.op == ast.OpKind.BitOr: return lv | rv + if bop.op == ast.OpKind.BitXor: return lv ^ rv + if bop.op == ast.OpKind.LShift: return lv << rv + if bop.op == ast.OpKind.RShift: return lv >> rv + _g_cif_eval_ok = 0 + return 0 + _g_cif_eval_ok = 0 + return 0 + + +def _evaluate_cif_test(pool: memhub.MemBuddy | t.CPtr, + trans: HT.Translator | t.CPtr, + test: ast.AST | t.CPtr) -> int: + """求值 CIf 调用(test 必须是 c.CIf 系调用)。 + + 成功: 置 _g_cif_eval_ok=1,返回条件值(0/1) + 失败(运行时变量/未知结构): 置 _g_cif_eval_ok=0,返回 0 + """ + global _g_cif_eval_ok + _g_cif_eval_ok = 0 + cl: ast.Call | t.CPtr = (ast.Call | t.CPtr)(test) + if cl is None or cl.func is None: + return 0 + kind: str = None + fk: int = cl.func.kind() + if fk == ast.ASTKind.Attribute: + at: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(cl.func) + kind = at.attr + elif fk == ast.ASTKind.Name: + nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(cl.func) + kind = nm.id + if kind is None: + return 0 + cargs: list[ast.AST | t.CPtr] | t.CPtr = cl.args + if cargs is None or cargs.__len__() < 1: + return 0 + arg0: ast.AST | t.CPtr = cargs.get(0) + if string.strcmp(kind, "CIf") == 0: + v: int = _cif_eval_node(pool, trans, arg0) + if _g_cif_eval_ok == 0: + return 0 + return 1 if v != 0 else 0 + # CIfdef / CIfndef: 判定宏名是否已定义 + defined: int = 0 + if arg0 is not None and arg0.kind() == ast.ASTKind.Name: + nm0: ast.Name | t.CPtr = (ast.Name | t.CPtr)(arg0) + if nm0.id is None: + return 0 + _cif_name_value(pool, trans, nm0.id) + defined = _g_cif_eval_ok + elif arg0 is not None and arg0.kind() == ast.ASTKind.Constant: + cn0: ast.Constant | t.CPtr = (ast.Constant | t.CPtr)(arg0) + if cn0.const_kind == ast.CONST_STR and cn0.str_val is not None: + _cif_name_value(pool, trans, cn0.str_val) + defined = _g_cif_eval_ok + else: + return 0 + elif arg0 is not None and arg0.kind() == ast.ASTKind.Attribute: + at0: ast.Attribute | t.CPtr = (ast.Attribute | t.CPtr)(arg0) + _cif_attr_value(pool, trans, at0) + defined = _g_cif_eval_ok + else: + return 0 + # 定义判定本身成功(未定义名特判:不报错,defined=0 走 else) + _g_cif_eval_ok = 1 + if string.strcmp(kind, "CIfdef") == 0: + return 1 if defined != 0 else 0 + # CIfndef + return 0 if defined != 0 else 1 # ============================================================ @@ -52,6 +411,39 @@ class IfHandle(HandlesBase.Mixin): if_node: ast.If | t.CPtr = (ast.If | t.CPtr)(node) + # 0. 编译期宏条件: if c.CIf(...) / c.CIfdef(...) / c.CIfndef(...) + # 求值成功 → 只编译命中的分支(剪枝,不发射运行时 IR),elif 递归 + # 求值失败(运行时变量等)→ 回退运行时翻译 + if _is_cif_call(if_node.test) == 1: + cif_val: int = _evaluate_cif_test(pool, trans, if_node.test) + if _g_cif_eval_ok != 0: + if cif_val != 0: + body_cif: list[ast.AST | t.CPtr] | t.CPtr = if_node.children + if body_cif is not None: + bc_cif: t.CSizeT = body_cif.__len__() + bi_cif: t.CSizeT + for bi_cif in range(bc_cif): + stmt_cif: ast.AST | t.CPtr = body_cif.get(bi_cif) + if stmt_cif is not None: + HandlesBody.translate_stmt(trans, stmt_cif) + else: + orelse_cif: list[ast.AST | t.CPtr] | t.CPtr = if_node.orelse + if orelse_cif is not None and orelse_cif.__len__() == 1: + sub_cif: ast.AST | t.CPtr = orelse_cif.get(0) + if sub_cif is not None and sub_cif.kind() == ast.ASTKind.If: + # elif: 递归(子 If 的 test 仍会走 CIf 判定或运行时翻译) + self.Handle(sub_cif) + elif sub_cif is not None: + HandlesBody.translate_stmt(trans, sub_cif) + elif orelse_cif is not None: + oc_cif: t.CSizeT = orelse_cif.__len__() + oi_cif: t.CSizeT + for oi_cif in range(oc_cif): + stmt_cif2: ast.AST | t.CPtr = orelse_cif.get(oi_cif) + if stmt_cif2 is not None: + HandlesBody.translate_stmt(trans, stmt_cif2) + return 0 + # 1. 求值条件表达式 cond_val: llvmlite.Value | t.CPtr = HandlesExpr.translate_value( builder, pool, trans.Module, if_node.test,